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
74521715
Commit
74521715
authored
Mar 19, 2003
by
Jaroslav Kysela
Browse files
Options
Browse Files
Download
Plain Diff
Merge suse.cz:/home/perex/bk/linux-sound/linux-sound
into suse.cz:/home/perex/bk/linux-sound/work
parents
d99c48c6
c3c8a7e8
Changes
33
Hide whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
1595 additions
and
761 deletions
+1595
-761
Documentation/sound/alsa/CMIPCI.txt
Documentation/sound/alsa/CMIPCI.txt
+2
-2
Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+13
-0
Documentation/sound/alsa/serial-u16550.txt
Documentation/sound/alsa/serial-u16550.txt
+12
-15
include/sound/ac97_codec.h
include/sound/ac97_codec.h
+11
-1
include/sound/asound.h
include/sound/asound.h
+25
-3
include/sound/hwdep.h
include/sound/hwdep.h
+9
-0
include/sound/initval.h
include/sound/initval.h
+1
-1
include/sound/pcm.h
include/sound/pcm.h
+1
-0
include/sound/uda1341.h
include/sound/uda1341.h
+6
-1
include/sound/version.h
include/sound/version.h
+1
-1
sound/arm/sa11xx-uda1341.c
sound/arm/sa11xx-uda1341.c
+205
-101
sound/core/hwdep.c
sound/core/hwdep.c
+61
-5
sound/core/ioctl32/hwdep32.c
sound/core/ioctl32/hwdep32.c
+42
-3
sound/core/misc.c
sound/core/misc.c
+0
-21
sound/core/pcm_lib.c
sound/core/pcm_lib.c
+4
-0
sound/core/pcm_misc.c
sound/core/pcm_misc.c
+1
-1
sound/core/pcm_native.c
sound/core/pcm_native.c
+124
-0
sound/core/seq/seq_midi.c
sound/core/seq/seq_midi.c
+12
-4
sound/core/sound.c
sound/core/sound.c
+0
-3
sound/drivers/mpu401/mpu401_uart.c
sound/drivers/mpu401/mpu401_uart.c
+1
-1
sound/drivers/mtpav.c
sound/drivers/mtpav.c
+1
-1
sound/isa/dt019x.c
sound/isa/dt019x.c
+1
-1
sound/isa/sb/es968.c
sound/isa/sb/es968.c
+1
-1
sound/isa/sb/sb16_csp.c
sound/isa/sb/sb16_csp.c
+4
-1
sound/isa/sgalaxy.c
sound/isa/sgalaxy.c
+4
-4
sound/pci/ac97/ac97_codec.c
sound/pci/ac97/ac97_codec.c
+359
-120
sound/pci/ac97/ac97_id.h
sound/pci/ac97/ac97_id.h
+1
-0
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/cs46xx/cs46xx_lib.c
+21
-76
sound/pci/emu10k1/emufx.c
sound/pci/emu10k1/emufx.c
+118
-45
sound/pci/intel8x0.c
sound/pci/intel8x0.c
+35
-17
sound/pci/korg1212/korg1212.c
sound/pci/korg1212/korg1212.c
+483
-324
sound/pci/via82xx.c
sound/pci/via82xx.c
+25
-5
sound/usb/usbaudio.c
sound/usb/usbaudio.c
+11
-3
No files found.
Documentation/sound/alsa/CMIPCI.txt
View file @
74521715
...
...
@@ -207,7 +207,7 @@ MIDI CONTROLLER
---------------
The MPU401-UART interface is enabled as default only for the first
(CMIPCI) card. You need to set module option "
snd_
midi_port" properly
(CMIPCI) card. You need to set module option "midi_port" properly
for the 2nd (CMIPCI) card.
There is _no_ hardware wavetable function on this chip (except for
...
...
@@ -221,7 +221,7 @@ FM OPL/3 Synth
--------------
The FM OPL/3 is also enabled as default only for the first card.
Set "
snd_
fm_port" module option for more cards.
Set "fm_port" module option for more cards.
The output quality of FM OPL/3 is, however, very weird.
I don't know why..
...
...
Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
View file @
74521715
...
...
@@ -1377,6 +1377,8 @@
module_init(alsa_card_mychip_init)
module_exit(alsa_card_mychip_exit)
EXPORT_NO_SYMBOLS;
/*
for
old
kernels
only
*/
]]
>
</programlisting>
</example>
...
...
@@ -2758,6 +2760,17 @@
</para>
</section>
<section
id=
"pcm-interface-operators-ack"
>
<title>
ack callback
</title>
<para>
This callback is also not mandatory. This callback is called
when the appl_ptr is updated in read or write operations.
Some drivers like emu10k1-fx and cs46xx need to track the
current appl_ptr for the internal buffer, and this callback
is useful only for such a purpose.
</para>
</section>
<section
id=
"pcm-interface-operators-page-callback"
>
<title>
page callback
</title>
...
...
Documentation/sound/alsa/serial-u16550.txt
View file @
74521715
...
...
@@ -2,7 +2,7 @@
Serial UART 16450/16550 MIDI driver
===================================
The
snd_
adaptor module parameter allows you to select either:
The adaptor module parameter allows you to select either:
0 - Roland Soundcanvas support (default)
1 - Midiator MS-124T support (1)
...
...
@@ -24,37 +24,35 @@ send the F5 NN command sequence at all; perhaps it ought to.
Usage example for simple serial converter:
/sbin/setserial /dev/ttyS0 none
/sbin/modprobe snd-serial-u16550 snd_port=0x3f8 snd_irq=4 \
snd_speed=115200
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 speed=115200
Usage example for Roland SoundCanvas with 4 MIDI ports:
/sbin/setserial /dev/ttyS0 none
/sbin/modprobe snd-serial-u16550
snd_port=0x3f8 snd_irq=4 snd_
outs=4
/sbin/modprobe snd-serial-u16550
port=0x3f8 irq=4
outs=4
In MS-124T mode, one raw MIDI substream is supported (midiCnD0); the
snd_
outs
In MS-124T mode, one raw MIDI substream is supported (midiCnD0); the outs
module parameter is automatically set to 1. The driver sends the same data to
all four MIDI Out connectors. Set the A-B switch and the s
nd_s
peed module
all four MIDI Out connectors. Set the A-B switch and the speed module
parameter to match (A=19200, B=9600).
Usage example for MS-124T, with A-B switch in A position:
/sbin/setserial /dev/ttyS0 none
/sbin/modprobe snd-serial-u16550
snd_port=0x3f8 snd_irq=4
\
s
nd_adaptor=1 snd_s
peed=19200
/sbin/modprobe snd-serial-u16550
port=0x3f8 irq=4 adaptor=1
\
speed=19200
In MS-124W S/A mode, one raw MIDI substream is supported (midiCnD0);
the
snd_
outs module parameter is automatically set to 1. The driver sends
the outs module parameter is automatically set to 1. The driver sends
the same data to all four MIDI Out connectors at full MIDI speed.
Usage example for S/A mode:
/sbin/setserial /dev/ttyS0 none
/sbin/modprobe snd-serial-u16550 snd_port=0x3f8 snd_irq=4 \
snd_adaptor=2
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=2
In MS-124W M/B mode, the driver supports 16 ALSA raw MIDI substreams;
the
snd_
outs module parameter is automatically set to 16. The substream
the outs module parameter is automatically set to 16. The substream
number gives a bitmask of which MIDI Out connectors the data should be
sent to, with midiCnD1 sending to Out 1, midiCnD2 to Out 2, midiCnD4 to
Out 3, and midiCnD8 to Out 4. Thus midiCnD15 sends the data to all 4 ports.
...
...
@@ -67,8 +65,7 @@ one byte every 320 us per port.
Usage example for M/B mode:
/sbin/setserial /dev/ttyS0 none
/sbin/modprobe snd-serial-u16550 snd_port=0x3f8 snd_irq=4 \
snd_adaptor=3
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=3
The MS-124W hardware's M/A mode is currently not supported. This mode allows
the MIDI Outs to act independently at double the aggregate throughput of M/B,
...
...
@@ -88,4 +85,4 @@ The Generic driver supports multiple input and output substreams over a single
serial port. Similar to Roland Soundcanvas mode, F5 NN is used to select the
appropriate input or output stream (depending on the data direction).
Additionally, the CTS signal is used to regulate the data flow. The number of
inputs is specified by the
snd_
ins parameter.
inputs is specified by the ins parameter.
include/sound/ac97_codec.h
View file @
74521715
...
...
@@ -268,6 +268,14 @@ struct _snd_ac97 {
};
/* conditions */
static
inline
int
ac97_is_audio
(
ac97_t
*
ac97
)
{
return
(
ac97
->
scaps
&
AC97_SCAP_AUDIO
);
}
static
inline
int
ac97_is_modem
(
ac97_t
*
ac97
)
{
return
(
ac97
->
scaps
&
AC97_SCAP_MODEM
);
}
static
inline
int
ac97_is_rev22
(
ac97_t
*
ac97
)
{
return
(
ac97
->
ext_id
&
AC97_EI_REV_MASK
)
==
AC97_EI_REV_22
;
...
...
@@ -278,7 +286,8 @@ static inline int ac97_can_amap(ac97_t * ac97)
}
/* functions */
int
snd_ac97_mixer
(
snd_card_t
*
card
,
ac97_t
*
_ac97
,
ac97_t
**
rac97
);
int
snd_ac97_mixer
(
snd_card_t
*
card
,
ac97_t
*
_ac97
,
ac97_t
**
rac97
);
/* create mixer controls */
int
snd_ac97_modem
(
snd_card_t
*
card
,
ac97_t
*
_ac97
,
ac97_t
**
rac97
);
/* create modem controls */
void
snd_ac97_write
(
ac97_t
*
ac97
,
unsigned
short
reg
,
unsigned
short
value
);
unsigned
short
snd_ac97_read
(
ac97_t
*
ac97
,
unsigned
short
reg
);
...
...
@@ -296,6 +305,7 @@ enum { AC97_TUNE_HP_ONLY, AC97_TUNE_SWAP_HP };
struct
ac97_quirk
{
unsigned
short
vendor
;
unsigned
short
device
;
const
char
*
name
;
int
type
;
};
...
...
include/sound/asound.h
View file @
74521715
...
...
@@ -93,7 +93,7 @@ struct sndrv_aes_iec958 {
* *
****************************************************************************/
#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0,
0
)
#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0,
1
)
enum
sndrv_hwdep_iface
{
SNDRV_HWDEP_IFACE_OPL2
=
0
,
...
...
@@ -104,9 +104,10 @@ enum sndrv_hwdep_iface {
SNDRV_HWDEP_IFACE_YSS225
,
/* Yamaha FX processor */
SNDRV_HWDEP_IFACE_ICS2115
,
/* Wavetable synth */
SNDRV_HWDEP_IFACE_SSCAPE
,
/* Ensoniq SoundScape ISA card (MC68EC000) */
SNDRV_HWDEP_IFACE_VX
,
/* Digigram VX cards */
/* Don't forget to change the following: */
SNDRV_HWDEP_IFACE_LAST
=
SNDRV_HWDEP_IFACE_
SSCAPE
,
SNDRV_HWDEP_IFACE_LAST
=
SNDRV_HWDEP_IFACE_
VX
,
};
struct
sndrv_hwdep_info
{
...
...
@@ -118,9 +119,29 @@ struct sndrv_hwdep_info {
unsigned
char
reserved
[
64
];
/* reserved for future */
};
/* generic DSP loader */
struct
sndrv_hwdep_dsp_status
{
unsigned
int
version
;
/* R: driver-specific version */
unsigned
char
id
[
32
];
/* R: driver-specific ID string */
unsigned
int
num_dsps
;
/* R: number of DSP images to transfer */
unsigned
int
dsp_loaded
;
/* R: bit flags indicating the loaded DSPs */
unsigned
int
chip_ready
;
/* R: 1 = initialization finished */
unsigned
char
reserved
[
16
];
/* reserved for future use */
};
struct
sndrv_hwdep_dsp_image
{
unsigned
int
index
;
/* W: DSP index */
unsigned
char
name
[
64
];
/* W: ID (e.g. file name) */
unsigned
char
*
image
;
/* W: binary image */
size_t
length
;
/* W: size of image in bytes */
unsigned
long
driver_data
;
/* W: driver-specific data */
};
enum
{
SNDRV_HWDEP_IOCTL_PVERSION
=
_IOR
(
'H'
,
0x00
,
int
),
SNDRV_HWDEP_IOCTL_INFO
=
_IOR
(
'H'
,
0x01
,
struct
sndrv_hwdep_info
),
SNDRV_HWDEP_IOCTL_DSP_STATUS
=
_IOR
(
'H'
,
0x02
,
struct
sndrv_hwdep_dsp_status
),
SNDRV_HWDEP_IOCTL_DSP_LOAD
=
_IOW
(
'H'
,
0x03
,
struct
sndrv_hwdep_dsp_image
)
};
/*****************************************************************************
...
...
@@ -129,7 +150,7 @@ enum {
* *
*****************************************************************************/
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0,
3
)
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0,
4
)
typedef
unsigned
long
sndrv_pcm_uframes_t
;
typedef
long
sndrv_pcm_sframes_t
;
...
...
@@ -434,6 +455,7 @@ enum {
SNDRV_PCM_IOCTL_REWIND
=
_IOW
(
'A'
,
0x46
,
sndrv_pcm_uframes_t
),
SNDRV_PCM_IOCTL_RESUME
=
_IO
(
'A'
,
0x47
),
SNDRV_PCM_IOCTL_XRUN
=
_IO
(
'A'
,
0x48
),
SNDRV_PCM_IOCTL_FORWARD
=
_IOW
(
'A'
,
0x49
,
sndrv_pcm_uframes_t
),
SNDRV_PCM_IOCTL_WRITEI_FRAMES
=
_IOW
(
'A'
,
0x50
,
struct
sndrv_xferi
),
SNDRV_PCM_IOCTL_READI_FRAMES
=
_IOR
(
'A'
,
0x51
,
struct
sndrv_xferi
),
SNDRV_PCM_IOCTL_WRITEN_FRAMES
=
_IOW
(
'A'
,
0x52
,
struct
sndrv_xfern
),
...
...
include/sound/hwdep.h
View file @
74521715
...
...
@@ -27,6 +27,8 @@
typedef
enum
sndrv_hwdep_iface
snd_hwdep_iface_t
;
typedef
struct
sndrv_hwdep_info
snd_hwdep_info_t
;
typedef
struct
sndrv_hwdep_dsp_status
snd_hwdep_dsp_status_t
;
typedef
struct
sndrv_hwdep_dsp_image
snd_hwdep_dsp_image_t
;
typedef
struct
_snd_hwdep_ops
{
long
long
(
*
llseek
)
(
snd_hwdep_t
*
hw
,
struct
file
*
file
,
long
long
offset
,
int
orig
);
...
...
@@ -37,6 +39,8 @@ typedef struct _snd_hwdep_ops {
unsigned
int
(
*
poll
)
(
snd_hwdep_t
*
hw
,
struct
file
*
file
,
poll_table
*
wait
);
int
(
*
ioctl
)
(
snd_hwdep_t
*
hw
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
);
int
(
*
mmap
)
(
snd_hwdep_t
*
hw
,
struct
file
*
file
,
struct
vm_area_struct
*
vma
);
int
(
*
dsp_status
)
(
snd_hwdep_t
*
hw
,
snd_hwdep_dsp_status_t
*
status
);
int
(
*
dsp_load
)
(
snd_hwdep_t
*
hw
,
snd_hwdep_dsp_image_t
*
image
);
}
snd_hwdep_ops_t
;
struct
_snd_hwdep
{
...
...
@@ -56,6 +60,11 @@ struct _snd_hwdep {
wait_queue_head_t
open_wait
;
void
*
private_data
;
void
(
*
private_free
)
(
snd_hwdep_t
*
hwdep
);
struct
semaphore
open_mutex
;
int
used
;
unsigned
int
dsp_loaded
;
unsigned
int
exclusive
:
1
;
};
extern
int
snd_hwdep_new
(
snd_card_t
*
card
,
char
*
id
,
int
device
,
snd_hwdep_t
**
rhwdep
);
...
...
include/sound/initval.h
View file @
74521715
...
...
@@ -67,7 +67,7 @@ static const char __module_generic_string_##name [] \
#define SNDRV_BOOLEAN_TRUE_DESC "allows:{{0,Disabled},{1,Enabled}},default:1,dialog:check"
#define SNDRV_BOOLEAN_FALSE_DESC "allows:{{0,Disabled},{1,Enabled}},default:0,dialog:check"
#define SNDRV_ENABLED "enable:(
snd_
enable)"
#define SNDRV_ENABLED "enable:(enable)"
#define SNDRV_INDEX_DESC SNDRV_ENABLED ",allows:{{0,7}},unique,skill:required,dialog:list"
#define SNDRV_ID_DESC SNDRV_ENABLED ",unique"
...
...
include/sound/pcm.h
View file @
74521715
...
...
@@ -97,6 +97,7 @@ typedef struct _snd_pcm_ops {
int
(
*
silence
)(
snd_pcm_substream_t
*
substream
,
int
channel
,
snd_pcm_uframes_t
pos
,
snd_pcm_uframes_t
count
);
struct
page
*
(
*
page
)(
snd_pcm_substream_t
*
substream
,
unsigned
long
offset
);
int
(
*
ack
)(
snd_pcm_substream_t
*
substream
);
}
snd_pcm_ops_t
;
/*
...
...
include/sound/uda1341.h
View file @
74521715
...
...
@@ -15,10 +15,15 @@
* features support
*/
/* $Id: uda1341.h,v 1.
2 2002/04/17 07:53:22
perex Exp $ */
/* $Id: uda1341.h,v 1.
4 2003/02/25 12:48:16
perex Exp $ */
#define UDA1341_ALSA_NAME "snd-uda1341"
/*
* Default rate set after inicialization
*/
#define AUDIO_RATE_DEFAULT 44100
/*
* UDA1341 L3 address and command types
*/
...
...
include/sound/version.h
View file @
74521715
/* include/version.h. Generated by configure. */
#define CONFIG_SND_VERSION "0.9.0rc7"
#define CONFIG_SND_DATE " (
Sat Feb 15 15:01:21
2003 UTC)"
#define CONFIG_SND_DATE " (
Tue Feb 25 13:00:09
2003 UTC)"
sound/arm/sa11xx-uda1341.c
View file @
74521715
...
...
@@ -13,9 +13,48 @@
* 2002-03-29 Tomas Kasparek basic capture is working (native ALSA)
* 2002-03-29 Tomas Kasparek capture is working (OSS emulation)
* 2002-04-04 Tomas Kasparek better rates handling (allow non-standard rates)
* 2003-02-14 Brian Avery fixed full duplex mode, other updates
* 2003-02-20 Tomas Kasparek merged updates by Brian (except HAL)
*/
/* $Id: sa11xx-uda1341.c,v 1.7 2003/02/13 19:19:18 perex Exp $ */
/* $Id: sa11xx-uda1341.c,v 1.8 2003/02/25 12:48:15 perex Exp $ */
/***************************************************************************************************
*
* To understand what Alsa Drivers should be doing look at "Writing an Alsa Driver" by Takashi Iwai
* available in the Alsa doc section on the website
*
* A few notes to make things clearer. The UDA1341 is hooked up to Serial port 4 on the SA1100.
* We are using SSP mode to talk to the UDA1341. The UDA1341 bit & wordselect clocks are generated
* by this UART. Unfortunately, the clock only runs if the transmit buffer has something in it.
* So, if we are just recording, we feed the transmit DMA stream a bunch of 0x0000 so that the
* transmit buffer is full and the clock keeps going. The zeroes come from FLUSH_BASE_PHYS which
* is a mem loc that always decodes to 0's w/ no off chip access.
*
* Some alsa terminology:
* frame => num_channels * sample_size e.g stereo 16 bit is 2 * 16 = 32 bytes
* period => the least number of bytes that will generate an interrupt e.g. we have a 1024 byte
* buffer and 4 periods in the runtime structure this means we'll get an int every 256
* bytes or 4 times per buffer.
* A number of the sizes are in frames rather than bytes, use frames_to_bytes and
* bytes_to_frames to convert. The easiest way to tell the units is to look at the
* type i.e. runtime-> buffer_size is in frames and its type is snd_pcm_uframes_t
*
* Notes about the pointer fxn:
* The pointer fxn needs to return the offset into the dma buffer in frames.
* Interrupts must be blocked before calling the dma_get_pos fxn to avoid race with interrupts.
*
* Notes about pause/resume
* Implementing this would be complicated so it's skipped. The problem case is:
* A full duplex connection is going, then play is paused. At this point you need to start xmitting
* 0's to keep the record active which means you cant just freeze the dma and resume it later you'd
* need to save off the dma info, and restore it properly on a resume. Yeach!
*
* Notes about transfer methods:
* The async write calls fail. I probably need to implement something else to support them?
*
***************************************************************************************************/
#include <sound/driver.h>
#include <linux/module.h>
...
...
@@ -53,8 +92,6 @@ MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard.");
#define chip_t sa11xx_uda1341_t
#define SHIFT_16_STEREO 2
typedef
enum
stream_id_t
{
PLAYBACK
=
0
,
CAPTURE
,
...
...
@@ -62,32 +99,29 @@ typedef enum stream_id_t{
}
stream_id_t
;
typedef
struct
audio_stream
{
char
*
id
;
/* identification string */
char
*
id
;
/* identification string */
int
stream_id
;
/* numeric identification */
dma_device_t
dma_dev
;
/* device identifier for DMA */
dma_regs_t
*
dma_regs
;
/* points to our DMA registers */
int
active
:
1
;
/* we are using this stream for transfer now */
int
active
:
1
;
/* we are using this stream for transfer now */
int
sent_periods
;
/* # of sent periods from actual DMA buffer */
int
sent_total
;
/* # of sent periods total (just for info & debug) */
int
sync
;
/* are we recoding - flag used to do DMA trans. for sync */
spinlock_t
dma_lock
;
/* for locking in DMA operations (see dma-sa1100.c in the kernel) */
snd_pcm_substream_t
*
stream
;
}
audio_stream_t
;
/* I do not want to have substream = NULL when syncing - ALSA does not like it */
#define SYNC_SUBSTREAM ((void *) -1)
typedef
struct
snd_card_sa11xx_uda1341
{
struct
pm_dev
*
pm_dev
;
snd_card_t
*
card
;
struct
l3_client
*
uda1341
;
long
samplerate
;
audio_stream_t
*
s
[
MAX_STREAMS
];
snd_info_entry_t
*
proc_entry
;
}
sa11xx_uda1341_t
;
static
struct
snd_card_sa11xx_uda1341
*
sa11xx_uda1341
=
NULL
;
...
...
@@ -217,7 +251,9 @@ static void sa11xx_uda1341_set_samplerate(sa11xx_uda1341_t *sa11xx_uda1341, long
break
;
}
/* FMT setting should be moved away when other FMTs are added (FIXME) */
l3_command
(
sa11xx_uda1341
->
uda1341
,
CMD_FORMAT
,
(
void
*
)
LSB16
);
l3_command
(
sa11xx_uda1341
->
uda1341
,
CMD_FS
,
(
void
*
)
clk
);
Ser4SSCR0
=
(
Ser4SSCR0
&
~
0xff00
)
+
clk_div
+
SSCR0_SSE
;
DEBUG
(
KERN_DEBUG
"set_samplerate done (new rate: %ld)
\n
"
,
rate
);
...
...
@@ -237,11 +273,13 @@ static void sa11xx_uda1341_audio_init(sa11xx_uda1341_t *sa11xx_uda1341)
/* Setup DMA stuff */
if
(
sa11xx_uda1341
->
s
[
PLAYBACK
])
{
sa11xx_uda1341
->
s
[
PLAYBACK
]
->
id
=
"UDA1341 out"
;
sa11xx_uda1341
->
s
[
PLAYBACK
]
->
stream_id
=
PLAYBACK
;
sa11xx_uda1341
->
s
[
PLAYBACK
]
->
dma_dev
=
DMA_Ser4SSPWr
;
}
if
(
sa11xx_uda1341
->
s
[
CAPTURE
])
{
sa11xx_uda1341
->
s
[
CAPTURE
]
->
id
=
"UDA1341 in"
;
sa11xx_uda1341
->
s
[
CAPTURE
]
->
stream_id
=
CAPTURE
;
sa11xx_uda1341
->
s
[
CAPTURE
]
->
dma_dev
=
DMA_Ser4SSPRd
;
}
...
...
@@ -255,22 +293,24 @@ static void sa11xx_uda1341_audio_init(sa11xx_uda1341_t *sa11xx_uda1341)
Ser4SSCR0
=
SSCR0_DataSize
(
16
)
+
SSCR0_TI
+
SSCR0_SerClkDiv
(
8
);
Ser4SSCR1
=
SSCR1_SClkIactL
+
SSCR1_SClk1P
+
SSCR1_ExtClk
;
Ser4SSCR0
|=
SSCR0_SSE
;
local_irq_restore
(
flags
);
/* Enable the audio power */
clr_sa11xx_uda1341_egpio
(
IPAQ_EGPIO_CODEC_NRESET
);
set_sa11xx_uda1341_egpio
(
IPAQ_EGPIO_AUDIO_ON
);
set_sa11xx_uda1341_egpio
(
IPAQ_EGPIO_QMUTE
);
local_irq_restore
(
flags
);
/* Initialize the UDA1341 internal state */
l3_open
(
sa11xx_uda1341
->
uda1341
);
/* external clock configuration */
sa11xx_uda1341_set_samplerate
(
sa11xx_uda1341
,
44100
);
/* default sample rate */
/* external clock configuration (after l3_open - regs must be
* initialized */
sa11xx_uda1341_set_samplerate
(
sa11xx_uda1341
,
AUDIO_RATE_DEFAULT
);
/* Wait for the UDA1341 to wake up */
set_sa11xx_uda1341_egpio
(
IPAQ_EGPIO_CODEC_NRESET
);
mdelay
(
1
);
/* make the left and right channels unswapped (flip the WS latch ) */
Ser4SSDR
=
0
;
...
...
@@ -280,11 +320,16 @@ static void sa11xx_uda1341_audio_init(sa11xx_uda1341_t *sa11xx_uda1341)
static
void
sa11xx_uda1341_audio_shutdown
(
sa11xx_uda1341_t
*
sa11xx_uda1341
)
{
/* mute on */
set_sa11xx_uda1341_egpio
(
IPAQ_EGPIO_QMUTE
);
/* disable the audio power and all signals leading to the audio chip */
l3_close
(
sa11xx_uda1341
->
uda1341
);
Ser4SSCR0
=
0
;
clr_sa11xx_uda1341_egpio
(
IPAQ_EGPIO_CODEC_NRESET
);
/* power off */
clr_sa11xx_uda1341_egpio
(
IPAQ_EGPIO_AUDIO_ON
);
/* mute off */
clr_sa11xx_uda1341_egpio
(
IPAQ_EGPIO_QMUTE
);
}
...
...
@@ -292,26 +337,29 @@ static void sa11xx_uda1341_audio_shutdown(sa11xx_uda1341_t *sa11xx_uda1341)
/* {{{ DMA staff */
#define SYNC_ADDR (dma_addr_t)FLUSH_BASE_PHYS
#define SYNC_SIZE 4096 // was 2048
#define DMA_REQUEST(s, cb) sa1100_request_dma((s)->dma_dev, (s)->id, cb, s, \
&((s)->dma_regs))
#define DMA_FREE(s) {sa1100_free_dma((s)->dma_regs); (s)->dma_regs = 0;}
#define DMA_START(s, d, l) sa1100_start_dma((s)->dma_regs, d, l)
#define DMA_STOP(s) sa1100_stop_dma((s)->dma_regs)
#define DMA_CLEAR(s) sa1100_clear_dma((s)->dma_regs)
#define DMA_RESET(s) sa1100_reset_dma((s)->dma_regs)
#define DMA_POS(s) sa1100_get_dma_pos((s)->dma_regs)
/*
* these are the address and sizes used to fill the xmit buffer
* so we can get a clock in record only mode
*/
#define FORCE_CLOCK_ADDR (dma_addr_t)FLUSH_BASE_PHYS
#define FORCE_CLOCK_SIZE 4096 // was 2048
static
void
audio_dma_request
(
audio_stream_t
*
s
,
void
(
*
callback
)(
void
*
))
{
DMA_REQUEST
(
s
,
callback
);
int
ret
;
DEBUG_NAME
(
KERN_DEBUG
"audio_dma_request"
);
DEBUG
(
"
\t
request id <%s>
\n
"
,
s
->
id
);
DEBUG
(
"
\t
request dma_dev = 0x%x
\n
"
,
s
->
dma_dev
);
ret
=
sa1100_request_dma
((
s
)
->
dma_dev
,
(
s
)
->
id
,
callback
,
s
,
&
((
s
)
->
dma_regs
));
DEBUG
(
"
\t
request ret = %d
\n
"
,
ret
);
}
static
void
audio_dma_free
(
audio_stream_t
*
s
)
{
DMA_FREE
(
s
);
sa1100_free_dma
((
s
)
->
dma_regs
);
(
s
)
->
dma_regs
=
0
;
}
static
u_int
audio_get_dma_pos
(
audio_stream_t
*
s
)
...
...
@@ -319,12 +367,17 @@ static u_int audio_get_dma_pos(audio_stream_t *s)
snd_pcm_substream_t
*
substream
=
s
->
stream
;
snd_pcm_runtime_t
*
runtime
=
substream
->
runtime
;
unsigned
int
offset
;
unsigned
long
flags
;
DEBUG_NAME
(
KERN_DEBUG
"get_dma_pos"
);
offset
=
DMA_POS
(
s
)
-
substream
->
runtime
->
dma_addr
;
// this must be called w/ interrupts locked out see dma-sa1100.c in the kernel
spin_lock_irqsave
(
&
s
->
dma_lock
,
flags
);
offset
=
sa1100_get_dma_pos
((
s
)
->
dma_regs
)
-
runtime
->
dma_addr
;
spin_unlock_irqrestore
(
&
s
->
dma_lock
,
flags
);
DEBUG
(
" %d ->"
,
offset
);
offset
>>=
SHIFT_16_STEREO
;
offset
=
bytes_to_frames
(
runtime
,
offset
);
DEBUG
(
" %d [fr]
\n
"
,
offset
);
if
(
offset
>=
runtime
->
buffer_size
){
...
...
@@ -339,27 +392,33 @@ static u_int audio_get_dma_pos(audio_stream_t *s)
return
offset
;
}
/*
* this stops the dma and clears the dma ptrs
*/
static
void
audio_stop_dma
(
audio_stream_t
*
s
)
{
long
flags
;
DEBUG_NAME
(
KERN_DEBUG
"stop_dma
\n
"
);
if
(
!
s
->
stream
)
/*
* zero filling streams (sync=1) don;t have alsa streams attached
* but the 0 fill dma xfer still needs to be stopped
*/
if
(
!
(
s
->
stream
||
s
->
sync
))
return
;
local_irq_save
(
flags
);
spin_lock_irqsave
(
&
(
s
->
dma_lock
),
flags
);
s
->
active
=
0
;
s
->
sent_periods
=
0
;
s
->
sent_total
=
0
;
s
->
sent_total
=
0
;
s
->
sync
=
0
;
DMA_STOP
(
s
);
DMA_CLEAR
(
s
);
local_irq_restore
(
flags
);
/* this stops the dma channel and clears the buffer ptrs */
sa1100_clear_dma
((
s
)
->
dma_regs
);
spin_unlock_irqrestore
(
&
(
s
->
dma_lock
),
flags
);
}
static
void
audio_reset
(
audio_stream_t
*
s
)
{
DEBUG_NAME
(
KERN_DEBUG
"dma_reset
\n
"
);
...
...
@@ -375,40 +434,58 @@ static void audio_process_dma(audio_stream_t *s)
{
snd_pcm_substream_t
*
substream
=
s
->
stream
;
snd_pcm_runtime_t
*
runtime
;
int
ret
,
i
;
int
ret
;
DEBUG_NAME
(
KERN_DEBUG
"process_dma
\n
"
);
if
(
!
s
->
active
){
DEBUG
(
"!!!want to process DMA when stopped!!!
\n
"
);
return
;
}
/* we are requested to process synchronization DMA transfer */
if
(
s
->
sync
)
{
if
(
!
s
->
active
&&
s
->
sync
){
snd_assert
(
s
->
stream_id
==
PLAYBACK
,
return
);
/* fill the xmit dma buffers and return */
while
(
1
)
{
DEBUG
(
KERN_DEBUG
"sent
sync period (dma_size[B]: %d)
\n
"
,
SYNC
_SIZE
);
ret
=
DMA_START
(
s
,
SYNC_ADDR
,
SYNC_SIZE
);
DEBUG
(
KERN_DEBUG
"sent
zero dma period (dma_size[B]: %d)
\n
"
,
FORCE_CLOCK
_SIZE
);
ret
=
sa1100_start_dma
((
s
)
->
dma_regs
,
FORCE_CLOCK_ADDR
,
FORCE_CLOCK_SIZE
);
if
(
ret
)
return
;
}
}
/* must be set here -
for sync there is no runtime struct
*/
/* must be set here -
only valid for running streams, not for forced_clock dma fills
*/
runtime
=
substream
->
runtime
;
while
(
1
)
{
unsigned
int
dma_size
=
runtime
->
period_size
<<
SHIFT_16_STEREO
;
unsigned
int
offset
=
dma_size
*
s
->
sent_periods
;
DEBUG
(
"audio_process_dma hw_ptr_base = 0x%x w_ptr_interrupt = 0x%x "
"period_size = %d periods = %d buffer_size = %d sync=0x%x dma_area = 0x%x
\n
"
,
runtime
->
hw_ptr_base
,
runtime
->
hw_ptr_interrupt
,
runtime
->
period_size
,
runtime
->
periods
,
runtime
->
buffer_size
,
runtime
->
sync
,
runtime
->
dma_area
);
DEBUG
(
"audio_process_dma sent_total = %d sent_period = %d
\n
"
,
s
->
sent_total
,
s
->
sent_periods
);
while
(
s
->
active
)
{
unsigned
int
dma_size
;
unsigned
int
offset
;
dma_size
=
frames_to_bytes
(
runtime
,
runtime
->
period_size
)
;
offset
=
dma_size
*
s
->
sent_periods
;
if
(
dma_size
>
MAX_DMA_SIZE
){
/* this should not happen! */
DEBUG
(
KERN_DEBUG
"--
---> cut dma_size: %d -> "
,
dma_size
);
printk
(
KERN_ERR
"
---> cut dma_size: %d -> "
,
dma_size
);
dma_size
=
CUT_DMA_SIZE
;
DEBUG
(
"%d <--
---
\n
"
,
dma_size
);
printk
(
"%d <
---
\n
"
,
dma_size
);
}
ret
=
DMA_START
(
s
,
runtime
->
dma_addr
+
offset
,
dma_size
);
/*
* the first time this while loop will run 3 times, i.e. it'll fill the 2 dma
* buffers then get a -EBUSY, every other time it'll refill the completed buffer
* and then get the -EBUSY so it'll just run twice
*/
ret
=
sa1100_start_dma
((
s
)
->
dma_regs
,
runtime
->
dma_addr
+
offset
,
dma_size
);
if
(
ret
)
return
;
...
...
@@ -429,7 +506,6 @@ static void audio_process_dma(audio_stream_t *s)
}
}
static
void
audio_dma_callback
(
void
*
data
)
{
audio_stream_t
*
s
=
data
;
...
...
@@ -438,24 +514,26 @@ static void audio_dma_callback(void *data)
DEBUG_NAME
(
KERN_DEBUG
"dma_callback
\n
"
);
/* when syncing we do not have any real stream from ALSA! */
if
(
!
s
->
sync
)
{
snd_pcm_period_elapsed
(
s
->
stream
);
DEBUG
(
KERN_DEBUG
"----> period done <----
\n
"
);
DEBUG
(
KERN_DEBUG
"----> period done <----
\n
"
);
#ifdef DEBUG_MODE
printk
(
KERN_DEBUG
" dma_area:"
);
buf
=
(
char
*
)
s
->
stream
->
runtime
->
dma_addr
+
((
s
->
sent_periods
-
1
)
*
(
s
->
stream
->
runtime
->
period_size
<<
SHIFT_16_STEREO
));
for
(
i
=
0
;
i
<
32
;
i
++
)
{
printk
(
" %02x"
,
*
(
char
*
)(
buf
+
i
));
}
printk
(
"
\n
"
);
#endif
printk
(
KERN_DEBUG
" dma_area:"
);
buf
=
(
char
*
)
s
->
stream
->
runtime
->
dma_addr
+
((
s
->
sent_periods
-
1
)
*
frames_to_bytes
(
s
->
stream
->
runtime
,
s
->
stream
->
runtime
->
period_size
));
for
(
i
=
0
;
i
<
32
;
i
++
)
{
printk
(
" %02x"
,
*
(
char
*
)(
buf
+
i
));
}
printk
(
"
\n
"
);
#endif
if
(
s
->
active
)
audio_process_dma
(
s
);
/*
* If we are getting a callback for an active stream then we inform
* the PCM middle layer we've finished a period
*/
if
(
s
->
active
)
snd_pcm_period_elapsed
(
s
->
stream
);
audio_process_dma
(
s
);
}
/* }}} */
...
...
@@ -491,18 +569,21 @@ static int snd_card_sa11xx_uda1341_pcm_trigger(stream_id_t stream_id,
case
SNDRV_PCM_TRIGGER_START
:
case
SNDRV_PCM_TRIGGER_RESUME
:
case
SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
/*
want to capture and have no playback - run DMA syncing
*/
/*
now we need to make sure a record only stream has a clock
*/
if
(
stream_id
==
CAPTURE
&&
!
chip
->
s
[
PLAYBACK
]
->
active
)
{
/* we need
synchronization DMA transfer (zeros)
*/
DEBUG
(
KERN_DEBUG
"starting
synchronization
DMA transfer
\n
"
);
/* we need
to force fill the xmit DMA with zeros
*/
DEBUG
(
KERN_DEBUG
"starting
zero fill
DMA transfer
\n
"
);
chip
->
s
[
PLAYBACK
]
->
sync
=
1
;
chip
->
s
[
PLAYBACK
]
->
active
=
1
;
chip
->
s
[
PLAYBACK
]
->
stream
=
SYNC_SUBSTREAM
;
/* not really used! */
audio_process_dma
(
chip
->
s
[
PLAYBACK
]);
}
/* want to playback and have capture - stop syncing */
if
(
stream_id
==
PLAYBACK
&&
chip
->
s
[
PLAYBACK
]
->
sync
)
{
chip
->
s
[
PLAYBACK
]
->
sync
=
0
;
/* this case is when you were recording then you turn on a
* playback stream so we
* stop (also clears it) the dma first, clear the sync flag
* and then we let it get turned on
*/
else
if
(
stream_id
==
PLAYBACK
&&
chip
->
s
[
PLAYBACK
]
->
sync
)
{
chip
->
s
[
PLAYBACK
]
->
sync
=
0
;
audio_stop_dma
(
chip
->
s
[
PLAYBACK
]);
}
/* requested stream startup */
...
...
@@ -512,27 +593,30 @@ static int snd_card_sa11xx_uda1341_pcm_trigger(stream_id_t stream_id,
case
SNDRV_PCM_TRIGGER_STOP
:
case
SNDRV_PCM_TRIGGER_SUSPEND
:
case
SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
/* want to stop capture and use syncing - stop DMA syncing */
if
(
stream_id
==
CAPTURE
&&
chip
->
s
[
PLAYBACK
]
->
sync
)
{
/* we do not need synchronization DMA transfer now */
DEBUG
(
KERN_DEBUG
"stopping synchronization DMA transfer
\n
"
);
chip
->
s
[
PLAYBACK
]
->
sync
=
0
;
chip
->
s
[
PLAYBACK
]
->
active
=
0
;
audio_stop_dma
(
chip
->
s
[
PLAYBACK
]);
}
/* want to stop playback and have capture - run DMA syncing */
if
(
stream_id
==
PLAYBACK
&&
chip
->
s
[
CAPTURE
]
->
active
)
{
/* we need synchronization DMA transfer (zeros) */
DEBUG
(
KERN_DEBUG
"starting synchronization DMA transfer
\n
"
);
chip
->
s
[
PLAYBACK
]
->
sync
=
1
;
chip
->
s
[
PLAYBACK
]
->
active
=
1
;
chip
->
s
[
PLAYBACK
]
->
stream
=
SYNC_SUBSTREAM
;
/* not really used! */
audio_process_dma
(
chip
->
s
[
PLAYBACK
]);
}
/* requested stream shutdown */
chip
->
s
[
stream_id
]
->
active
=
0
;
audio_stop_dma
(
chip
->
s
[
stream_id
]);
/*
* now we need to make sure a record only stream has a clock
* so if we're stopping a playback with an active capture
* we need to turn the 0 fill dma on for the xmit side
*/
if
(
stream_id
==
PLAYBACK
&&
chip
->
s
[
CAPTURE
]
->
active
)
{
/* we need to force fill the xmit DMA with zeros */
DEBUG
(
KERN_DEBUG
"starting zero fill DMA transfer
\n
"
);
chip
->
s
[
PLAYBACK
]
->
sync
=
1
;
chip
->
s
[
PLAYBACK
]
->
active
=
0
;
audio_process_dma
(
chip
->
s
[
PLAYBACK
]);
}
/*
* we killed a capture only stream, so we should also kill
* the zero fill transmit
*/
else
if
(
stream_id
==
CAPTURE
&&
chip
->
s
[
PLAYBACK
]
->
sync
)
{
audio_stop_dma
(
chip
->
s
[
PLAYBACK
]);
}
break
;
default:
return
-
EINVAL
;
...
...
@@ -601,7 +685,11 @@ static int snd_card_sa11xx_uda1341_playback_open(snd_pcm_substream_t * substream
chip
->
s
[
PLAYBACK
]
->
sent_periods
=
0
;
chip
->
s
[
PLAYBACK
]
->
sent_total
=
0
;
audio_reset
(
chip
->
s
[
PLAYBACK
]);
/* no reset here since we may be zero filling the DMA
* if we are, the dma stream will get reset in the pcm_trigger
* i.e. when it actually starts to play
*/
/* audio_reset(chip->s[PLAYBACK]); */
runtime
->
hw
=
snd_sa11xx_uda1341_playback
;
if
((
err
=
snd_pcm_hw_constraint_integer
(
runtime
,
SNDRV_PCM_HW_PARAM_PERIODS
))
<
0
)
...
...
@@ -652,10 +740,13 @@ static int snd_card_sa11xx_uda1341_playback_trigger(snd_pcm_substream_t * substr
static
snd_pcm_uframes_t
snd_card_sa11xx_uda1341_playback_pointer
(
snd_pcm_substream_t
*
substream
)
{
snd_pcm_uframes_t
pos
;
sa11xx_uda1341_t
*
chip
=
snd_pcm_substream_chip
(
substream
);
DEBUG_NAME
(
KERN_DEBUG
"playback_pointer
\n
"
);
return
audio_get_dma_pos
(
chip
->
s
[
PLAYBACK
]);
pos
=
audio_get_dma_pos
(
chip
->
s
[
PLAYBACK
]);
return
pos
;
}
/* }}} */
...
...
@@ -674,7 +765,7 @@ static int snd_card_sa11xx_uda1341_capture_open(snd_pcm_substream_t * substream)
chip
->
s
[
CAPTURE
]
->
sent_periods
=
0
;
chip
->
s
[
CAPTURE
]
->
sent_total
=
0
;
audio_reset
(
chip
->
s
[
PLAYBACK
]);
audio_reset
(
chip
->
s
[
CAPTURE
]);
runtime
->
hw
=
snd_sa11xx_uda1341_capture
;
if
((
err
=
snd_pcm_hw_constraint_integer
(
runtime
,
SNDRV_PCM_HW_PARAM_PERIODS
))
<
0
)
...
...
@@ -725,10 +816,12 @@ static int snd_card_sa11xx_uda1341_capture_trigger(snd_pcm_substream_t * substre
static
snd_pcm_uframes_t
snd_card_sa11xx_uda1341_capture_pointer
(
snd_pcm_substream_t
*
substream
)
{
snd_pcm_uframes_t
pos
;
sa11xx_uda1341_t
*
chip
=
snd_pcm_substream_chip
(
substream
);
DEBUG_NAME
(
KERN_DEBUG
"record_pointer
\n
"
);
return
audio_get_dma_pos
(
chip
->
s
[
CAPTURE
]);
pos
=
audio_get_dma_pos
(
chip
->
s
[
CAPTURE
]);
return
pos
;
}
/* }}} */
...
...
@@ -784,6 +877,13 @@ static int __init snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341_t *sa11xx_uda1341,
substreams
,
substreams
,
&
pcm
))
<
0
)
return
err
;
/*
* this sets up our initial buffers and sets the dma_type to isa.
* isa works but I'm not sure why (or if) it's the right choice
* this may be too large, trying it for now
*/
snd_pcm_lib_preallocate_isa_pages_for_all
(
pcm
,
64
*
1024
,
64
*
1024
);
snd_pcm_set_ops
(
pcm
,
SNDRV_PCM_STREAM_PLAYBACK
,
&
snd_card_sa11xx_uda1341_playback_ops
);
snd_pcm_set_ops
(
pcm
,
SNDRV_PCM_STREAM_CAPTURE
,
&
snd_card_sa11xx_uda1341_capture_ops
);
pcm
->
private_data
=
sa11xx_uda1341
;
...
...
@@ -816,6 +916,10 @@ static int sa11xx_uda1341_pm_callback(struct pm_dev *pm_dev, pm_request_t req, v
DEBUG_NAME
(
KERN_DEBUG
"pm_callback
\n
"
);
/* pause resume is broken see note */
printk
(
"Pause/Resume support currently broken...
\n
"
);
return
-
1
;
is
=
sa11xx_uda1341
->
s
[
PLAYBACK
];
os
=
sa11xx_uda1341
->
s
[
CAPTURE
];
...
...
sound/core/hwdep.c
View file @
74521715
...
...
@@ -107,7 +107,12 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
#endif
init_waitqueue_entry
(
&
wait
,
current
);
add_wait_queue
(
&
hw
->
open_wait
,
&
wait
);
down
(
&
hw
->
open_mutex
);
while
(
1
)
{
if
(
hw
->
exclusive
&&
hw
->
used
>
0
)
{
err
=
-
EBUSY
;
break
;
}
err
=
hw
->
ops
.
open
(
hw
,
file
);
if
(
err
>=
0
)
break
;
...
...
@@ -127,20 +132,26 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
}
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
hw
->
open_wait
,
&
wait
);
if
(
err
>=
0
)
if
(
err
>=
0
)
{
file
->
private_data
=
hw
;
hw
->
used
++
;
}
up
(
&
hw
->
open_mutex
);
return
err
;
}
static
int
snd_hwdep_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
int
err
;
int
err
=
-
ENXIO
;
snd_hwdep_t
*
hw
=
snd_magic_cast
(
snd_hwdep_t
,
file
->
private_data
,
return
-
ENXIO
);
down
(
&
hw
->
open_mutex
);
if
(
hw
->
ops
.
release
)
{
err
=
hw
->
ops
.
release
(
hw
,
file
);
wake_up
(
&
hw
->
open_wait
);
return
err
;
}
if
(
hw
->
used
>
0
)
hw
->
used
--
;
up
(
&
hw
->
open_mutex
);
return
-
ENXIO
;
}
...
...
@@ -166,14 +177,58 @@ static int snd_hwdep_info(snd_hwdep_t *hw, snd_hwdep_info_t *_info)
return
0
;
}
static
int
snd_hwdep_dsp_status
(
snd_hwdep_t
*
hw
,
snd_hwdep_dsp_status_t
*
_info
)
{
snd_hwdep_dsp_status_t
info
;
int
err
;
if
(
!
hw
->
ops
.
dsp_status
)
return
-
ENXIO
;
memset
(
&
info
,
0
,
sizeof
(
info
));
info
.
dsp_loaded
=
hw
->
dsp_loaded
;
if
((
err
=
hw
->
ops
.
dsp_status
(
hw
,
&
info
))
<
0
)
return
err
;
if
(
copy_to_user
(
_info
,
&
info
,
sizeof
(
info
)))
return
-
EFAULT
;
return
0
;
}
static
int
snd_hwdep_dsp_load
(
snd_hwdep_t
*
hw
,
snd_hwdep_dsp_image_t
*
_info
)
{
snd_hwdep_dsp_image_t
info
;
int
err
;
if
(
!
hw
->
ops
.
dsp_load
||
!
hw
->
ops
.
dsp_status
)
return
-
ENXIO
;
memset
(
&
info
,
0
,
sizeof
(
info
));
if
(
copy_from_user
(
&
info
,
_info
,
sizeof
(
info
)))
return
-
EFAULT
;
/* check whether the dsp was already loaded */
if
(
hw
->
dsp_loaded
&
(
1
<<
info
.
index
))
return
-
EBUSY
;
if
(
verify_area
(
VERIFY_READ
,
info
.
image
,
info
.
length
))
return
-
EFAULT
;
err
=
hw
->
ops
.
dsp_load
(
hw
,
&
info
);
if
(
err
<
0
)
return
err
;
hw
->
dsp_loaded
|=
(
1
<<
info
.
index
);
return
0
;
}
static
int
snd_hwdep_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
snd_hwdep_t
*
hw
=
snd_magic_cast
(
snd_hwdep_t
,
file
->
private_data
,
return
-
ENXIO
);
if
(
cmd
==
SNDRV_HWDEP_IOCTL_PVERSION
)
switch
(
cmd
)
{
case
SNDRV_HWDEP_IOCTL_PVERSION
:
return
put_user
(
SNDRV_HWDEP_VERSION
,
(
int
*
)
arg
);
if
(
cmd
==
SNDRV_HWDEP_IOCTL_INFO
)
case
SNDRV_HWDEP_IOCTL_INFO
:
return
snd_hwdep_info
(
hw
,
(
snd_hwdep_info_t
*
)
arg
);
case
SNDRV_HWDEP_IOCTL_DSP_STATUS
:
return
snd_hwdep_dsp_status
(
hw
,
(
snd_hwdep_dsp_status_t
*
)
arg
);
case
SNDRV_HWDEP_IOCTL_DSP_LOAD
:
return
snd_hwdep_dsp_load
(
hw
,
(
snd_hwdep_dsp_image_t
*
)
arg
);
}
if
(
hw
->
ops
.
ioctl
)
return
hw
->
ops
.
ioctl
(
hw
,
file
,
cmd
,
arg
);
return
-
ENOTTY
;
...
...
@@ -298,6 +353,7 @@ int snd_hwdep_new(snd_card_t * card, char *id, int device, snd_hwdep_t ** rhwdep
return
err
;
}
init_waitqueue_head
(
&
hwdep
->
open_wait
);
init_MUTEX
(
&
hwdep
->
open_mutex
);
*
rhwdep
=
hwdep
;
return
0
;
}
...
...
sound/core/ioctl32/hwdep32.c
View file @
74521715
...
...
@@ -20,13 +20,52 @@
#include <sound/driver.h>
#include <linux/time.h>
#include <linux/fs.h>
#include <sound/core.h>
#include <sound/
timer
.h>
#include <sound/
hwdep
.h>
#include <asm/uaccess.h>
#include "ioctl32.h"
struct
sndrv_hwdep_dsp_image32
{
u32
index
;
unsigned
char
name
[
64
];
u32
image
;
/* pointer */
u32
length
;
}
/* don't set packed attribute here */
;
static
int
_snd_ioctl32_hwdep_dsp_image
(
unsigned
int
fd
,
unsigned
int
cmd
,
unsigned
long
arg
,
struct
file
*
file
,
unsigned
int
native_ctl
)
{
struct
sndrv_hwdep_dsp_image
data
;
struct
sndrv_hwdep_dsp_image
data32
;
mm_segment_t
oldseg
;
int
err
;
if
(
copy_from_user
(
&
data32
,
(
void
*
)
arg
,
sizeof
(
data32
)))
return
-
EFAULT
;
memset
(
&
data
,
0
,
sizeof
(
data
));
data
.
index
=
data32
.
index
;
memcpy
(
data
.
name
,
data32
.
name
,
sizeof
(
data
.
name
));
data
.
image
=
A
(
data32
.
image
);
data
.
length
=
data32
.
length
;
oldseg
=
get_fs
();
set_fs
(
KERNEL_DS
);
err
=
file
->
f_op
->
ioctl
(
file
->
f_dentry
->
d_inode
,
file
,
native_ctl
,
(
unsigned
long
)
&
data
);
set_fs
(
oldseg
);
return
err
;
}
DEFINE_ALSA_IOCTL_ENTRY
(
hwdep_dsp_image
,
hwdep_dsp_image
,
SNDRV_HWDEP_IOCTL_DSP_LOAD
);
#define AP(x) snd_ioctl32_##x
enum
{
SNDRV_HWDEP_IOCTL_DSP_LOAD32
=
_IOW
(
'H'
,
0x03
,
struct
sndrv_hwdep_dsp_image32
)
};
struct
ioctl32_mapper
hwdep_mappers
[]
=
{
{
SNDRV_HWDEP_IOCTL_PVERSION
,
NULL
},
{
SNDRV_HWDEP_IOCTL_INFO
,
NULL
},
MAP_COMPAT
(
SNDRV_HWDEP_IOCTL_PVERSION
),
MAP_COMPAT
(
SNDRV_HWDEP_IOCTL_INFO
),
MAP_COMPAT
(
SNDRV_HWDEP_IOCTL_DSP_STATUS
),
{
SNDRV_HWDEP_IOCTL_DSP_LOAD32
,
AP
(
hwdep_dsp_image
)
},
{
0
},
};
sound/core/misc.c
View file @
74521715
...
...
@@ -77,27 +77,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
va_end
(
args
);
tmpbuf
[
sizeof
(
tmpbuf
)
-
1
]
=
'\0'
;
printk
(
tmpbuf
);
}
#endif
#if defined(CONFIG_SND_DEBUG) && !defined(CONFIG_SND_VERBOSE_PRINTK)
void
snd_printd
(
const
char
*
format
,
...)
{
va_list
args
;
char
tmpbuf
[
512
];
if
(
format
[
0
]
==
'<'
&&
format
[
1
]
>=
'0'
&&
format
[
1
]
<=
'9'
&&
format
[
2
]
==
'>'
)
{
char
tmp
[]
=
"<0>"
;
tmp
[
1
]
=
format
[
1
];
printk
(
"%sALSA: "
,
tmp
);
format
+=
3
;
}
else
{
printk
(
KERN_DEBUG
"ALSA: "
);
}
va_start
(
args
,
format
);
vsnprintf
(
tmpbuf
,
sizeof
(
tmpbuf
)
-
1
,
format
,
args
);
va_end
(
args
);
tmpbuf
[
sizeof
(
tmpbuf
)
-
1
]
=
'\0'
;
printk
(
tmpbuf
);
}
#endif
sound/core/pcm_lib.c
View file @
74521715
...
...
@@ -2186,6 +2186,8 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
}
else
{
runtime
->
control
->
appl_ptr
=
appl_ptr
;
}
if
(
substream
->
ops
->
ack
)
substream
->
ops
->
ack
(
substream
);
offset
+=
frames
;
size
-=
frames
;
...
...
@@ -2478,6 +2480,8 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void
}
else
{
runtime
->
control
->
appl_ptr
=
appl_ptr
;
}
if
(
substream
->
ops
->
ack
)
substream
->
ops
->
ack
(
substream
);
offset
+=
frames
;
size
-=
frames
;
...
...
sound/core/pcm_misc.c
View file @
74521715
...
...
@@ -527,7 +527,7 @@ u_int8_t snd_pcm_format_silence(snd_pcm_format_t format)
*
* Sets the silence data on the buffer for the given samples.
*
* Returns zero if sucessful, or a negative error code on failure.
* Returns zero if suc
c
essful, or a negative error code on failure.
*/
int
snd_pcm_format_set_silence
(
snd_pcm_format_t
format
,
void
*
data
,
unsigned
int
samples
)
{
...
...
sound/core/pcm_native.c
View file @
74521715
...
...
@@ -1982,6 +1982,106 @@ snd_pcm_sframes_t snd_pcm_capture_rewind(snd_pcm_substream_t *substream, snd_pcm
return
ret
;
}
snd_pcm_sframes_t
snd_pcm_playback_forward
(
snd_pcm_substream_t
*
substream
,
snd_pcm_uframes_t
frames
)
{
snd_pcm_runtime_t
*
runtime
=
substream
->
runtime
;
snd_pcm_sframes_t
appl_ptr
;
snd_pcm_sframes_t
ret
;
snd_pcm_sframes_t
avail
;
if
(
frames
==
0
)
return
0
;
spin_lock_irq
(
&
runtime
->
lock
);
switch
(
runtime
->
status
->
state
)
{
case
SNDRV_PCM_STATE_PREPARED
:
case
SNDRV_PCM_STATE_PAUSED
:
break
;
case
SNDRV_PCM_STATE_DRAINING
:
case
SNDRV_PCM_STATE_RUNNING
:
if
(
snd_pcm_update_hw_ptr
(
substream
)
>=
0
)
break
;
/* Fall through */
case
SNDRV_PCM_STATE_XRUN
:
ret
=
-
EPIPE
;
goto
__end
;
default:
ret
=
-
EBADFD
;
goto
__end
;
}
avail
=
snd_pcm_playback_avail
(
runtime
);
if
(
avail
<=
0
)
{
ret
=
0
;
goto
__end
;
}
if
(
frames
>
(
snd_pcm_uframes_t
)
avail
)
frames
=
avail
;
else
frames
-=
frames
%
runtime
->
xfer_align
;
appl_ptr
=
runtime
->
control
->
appl_ptr
+
frames
;
if
(
appl_ptr
>=
runtime
->
boundary
)
appl_ptr
-=
runtime
->
boundary
;
runtime
->
control
->
appl_ptr
=
appl_ptr
;
if
(
runtime
->
status
->
state
==
SNDRV_PCM_STATE_RUNNING
&&
runtime
->
sleep_min
)
snd_pcm_tick_prepare
(
substream
);
ret
=
frames
;
__end:
spin_unlock_irq
(
&
runtime
->
lock
);
return
ret
;
}
snd_pcm_sframes_t
snd_pcm_capture_forward
(
snd_pcm_substream_t
*
substream
,
snd_pcm_uframes_t
frames
)
{
snd_pcm_runtime_t
*
runtime
=
substream
->
runtime
;
snd_pcm_sframes_t
appl_ptr
;
snd_pcm_sframes_t
ret
;
snd_pcm_sframes_t
avail
;
if
(
frames
==
0
)
return
0
;
spin_lock_irq
(
&
runtime
->
lock
);
switch
(
runtime
->
status
->
state
)
{
case
SNDRV_PCM_STATE_PREPARED
:
case
SNDRV_PCM_STATE_DRAINING
:
case
SNDRV_PCM_STATE_PAUSED
:
break
;
case
SNDRV_PCM_STATE_RUNNING
:
if
(
snd_pcm_update_hw_ptr
(
substream
)
>=
0
)
break
;
/* Fall through */
case
SNDRV_PCM_STATE_XRUN
:
ret
=
-
EPIPE
;
goto
__end
;
default:
ret
=
-
EBADFD
;
goto
__end
;
}
avail
=
snd_pcm_capture_avail
(
runtime
);
if
(
avail
<=
0
)
{
ret
=
0
;
goto
__end
;
}
if
(
frames
>
(
snd_pcm_uframes_t
)
avail
)
frames
=
avail
;
else
frames
-=
frames
%
runtime
->
xfer_align
;
appl_ptr
=
runtime
->
control
->
appl_ptr
+
frames
;
if
(
appl_ptr
>=
runtime
->
boundary
)
appl_ptr
-=
runtime
->
boundary
;
runtime
->
control
->
appl_ptr
=
appl_ptr
;
if
(
runtime
->
status
->
state
==
SNDRV_PCM_STATE_RUNNING
&&
runtime
->
sleep_min
)
snd_pcm_tick_prepare
(
substream
);
ret
=
frames
;
__end:
spin_unlock_irq
(
&
runtime
->
lock
);
return
ret
;
}
static
int
snd_pcm_hwsync
(
snd_pcm_substream_t
*
substream
)
{
snd_pcm_runtime_t
*
runtime
=
substream
->
runtime
;
...
...
@@ -2169,6 +2269,18 @@ static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
__put_user
(
result
,
_frames
);
return
result
<
0
?
result
:
0
;
}
case
SNDRV_PCM_IOCTL_FORWARD
:
{
snd_pcm_uframes_t
frames
,
*
_frames
=
arg
;
snd_pcm_sframes_t
result
;
if
(
get_user
(
frames
,
_frames
))
return
-
EFAULT
;
if
(
put_user
(
0
,
_frames
))
return
-
EFAULT
;
result
=
snd_pcm_playback_forward
(
substream
,
frames
);
__put_user
(
result
,
_frames
);
return
result
<
0
?
result
:
0
;
}
case
SNDRV_PCM_IOCTL_PAUSE
:
{
int
res
;
...
...
@@ -2244,6 +2356,18 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
__put_user
(
result
,
_frames
);
return
result
<
0
?
result
:
0
;
}
case
SNDRV_PCM_IOCTL_FORWARD
:
{
snd_pcm_uframes_t
frames
,
*
_frames
=
arg
;
snd_pcm_sframes_t
result
;
if
(
get_user
(
frames
,
_frames
))
return
-
EFAULT
;
if
(
put_user
(
0
,
_frames
))
return
-
EFAULT
;
result
=
snd_pcm_capture_forward
(
substream
,
frames
);
__put_user
(
result
,
_frames
);
return
result
<
0
?
result
:
0
;
}
case
SNDRV_PCM_IOCTL_DRAIN
:
return
snd_pcm_capture_drain
(
substream
);
case
SNDRV_PCM_IOCTL_DROP
:
...
...
sound/core/seq/seq_midi.c
View file @
74521715
...
...
@@ -358,10 +358,18 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
if
(
snd_rawmidi_info_select
(
card
,
&
info
)
>=
0
)
strcpy
(
port
.
name
,
info
.
subname
);
if
(
!
port
.
name
[
0
])
{
if
(
ports
>
1
)
sprintf
(
port
.
name
,
"MIDI %d-%d-%d"
,
card
->
number
,
device
,
p
);
else
sprintf
(
port
.
name
,
"MIDI %d-%d"
,
card
->
number
,
device
);
if
(
info
.
name
[
0
])
{
if
(
ports
>
1
)
snprintf
(
port
.
name
,
sizeof
(
port
.
name
),
"%s-%d"
,
info
.
name
,
p
);
else
snprintf
(
port
.
name
,
sizeof
(
port
.
name
),
"%s"
,
info
.
name
);
}
else
{
/* last resort */
if
(
ports
>
1
)
sprintf
(
port
.
name
,
"MIDI %d-%d-%d"
,
card
->
number
,
device
,
p
);
else
sprintf
(
port
.
name
,
"MIDI %d-%d"
,
card
->
number
,
device
);
}
}
if
((
info
.
flags
&
SNDRV_RAWMIDI_INFO_OUTPUT
)
&&
p
<
output_count
)
port
.
capability
|=
SNDRV_SEQ_PORT_CAP_WRITE
|
SNDRV_SEQ_PORT_CAP_SYNC_WRITE
|
SNDRV_SEQ_PORT_CAP_SUBS_WRITE
;
...
...
sound/core/sound.c
View file @
74521715
...
...
@@ -521,9 +521,6 @@ EXPORT_SYMBOL(snd_verbose_printk);
#endif
#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK)
EXPORT_SYMBOL
(
snd_verbose_printd
);
#endif
#if defined(CONFIG_SND_DEBUG) && !defined(CONFIG_SND_VERBOSE_PRINTK)
EXPORT_SYMBOL
(
snd_printd
);
#endif
/* wrappers */
#ifdef CONFIG_SND_DEBUG_MEMORY
...
...
sound/drivers/mpu401/mpu401_uart.c
View file @
74521715
...
...
@@ -474,7 +474,7 @@ int snd_mpu401_uart_new(snd_card_t * card, int device,
}
mpu
->
irq
=
irq
;
mpu
->
irq_flags
=
irq_flags
;
s
trcpy
(
rmidi
->
name
,
"MPU-401 (UART)"
);
s
printf
(
rmidi
->
name
,
"MPU-401 (UART) %d-%d"
,
card
->
number
,
device
);
snd_rawmidi_set_ops
(
rmidi
,
SNDRV_RAWMIDI_STREAM_OUTPUT
,
&
snd_mpu401_uart_output
);
snd_rawmidi_set_ops
(
rmidi
,
SNDRV_RAWMIDI_STREAM_INPUT
,
&
snd_mpu401_uart_input
);
rmidi
->
info_flags
|=
SNDRV_RAWMIDI_INFO_OUTPUT
|
...
...
sound/drivers/mtpav.c
View file @
74521715
...
...
@@ -802,7 +802,7 @@ module_exit(alsa_card_mtpav_exit)
#ifndef MODULE
/* format is: snd-mtpav=
snd_
enable,index,id,
/* format is: snd-mtpav=enable,index,id,
port,irq,hwports */
static
int
__init
alsa_card_mtpav_setup
(
char
*
str
)
...
...
sound/isa/dt019x.c
View file @
74521715
...
...
@@ -379,7 +379,7 @@ module_exit(alsa_card_dt019x_exit)
#ifndef MODULE
/* format is: snd-dt019x=enable,index,id,
snd_isapnp,
/* format is: snd-dt019x=enable,index,id,
port,mpu_port,fm_port,
irq,mpu_irq,dma8,dma8_size */
...
...
sound/isa/sb/es968.c
View file @
74521715
...
...
@@ -277,7 +277,7 @@ module_exit(alsa_card_es968_exit)
#ifndef MODULE
/* format is: snd-es968=enable,index,id,
port,irq,
snd_
dma1 */
port,irq,dma1 */
static
int
__init
alsa_card_es968_setup
(
char
*
str
)
{
...
...
sound/isa/sb/sb16_csp.c
View file @
74521715
...
...
@@ -213,7 +213,10 @@ static int snd_sb_csp_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cm
info
.
run_width
=
p
->
run_width
;
info
.
version
=
p
->
version
;
info
.
state
=
p
->
running
;
err
=
copy_to_user
((
void
*
)
arg
,
&
info
,
sizeof
(
info
));
if
(
copy_to_user
((
void
*
)
arg
,
&
info
,
sizeof
(
info
)))
err
=
-
EFAULT
;
else
err
=
0
;
break
;
/* load CSP microcode */
...
...
sound/isa/sgalaxy.c
View file @
74521715
...
...
@@ -44,7 +44,7 @@ MODULE_DEVICES("{{Aztech Systems,Sound Galaxy}}");
static
int
index
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_IDX
;
/* Index 0-MAX */
static
char
*
id
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_STR
;
/* ID for this card */
static
int
snd_
enable
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_ENABLE
;
/* Enable this card */
static
int
enable
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_ENABLE
;
/* Enable this card */
static
long
sbport
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_PORT
;
/* 0x220,0x240 */
static
long
wssport
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_PORT
;
/* 0x530,0xe80,0xf40,0x604 */
static
int
irq
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_IRQ
;
/* 7,9,10,11 */
...
...
@@ -300,7 +300,7 @@ static int __init alsa_card_sgalaxy_init(void)
{
int
dev
,
cards
;
for
(
dev
=
cards
=
0
;
dev
<
SNDRV_CARDS
&&
snd_
enable
[
dev
];
dev
++
)
{
for
(
dev
=
cards
=
0
;
dev
<
SNDRV_CARDS
&&
enable
[
dev
];
dev
++
)
{
if
(
snd_sgalaxy_probe
(
dev
)
>=
0
)
cards
++
;
}
...
...
@@ -327,7 +327,7 @@ module_exit(alsa_card_sgalaxy_exit)
#ifndef MODULE
/* format is: snd-sgalaxy=
snd_
enable,index,id,
/* format is: snd-sgalaxy=enable,index,id,
sbport,wssport,
irq,dma1 */
...
...
@@ -337,7 +337,7 @@ static int __init alsa_card_sgalaxy_setup(char *str)
if
(
nr_dev
>=
SNDRV_CARDS
)
return
0
;
(
void
)(
get_option
(
&
str
,
&
snd_
enable
[
nr_dev
])
==
2
&&
(
void
)(
get_option
(
&
str
,
&
enable
[
nr_dev
])
==
2
&&
get_option
(
&
str
,
&
index
[
nr_dev
])
==
2
&&
get_id
(
&
str
,
&
id
[
nr_dev
])
==
2
&&
get_option
(
&
str
,(
int
*
)
&
sbport
[
nr_dev
])
==
2
&&
...
...
sound/pci/ac97/ac97_codec.c
View file @
74521715
...
...
@@ -56,110 +56,111 @@ static void snd_ac97_proc_init(snd_card_t * card, ac97_t * ac97);
typedef
struct
{
unsigned
int
id
;
unsigned
int
mask
;
char
*
name
;
c
onst
c
har
*
name
;
int
(
*
patch
)(
ac97_t
*
ac97
);
int
(
*
mpatch
)(
ac97_t
*
ac97
);
}
ac97_codec_id_t
;
static
const
ac97_codec_id_t
snd_ac97_codec_id_vendors
[]
=
{
{
0x414b4d00
,
0xffffff00
,
"Asahi Kasei"
,
NULL
},
{
0x41445300
,
0xffffff00
,
"Analog Devices"
,
NULL
},
{
0x414c4300
,
0xffffff00
,
"Realtek"
,
NULL
},
{
0x414c4700
,
0xffffff00
,
"Avance Logic"
,
NULL
},
{
0x434d4900
,
0xffffff00
,
"C-Media Electronics"
,
NULL
},
{
0x43525900
,
0xffffff00
,
"Cirrus Logic"
,
NULL
},
{
0x43585400
,
0xffffff00
,
"Conexant"
,
NULL
},
{
0x44543000
,
0xffffff00
,
"Diamond Technology"
,
NULL
},
{
0x454d4300
,
0xffffff00
,
"eMicro"
,
NULL
},
{
0x45838300
,
0xffffff00
,
"ESS Technology"
,
NULL
},
{
0x48525300
,
0xffffff00
,
"Intersil"
,
NULL
},
{
0x49434500
,
0xffffff00
,
"ICEnsemble"
,
NULL
},
{
0x49544500
,
0xffffff00
,
"ITE Tech.Inc"
,
NULL
},
{
0x4e534300
,
0xffffff00
,
"National Semiconductor"
,
NULL
},
{
0x50534300
,
0xffffff00
,
"Philips"
,
NULL
},
{
0x53494c00
,
0xffffff00
,
"Silicon Laboratory"
,
NULL
},
{
0x54524100
,
0xffffff00
,
"TriTech"
,
NULL
},
{
0x54584e00
,
0xffffff00
,
"Texas Instruments"
,
NULL
},
{
0x56494100
,
0xffffff00
,
"VIA Technologies"
,
NULL
},
{
0x57454300
,
0xffffff00
,
"Winbond"
,
NULL
},
{
0x574d4c00
,
0xffffff00
,
"Wolfson"
,
NULL
},
{
0x594d4800
,
0xffffff00
,
"Yamaha"
,
NULL
},
{
0x83847600
,
0xffffff00
,
"SigmaTel"
,
NULL
},
{
0
,
0
,
NULL
,
NULL
}
{
0x414b4d00
,
0xffffff00
,
"Asahi Kasei"
,
NULL
,
NULL
},
{
0x41445300
,
0xffffff00
,
"Analog Devices"
,
NULL
,
NULL
},
{
0x414c4300
,
0xffffff00
,
"Realtek"
,
NULL
,
NULL
},
{
0x414c4700
,
0xffffff00
,
"Avance Logic"
,
NULL
,
NULL
},
{
0x434d4900
,
0xffffff00
,
"C-Media Electronics"
,
NULL
,
NULL
},
{
0x43525900
,
0xffffff00
,
"Cirrus Logic"
,
NULL
,
NULL
},
{
0x43585400
,
0xffffff00
,
"Conexant"
,
NULL
,
NULL
},
{
0x44543000
,
0xffffff00
,
"Diamond Technology"
,
NULL
,
NULL
},
{
0x454d4300
,
0xffffff00
,
"eMicro"
,
NULL
,
NULL
},
{
0x45838300
,
0xffffff00
,
"ESS Technology"
,
NULL
,
NULL
},
{
0x48525300
,
0xffffff00
,
"Intersil"
,
NULL
,
NULL
},
{
0x49434500
,
0xffffff00
,
"ICEnsemble"
,
NULL
,
NULL
},
{
0x49544500
,
0xffffff00
,
"ITE Tech.Inc"
,
NULL
,
NULL
},
{
0x4e534300
,
0xffffff00
,
"National Semiconductor"
,
NULL
,
NULL
},
{
0x50534300
,
0xffffff00
,
"Philips"
,
NULL
,
NULL
},
{
0x53494c00
,
0xffffff00
,
"Silicon Laboratory"
,
NULL
,
NULL
},
{
0x54524100
,
0xffffff00
,
"TriTech"
,
NULL
,
NULL
},
{
0x54584e00
,
0xffffff00
,
"Texas Instruments"
,
NULL
,
NULL
},
{
0x56494100
,
0xffffff00
,
"VIA Technologies"
,
NULL
,
NULL
},
{
0x57454300
,
0xffffff00
,
"Winbond"
,
NULL
,
NULL
},
{
0x574d4c00
,
0xffffff00
,
"Wolfson"
,
NULL
,
NULL
},
{
0x594d4800
,
0xffffff00
,
"Yamaha"
,
NULL
,
NULL
},
{
0x83847600
,
0xffffff00
,
"SigmaTel"
,
NULL
,
NULL
},
{
0
,
0
,
NULL
,
NULL
,
NULL
}
};
static
const
ac97_codec_id_t
snd_ac97_codec_ids
[]
=
{
{
0x014b0502
,
0xffffffff
,
"NM256AV"
,
NULL
},
// FIXME: which real one?
{
0x414b4d00
,
0xffffffff
,
"AK4540"
,
NULL
},
{
0x414b4d01
,
0xffffffff
,
"AK4542"
,
NULL
},
{
0x414b4d02
,
0xffffffff
,
"AK4543"
,
NULL
},
{
0x414b4d06
,
0xffffffff
,
"AK4544A"
,
NULL
},
{
0x414b4d07
,
0xffffffff
,
"AK4545"
,
NULL
},
{
0x41445303
,
0xffffffff
,
"AD1819"
,
patch_ad1819
},
{
0x41445340
,
0xffffffff
,
"AD1881"
,
patch_ad1881
},
{
0x41445348
,
0xffffffff
,
"AD1881A"
,
patch_ad1881
},
{
0x41445360
,
0xffffffff
,
"AD1885"
,
patch_ad1885
},
{
0x41445361
,
0xffffffff
,
"AD1886"
,
patch_ad1886
},
{
0x41445362
,
0xffffffff
,
"AD1887"
,
patch_ad1881
},
{
0x41445363
,
0xffffffff
,
"AD1886A"
,
patch_ad1881
},
{
0x41445370
,
0xffffffff
,
"AD1980"
,
patch_ad1980
},
{
0x41445372
,
0xffffffff
,
"AD1981A"
,
patch_ad1881
},
{
0x414c4300
,
0xfffffff0
,
"RL5306"
,
NULL
},
{
0x414c4310
,
0xfffffff0
,
"RL5382"
,
NULL
},
{
0x414c4320
,
0xfffffff0
,
"RL5383"
,
NULL
},
{
0x414c4710
,
0xfffffff0
,
"ALC200/200P"
,
NULL
},
{
0x414c4720
,
0xfffffff0
,
"ALC650"
,
patch_alc650
},
{
0x414c4730
,
0xffffffff
,
"ALC101"
,
NULL
},
{
0x414c4740
,
0xfffffff0
,
"ALC202"
,
NULL
},
{
0x414c4750
,
0xfffffff0
,
"ALC250"
,
NULL
},
{
0x434d4941
,
0xffffffff
,
"CMI9738"
,
NULL
},
{
0x434d4961
,
0xffffffff
,
"CMI9739"
,
NULL
},
{
0x43525900
,
0xfffffff8
,
"CS4297"
,
NULL
},
{
0x43525910
,
0xfffffff8
,
"CS4297A"
,
patch_cirrus_spdif
},
{
0x43525920
,
0xfffffff8
,
"CS4294/4298"
,
NULL
},
{
0x43525928
,
0xfffffff8
,
"CS4294"
,
NULL
},
{
0x43525930
,
0xfffffff8
,
"CS4299"
,
patch_cirrus_cs4299
},
{
0x43525948
,
0xfffffff8
,
"CS4201"
,
NULL
},
{
0x43525958
,
0xfffffff8
,
"CS4205"
,
patch_cirrus_spdif
},
{
0x43525960
,
0xfffffff8
,
"CS4291"
,
NULL
},
{
0x43585421
,
0xffffffff
,
"HSD11246"
,
NULL
},
// SmartMC II
{
0x43585428
,
0xfffffff8
,
"Cx20468"
,
patch_conexant
},
// SmartAMC fixme: the mask might be different
{
0x44543031
,
0xfffffff0
,
"DT0398"
,
NULL
},
{
0x454d4328
,
0xffffffff
,
"28028"
,
NULL
},
// same as TR28028?
{
0x45838308
,
0xffffffff
,
"ESS1988"
,
NULL
},
{
0x48525300
,
0xffffff00
,
"HMP9701"
,
NULL
},
{
0x49434501
,
0xffffffff
,
"ICE1230"
,
NULL
},
{
0x49434511
,
0xffffffff
,
"ICE1232"
,
NULL
},
// alias VIA VT1611A?
{
0x49434551
,
0xffffffff
,
"VT1616"
,
NULL
},
{
0x49544520
,
0xffffffff
,
"IT2226E"
,
NULL
},
{
0x4e534300
,
0xffffffff
,
"LM4540/43/45/46/48"
,
NULL
},
// only guess --jk
{
0x4e534331
,
0xffffffff
,
"LM4549"
,
NULL
},
{
0x50534304
,
0xffffffff
,
"UCB1400"
,
NULL
},
{
0x53494c22
,
0xffffffff
,
"Si3036"
,
NULL
},
{
0x53494c23
,
0xffffffff
,
"Si3038"
,
NULL
},
{
0x54524102
,
0xffffffff
,
"TR28022"
,
NULL
},
{
0x54524106
,
0xffffffff
,
"TR28026"
,
NULL
},
{
0x54524108
,
0xffffffff
,
"TR28028"
,
patch_tritech_tr28028
},
// added by xin jin [07/09/99]
{
0x54524123
,
0xffffffff
,
"TR28602"
,
NULL
},
// only guess --jk [TR28023 = eMicro EM28023 (new CT1297)]
{
0x54584e20
,
0xffffffff
,
"TLC320AD9xC"
,
NULL
},
{
0x56494161
,
0xffffffff
,
"VIA1612A"
,
NULL
},
// modified ICE1232 with S/PDIF
{
0x57454301
,
0xffffffff
,
"W83971D"
,
NULL
},
{
0x574d4c00
,
0xffffffff
,
"WM9701A"
,
patch_wolfson00
},
{
0x574d4c03
,
0xffffffff
,
"WM9703/9707"
,
patch_wolfson03
},
{
0x574d4c04
,
0xffffffff
,
"WM9704/quad"
,
patch_wolfson04
},
{
0x574d4c05
,
0xffffffff
,
"WM9705"
,
NULL
},
// patch?
{
0x594d4800
,
0xffffffff
,
"YMF743"
,
NULL
},
{
0x594d4802
,
0xffffffff
,
"YMF752"
,
NULL
},
{
0x594d4803
,
0xffffffff
,
"YMF753"
,
patch_yamaha_ymf753
},
{
0x83847600
,
0xffffffff
,
"STAC9700/83/84"
,
NULL
},
{
0x83847604
,
0xffffffff
,
"STAC9701/3/4/5"
,
NULL
},
{
0x83847605
,
0xffffffff
,
"STAC9704"
,
NULL
},
{
0x83847608
,
0xffffffff
,
"STAC9708/11"
,
patch_sigmatel_stac9708
},
{
0x83847609
,
0xffffffff
,
"STAC9721/23"
,
patch_sigmatel_stac9721
},
{
0x83847644
,
0xffffffff
,
"STAC9744"
,
patch_sigmatel_stac9744
},
{
0x83847650
,
0xffffffff
,
"STAC9750/51"
,
NULL
},
// patch?
{
0x83847656
,
0xffffffff
,
"STAC9756/57"
,
patch_sigmatel_stac9756
},
{
0x83847666
,
0xffffffff
,
"STAC9766/67"
,
NULL
},
// patch?
{
0
,
0
,
NULL
,
NULL
}
{
0x014b0502
,
0xffffffff
,
"NM256AV"
,
NULL
,
NULL
},
// FIXME: which real one?
{
0x414b4d00
,
0xffffffff
,
"AK4540"
,
NULL
,
NULL
},
{
0x414b4d01
,
0xffffffff
,
"AK4542"
,
NULL
,
NULL
},
{
0x414b4d02
,
0xffffffff
,
"AK4543"
,
NULL
,
NULL
},
{
0x414b4d06
,
0xffffffff
,
"AK4544A"
,
NULL
,
NULL
},
{
0x414b4d07
,
0xffffffff
,
"AK4545"
,
NULL
,
NULL
},
{
0x41445303
,
0xffffffff
,
"AD1819"
,
patch_ad1819
,
NULL
},
{
0x41445340
,
0xffffffff
,
"AD1881"
,
patch_ad1881
,
NULL
},
{
0x41445348
,
0xffffffff
,
"AD1881A"
,
patch_ad1881
,
NULL
},
{
0x41445360
,
0xffffffff
,
"AD1885"
,
patch_ad1885
,
NULL
},
{
0x41445361
,
0xffffffff
,
"AD1886"
,
patch_ad1886
,
NULL
},
{
0x41445362
,
0xffffffff
,
"AD1887"
,
patch_ad1881
,
NULL
},
{
0x41445363
,
0xffffffff
,
"AD1886A"
,
patch_ad1881
,
NULL
},
{
0x41445370
,
0xffffffff
,
"AD1980"
,
patch_ad1980
,
NULL
},
{
0x41445372
,
0xffffffff
,
"AD1981A"
,
patch_ad1881
,
NULL
},
{
0x414c4300
,
0xfffffff0
,
"RL5306"
,
NULL
,
NULL
},
{
0x414c4310
,
0xfffffff0
,
"RL5382"
,
NULL
,
NULL
},
{
0x414c4320
,
0xfffffff0
,
"RL5383"
,
NULL
,
NULL
},
{
0x414c4710
,
0xfffffff0
,
"ALC200/200P"
,
NULL
,
NULL
},
{
0x414c4720
,
0xfffffff0
,
"ALC650"
,
patch_alc650
,
NULL
},
{
0x414c4730
,
0xffffffff
,
"ALC101"
,
NULL
,
NULL
},
{
0x414c4740
,
0xfffffff0
,
"ALC202"
,
NULL
,
NULL
},
{
0x414c4750
,
0xfffffff0
,
"ALC250"
,
NULL
,
NULL
},
{
0x434d4941
,
0xffffffff
,
"CMI9738"
,
NULL
,
NULL
},
{
0x434d4961
,
0xffffffff
,
"CMI9739"
,
NULL
,
NULL
},
{
0x43525900
,
0xfffffff8
,
"CS4297"
,
NULL
,
NULL
},
{
0x43525910
,
0xfffffff8
,
"CS4297A"
,
patch_cirrus_spdif
,
NULL
},
{
0x43525920
,
0xfffffff8
,
"CS4294/4298"
,
NULL
,
NULL
},
{
0x43525928
,
0xfffffff8
,
"CS4294"
,
NULL
,
NULL
},
{
0x43525930
,
0xfffffff8
,
"CS4299"
,
patch_cirrus_cs4299
,
NULL
},
{
0x43525948
,
0xfffffff8
,
"CS4201"
,
NULL
,
NULL
},
{
0x43525958
,
0xfffffff8
,
"CS4205"
,
patch_cirrus_spdif
,
NULL
},
{
0x43525960
,
0xfffffff8
,
"CS4291"
,
NULL
,
NULL
},
{
0x43585421
,
0xffffffff
,
"HSD11246"
,
NULL
,
NULL
},
// SmartMC II
{
0x43585428
,
0xfffffff8
,
"Cx20468"
,
patch_conexant
,
NULL
},
// SmartAMC fixme: the mask might be different
{
0x44543031
,
0xfffffff0
,
"DT0398"
,
NULL
,
NULL
},
{
0x454d4328
,
0xffffffff
,
"28028"
,
NULL
,
NULL
},
// same as TR28028?
{
0x45838308
,
0xffffffff
,
"ESS1988"
,
NULL
,
NULL
},
{
0x48525300
,
0xffffff00
,
"HMP9701"
,
NULL
,
NULL
},
{
0x49434501
,
0xffffffff
,
"ICE1230"
,
NULL
,
NULL
},
{
0x49434511
,
0xffffffff
,
"ICE1232"
,
NULL
,
NULL
},
// alias VIA VT1611A?
{
0x49434551
,
0xffffffff
,
"VT1616"
,
NULL
,
NULL
},
{
0x49544520
,
0xffffffff
,
"IT2226E"
,
NULL
,
NULL
},
{
0x4e534300
,
0xffffffff
,
"LM4540/43/45/46/48"
,
NULL
,
NULL
},
// only guess --jk
{
0x4e534331
,
0xffffffff
,
"LM4549"
,
NULL
,
NULL
},
{
0x50534304
,
0xffffffff
,
"UCB1400"
,
NULL
,
NULL
},
{
0x53494c22
,
0xffffffff
,
"Si3036"
,
NULL
,
NULL
},
{
0x53494c23
,
0xffffffff
,
"Si3038"
,
NULL
,
NULL
},
{
0x54524102
,
0xffffffff
,
"TR28022"
,
NULL
,
NULL
},
{
0x54524106
,
0xffffffff
,
"TR28026"
,
NULL
,
NULL
},
{
0x54524108
,
0xffffffff
,
"TR28028"
,
patch_tritech_tr28028
,
NULL
},
// added by xin jin [07/09/99]
{
0x54524123
,
0xffffffff
,
"TR28602"
,
NULL
,
NULL
},
// only guess --jk [TR28023 = eMicro EM28023 (new CT1297)]
{
0x54584e20
,
0xffffffff
,
"TLC320AD9xC"
,
NULL
,
NULL
},
{
0x56494161
,
0xffffffff
,
"VIA1612A"
,
NULL
,
NULL
},
// modified ICE1232 with S/PDIF
{
0x57454301
,
0xffffffff
,
"W83971D"
,
NULL
,
NULL
},
{
0x574d4c00
,
0xffffffff
,
"WM9701A"
,
patch_wolfson00
,
NULL
},
{
0x574d4c03
,
0xffffffff
,
"WM9703/9707"
,
patch_wolfson03
,
NULL
},
{
0x574d4c04
,
0xffffffff
,
"WM9704/quad"
,
patch_wolfson04
,
NULL
},
{
0x574d4c05
,
0xffffffff
,
"WM9705"
,
NULL
,
NULL
},
// patch?
{
0x594d4800
,
0xffffffff
,
"YMF743"
,
NULL
,
NULL
},
{
0x594d4802
,
0xffffffff
,
"YMF752"
,
NULL
,
NULL
},
{
0x594d4803
,
0xffffffff
,
"YMF753"
,
patch_yamaha_ymf753
,
NULL
},
{
0x83847600
,
0xffffffff
,
"STAC9700/83/84"
,
NULL
,
NULL
},
{
0x83847604
,
0xffffffff
,
"STAC9701/3/4/5"
,
NULL
,
NULL
},
{
0x83847605
,
0xffffffff
,
"STAC9704"
,
NULL
,
NULL
},
{
0x83847608
,
0xffffffff
,
"STAC9708/11"
,
patch_sigmatel_stac9708
,
NULL
},
{
0x83847609
,
0xffffffff
,
"STAC9721/23"
,
patch_sigmatel_stac9721
,
NULL
},
{
0x83847644
,
0xffffffff
,
"STAC9744"
,
patch_sigmatel_stac9744
,
NULL
},
{
0x83847650
,
0xffffffff
,
"STAC9750/51"
,
NULL
,
NULL
},
// patch?
{
0x83847656
,
0xffffffff
,
"STAC9756/57"
,
patch_sigmatel_stac9756
,
NULL
},
{
0x83847666
,
0xffffffff
,
"STAC9766/67"
,
NULL
,
NULL
},
// patch?
{
0
,
0
,
NULL
,
NULL
,
NULL
}
};
static
const
char
*
snd_ac97_stereo_enhancements
[]
=
...
...
@@ -325,7 +326,7 @@ static void snd_ac97_write_cache_test(ac97_t *ac97, unsigned short reg, unsigned
* Compares the value with the register cache and updates the value
* only when the value is changed.
*
* Ret
ru
ns 1 if the value is changed, 0 if no change, or a negative
* Ret
ur
ns 1 if the value is changed, 0 if no change, or a negative
* code on failure.
*/
int
snd_ac97_update
(
ac97_t
*
ac97
,
unsigned
short
reg
,
unsigned
short
value
)
...
...
@@ -352,7 +353,7 @@ int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value)
* @mask: the bit-mask to change
* @value: the value to set
*
* Updates the masked-bits on the given register onl
e
when the value
* Updates the masked-bits on the given register onl
y
when the value
* is changed.
*
* Returns 1 if the bits are changed, 0 if no change, or a negative
...
...
@@ -1022,6 +1023,50 @@ static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_lfe[1] = {
AD18XX_PCM_BITS
(
"LFE Playback Volume"
,
2
,
0
,
31
)
};
static
int
snd_ac97_ad1980_spdif_source_info
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_info_t
*
uinfo
)
{
static
char
*
texts
[
2
]
=
{
"AC-Link"
,
"A/D Converter"
};
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
uinfo
->
count
=
1
;
uinfo
->
value
.
enumerated
.
items
=
2
;
if
(
uinfo
->
value
.
enumerated
.
item
>
1
)
uinfo
->
value
.
enumerated
.
item
=
1
;
strcpy
(
uinfo
->
value
.
enumerated
.
name
,
texts
[
uinfo
->
value
.
enumerated
.
item
]);
return
0
;
}
static
int
snd_ac97_ad1980_spdif_source_get
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
ucontrol
)
{
ac97_t
*
ac97
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
short
val
;
val
=
ac97
->
regs
[
AC97_AD_SERIAL_CFG
];
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
(
val
>>
2
)
&
1
;
return
0
;
}
static
int
snd_ac97_ad1980_spdif_source_put
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
ucontrol
)
{
ac97_t
*
ac97
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
short
val
;
if
(
ucontrol
->
value
.
enumerated
.
item
[
0
]
>
1
)
return
-
EINVAL
;
val
=
ucontrol
->
value
.
enumerated
.
item
[
0
]
<<
2
;
return
snd_ac97_update_bits
(
ac97
,
AC97_AD_SERIAL_CFG
,
0x0004
,
val
);
}
static
const
snd_kcontrol_new_t
snd_ac97_ad1980_spdif_source
=
{
iface:
SNDRV_CTL_ELEM_IFACE_MIXER
,
name:
SNDRV_CTL_NAME_IEC958
(
""
,
PLAYBACK
,
NONE
)
"Source"
,
info:
snd_ac97_ad1980_spdif_source_info
,
get:
snd_ac97_ad1980_spdif_source_get
,
put:
snd_ac97_ad1980_spdif_source_put
,
};
/*
* ALC650
*/
...
...
@@ -1032,8 +1077,8 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
AC97_SINGLE
(
"Exchange Center/LFE"
,
AC97_ALC650_MULTICH
,
3
,
1
,
0
),
/* 4: Analog Input To Surround */
/* 5: Analog Input To Center/LFE */
/* 6: Indepedent Master Volume Right */
/* 7: Indepedent Master Volume Left */
/* 6: Indepe
n
dent Master Volume Right */
/* 7: Indepe
n
dent Master Volume Left */
/* 8: reserved */
AC97_SINGLE
(
"Line-In As Surround"
,
AC97_ALC650_MULTICH
,
9
,
1
,
0
),
AC97_SINGLE
(
"Mic As Center/LFE"
,
AC97_ALC650_MULTICH
,
10
,
1
,
0
),
...
...
@@ -1140,7 +1185,7 @@ static int snd_ac97_ymf753_spdif_source_put(snd_kcontrol_t * kcontrol, snd_ctl_e
}
/* The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
The YMF753 will ouput the S/PDIF signal to pin 43, 47 (EAPD), or 48.
The YMF753 will ou
t
put the S/PDIF signal to pin 43, 47 (EAPD), or 48.
By default, no output pin is selected, and the S/PDIF signal is not output.
There is also a bit to mute S/PDIF output in a vendor-specific register. */
static
int
snd_ac97_ymf753_spdif_output_pin_info
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_info_t
*
uinfo
)
...
...
@@ -1680,6 +1725,9 @@ static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97)
for
(
idx
=
0
;
idx
<
3
;
idx
++
)
if
((
err
=
snd_ctl_add
(
card
,
snd_ac97_cnew
(
&
snd_ac97_ymf753_controls_spdif
[
idx
],
ac97
)))
<
0
)
return
err
;
}
else
if
(
ac97
->
id
==
AC97_ID_AD1980
)
{
if
((
err
=
snd_ctl_add
(
card
,
snd_ac97_cnew
(
&
snd_ac97_ad1980_spdif_source
,
ac97
)))
<
0
)
return
err
;
}
/* set default PCM S/PDIF params */
/* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
...
...
@@ -1735,6 +1783,12 @@ static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97)
return
0
;
}
static
int
snd_ac97_modem_build
(
snd_card_t
*
card
,
ac97_t
*
ac97
)
{
/* TODO */
return
0
;
}
static
int
snd_ac97_test_rate
(
ac97_t
*
ac97
,
int
reg
,
int
rate
)
{
unsigned
short
val
;
...
...
@@ -1771,7 +1825,7 @@ static void snd_ac97_determine_rates(ac97_t *ac97, int reg, unsigned int *r_resu
*
r_result
=
result
;
}
static
void
snd_ac97_get_name
(
ac97_t
*
ac97
,
unsigned
int
id
,
char
*
name
)
static
void
snd_ac97_get_name
(
ac97_t
*
ac97
,
unsigned
int
id
,
char
*
name
,
int
modem
)
{
const
ac97_codec_id_t
*
pid
;
...
...
@@ -1782,8 +1836,12 @@ static void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name)
for
(
pid
=
snd_ac97_codec_id_vendors
;
pid
->
id
;
pid
++
)
if
(
pid
->
id
==
(
id
&
pid
->
mask
))
{
strcpy
(
name
,
pid
->
name
);
if
(
ac97
&&
pid
->
patch
)
pid
->
patch
(
ac97
);
if
(
ac97
)
{
if
(
!
modem
&&
pid
->
patch
)
pid
->
patch
(
ac97
);
else
if
(
modem
&&
pid
->
mpatch
)
pid
->
mpatch
(
ac97
);
}
goto
__vendor_ok
;
}
return
;
...
...
@@ -1795,8 +1853,12 @@ static void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name)
strcat
(
name
,
pid
->
name
);
if
(
pid
->
mask
!=
0xffffffff
)
sprintf
(
name
+
strlen
(
name
),
" rev %d"
,
id
&
~
pid
->
mask
);
if
(
ac97
&&
pid
->
patch
)
pid
->
patch
(
ac97
);
if
(
ac97
)
{
if
(
!
modem
&&
pid
->
patch
)
pid
->
patch
(
ac97
);
else
if
(
modem
&&
pid
->
mpatch
)
pid
->
mpatch
(
ac97
);
}
return
;
}
sprintf
(
name
+
strlen
(
name
),
" id %x"
,
id
&
0xff
);
...
...
@@ -1850,7 +1912,7 @@ static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem)
* The template must include the valid callbacks (at least read and
* write), the codec number (num) and address (addr), and the private
* data (private_data). The other callbacks, wait and reset, are not
* manda
n
tory.
* mandatory.
*
* The clock is set to 48000. If another clock is needed, reset
* ac97->clock manually afterwards.
...
...
@@ -1858,9 +1920,11 @@ static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem)
* The ac97 instance is registered as a low-level device, so you don't
* have to release it manually.
*
* Returns zero if sucessful, or a negative error code on failure.
* The MCs (Modem Codecs only) are only detected but valid. The PCM driver
* have to check for MCs using the !ac97_is_audio() function.
*
* Returns zero if successful, or a negative error code on failure.
*/
int
snd_ac97_mixer
(
snd_card_t
*
card
,
ac97_t
*
_ac97
,
ac97_t
**
rac97
)
{
int
err
;
...
...
@@ -1929,8 +1993,8 @@ int snd_ac97_mixer(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97)
goto
__ready_ok
;
/* FIXME: add powerdown control */
/* nothing should be in powerdown mode */
if
(
ac97
->
scaps
&
AC97_SCAP_AUDIO
)
{
if
(
ac97_is_audio
(
ac97
))
{
/* nothing should be in powerdown mode */
snd_ac97_write_cache_test
(
ac97
,
AC97_POWERDOWN
,
0
);
snd_ac97_write_cache_test
(
ac97
,
AC97_RESET
,
0
);
/* reset to defaults */
udelay
(
100
);
...
...
@@ -1950,7 +2014,7 @@ int snd_ac97_mixer(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97)
__ready_ok:
if
(
ac97
->
clock
==
0
)
ac97
->
clock
=
48000
;
/* standard value */
if
(
ac97
->
scaps
&
AC97_SCAP_AUDIO
)
if
(
ac97
_is_audio
(
ac97
)
)
ac97
->
addr
=
(
ac97
->
ext_id
&
AC97_EI_ADDR_MASK
)
>>
AC97_EI_ADDR_SHIFT
;
else
ac97
->
addr
=
(
ac97
->
ext_mid
&
AC97_MEI_ADDR_MASK
)
>>
AC97_MEI_ADDR_SHIFT
;
...
...
@@ -1985,8 +2049,8 @@ int snd_ac97_mixer(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97)
/* additional initializations */
if
(
ac97
->
init
)
ac97
->
init
(
ac97
);
snd_ac97_get_name
(
ac97
,
ac97
->
id
,
name
);
snd_ac97_get_name
(
NULL
,
ac97
->
id
,
name
);
// ac97->id might be changed in the special setup code
snd_ac97_get_name
(
ac97
,
ac97
->
id
,
name
,
0
);
snd_ac97_get_name
(
NULL
,
ac97
->
id
,
name
,
0
);
// ac97->id might be changed in the special setup code
if
(
card
->
mixername
[
0
]
==
'\0'
)
{
strcpy
(
card
->
mixername
,
name
);
}
else
{
...
...
@@ -1995,19 +2059,188 @@ int snd_ac97_mixer(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97)
strcat
(
card
->
mixername
,
name
);
}
}
if
(
ac97
->
scaps
&
AC97_SCAP_AUDIO
)
{
if
(
ac97
_is_audio
(
ac97
)
)
{
if
((
err
=
snd_component_add
(
card
,
"AC97a"
))
<
0
)
{
snd_ac97_free
(
ac97
);
return
err
;
}
}
if
(
ac97_is_audio
(
ac97
)
&&
snd_ac97_mixer_build
(
card
,
ac97
)
<
0
)
{
snd_ac97_free
(
ac97
);
return
-
ENOMEM
;
}
snd_ac97_proc_init
(
card
,
ac97
);
if
((
err
=
snd_device_new
(
card
,
SNDRV_DEV_LOWLEVEL
,
ac97
,
&
ops
))
<
0
)
{
snd_ac97_free
(
ac97
);
return
err
;
}
*
rac97
=
ac97
;
return
0
;
}
/* wait for a while until registers are accessible after RESET
* return 0 if ok, negative not ready
*/
static
int
ac97_modem_reset_wait
(
ac97_t
*
ac97
,
int
timeout
)
{
signed
long
end_time
;
end_time
=
jiffies
+
timeout
;
do
{
unsigned
short
ext_mid
;
/* use preliminary reads to settle the communication */
snd_ac97_read
(
ac97
,
AC97_EXTENDED_MID
);
snd_ac97_read
(
ac97
,
AC97_VENDOR_ID1
);
snd_ac97_read
(
ac97
,
AC97_VENDOR_ID2
);
ext_mid
=
snd_ac97_read
(
ac97
,
AC97_EXTENDED_MID
);
if
(
ext_mid
!=
0xffff
&&
(
ext_mid
&
1
)
!=
0
)
return
0
;
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
HZ
/
100
);
}
while
(
time_after_eq
(
end_time
,
jiffies
));
return
-
ENODEV
;
}
/**
* snd_ac97_modem - create an MC97 codec component
* @card: the card instance
* @_ac97: the template of ac97, including index, callbacks and
* the private data.
* @rac97: the pointer to store the new ac97 instance.
*
* Creates an MC97 codec component. An ac97_t instance is newly
* allocated and initialized from the template (_ac97). The codec
* is then initialized by the standard procedure.
*
* The template must include the valid callbacks (at least read and
* write), the codec number (num) and address (addr), and the private
* data (private_data). The other callbacks, wait and reset, are not
* mandatory.
*
* The clock is set to 48000. If another clock is needed, reset
* ac97->clock manually afterwards.
*
* The ac97 instance is registered as a low-level device, so you don't
* have to release it manually.
*
* The ACs (Audio Codecs only) are only detected but valid. The PCM driver
* have to check for ACs using the !ac97_is_modem() function.
*
* Returns zero if successful, or a negative error code on failure.
*/
int
snd_ac97_modem
(
snd_card_t
*
card
,
ac97_t
*
_ac97
,
ac97_t
**
rac97
)
{
int
err
;
ac97_t
*
ac97
;
char
name
[
64
];
// signed long end_time;
unsigned
short
tmp
;
static
snd_device_ops_t
ops
=
{
.
dev_free
=
snd_ac97_dev_free
,
};
snd_assert
(
rac97
!=
NULL
,
return
-
EINVAL
);
*
rac97
=
NULL
;
snd_assert
(
card
!=
NULL
&&
_ac97
!=
NULL
,
return
-
EINVAL
);
ac97
=
snd_magic_kcalloc
(
ac97_t
,
0
,
GFP_KERNEL
);
if
(
ac97
==
NULL
)
return
-
ENOMEM
;
*
ac97
=
*
_ac97
;
ac97
->
card
=
card
;
spin_lock_init
(
&
ac97
->
reg_lock
);
if
(
ac97
->
reset
)
{
ac97
->
reset
(
ac97
);
goto
__access_ok
;
}
snd_ac97_write
(
ac97
,
AC97_EXTENDED_MID
,
0
);
/* reset to defaults */
if
(
ac97
->
wait
)
ac97
->
wait
(
ac97
);
else
{
udelay
(
50
);
if
(
ac97_modem_reset_wait
(
ac97
,
HZ
/
2
)
<
0
)
{
snd_printk
(
"MC'97 %d:%d does not respond - MODEM RESET
\n
"
,
ac97
->
num
,
ac97
->
addr
);
snd_ac97_free
(
ac97
);
return
-
ENXIO
;
}
}
__access_ok:
ac97
->
id
=
snd_ac97_read
(
ac97
,
AC97_VENDOR_ID1
)
<<
16
;
ac97
->
id
|=
snd_ac97_read
(
ac97
,
AC97_VENDOR_ID2
);
if
(
ac97
->
id
==
0x00000000
||
ac97
->
id
==
0xffffffff
)
{
snd_printk
(
"AC'97 %d:%d access is not valid [0x%x], removing modem controls.
\n
"
,
ac97
->
num
,
ac97
->
addr
,
ac97
->
id
);
snd_ac97_free
(
ac97
);
return
-
EIO
;
}
/* test for MC'97 */
ac97
->
ext_mid
=
snd_ac97_read
(
ac97
,
AC97_EXTENDED_MID
);
if
(
ac97
->
ext_mid
==
0xffff
)
/* invalid combination */
ac97
->
ext_mid
=
0
;
if
(
ac97
->
ext_mid
&
1
)
ac97
->
scaps
|=
AC97_SCAP_MODEM
;
/* non-destructive test for AC'97 */
tmp
=
snd_ac97_read
(
ac97
,
AC97_RESET
);
if
(
tmp
==
0
||
tmp
==
0xffff
)
{
tmp
=
snd_ac97_read
(
ac97
,
AC97_EXTENDED_ID
);
if
(
tmp
==
0
||
tmp
==
0xffff
)
{
tmp
=
snd_ac97_read
(
ac97
,
AC97_REC_GAIN
);
if
(
tmp
==
0
||
tmp
==
0xffff
)
tmp
=
snd_ac97_read
(
ac97
,
AC97_POWERDOWN
);
}
}
if
((
tmp
!=
0
&&
tmp
!=
0xffff
)
||
!
(
ac97
->
scaps
&
AC97_SCAP_MODEM
))
ac97
->
scaps
|=
AC97_SCAP_AUDIO
;
if
(
ac97
->
reset
)
// FIXME: always skipping?
goto
__ready_ok
;
/* FIXME: add powerdown control */
if
(
ac97
->
scaps
&
AC97_SCAP_MODEM
)
{
#if 0 /* FIXME - add modem powerup */
/* nothing should be in powerdown mode */
snd_ac97_write_cache_test(ac97, AC97_POWERDOWN, 0);
snd_ac97_write_cache_test(ac97, AC97_RESET, 0); /* reset to defaults */
udelay(100);
/* nothing should be in powerdown mode */
snd_ac97_write_cache_test(ac97, AC97_POWERDOWN, 0);
snd_ac97_write_cache_test(ac97, AC97_GENERAL_PURPOSE, 0);
end_time = jiffies + (HZ / 10);
do {
if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)
goto __ready_ok;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/10);
} while (time_after_eq(end_time, jiffies));
snd_printk("AC'97 %d:%d analog subsections not ready\n", ac97->num, ac97->addr);
#endif
}
__ready_ok:
/* additional initializations */
/* FIXME: ADD MODEM INITALIZATION */
if
(
ac97
->
init
)
ac97
->
init
(
ac97
);
snd_ac97_get_name
(
ac97
,
ac97
->
id
,
name
,
1
);
snd_ac97_get_name
(
NULL
,
ac97
->
id
,
name
,
1
);
// ac97->id might be changed in the special setup code
if
(
card
->
mixername
[
0
]
==
'\0'
)
{
strcpy
(
card
->
mixername
,
name
);
}
else
{
if
(
strlen
(
card
->
mixername
)
+
1
+
strlen
(
name
)
+
1
<=
sizeof
(
card
->
mixername
))
{
strcat
(
card
->
mixername
,
","
);
strcat
(
card
->
mixername
,
name
);
}
}
if
(
ac97_is_modem
(
ac97
))
{
if
((
err
=
snd_component_add
(
card
,
"AC97m"
))
<
0
)
{
snd_ac97_free
(
ac97
);
return
err
;
}
}
if
(
snd_ac97_mixer
_build
(
card
,
ac97
)
<
0
)
{
if
(
ac97_is_modem
(
ac97
)
&&
snd_ac97_modem
_build
(
card
,
ac97
)
<
0
)
{
snd_ac97_free
(
ac97
);
return
-
ENOMEM
;
}
...
...
@@ -2035,7 +2268,7 @@ static void snd_ac97_proc_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, in
id
=
snd_ac97_read
(
ac97
,
AC97_VENDOR_ID1
)
<<
16
;
id
|=
snd_ac97_read
(
ac97
,
AC97_VENDOR_ID2
);
snd_ac97_get_name
(
NULL
,
id
,
name
);
snd_ac97_get_name
(
NULL
,
id
,
name
,
0
);
snd_iprintf
(
buffer
,
"%d-%d/%d: %s
\n\n
"
,
ac97
->
addr
,
ac97
->
num
,
subidx
,
name
);
if
((
ac97
->
scaps
&
AC97_SCAP_AUDIO
)
==
0
)
goto
__modem
;
...
...
@@ -2430,6 +2663,7 @@ static int remove_ctl(ac97_t *ac97, const char *name)
snd_ctl_elem_id_t
id
;
memset
(
&
id
,
0
,
sizeof
(
id
));
strcpy
(
id
.
name
,
name
);
id
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
;
return
snd_ctl_remove_id
(
ac97
->
card
,
&
id
);
}
...
...
@@ -2438,8 +2672,10 @@ static int rename_ctl(ac97_t *ac97, const char *src, const char *dst)
snd_ctl_elem_id_t
sid
,
did
;
memset
(
&
sid
,
0
,
sizeof
(
sid
));
strcpy
(
sid
.
name
,
src
);
sid
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
;
memset
(
&
did
,
0
,
sizeof
(
did
));
strcpy
(
did
.
name
,
dst
);
did
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
;
return
snd_ctl_rename_id
(
ac97
->
card
,
&
sid
,
&
did
);
}
...
...
@@ -2476,19 +2712,21 @@ int snd_ac97_tune_hardware(ac97_t *ac97, struct pci_dev *pci, struct ac97_quirk
{
unsigned
short
vendor
,
device
;
snd_assert
(
quirk
,
return
-
EINVAL
);
pci_read_config_word
(
pci
,
PCI_SUBSYSTEM_VENDOR_ID
,
&
vendor
);
pci_read_config_word
(
pci
,
PCI_SUBSYSTEM_ID
,
&
device
);
for
(;
quirk
->
vendor
;
quirk
++
)
{
if
(
quirk
->
vendor
==
vendor
&&
quirk
->
device
==
device
)
{
snd_printdd
(
"ac97 quirk for %
04x:%04x
\n
"
,
vendor
,
device
);
snd_printdd
(
"ac97 quirk for %
s (%04x:%04x)
\n
"
,
quirk
->
name
,
vendor
,
device
);
switch
(
quirk
->
type
)
{
case
AC97_TUNE_HP_ONLY
:
return
swap_headphone
(
ac97
,
1
);
case
AC97_TUNE_SWAP_HP
:
return
swap_headphone
(
ac97
,
0
);
}
snd_printk
(
KERN_ERR
"invalid quirk type %d
\n
"
,
quirk
->
typ
e
);
snd_printk
(
KERN_ERR
"invalid quirk type %d
for %s
\n
"
,
quirk
->
type
,
quirk
->
nam
e
);
return
-
EINVAL
;
}
}
...
...
@@ -2506,6 +2744,7 @@ EXPORT_SYMBOL(snd_ac97_write_cache);
EXPORT_SYMBOL
(
snd_ac97_update
);
EXPORT_SYMBOL
(
snd_ac97_update_bits
);
EXPORT_SYMBOL
(
snd_ac97_mixer
);
EXPORT_SYMBOL
(
snd_ac97_modem
);
EXPORT_SYMBOL
(
snd_ac97_set_rate
);
EXPORT_SYMBOL
(
snd_ac97_tune_hardware
);
#ifdef CONFIG_PM
...
...
sound/pci/ac97/ac97_id.h
View file @
74521715
...
...
@@ -31,6 +31,7 @@
#define AC97_ID_AD1886 0x41445361
#define AC97_ID_AD1887 0x41445362
#define AC97_ID_AD1886A 0x41445363
#define AC97_ID_AD1980 0x41445370
#define AC97_ID_TR28028 0x54524108
#define AC97_ID_STAC9700 0x83847600
#define AC97_ID_STAC9704 0x83847604
...
...
sound/pci/cs46xx/cs46xx_lib.c
View file @
74521715
...
...
@@ -672,28 +672,21 @@ static void snd_cs46xx_set_capture_sample_rate(cs46xx_t *chip, unsigned int rate
* PCM part
*/
static
int
snd_cs46xx_playback_transfer
(
snd_pcm_substream_t
*
substream
,
snd_pcm_uframes_t
frames
)
static
int
snd_cs46xx_playback_transfer
(
snd_pcm_substream_t
*
substream
)
{
/* cs46xx_t *chip = snd_pcm_substream_chip(substream); */
snd_pcm_runtime_t
*
runtime
=
substream
->
runtime
;
cs46xx_pcm_t
*
cpcm
=
snd_magic_cast
(
cs46xx_pcm_t
,
runtime
->
private_data
,
return
-
ENXIO
);
snd_pcm_uframes_t
appl_ptr
=
runtime
->
control
->
appl_ptr
;
snd_pcm_sframes_t
diff
;
cs46xx_pcm_t
*
cpcm
;
int
buffer_size
;
cpcm
=
snd_magic_cast
(
cs46xx_pcm_t
,
substream
->
runtime
->
private_data
,
return
-
ENXIO
);
buffer_size
=
runtime
->
period_size
*
CS46XX_FRAGS
<<
cpcm
->
shift
;
snd_pcm_sframes_t
diff
=
appl_ptr
-
cpcm
->
appl_ptr
;
int
buffer_size
=
runtime
->
period_size
*
CS46XX_FRAGS
<<
cpcm
->
shift
;
diff
=
appl_ptr
-
cpcm
->
appl_ptr
;
if
(
diff
)
{
if
(
diff
<
-
(
snd_pcm_sframes_t
)
(
runtime
->
boundary
/
2
))
diff
+=
runtime
->
boundary
;
frames
+=
diff
;
cpcm
->
sw_ready
+=
diff
*
(
1
<<
cpcm
->
shift
);
cpcm
->
appl_ptr
=
appl_ptr
;
}
cpcm
->
sw_ready
+=
frames
<<
cpcm
->
shift
;
cpcm
->
appl_ptr
=
appl_ptr
+
frames
;
while
(
cpcm
->
hw_ready
<
buffer_size
&&
cpcm
->
sw_ready
>
0
)
{
size_t
hw_to_end
=
buffer_size
-
cpcm
->
hw_data
;
...
...
@@ -720,21 +713,20 @@ static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream,
return
0
;
}
static
int
snd_cs46xx_capture_transfer
(
snd_pcm_substream_t
*
substream
,
snd_pcm_uframes_t
frames
)
static
int
snd_cs46xx_capture_transfer
(
snd_pcm_substream_t
*
substream
)
{
cs46xx_t
*
chip
=
snd_pcm_substream_chip
(
substream
);
snd_pcm_runtime_t
*
runtime
=
substream
->
runtime
;
snd_pcm_uframes_t
appl_ptr
=
runtime
->
control
->
appl_ptr
;
snd_pcm_sframes_t
diff
=
appl_ptr
-
chip
->
capt
.
appl_ptr
;
int
buffer_size
=
runtime
->
period_size
*
CS46XX_FRAGS
<<
chip
->
capt
.
shift
;
if
(
diff
)
{
if
(
diff
<
-
(
snd_pcm_sframes_t
)
(
runtime
->
boundary
/
2
))
diff
+=
runtime
->
boundary
;
frames
+=
diff
;
chip
->
capt
.
sw_ready
-=
diff
*
(
1
<<
chip
->
capt
.
shift
);
chip
->
capt
.
appl_ptr
=
appl_ptr
;
}
chip
->
capt
.
sw_ready
-=
frames
<<
chip
->
capt
.
shift
;
chip
->
capt
.
appl_ptr
=
appl_ptr
+
frames
;
while
(
chip
->
capt
.
hw_ready
>
0
&&
chip
->
capt
.
sw_ready
<
(
int
)
chip
->
capt
.
sw_bufsize
)
{
size_t
hw_to_end
=
buffer_size
-
chip
->
capt
.
hw_data
;
...
...
@@ -802,7 +794,7 @@ static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_
cpcm
->
sw_io
+=
bytes
;
if
(
cpcm
->
sw_io
>=
cpcm
->
sw_bufsize
)
cpcm
->
sw_io
-=
cpcm
->
sw_bufsize
;
snd_cs46xx_playback_transfer
(
substream
,
0
);
snd_cs46xx_playback_transfer
(
substream
);
return
cpcm
->
sw_io
>>
cpcm
->
shift
;
}
...
...
@@ -827,57 +819,10 @@ static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(snd_pcm_substream_t
chip
->
capt
.
sw_io
+=
bytes
;
if
(
chip
->
capt
.
sw_io
>=
chip
->
capt
.
sw_bufsize
)
chip
->
capt
.
sw_io
-=
chip
->
capt
.
sw_bufsize
;
snd_cs46xx_capture_transfer
(
substream
,
0
);
snd_cs46xx_capture_transfer
(
substream
);
return
chip
->
capt
.
sw_io
>>
chip
->
capt
.
shift
;
}
static
int
snd_cs46xx_playback_copy
(
snd_pcm_substream_t
*
substream
,
int
channel
,
snd_pcm_uframes_t
hwoff
,
void
*
src
,
snd_pcm_uframes_t
frames
)
{
snd_pcm_runtime_t
*
runtime
=
substream
->
runtime
;
/*cs46xx_t *chip = snd_pcm_substream_chip(substream); */
size_t
hwoffb
;
size_t
bytes
;
char
*
hwbuf
;
cs46xx_pcm_t
*
cpcm
=
snd_magic_cast
(
cs46xx_pcm_t
,
substream
->
runtime
->
private_data
,
return
-
ENXIO
);
snd_assert
(
runtime
->
dma_area
,
return
-
EINVAL
);
hwoffb
=
hwoff
<<
cpcm
->
shift
;
bytes
=
frames
<<
cpcm
->
shift
;
hwbuf
=
runtime
->
dma_area
+
hwoffb
;
if
(
copy_from_user
(
hwbuf
,
src
,
bytes
))
return
-
EFAULT
;
spin_lock_irq
(
&
runtime
->
lock
);
snd_cs46xx_playback_transfer
(
substream
,
frames
);
spin_unlock_irq
(
&
runtime
->
lock
);
return
0
;
}
static
int
snd_cs46xx_capture_copy
(
snd_pcm_substream_t
*
substream
,
int
channel
,
snd_pcm_uframes_t
hwoff
,
void
*
dst
,
snd_pcm_uframes_t
frames
)
{
snd_pcm_runtime_t
*
runtime
=
substream
->
runtime
;
cs46xx_t
*
chip
=
snd_pcm_substream_chip
(
substream
);
size_t
hwoffb
=
hwoff
<<
chip
->
capt
.
shift
;
size_t
bytes
=
frames
<<
chip
->
capt
.
shift
;
char
*
hwbuf
=
runtime
->
dma_area
+
hwoffb
;
if
(
copy_to_user
(
dst
,
hwbuf
,
bytes
))
return
-
EFAULT
;
spin_lock_irq
(
&
runtime
->
lock
);
snd_cs46xx_capture_transfer
(
substream
,
frames
);
spin_unlock_irq
(
&
runtime
->
lock
);
return
0
;
}
static
int
snd_cs46xx_playback_trigger
(
snd_pcm_substream_t
*
substream
,
int
cmd
)
{
...
...
@@ -909,10 +854,10 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
cs46xx_dsp_pcm_link
(
chip
,
cpcm
->
pcm_channel
);
if
(
substream
->
runtime
->
periods
!=
CS46XX_FRAGS
)
snd_cs46xx_playback_transfer
(
substream
,
0
);
snd_cs46xx_playback_transfer
(
substream
);
#else
if
(
substream
->
runtime
->
periods
!=
CS46XX_FRAGS
)
snd_cs46xx_playback_transfer
(
substream
,
0
);
snd_cs46xx_playback_transfer
(
substream
);
{
unsigned
int
tmp
;
tmp
=
snd_cs46xx_peek
(
chip
,
BA1_PCTL
);
tmp
&=
0x0000ffff
;
...
...
@@ -1587,8 +1532,8 @@ snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops = {
.
hw_free
=
snd_cs46xx_playback_hw_free
,
.
prepare
=
snd_cs46xx_playback_prepare
,
.
trigger
=
snd_cs46xx_playback_trigger
,
.
copy
=
snd_cs46xx_playback_copy
,
.
pointer
=
snd_cs46xx_playback_indirect_pointer
,
.
ack
=
snd_cs46xx_playback_transfer
,
};
snd_pcm_ops_t
snd_cs46xx_playback_iec958_ops
=
{
...
...
@@ -1610,8 +1555,8 @@ snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops = {
.
hw_free
=
snd_cs46xx_playback_hw_free
,
.
prepare
=
snd_cs46xx_playback_prepare
,
.
trigger
=
snd_cs46xx_playback_trigger
,
.
copy
=
snd_cs46xx_playback_copy
,
.
pointer
=
snd_cs46xx_playback_indirect_pointer
,
.
ack
=
snd_cs46xx_playback_transfer
,
};
#endif
...
...
@@ -1635,8 +1580,8 @@ snd_pcm_ops_t snd_cs46xx_playback_indirect_ops = {
.
hw_free
=
snd_cs46xx_playback_hw_free
,
.
prepare
=
snd_cs46xx_playback_prepare
,
.
trigger
=
snd_cs46xx_playback_trigger
,
.
copy
=
snd_cs46xx_playback_copy
,
.
pointer
=
snd_cs46xx_playback_indirect_pointer
,
.
ack
=
snd_cs46xx_playback_transfer
,
};
snd_pcm_ops_t
snd_cs46xx_capture_ops
=
{
...
...
@@ -1658,8 +1603,8 @@ snd_pcm_ops_t snd_cs46xx_capture_indirect_ops = {
.
hw_free
=
snd_cs46xx_capture_hw_free
,
.
prepare
=
snd_cs46xx_capture_prepare
,
.
trigger
=
snd_cs46xx_capture_trigger
,
.
copy
=
snd_cs46xx_capture_copy
,
.
pointer
=
snd_cs46xx_capture_indirect_pointer
,
.
ack
=
snd_cs46xx_capture_transfer
,
};
static
void
snd_cs46xx_pcm_free
(
snd_pcm_t
*
pcm
)
...
...
@@ -2505,9 +2450,6 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
strcpy
(
id
.
name
,
"External Amplifier Power Down"
);
chip
->
eapd_switch
=
snd_ctl_find_id
(
chip
->
card
,
&
id
);
/* turn on amplifier */
chip
->
amplifier_ctrl
(
chip
,
1
);
#ifdef CONFIG_SND_CS46XX_NEW_DSP
/* do soundcard specific mixer setup */
if
(
chip
->
mixer_init
)
{
...
...
@@ -2515,6 +2457,9 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
chip
->
mixer_init
(
chip
);
}
#endif
/* turn on amplifier */
chip
->
amplifier_ctrl
(
chip
,
1
);
return
0
;
}
...
...
sound/pci/emu10k1/emufx.c
View file @
74521715
...
...
@@ -520,8 +520,7 @@ static void snd_emu10k1_fx8010_playback_tram_poke(emu10k1_t *emu,
*
tram_pos
-=
frames
;
}
static
int
snd_emu10k1_fx8010_playback_transfer
(
snd_pcm_substream_t
*
substream
,
snd_pcm_uframes_t
frames
)
static
int
snd_emu10k1_fx8010_playback_transfer
(
snd_pcm_substream_t
*
substream
)
{
emu10k1_t
*
emu
=
snd_pcm_substream_chip
(
substream
);
snd_pcm_runtime_t
*
runtime
=
substream
->
runtime
;
...
...
@@ -529,13 +528,13 @@ static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream,
snd_pcm_uframes_t
appl_ptr
=
runtime
->
control
->
appl_ptr
;
snd_pcm_sframes_t
diff
=
appl_ptr
-
pcm
->
appl_ptr
;
snd_pcm_uframes_t
buffer_size
=
pcm
->
buffer_size
/
2
;
if
(
diff
)
{
if
(
diff
<
-
(
snd_pcm_sframes_t
)
(
runtime
->
boundary
/
2
))
diff
+=
runtime
->
boundary
;
frames
+=
diff
;
pcm
->
sw_ready
+=
diff
;
pcm
->
appl_ptr
=
appl_ptr
;
}
pcm
->
sw_ready
+=
frames
;
pcm
->
appl_ptr
=
appl_ptr
+
frames
;
while
(
pcm
->
hw_ready
<
buffer_size
&&
pcm
->
sw_ready
>
0
)
{
size_t
hw_to_end
=
buffer_size
-
pcm
->
hw_data
;
...
...
@@ -632,7 +631,7 @@ static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream,
result
=
snd_emu10k1_fx8010_register_irq_handler
(
emu
,
snd_emu10k1_fx8010_playback_irq
,
pcm
->
gpr_running
,
substream
,
&
pcm
->
irq
);
if
(
result
<
0
)
goto
__err
;
snd_emu10k1_fx8010_playback_transfer
(
substream
,
0
);
/* roll the ball */
snd_emu10k1_fx8010_playback_transfer
(
substream
);
/* roll the ball */
snd_emu10k1_ptr_write
(
emu
,
emu
->
gpr_base
+
pcm
->
gpr_trigger
,
0
,
1
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
...
...
@@ -670,28 +669,10 @@ static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t
pcm
->
sw_io
+=
frames
;
if
(
pcm
->
sw_io
>
runtime
->
buffer_size
)
pcm
->
sw_io
-=
runtime
->
buffer_size
;
snd_emu10k1_fx8010_playback_transfer
(
substream
,
0
);
snd_emu10k1_fx8010_playback_transfer
(
substream
);
return
pcm
->
sw_io
;
}
static
int
snd_emu10k1_fx8010_playback_copy
(
snd_pcm_substream_t
*
substream
,
int
channel
,
snd_pcm_uframes_t
hwoff
,
void
*
src
,
snd_pcm_uframes_t
frames
)
{
snd_pcm_runtime_t
*
runtime
=
substream
->
runtime
;
size_t
hwoffb
=
hwoff
<<
2
;
size_t
bytes
=
frames
<<
2
;
char
*
hwbuf
=
runtime
->
dma_area
+
hwoffb
;
if
(
copy_from_user
(
hwbuf
,
src
,
bytes
))
return
-
EFAULT
;
spin_lock_irq
(
&
runtime
->
lock
);
snd_emu10k1_fx8010_playback_transfer
(
substream
,
frames
);
spin_unlock_irq
(
&
runtime
->
lock
);
return
0
;
}
static
snd_pcm_hardware_t
snd_emu10k1_fx8010_playback
=
{
.
info
=
(
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_INTERLEAVED
|
...
...
@@ -748,8 +729,8 @@ static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {
.
hw_free
=
snd_emu10k1_fx8010_playback_hw_free
,
.
prepare
=
snd_emu10k1_fx8010_playback_prepare
,
.
trigger
=
snd_emu10k1_fx8010_playback_trigger
,
.
copy
=
snd_emu10k1_fx8010_playback_copy
,
.
pointer
=
snd_emu10k1_fx8010_playback_pointer
,
.
ack
=
snd_emu10k1_fx8010_playback_transfer
,
};
static
void
snd_emu10k1_fx8010_pcm_free
(
snd_pcm_t
*
pcm
)
...
...
@@ -1221,7 +1202,7 @@ static void __devinit snd_emu10k1_init_stereo_control(emu10k1_fx8010_control_gpr
ctl
->
gpr
[
1
]
=
gpr
+
1
;
ctl
->
value
[
1
]
=
defval
;
ctl
->
min
=
0
;
ctl
->
max
=
100
;
ctl
->
translation
=
EMU10K1_GPR_TRANSLATION_TABLE100
;
ctl
->
translation
=
EMU10K1_GPR_TRANSLATION_TABLE100
;
}
static
void
__devinit
snd_emu10k1_init_mono_onoff_control
(
emu10k1_fx8010_control_gpr_t
*
ctl
,
const
char
*
name
,
int
gpr
,
int
defval
)
...
...
@@ -1252,12 +1233,14 @@ static void __devinit snd_emu10k1_init_stereo_onoff_control(emu10k1_fx8010_contr
* initial DSP configuration for Audigy
*/
#define A_GPR_ACCU 0xd6
static
int
__devinit
_snd_emu10k1_audigy_init_efx
(
emu10k1_t
*
emu
)
{
int
err
,
i
,
gpr
,
tmp
,
playback
,
capture
,
nctl
;
int
err
,
i
,
z
,
gpr
,
tmp
,
playback
,
capture
,
nctl
;
u32
ptr
;
emu10k1_fx8010_code_t
*
icode
;
emu10k1_fx8010_control_gpr_t
*
controls
;
emu10k1_fx8010_control_gpr_t
*
controls
,
*
ctl
;
mm_segment_t
seg
;
spin_lock_init
(
&
emu
->
fx8010
.
irq_lock
);
...
...
@@ -1269,7 +1252,7 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
kfree
(
icode
);
return
-
ENOMEM
;
}
/* clear free GPRs */
for
(
i
=
0
;
i
<
256
;
i
++
)
set_bit
(
i
,
icode
->
gpr_valid
);
...
...
@@ -1278,10 +1261,10 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
ptr
=
0
;
nctl
=
0
;
playback
=
10
;
capture
=
playback
+
10
;
/* we reserve 10 voices */
capture
=
playback
+
(
SND_EMU10K1_PLAYBACK_CHANNELS
*
2
)
;
/* we reserve 10 voices */
gpr
=
capture
+
10
;
tmp
=
0x8
0
;
tmp
=
0x8
8
;
/* stop FX processor */
snd_emu10k1_ptr_write
(
emu
,
A_DBG
,
0
,
(
emu
->
fx8010
.
dbg
=
0
)
|
A_DBG_SINGLE_STEP
);
...
...
@@ -1422,21 +1405,111 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
#define A_PUT_STEREO_OUTPUT(out1,out2,src) \
{A_PUT_OUTPUT(out1,src); A_PUT_OUTPUT(out2,src+1);}
#define _A_SWITCH(icode, ptr, dst, src, sw) \
A_OP((icode), ptr, iMACINT0, dst, A_C_00000000, src, sw);
#define A_SWITCH(icode, ptr, dst, src, sw) \
_A_SWITCH(icode, ptr, A_GPR(dst), A_GPR(src), A_GPR(sw))
#define _A_SWITCH_NEG(icode, ptr, dst, src) \
A_OP((icode), ptr, iANDXOR, dst, src, A_C_00000001, A_C_00000001);
#define A_SWITCH_NEG(icode, ptr, dst, src) \
_A_SWITCH_NEG(icode, ptr, A_GPR(dst), A_GPR(src))
/*
* Process tone control
*/
A_OP
(
icode
,
&
ptr
,
iACC3
,
A_GPR
(
playback
+
SND_EMU10K1_PLAYBACK_CHANNELS
+
0
),
A_GPR
(
playback
+
0
),
A_C_00000000
,
A_C_00000000
);
/* left */
A_OP
(
icode
,
&
ptr
,
iACC3
,
A_GPR
(
playback
+
SND_EMU10K1_PLAYBACK_CHANNELS
+
1
),
A_GPR
(
playback
+
1
),
A_C_00000000
,
A_C_00000000
);
/* right */
A_OP
(
icode
,
&
ptr
,
iACC3
,
A_GPR
(
playback
+
SND_EMU10K1_PLAYBACK_CHANNELS
+
2
),
A_GPR
(
playback
+
2
),
A_C_00000000
,
A_C_00000000
);
/* rear left */
A_OP
(
icode
,
&
ptr
,
iACC3
,
A_GPR
(
playback
+
SND_EMU10K1_PLAYBACK_CHANNELS
+
3
),
A_GPR
(
playback
+
3
),
A_C_00000000
,
A_C_00000000
);
/* rear right */
A_OP
(
icode
,
&
ptr
,
iACC3
,
A_GPR
(
playback
+
SND_EMU10K1_PLAYBACK_CHANNELS
+
4
),
A_GPR
(
playback
+
4
),
A_C_00000000
,
A_C_00000000
);
/* center */
A_OP
(
icode
,
&
ptr
,
iACC3
,
A_GPR
(
playback
+
SND_EMU10K1_PLAYBACK_CHANNELS
+
5
),
A_GPR
(
playback
+
5
),
A_C_00000000
,
A_C_00000000
);
/* LFE */
ctl
=
&
controls
[
nctl
+
0
];
ctl
->
id
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
;
strcpy
(
ctl
->
id
.
name
,
"Tone Control - Bass"
);
ctl
->
vcount
=
2
;
ctl
->
count
=
10
;
ctl
->
min
=
0
;
ctl
->
max
=
40
;
ctl
->
value
[
0
]
=
ctl
->
value
[
1
]
=
20
;
ctl
->
translation
=
EMU10K1_GRP_TRANSLATION_BASS
;
ctl
=
&
controls
[
nctl
+
1
];
ctl
->
id
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
;
strcpy
(
ctl
->
id
.
name
,
"Tone Control - Treble"
);
ctl
->
vcount
=
2
;
ctl
->
count
=
10
;
ctl
->
min
=
0
;
ctl
->
max
=
40
;
ctl
->
value
[
0
]
=
ctl
->
value
[
1
]
=
20
;
ctl
->
translation
=
EMU10K1_GRP_TRANSLATION_TREBLE
;
#define BASS_GPR 0x8c
#define TREBLE_GPR 0x96
for
(
z
=
0
;
z
<
5
;
z
++
)
{
int
j
;
for
(
j
=
0
;
j
<
2
;
j
++
)
{
controls
[
nctl
+
0
].
gpr
[
z
*
2
+
j
]
=
BASS_GPR
+
z
*
2
+
j
;
controls
[
nctl
+
1
].
gpr
[
z
*
2
+
j
]
=
TREBLE_GPR
+
z
*
2
+
j
;
}
}
for
(
z
=
0
;
z
<
3
;
z
++
)
{
/* front/rear/center-lfe */
int
j
,
k
,
l
,
d
;
for
(
j
=
0
;
j
<
2
;
j
++
)
{
/* left/right */
k
=
0xb0
+
(
z
*
8
)
+
(
j
*
4
);
l
=
0xe0
+
(
z
*
8
)
+
(
j
*
4
);
d
=
playback
+
SND_EMU10K1_PLAYBACK_CHANNELS
+
z
*
2
+
j
;
A_OP
(
icode
,
&
ptr
,
iMAC0
,
A_C_00000000
,
A_C_00000000
,
A_GPR
(
d
),
A_GPR
(
BASS_GPR
+
0
+
j
));
A_OP
(
icode
,
&
ptr
,
iMACMV
,
A_GPR
(
k
+
1
),
A_GPR
(
k
),
A_GPR
(
k
+
1
),
A_GPR
(
BASS_GPR
+
4
+
j
));
A_OP
(
icode
,
&
ptr
,
iMACMV
,
A_GPR
(
k
),
A_GPR
(
d
),
A_GPR
(
k
),
A_GPR
(
BASS_GPR
+
2
+
j
));
A_OP
(
icode
,
&
ptr
,
iMACMV
,
A_GPR
(
k
+
3
),
A_GPR
(
k
+
2
),
A_GPR
(
k
+
3
),
A_GPR
(
BASS_GPR
+
8
+
j
));
A_OP
(
icode
,
&
ptr
,
iMAC0
,
A_GPR
(
k
+
2
),
A_GPR_ACCU
,
A_GPR
(
k
+
2
),
A_GPR
(
BASS_GPR
+
6
+
j
));
A_OP
(
icode
,
&
ptr
,
iACC3
,
A_GPR
(
k
+
2
),
A_GPR
(
k
+
2
),
A_GPR
(
k
+
2
),
A_C_00000000
);
A_OP
(
icode
,
&
ptr
,
iMAC0
,
A_C_00000000
,
A_C_00000000
,
A_GPR
(
k
+
2
),
A_GPR
(
TREBLE_GPR
+
0
+
j
));
A_OP
(
icode
,
&
ptr
,
iMACMV
,
A_GPR
(
l
+
1
),
A_GPR
(
l
),
A_GPR
(
l
+
1
),
A_GPR
(
TREBLE_GPR
+
4
+
j
));
A_OP
(
icode
,
&
ptr
,
iMACMV
,
A_GPR
(
l
),
A_GPR
(
k
+
2
),
A_GPR
(
l
),
A_GPR
(
TREBLE_GPR
+
2
+
j
));
A_OP
(
icode
,
&
ptr
,
iMACMV
,
A_GPR
(
l
+
3
),
A_GPR
(
l
+
2
),
A_GPR
(
l
+
3
),
A_GPR
(
TREBLE_GPR
+
8
+
j
));
A_OP
(
icode
,
&
ptr
,
iMAC0
,
A_GPR
(
l
+
2
),
A_GPR_ACCU
,
A_GPR
(
l
+
2
),
A_GPR
(
TREBLE_GPR
+
6
+
j
));
A_OP
(
icode
,
&
ptr
,
iMACINT0
,
A_GPR
(
l
+
2
),
A_C_00000000
,
A_GPR
(
l
+
2
),
A_C_00000010
);
A_OP
(
icode
,
&
ptr
,
iACC3
,
A_GPR
(
d
),
A_GPR
(
l
+
2
),
A_C_00000000
,
A_C_00000000
);
if
(
z
==
2
)
/* center */
break
;
}
}
nctl
+=
2
;
#undef BASS_GPR
#undef TREBLE_GPR
for
(
z
=
0
;
z
<
6
;
z
++
)
{
A_SWITCH
(
icode
,
&
ptr
,
tmp
+
0
,
playback
+
SND_EMU10K1_PLAYBACK_CHANNELS
+
z
,
gpr
+
0
);
A_SWITCH_NEG
(
icode
,
&
ptr
,
tmp
+
1
,
gpr
+
0
);
A_SWITCH
(
icode
,
&
ptr
,
tmp
+
1
,
playback
+
z
,
tmp
+
1
);
A_OP
(
icode
,
&
ptr
,
iACC3
,
A_GPR
(
playback
+
SND_EMU10K1_PLAYBACK_CHANNELS
+
z
),
A_GPR
(
tmp
+
0
),
A_GPR
(
tmp
+
1
),
A_C_00000000
);
}
snd_emu10k1_init_stereo_onoff_control
(
controls
+
nctl
++
,
"Tone Control - Switch"
,
gpr
,
0
);
gpr
+=
2
;
/* digital outputs */
A_PUT_STEREO_OUTPUT
(
A_EXTOUT_FRONT_L
,
A_EXTOUT_FRONT_R
,
playback
);
A_PUT_STEREO_OUTPUT
(
A_EXTOUT_REAR_L
,
A_EXTOUT_REAR_R
,
playback
+
2
);
A_PUT_OUTPUT
(
A_EXTOUT_CENTER
,
playback
+
4
);
A_PUT_OUTPUT
(
A_EXTOUT_LFE
,
playback
+
5
);
A_PUT_STEREO_OUTPUT
(
A_EXTOUT_FRONT_L
,
A_EXTOUT_FRONT_R
,
playback
+
SND_EMU10K1_PLAYBACK_CHANNELS
);
A_PUT_STEREO_OUTPUT
(
A_EXTOUT_REAR_L
,
A_EXTOUT_REAR_R
,
playback
+
2
+
SND_EMU10K1_PLAYBACK_CHANNELS
);
A_PUT_OUTPUT
(
A_EXTOUT_CENTER
,
playback
+
4
+
SND_EMU10K1_PLAYBACK_CHANNELS
);
A_PUT_OUTPUT
(
A_EXTOUT_LFE
,
playback
+
5
+
SND_EMU10K1_PLAYBACK_CHANNELS
);
/* analog speakers */
//A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback);
A_PUT_STEREO_OUTPUT
(
A_EXTOUT_AC97_L
,
A_EXTOUT_AC97_R
,
playback
);
A_PUT_STEREO_OUTPUT
(
A_EXTOUT_AREAR_L
,
A_EXTOUT_AREAR_R
,
playback
+
2
);
A_PUT_OUTPUT
(
A_EXTOUT_ACENTER
,
playback
+
4
);
A_PUT_OUTPUT
(
A_EXTOUT_ALFE
,
playback
+
5
);
//A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback
+ SND_EMU10K1_PLAYBACK_CHANNELS
);
A_PUT_STEREO_OUTPUT
(
A_EXTOUT_AC97_L
,
A_EXTOUT_AC97_R
,
playback
+
SND_EMU10K1_PLAYBACK_CHANNELS
);
A_PUT_STEREO_OUTPUT
(
A_EXTOUT_AREAR_L
,
A_EXTOUT_AREAR_R
,
playback
+
2
+
SND_EMU10K1_PLAYBACK_CHANNELS
);
A_PUT_OUTPUT
(
A_EXTOUT_ACENTER
,
playback
+
4
+
SND_EMU10K1_PLAYBACK_CHANNELS
);
A_PUT_OUTPUT
(
A_EXTOUT_ALFE
,
playback
+
5
+
SND_EMU10K1_PLAYBACK_CHANNELS
);
/* headphone */
A_PUT_STEREO_OUTPUT
(
A_EXTOUT_HEADPHONE_L
,
A_EXTOUT_HEADPHONE_R
,
playback
);
A_PUT_STEREO_OUTPUT
(
A_EXTOUT_HEADPHONE_L
,
A_EXTOUT_HEADPHONE_R
,
playback
+
SND_EMU10K1_PLAYBACK_CHANNELS
);
/* ADC buffer */
A_PUT_OUTPUT
(
A_EXTOUT_ADC_CAP_L
,
capture
);
...
...
@@ -1561,7 +1634,7 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
gpr
=
capture
+
SND_EMU10K1_CAPTURE_CHANNELS
;
tmp
=
0x88
;
/* we need 4 temporary GPR */
/* from 0x8c to 0xff is the area for tone control */
/* stop FX processor */
snd_emu10k1_ptr_write
(
emu
,
DBG
,
0
,
(
emu
->
fx8010
.
dbg
=
0
)
|
EMU10K1_DBG_SINGLE_STEP
);
...
...
@@ -1608,7 +1681,7 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
icode
->
gpr_map
[
gpr
+
12
]
=
0
;
/* if the trigger flag is not set, skip */
/* 00: */
OP
(
icode
,
&
ptr
,
iMAC0
,
C_00000000
,
GPR
(
ipcm
->
gpr_trigger
),
C_00000000
,
C_00000000
);
/* 00: */
OP
(
icode
,
&
ptr
,
iMAC0
,
C_00000000
,
GPR
(
ipcm
->
gpr_trigger
),
C_00000000
,
C_00000000
);
/* 01: */
OP
(
icode
,
&
ptr
,
iSKIP
,
GPR_COND
,
GPR_COND
,
CC_REG_ZERO
,
GPR
(
gpr
+
6
));
/* if the running flag is set, we're running */
/* 02: */
OP
(
icode
,
&
ptr
,
iMAC0
,
C_00000000
,
GPR
(
ipcm
->
gpr_running
),
C_00000000
,
C_00000000
);
...
...
sound/pci/intel8x0.c
View file @
74521715
...
...
@@ -1508,12 +1508,16 @@ static struct _ac97_ali_rate_regs {
{
ALID_SPDIFIN
,
{
0
,
0
,
0
},
-
1
},
};
static
struct
ac97_quirk
ac97_quirks
[]
=
{
{
0x1028
,
0x0126
,
"Dell Optiplex GX260"
,
AC97_TUNE_HP_ONLY
},
{
}
/* terminator */
};
static
int
__devinit
snd_intel8x0_mixer
(
intel8x0_t
*
chip
,
int
ac97_clock
)
{
ac97_t
ac97
,
*
x97
;
ichdev_t
*
ichdev
;
int
err
,
i
,
channels
=
2
,
codecs
;
int
err
,
i
,
num
,
channels
=
2
,
codecs
,
_
codecs
;
unsigned
int
glob_sta
=
0
;
for
(
i
=
0
;
i
<=
ICHD_LAST
;
i
++
)
{
...
...
@@ -1589,6 +1593,7 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
if
((
err
=
snd_ac97_mixer
(
chip
->
card
,
&
ac97
,
&
x97
))
<
0
)
return
err
;
chip
->
ac97
[
0
]
=
x97
;
snd_ac97_tune_hardware
(
chip
->
ac97
[
0
],
chip
->
pci
,
ac97_quirks
);
chip
->
ichd
[
ICHD_PCMOUT
].
ac97
=
x97
;
chip
->
ichd
[
ICHD_PCMIN
].
ac97
=
x97
;
if
(
x97
->
ext_id
&
AC97_EI_VRM
)
...
...
@@ -1604,20 +1609,20 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
snd_ac97_update_bits
(
x97
,
AC97_EXTENDED_ID
,
AC97_EI_DACS_SLOT_MASK
,
0
);
/* AnalogDevices CNR boards uses special codec chaining */
/* skip standard test method for secondary codecs in this case */
if
(
x97
->
flags
&
AC97_AD_MULTI
)
{
if
(
x97
->
flags
&
AC97_AD_MULTI
)
codecs
=
1
;
goto
__skip_secondary
;
}
if
(
codecs
<
2
)
goto
__skip_secondary
;
for
(
i
=
1
;
i
<
codecs
;
i
++
)
{
ac97
.
num
=
i
;
for
(
i
=
1
,
num
=
1
,
_codecs
=
codecs
;
num
<
_codecs
;
num
++
)
{
ac97
.
num
=
num
;
if
((
err
=
snd_ac97_mixer
(
chip
->
card
,
&
ac97
,
&
x97
))
<
0
)
{
snd_printk
(
"Unable to initialize codec #%i [device = %i, GLOB_STA = 0x%x]
\n
"
,
i
,
chip
->
device_type
,
glob_sta
);
codecs
=
i
;
break
;
codecs
--
;
continue
;
}
chip
->
ac97
[
i
]
=
x97
;
chip
->
ac97
[
i
++
]
=
x97
;
if
(
!
ac97_is_audio
(
x97
))
continue
;
switch
(
chip
->
device_type
)
{
case
DEVICE_INTEL_ICH4
:
if
(
chip
->
ichd
[
ICHD_PCM2IN
].
ac97
==
NULL
)
...
...
@@ -1656,14 +1661,16 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
}
iputbyte
(
chip
,
ICHREG
(
SDM
),
tmp
);
}
for
(
i
=
0
;
i
<
3
;
i
++
)
{
if
((
x97
=
chip
->
ac97
[
i
])
==
NULL
)
for
(
i
=
0
;
i
<
codecs
;
i
++
)
{
x97
=
chip
->
ac97
[
i
];
if
(
!
ac97_is_audio
(
x97
))
continue
;
if
(
x97
->
scaps
&
AC97_SCAP_SURROUND_DAC
)
chip
->
multi4
=
1
;
}
for
(
i
=
0
;
i
<
3
&&
chip
->
multi4
;
i
++
)
{
if
((
x97
=
chip
->
ac97
[
i
])
==
NULL
)
for
(
i
=
0
;
i
<
codecs
&&
chip
->
multi4
;
i
++
)
{
x97
=
chip
->
ac97
[
i
];
if
(
!
ac97_is_audio
(
x97
))
continue
;
if
(
x97
->
scaps
&
AC97_SCAP_CENTER_LFE_DAC
)
chip
->
multi6
=
1
;
...
...
@@ -1674,7 +1681,10 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
if
(
chip
->
multi4
)
goto
__6ch
;
for
(
;
i
<
codecs
;
i
++
)
{
if
(
ac97_is_rev22
(
x97
=
chip
->
ac97
[
i
]))
{
x97
=
chip
->
ac97
[
i
];
if
(
!
ac97_is_audio
(
x97
))
continue
;
if
(
ac97_is_rev22
(
x97
))
{
snd_ac97_update_bits
(
x97
,
AC97_EXTENDED_ID
,
AC97_EI_DACS_SLOT_MASK
,
1
);
chip
->
multi4
=
1
;
break
;
...
...
@@ -1682,7 +1692,10 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
}
__6ch:
for
(
;
i
<
codecs
&&
chip
->
multi4
;
i
++
)
{
if
(
ac97_is_rev22
(
x97
=
chip
->
ac97
[
i
]))
{
x97
=
chip
->
ac97
[
i
];
if
(
!
ac97_is_audio
(
x97
))
continue
;
if
(
ac97_is_rev22
(
x97
))
{
snd_ac97_update_bits
(
x97
,
AC97_EXTENDED_ID
,
AC97_EI_DACS_SLOT_MASK
,
2
);
chip
->
multi6
=
1
;
break
;
...
...
@@ -1691,7 +1704,10 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
/* ok, some older codecs might support only AMAP */
if
(
!
chip
->
multi4
)
{
for
(
i
=
1
;
i
<
codecs
;
i
++
)
{
if
(
ac97_can_amap
(
x97
=
chip
->
ac97
[
i
]))
{
x97
=
chip
->
ac97
[
i
];
if
(
!
ac97_is_audio
(
x97
))
continue
;
if
(
ac97_can_amap
(
x97
))
{
if
(
x97
->
addr
==
1
)
{
chip
->
multi4
=
1
;
break
;
...
...
@@ -1699,7 +1715,9 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
}
}
for
(
;
i
<
codecs
&&
chip
->
multi4
;
i
++
)
{
if
(
ac97_can_amap
(
x97
=
chip
->
ac97
[
i
]))
{
if
(
!
ac97_is_audio
(
x97
))
continue
;
if
(
ac97_can_amap
(
x97
))
{
if
(
x97
->
addr
==
2
)
{
chip
->
multi6
=
1
;
break
;
...
...
sound/pci/korg1212/korg1212.c
View file @
74521715
...
...
@@ -42,6 +42,7 @@
// ----------------------------------------------------------------------------
#define K1212_DEBUG_LEVEL 0
#define K1212_DEBUG_PRINTK printk
//#define K1212_DEBUG_PRINTK(x...) printk("<0>" x)
// ----------------------------------------------------------------------------
// Record/Play Buffer Allocation Method. If K1212_LARGEALLOC is defined all
...
...
@@ -178,13 +179,21 @@ typedef enum {
#define kAudioChannels (k16BitChannels + k32BitChannels)
#define kPlayBufferFrames 1024
#define K1212_CHANNELS 16
#define K1212_ANALOG_CHANNELS 2
#define K1212_SPDIF_CHANNELS 2
#define K1212_ADAT_CHANNELS 8
#define K1212_CHANNELS (K1212_ADAT_CHANNELS + K1212_ANALOG_CHANNELS)
#define K1212_MIN_CHANNELS 1
#define K1212_MAX_CHANNELS K1212_CHANNELS
#define K1212_FRAME_SIZE (sizeof(KorgAudioFrame))
#define K1212_MAX_SAMPLES (kPlayBufferFrames*kNumBuffers)
#define K1212_PERIODS (K1212_BUF_SIZE/K1212_BLOCK_SIZE)
#define K1212_PERIOD_BYTES (K1212_BLOCK_SIZE)
#define K1212_BLOCK_SIZE (K1212_FRAME_SIZE*kPlayBufferFrames)
#define K1212_BUF_SIZE (K1212_BLOCK_SIZE*kNumBuffers)
#define K1212_PERIODS (kNumBuffers)
#define K1212_PERIOD_BYTES (K1212_FRAME_SIZE*kPlayBufferFrames)
#define K1212_BUF_SIZE (K1212_PERIOD_BYTES*kNumBuffers)
#define K1212_ANALOG_BUF_SIZE (K1212_ANALOG_CHANNELS * 2 * kPlayBufferFrames * kNumBuffers)
#define K1212_SPDIF_BUF_SIZE (K1212_SPDIF_CHANNELS * 3 * kPlayBufferFrames * kNumBuffers)
#define K1212_ADAT_BUF_SIZE (K1212_ADAT_CHANNELS * 2 * kPlayBufferFrames * kNumBuffers)
#define K1212_MAX_BUF_SIZE (K1212_ANALOG_BUF_SIZE + K1212_ADAT_BUF_SIZE)
#define k1212MinADCSens 0x7f
#define k1212MaxADCSens 0x00
...
...
@@ -314,9 +323,9 @@ typedef struct SensBits {
}
SensBits
;
struct
_snd_korg1212
{
struct
pci_dev
*
pci
;
snd_card_t
*
card
;
snd_pcm_t
*
pcm16
;
struct
pci_dev
*
pci
;
snd_pcm_t
*
pcm
;
int
irq
;
spinlock_t
lock
;
...
...
@@ -362,9 +371,9 @@ struct _snd_korg1212 {
u16
*
sensRegPtr
;
// address of the sensitivity setting register
u32
*
idRegPtr
;
// address of the device and vendor ID registers
size_t
periodsize
;
size_t
currentBuffer
;
int
channels
;
int
currentBuffer
;
snd_pcm_substream_t
*
playback_substream
;
snd_pcm_substream_t
*
capture_substream
;
...
...
@@ -383,6 +392,11 @@ struct _snd_korg1212 {
u16
leftADCInSens
;
// ADC left channel input sensitivity
u16
rightADCInSens
;
// ADC right channel input sensitivity
int
opencnt
;
// Open/Close count
int
setcnt
;
// SetupForPlay count
int
playcnt
;
// TriggerPlay count
};
MODULE_DESCRIPTION
(
"korg1212"
);
...
...
@@ -465,7 +479,6 @@ u16 ClockSourceSelector[] = {0x8000, // selects source as ADAT at 44.1 kHz
static
snd_korg1212rc
rc
;
MODULE_DEVICE_TABLE
(
pci
,
snd_korg1212_ids
);
typedef
union
swap_u32
{
unsigned
char
c
[
4
];
u32
i
;
}
swap_u32
;
...
...
@@ -521,11 +534,6 @@ static u32 EndianSwap(u32 swappee)
#endif /* not used */
void
TickDelay
(
int
time
)
{
udelay
(
time
);
}
#define SetBitInWord(theWord,bitPosition) (*theWord) |= (0x0001 << bitPosition)
#define SetBitInDWord(theWord,bitPosition) (*theWord) |= (0x00000001 << bitPosition)
#define ClearBitInWord(theWord,bitPosition) (*theWord) &= ~(0x0001 << bitPosition)
...
...
@@ -536,76 +544,95 @@ static snd_korg1212rc snd_korg1212_Send1212Command(korg1212_t *korg1212, korg121
{
u32
retryCount
;
u16
mailBox3Lo
;
snd_korg1212rc
rc
=
K1212_CMDRET_Success
;
if
(
!
korg1212
->
outDoorbellPtr
)
{
#if K1212_DEBUG_LEVEL > 1
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: CardUninitialized
\n
"
);
#endif
return
K1212_CMDRET_CardUninitialized
;
}
if
(
korg1212
->
outDoorbellPtr
)
{
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: Card <- 0x%08x 0x%08x [%s]
\n
"
,
doorbellVal
,
mailBox0Val
,
stateName
[
korg1212
->
cardState
]);
#endif
for
(
retryCount
=
0
;
retryCount
<
MAX_COMMAND_RETRIES
;
retryCount
++
)
{
writel
(
mailBox3Val
,
korg1212
->
mailbox3Ptr
);
writel
(
mailBox2Val
,
korg1212
->
mailbox2Ptr
);
writel
(
mailBox1Val
,
korg1212
->
mailbox1Ptr
);
writel
(
mailBox0Val
,
korg1212
->
mailbox0Ptr
);
writel
(
doorbellVal
,
korg1212
->
outDoorbellPtr
);
// interrupt the card
// --------------------------------------------------------------
// the reboot command will not give an acknowledgement.
// --------------------------------------------------------------
switch
(
doorbellVal
)
{
case
K1212_DB_RebootCard
:
case
K1212_DB_BootFromDSPPage4
:
case
K1212_DB_StartDSPDownload
:
return
K1212_CMDRET_Success
;
default:
break
;
}
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: Card <- 0x%08x 0x%08x [%s]
\n
"
,
doorbellVal
,
mailBox0Val
,
stateName
[
korg1212
->
cardState
]);
#endif
for
(
retryCount
=
0
;
retryCount
<
MAX_COMMAND_RETRIES
;
retryCount
++
)
{
writel
(
mailBox3Val
,
korg1212
->
mailbox3Ptr
);
writel
(
mailBox2Val
,
korg1212
->
mailbox2Ptr
);
writel
(
mailBox1Val
,
korg1212
->
mailbox1Ptr
);
writel
(
mailBox0Val
,
korg1212
->
mailbox0Ptr
);
writel
(
doorbellVal
,
korg1212
->
outDoorbellPtr
);
// interrupt the card
// --------------------------------------------------------------
// the reboot command will not give an acknowledgement.
// --------------------------------------------------------------
if
(
doorbellVal
==
K1212_DB_RebootCard
||
doorbellVal
==
K1212_DB_BootFromDSPPage4
||
doorbellVal
==
K1212_DB_StartDSPDownload
)
{
rc
=
K1212_CMDRET_Success
;
break
;
}
// --------------------------------------------------------------
// See if the card acknowledged the command. Wait a bit, then
// read in the low word of mailbox3. If the MSB is set and the
// low byte is equal to the doorbell value, then it ack'd.
// --------------------------------------------------------------
TickDelay
(
COMMAND_ACK_DELAY
);
mailBox3Lo
=
readl
(
korg1212
->
mailbox3Ptr
);
if
(
mailBox3Lo
&
COMMAND_ACK_MASK
)
{
if
((
mailBox3Lo
&
DOORBELL_VAL_MASK
)
==
(
doorbellVal
&
DOORBELL_VAL_MASK
))
{
korg1212
->
cmdRetryCount
+=
retryCount
;
return
K1212_CMDRET_Success
;
}
// --------------------------------------------------------------
// See if the card acknowledged the command. Wait a bit, then
// read in the low word of mailbox3. If the MSB is set and the
// low byte is equal to the doorbell value, then it ack'd.
// --------------------------------------------------------------
udelay
(
COMMAND_ACK_DELAY
);
mailBox3Lo
=
readl
(
korg1212
->
mailbox3Ptr
);
if
(
mailBox3Lo
&
COMMAND_ACK_MASK
)
{
if
((
mailBox3Lo
&
DOORBELL_VAL_MASK
)
==
(
doorbellVal
&
DOORBELL_VAL_MASK
))
{
#if K1212_DEBUG_LEVEL > 1
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: Card <- Success
\n
"
);
#endif
rc
=
K1212_CMDRET_Success
;
break
;
}
}
korg1212
->
cmdRetryCount
+=
retryCount
;
return
K1212_CMDRET_NoAckFromCard
;
}
else
{
return
K1212_CMDRET_CardUninitialized
;
}
}
korg1212
->
cmdRetryCount
+=
retryCount
;
if
(
retryCount
>=
MAX_COMMAND_RETRIES
)
{
#if K1212_DEBUG_LEVEL > 1
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: Card <- NoAckFromCard
\n
"
);
#endif
rc
=
K1212_CMDRET_NoAckFromCard
;
}
return
rc
;
}
static
void
snd_korg1212_WaitForCardStopAck
(
korg1212_t
*
korg1212
)
{
u
nsigned
long
endtime
=
jiffies
+
20
*
HZ
;
u
32
endtime
=
jiffies
+
2
*
HZ
;
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: WaitForCardStopAck
[%s]
\n
"
,
stateName
[
korg1212
->
cardState
]
);
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: WaitForCardStopAck
.in [%s] %lu %lu
\n
"
,
stateName
[
korg1212
->
cardState
],
jiffies
,
korg1212
->
inIRQ
);
#endif
if
(
korg1212
->
inIRQ
)
return
;
do
{
if
(
readl
(
&
korg1212
->
sharedBufferPtr
->
cardCommand
)
==
0
)
if
(
readl
(
&
korg1212
->
sharedBufferPtr
->
cardCommand
)
==
0
)
{
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: WaitForCardStopAck.out [%s] %lu %lu
\n
"
,
stateName
[
korg1212
->
cardState
],
jiffies
,
korg1212
->
inIRQ
);
#endif
return
;
}
if
(
!
korg1212
->
inIRQ
)
schedule
();
}
while
(
time_before
(
jiffies
,
endtime
));
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: WaitForCardStopAck.out TO [%s] %lu %lu
\n
"
,
stateName
[
korg1212
->
cardState
],
jiffies
,
korg1212
->
inIRQ
);
#endif
writel
(
0
,
&
korg1212
->
sharedBufferPtr
->
cardCommand
);
}
static
void
snd_korg1212_TurnOnIdleMonitor
(
korg1212_t
*
korg1212
)
{
TickD
elay
(
INTERCOMMAND_DELAY
);
ud
elay
(
INTERCOMMAND_DELAY
);
korg1212
->
idleMonitorOn
=
1
;
rc
=
snd_korg1212_Send1212Command
(
korg1212
,
K1212_DB_SelectPlayMode
,
K1212_MODE_MonitorOn
,
0
,
0
,
0
);
...
...
@@ -641,18 +668,22 @@ static void snd_korg1212_setCardState(korg1212_t * korg1212, CardState csState)
static
int
snd_korg1212_OpenCard
(
korg1212_t
*
korg1212
)
{
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: OpenCard [%s]
\n
"
,
stateName
[
korg1212
->
cardState
]
);
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: OpenCard [%s]
%d
\n
"
,
stateName
[
korg1212
->
cardState
],
korg1212
->
opencnt
);
#endif
snd_korg1212_setCardState
(
korg1212
,
K1212_STATE_OPEN
);
if
(
korg1212
->
opencnt
++
==
0
)
snd_korg1212_setCardState
(
korg1212
,
K1212_STATE_OPEN
);
return
1
;
}
static
int
snd_korg1212_CloseCard
(
korg1212_t
*
korg1212
)
{
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: CloseCard [%s]
\n
"
,
stateName
[
korg1212
->
cardState
]
);
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: CloseCard [%s]
%d
\n
"
,
stateName
[
korg1212
->
cardState
],
korg1212
->
opencnt
);
#endif
if
(
--
(
korg1212
->
opencnt
))
return
0
;
if
(
korg1212
->
cardState
==
K1212_STATE_SETUP
)
{
rc
=
snd_korg1212_Send1212Command
(
korg1212
,
K1212_DB_SelectPlayMode
,
K1212_MODE_StopPlay
,
0
,
0
,
0
);
...
...
@@ -676,9 +707,12 @@ static int snd_korg1212_CloseCard(korg1212_t * korg1212)
static
int
snd_korg1212_SetupForPlay
(
korg1212_t
*
korg1212
)
{
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: SetupForPlay [%s]
\n
"
,
stateName
[
korg1212
->
cardState
]
);
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: SetupForPlay [%s]
%d
\n
"
,
stateName
[
korg1212
->
cardState
],
korg1212
->
setcnt
);
#endif
if
(
korg1212
->
setcnt
++
)
return
0
;
snd_korg1212_setCardState
(
korg1212
,
K1212_STATE_SETUP
);
rc
=
snd_korg1212_Send1212Command
(
korg1212
,
K1212_DB_SelectPlayMode
,
K1212_MODE_SetupPlay
,
0
,
0
,
0
);
...
...
@@ -687,17 +721,20 @@ static int snd_korg1212_SetupForPlay(korg1212_t * korg1212)
if
(
rc
)
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: SetupForPlay - RC = %d [%s]
\n
"
,
rc
,
stateName
[
korg1212
->
cardState
]);
#endif
if
(
rc
!=
K1212_CMDRET_Success
)
{
return
0
;
return
1
;
}
return
1
;
return
0
;
}
static
int
snd_korg1212_TriggerPlay
(
korg1212_t
*
korg1212
)
{
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: TriggerPlay [%s]
\n
"
,
stateName
[
korg1212
->
cardState
]
);
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: TriggerPlay [%s]
%d
\n
"
,
stateName
[
korg1212
->
cardState
],
korg1212
->
playcnt
);
#endif
if
(
korg1212
->
playcnt
++
)
return
0
;
snd_korg1212_setCardState
(
korg1212
,
K1212_STATE_PLAYING
);
rc
=
snd_korg1212_Send1212Command
(
korg1212
,
K1212_DB_TriggerPlay
,
0
,
0
,
0
,
0
);
...
...
@@ -706,23 +743,28 @@ static int snd_korg1212_TriggerPlay(korg1212_t * korg1212)
#endif
if
(
rc
!=
K1212_CMDRET_Success
)
{
return
0
;
return
1
;
}
return
1
;
return
0
;
}
static
int
snd_korg1212_StopPlay
(
korg1212_t
*
korg1212
)
{
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: StopPlay [%s]
\n
"
,
stateName
[
korg1212
->
cardState
]
);
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: StopPlay [%s]
%d
\n
"
,
stateName
[
korg1212
->
cardState
],
korg1212
->
playcnt
);
#endif
if
(
--
(
korg1212
->
playcnt
))
return
0
;
korg1212
->
setcnt
=
0
;
if
(
korg1212
->
cardState
!=
K1212_STATE_ERRORSTOP
)
{
writel
(
0xffffffff
,
&
korg1212
->
sharedBufferPtr
->
cardCommand
);
snd_korg1212_WaitForCardStopAck
(
korg1212
);
}
snd_korg1212_setCardState
(
korg1212
,
K1212_STATE_OPEN
);
return
1
;
return
0
;
}
static
void
snd_korg1212_EnableCardInterrupts
(
korg1212_t
*
korg1212
)
...
...
@@ -802,7 +844,7 @@ static int snd_korg1212_SetRate(korg1212_t *korg1212, int rate)
korg1212
->
clkSrcRate
=
parm
;
korg1212
->
clkRate
=
rate
;
TickD
elay
(
INTERCOMMAND_DELAY
);
ud
elay
(
INTERCOMMAND_DELAY
);
rc
=
snd_korg1212_Send1212Command
(
korg1212
,
K1212_DB_SetClockSourceRate
,
ClockSourceSelector
[
korg1212
->
clkSrcRate
],
0
,
0
,
0
);
...
...
@@ -869,7 +911,7 @@ static int snd_korg1212_WriteADCSensitivity(korg1212_t *korg1212)
// flag. Also, clear out mailbox 3, so we don't lockup.
// ----------------------------------------------------------------------------
writel
(
0
,
korg1212
->
mailbox3Ptr
);
TickD
elay
(
LOADSHIFT_DELAY
);
ud
elay
(
LOADSHIFT_DELAY
);
// ----------------------------------------------------------------------------
// determine whether we are running a 48K or 44.1K clock. This info is used
...
...
@@ -910,7 +952,7 @@ static int snd_korg1212_WriteADCSensitivity(korg1212_t *korg1212)
ClearBitInWord
(
&
controlValue
,
SET_SENS_LOADSHIFT_BITPOS
);
ClearBitInWord
(
&
controlValue
,
SET_SENS_DATA_BITPOS
);
writew
(
controlValue
,
korg1212
->
sensRegPtr
);
// load/shift goes low
TickD
elay
(
LOADSHIFT_DELAY
);
ud
elay
(
LOADSHIFT_DELAY
);
for
(
bitPosition
=
15
;
bitPosition
>=
0
;
bitPosition
--
)
{
// for all the bits
if
(
channel
==
0
)
{
...
...
@@ -929,10 +971,10 @@ static int snd_korg1212_WriteADCSensitivity(korg1212_t *korg1212)
ClearBitInWord
(
&
controlValue
,
SET_SENS_CLOCK_BITPOS
);
writew
(
controlValue
,
korg1212
->
sensRegPtr
);
// clock goes low
TickD
elay
(
SENSCLKPULSE_WIDTH
);
ud
elay
(
SENSCLKPULSE_WIDTH
);
SetBitInWord
(
&
controlValue
,
SET_SENS_CLOCK_BITPOS
);
writew
(
controlValue
,
korg1212
->
sensRegPtr
);
// clock goes high
TickD
elay
(
SENSCLKPULSE_WIDTH
);
ud
elay
(
SENSCLKPULSE_WIDTH
);
}
// ----------------------------------------------------------------------------
...
...
@@ -943,19 +985,19 @@ static int snd_korg1212_WriteADCSensitivity(korg1212_t *korg1212)
ClearBitInWord
(
&
controlValue
,
SET_SENS_CLOCK_BITPOS
);
SetBitInWord
(
&
controlValue
,
SET_SENS_LOADSHIFT_BITPOS
);
writew
(
controlValue
,
korg1212
->
sensRegPtr
);
// load shift goes high - clk low
TickD
elay
(
SENSCLKPULSE_WIDTH
);
ud
elay
(
SENSCLKPULSE_WIDTH
);
if
(
clkIs48K
)
SetBitInWord
(
&
controlValue
,
SET_SENS_DATA_BITPOS
);
writew
(
controlValue
,
korg1212
->
sensRegPtr
);
// set/clear data bit
TickD
elay
(
ONE_RTC_TICK
);
ud
elay
(
ONE_RTC_TICK
);
SetBitInWord
(
&
controlValue
,
SET_SENS_CLOCK_BITPOS
);
writew
(
controlValue
,
korg1212
->
sensRegPtr
);
// clock goes high
TickD
elay
(
SENSCLKPULSE_WIDTH
);
ud
elay
(
SENSCLKPULSE_WIDTH
);
ClearBitInWord
(
&
controlValue
,
SET_SENS_CLOCK_BITPOS
);
writew
(
controlValue
,
korg1212
->
sensRegPtr
);
// clock goes low
TickD
elay
(
SENSCLKPULSE_WIDTH
);
ud
elay
(
SENSCLKPULSE_WIDTH
);
}
// ----------------------------------------------------------------------------
...
...
@@ -963,7 +1005,7 @@ static int snd_korg1212_WriteADCSensitivity(korg1212_t *korg1212)
// Also, if the card was in monitor mode, restore it.
// ----------------------------------------------------------------------------
for
(
count
=
0
;
count
<
10
;
count
++
)
TickD
elay
(
SENSCLKPULSE_WIDTH
);
ud
elay
(
SENSCLKPULSE_WIDTH
);
if
(
monModeSet
)
{
rc
=
snd_korg1212_Send1212Command
(
korg1212
,
K1212_DB_SelectPlayMode
,
...
...
@@ -1011,7 +1053,7 @@ static void snd_korg1212_OnDSPDownloadComplete(korg1212_t *korg1212)
if
(
rc
)
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: Configure Buffer Memory - RC = %d [%s]
\n
"
,
rc
,
stateName
[
korg1212
->
cardState
]);
#endif
TickD
elay
(
INTERCOMMAND_DELAY
);
ud
elay
(
INTERCOMMAND_DELAY
);
rc
=
snd_korg1212_Send1212Command
(
korg1212
,
K1212_DB_ConfigureMiscMemory
,
...
...
@@ -1029,7 +1071,7 @@ static void snd_korg1212_OnDSPDownloadComplete(korg1212_t *korg1212)
// --------------------------------------------------------------------------------
// Initialize the routing and volume tables, then update the card's state.
// --------------------------------------------------------------------------------
TickD
elay
(
INTERCOMMAND_DELAY
);
ud
elay
(
INTERCOMMAND_DELAY
);
for
(
channel
=
0
;
channel
<
kAudioChannels
;
channel
++
)
{
korg1212
->
sharedBufferPtr
->
volumeData
[
channel
]
=
k1212MaxVolume
;
...
...
@@ -1039,7 +1081,7 @@ static void snd_korg1212_OnDSPDownloadComplete(korg1212_t *korg1212)
snd_korg1212_WriteADCSensitivity
(
korg1212
);
TickD
elay
(
INTERCOMMAND_DELAY
);
ud
elay
(
INTERCOMMAND_DELAY
);
rc
=
snd_korg1212_Send1212Command
(
korg1212
,
K1212_DB_SetClockSourceRate
,
ClockSourceSelector
[
korg1212
->
clkSrcRate
],
0
,
0
,
0
);
...
...
@@ -1056,7 +1098,6 @@ static void snd_korg1212_OnDSPDownloadComplete(korg1212_t *korg1212)
wake_up_interruptible
(
&
korg1212
->
wait
);
}
static
void
snd_korg1212_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
u32
doorbellValue
;
...
...
@@ -1092,10 +1133,11 @@ static void snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs *regs)
// an error occurred - stop the card
// ------------------------------------------------------------------------
case
K1212_ISRCODE_DMAERROR
:
#if K1212_DEBUG_LEVEL >
0
#if K1212_DEBUG_LEVEL >
1
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: IRQ DMAE count - %ld, %x, [%s].
\n
"
,
korg1212
->
irqcount
,
doorbellValue
,
stateName
[
korg1212
->
cardState
]);
#endif
writel
(
0
,
&
korg1212
->
sharedBufferPtr
->
cardCommand
);
snd_korg1212_setCardState
(
korg1212
,
K1212_STATE_ERRORSTOP
);
break
;
// ------------------------------------------------------------------------
...
...
@@ -1103,14 +1145,14 @@ static void snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs *regs)
// the semaphore in case someone is waiting for this.
// ------------------------------------------------------------------------
case
K1212_ISRCODE_CARDSTOPPED
:
#if K1212_DEBUG_LEVEL >
0
#if K1212_DEBUG_LEVEL >
1
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: IRQ CSTP count - %ld, %x, [%s].
\n
"
,
korg1212
->
irqcount
,
doorbellValue
,
stateName
[
korg1212
->
cardState
]);
#endif
writel
(
0
,
&
korg1212
->
sharedBufferPtr
->
cardCommand
);
break
;
default:
#if K1212_DEBUG_LEVEL >
1
#if K1212_DEBUG_LEVEL >
3
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: IRQ DFLT count - %ld, %x, cpos=%d [%s].
\n
"
,
korg1212
->
irqcount
,
doorbellValue
,
korg1212
->
currentBuffer
,
stateName
[
korg1212
->
cardState
]);
#endif
...
...
@@ -1170,7 +1212,7 @@ static int snd_korg1212_downloadDSPCode(korg1212_t *korg1212)
static
snd_pcm_hardware_t
snd_korg1212_playback_info
=
{
.
info
=
(
SNDRV_PCM_INFO_MMAP
|
.
info
=
(
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_MMAP_VALID
|
SNDRV_PCM_INFO_INTERLEAVED
),
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
,
...
...
@@ -1178,11 +1220,11 @@ static snd_pcm_hardware_t snd_korg1212_playback_info =
SNDRV_PCM_RATE_48000
),
.
rate_min
=
44100
,
.
rate_max
=
48000
,
.
channels_min
=
K1212_CHANNELS
,
.
channels_max
=
K1212_CHANNELS
,
.
buffer_bytes_max
=
K1212_BUF_SIZE
,
.
period_bytes_min
=
K1212_
PERIOD_BYTES
,
.
period_bytes_max
=
K1212_
PERIOD_BYTES
,
.
channels_min
=
K1212_
MIN_
CHANNELS
,
.
channels_max
=
K1212_
MAX_
CHANNELS
,
.
buffer_bytes_max
=
K1212_
MAX_
BUF_SIZE
,
.
period_bytes_min
=
K1212_
MIN_CHANNELS
*
2
*
kPlayBufferFrames
,
.
period_bytes_max
=
K1212_
MAX_CHANNELS
*
2
*
kPlayBufferFrames
,
.
periods_min
=
K1212_PERIODS
,
.
periods_max
=
K1212_PERIODS
,
.
fifo_size
=
0
,
...
...
@@ -1190,7 +1232,7 @@ static snd_pcm_hardware_t snd_korg1212_playback_info =
static
snd_pcm_hardware_t
snd_korg1212_capture_info
=
{
.
info
=
(
SNDRV_PCM_INFO_MMAP
|
.
info
=
(
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_MMAP_VALID
|
SNDRV_PCM_INFO_INTERLEAVED
),
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
,
...
...
@@ -1198,36 +1240,116 @@ static snd_pcm_hardware_t snd_korg1212_capture_info =
SNDRV_PCM_RATE_48000
),
.
rate_min
=
44100
,
.
rate_max
=
48000
,
.
channels_min
=
K1212_CHANNELS
,
.
channels_max
=
K1212_CHANNELS
,
.
buffer_bytes_max
=
K1212_BUF_SIZE
,
.
period_bytes_min
=
K1212_
PERIOD_BYTES
,
.
period_bytes_max
=
K1212_
PERIOD_BYTES
,
.
channels_min
=
K1212_
MIN_
CHANNELS
,
.
channels_max
=
K1212_
MAX_
CHANNELS
,
.
buffer_bytes_max
=
K1212_
MAX_
BUF_SIZE
,
.
period_bytes_min
=
K1212_
MIN_CHANNELS
*
2
*
kPlayBufferFrames
,
.
period_bytes_max
=
K1212_
MAX_CHANNELS
*
2
*
kPlayBufferFrames
,
.
periods_min
=
K1212_PERIODS
,
.
periods_max
=
K1212_PERIODS
,
.
fifo_size
=
0
,
};
static
void
snd_korg1212_free_pcm
(
snd_pcm_t
*
pcm
)
static
int
snd_korg1212_silence
(
korg1212_t
*
korg1212
,
int
pos
,
int
count
,
int
offset
,
int
size
)
{
korg1212_t
*
korg1212
=
(
korg1212_t
*
)
pcm
->
private_data
;
KorgAudioFrame
*
dst
=
korg1212
->
playDataBufsPtr
[
0
].
bufferData
+
pos
;
int
i
;
#if K1212_DEBUG_LEVEL > 2
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_silence pos=%d offset=%d size=%d count=%d
\n
"
,
pos
,
offset
,
size
,
count
);
#endif
snd_assert
(
pos
+
count
<=
K1212_MAX_SAMPLES
,
return
-
EINVAL
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_free_pcm [%s]
\n
"
,
stateName
[
korg1212
->
cardState
]);
if
(
(
void
*
)
dst
<
(
void
*
)
korg1212
->
playDataBufsPtr
||
(
void
*
)
dst
>
(
void
*
)
korg1212
->
playDataBufsPtr
[
8
].
bufferData
)
{
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_silence KERNEL EFAULT dst=%p iter=%d
\n
"
,
dst
,
i
);
return
-
EFAULT
;
}
#endif
memset
((
void
*
)
dst
+
offset
,
0
,
size
);
dst
++
;
}
return
0
;
}
static
int
snd_korg1212_copy_to
(
korg1212_t
*
korg1212
,
void
*
dst
,
int
pos
,
int
count
,
int
offset
,
int
size
)
{
KorgAudioFrame
*
src
=
korg1212
->
recordDataBufsPtr
[
0
].
bufferData
+
pos
;
int
i
,
rc
;
#if K1212_DEBUG_LEVEL > 2
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_copy_to pos=%d offset=%d size=%d
\n
"
,
pos
,
offset
,
size
);
#endif
snd_assert
(
pos
+
count
<=
K1212_MAX_SAMPLES
,
return
-
EINVAL
);
korg1212
->
pcm16
=
NULL
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
#if K1212_DEBUG_LEVEL > 0
if
(
(
void
*
)
src
<
(
void
*
)
korg1212
->
recordDataBufsPtr
||
(
void
*
)
src
>
(
void
*
)
korg1212
->
recordDataBufsPtr
[
8
].
bufferData
)
{
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_copy_to KERNEL EFAULT, src=%p dst=%p iter=%d
\n
"
,
src
,
dst
,
i
);
return
-
EFAULT
;
}
#endif
rc
=
copy_to_user
((
void
*
)
dst
+
offset
,
src
,
size
);
if
(
rc
)
{
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_copy_to USER EFAULT src=%p dst=%p iter=%d
\n
"
,
src
,
dst
,
i
);
#endif
return
-
EFAULT
;
}
src
++
;
dst
+=
size
;
}
return
0
;
}
static
unsigned
int
period_bytes
[]
=
{
K1212_PERIOD_BYTES
};
static
int
snd_korg1212_copy_from
(
korg1212_t
*
korg1212
,
void
*
src
,
int
pos
,
int
count
,
int
offset
,
int
size
)
{
KorgAudioFrame
*
dst
=
korg1212
->
playDataBufsPtr
[
0
].
bufferData
+
pos
;
int
i
,
rc
;
#define PERIOD_BYTES sizeof(period_bytes) / sizeof(period_bytes[0])
#if K1212_DEBUG_LEVEL > 2
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_copy_from pos=%d offset=%d size=%d count=%d
\n
"
,
pos
,
offset
,
size
,
count
);
#endif
static
snd_pcm_hw_constraint_list_t
hw_constraints_period_bytes
=
{
.
count
=
PERIOD_BYTES
,
.
list
=
period_bytes
,
.
mask
=
0
};
snd_assert
(
pos
+
count
<=
K1212_MAX_SAMPLES
,
return
-
EINVAL
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
#if K1212_DEBUG_LEVEL > 0
if
(
(
void
*
)
dst
<
(
void
*
)
korg1212
->
playDataBufsPtr
||
(
void
*
)
dst
>
(
void
*
)
korg1212
->
playDataBufsPtr
[
8
].
bufferData
)
{
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_copy_from KERNEL EFAULT, src=%p dst=%p iter=%d
\n
"
,
src
,
dst
,
i
);
return
-
EFAULT
;
}
#endif
rc
=
copy_from_user
((
void
*
)
dst
+
offset
,
src
,
size
);
if
(
rc
)
{
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_copy_from USER EFAULT src=%p dst=%p iter=%d
\n
"
,
src
,
dst
,
i
);
#endif
return
-
EFAULT
;
}
dst
++
;
src
+=
size
;
}
return
0
;
}
static
void
snd_korg1212_free_pcm
(
snd_pcm_t
*
pcm
)
{
korg1212_t
*
korg1212
=
(
korg1212_t
*
)
pcm
->
private_data
;
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_free_pcm [%s]
\n
"
,
stateName
[
korg1212
->
cardState
]);
#endif
korg1212
->
pcm
=
NULL
;
}
static
int
snd_korg1212_playback_open
(
snd_pcm_substream_t
*
substream
)
{
...
...
@@ -1239,11 +1361,11 @@ static int snd_korg1212_playback_open(snd_pcm_substream_t *substream)
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_playback_open [%s]
\n
"
,
stateName
[
korg1212
->
cardState
]);
#endif
s
pin_lock_irqsave
(
&
korg1212
->
lock
,
flags
);
s
nd_pcm_set_sync
(
substream
);
// ???
s
nd_korg1212_OpenCard
(
korg1212
);
s
pin_lock_irqsave
(
&
korg1212
->
lock
,
flags
);
snd_pcm_set_sync
(
substream
);
// ???
snd_korg1212_OpenCard
(
korg1212
);
runtime
->
hw
=
snd_korg1212_playback_info
;
runtime
->
dma_area
=
(
char
*
)
korg1212
->
playDataBufsPtr
;
...
...
@@ -1251,14 +1373,15 @@ static int snd_korg1212_playback_open(snd_pcm_substream_t *substream)
korg1212
->
playback_substream
=
substream
;
korg1212
->
periodsize
=
K1212_PERIODS
;
korg1212
->
channels
=
K1212_CHANNELS
;
spin_unlock_irqrestore
(
&
korg1212
->
lock
,
flags
);
snd_pcm_hw_constraint_minmax
(
runtime
,
SNDRV_PCM_HW_PARAM_BUFFER_BYTES
,
K1212_BUF_SIZE
,
K1212_BUF_SIZE
);
snd_pcm_hw_constraint_list
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_PERIOD_BYTES
,
&
hw_constraints_period_bytes
);
snd_pcm_hw_constraint_minmax
(
runtime
,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE
,
kPlayBufferFrames
,
kPlayBufferFrames
);
return
0
;
}
static
int
snd_korg1212_capture_open
(
snd_pcm_substream_t
*
substream
)
{
unsigned
long
flags
;
...
...
@@ -1269,11 +1392,11 @@ static int snd_korg1212_capture_open(snd_pcm_substream_t *substream)
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_capture_open [%s]
\n
"
,
stateName
[
korg1212
->
cardState
]);
#endif
s
pin_lock_irqsave
(
&
korg1212
->
lock
,
flags
);
s
nd_pcm_set_sync
(
substream
);
// ???
s
nd_korg1212_OpenCard
(
korg1212
);
s
pin_lock_irqsave
(
&
korg1212
->
lock
,
flags
);
snd_pcm_set_sync
(
substream
);
// ???
snd_korg1212_OpenCard
(
korg1212
);
runtime
->
hw
=
snd_korg1212_capture_info
;
runtime
->
dma_area
=
(
char
*
)
korg1212
->
recordDataBufsPtr
;
...
...
@@ -1281,11 +1404,11 @@ static int snd_korg1212_capture_open(snd_pcm_substream_t *substream)
korg1212
->
capture_substream
=
substream
;
korg1212
->
periodsize
=
K1212_PERIODS
;
korg1212
->
channels
=
K1212_CHANNELS
;
spin_unlock_irqrestore
(
&
korg1212
->
lock
,
flags
);
snd_pcm_hw_constraint_minmax
(
runtime
,
SNDRV_PCM_HW_PARAM_BUFFER_BYTES
,
K1212_BUF_SIZE
,
K1212_BUF_SIZE
);
snd_pcm_hw_constraint_list
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_PERIOD_BYTES
,
&
hw_constraints_period_bytes
);
snd_pcm_hw_constraint_minmax
(
runtime
,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE
,
kPlayBufferFrames
,
kPlayBufferFrames
);
return
0
;
}
...
...
@@ -1298,12 +1421,14 @@ static int snd_korg1212_playback_close(snd_pcm_substream_t *substream)
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_playback_close [%s]
\n
"
,
stateName
[
korg1212
->
cardState
]);
#endif
snd_korg1212_silence
(
korg1212
,
0
,
K1212_MAX_SAMPLES
,
0
,
korg1212
->
channels
*
2
);
spin_lock_irqsave
(
&
korg1212
->
lock
,
flags
);
korg1212
->
playback_substream
=
NULL
;
korg1212
->
periodsize
=
0
;
snd_korg1212_CloseCard
(
korg1212
);
snd_korg1212_CloseCard
(
korg1212
);
spin_unlock_irqrestore
(
&
korg1212
->
lock
,
flags
);
return
0
;
...
...
@@ -1323,43 +1448,28 @@ static int snd_korg1212_capture_close(snd_pcm_substream_t *substream)
korg1212
->
capture_substream
=
NULL
;
korg1212
->
periodsize
=
0
;
snd_korg1212_CloseCard
(
korg1212
);
snd_korg1212_CloseCard
(
korg1212
);
spin_unlock_irqrestore
(
&
korg1212
->
lock
,
flags
);
return
0
;
}
static
int
snd_korg1212_channel_info
(
snd_pcm_substream_t
*
substream
,
snd_pcm_channel_info_t
*
info
)
{
int
chn
=
info
->
channel
;
// snd_assert(info->channel < kAudioChannels + 1, return -EINVAL);
info
->
offset
=
0
;
// if (chn < k16BitChannels) {
info
->
first
=
chn
*
16
;
// } else {
// info->first = k16BitChannels * 16 + (chn - k16BitChannels - 1) * 32;
// }
info
->
step
=
sizeof
(
KorgAudioFrame
)
*
8
;
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_channel_info %d:, offset=%ld, first=%d, step=%d
\n
"
,
chn
,
info
->
offset
,
info
->
first
,
info
->
step
);
#endif
return
0
;
}
static
int
snd_korg1212_ioctl
(
snd_pcm_substream_t
*
substream
,
unsigned
int
cmd
,
void
*
arg
)
{
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_ioctl: cmd=%d
\n
"
,
cmd
);
#endif
if
(
cmd
==
SNDRV_PCM_IOCTL1_CHANNEL_INFO
)
{
snd_pcm_channel_info_t
*
info
=
arg
;
return
snd_korg1212_channel_info
(
substream
,
info
);
info
->
offset
=
0
;
info
->
first
=
info
->
channel
*
16
;
info
->
step
=
256
;
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: channel_info %d:, offset=%ld, first=%d, step=%d
\n
"
,
info
->
channel
,
info
->
offset
,
info
->
first
,
info
->
step
);
#endif
return
0
;
}
return
snd_pcm_lib_ioctl
(
substream
,
cmd
,
arg
);
...
...
@@ -1381,13 +1491,14 @@ static int snd_korg1212_hw_params(snd_pcm_substream_t *substream,
spin_unlock_irqrestore
(
&
korg1212
->
lock
,
flags
);
return
err
;
}
/*
if (params_format(params) != SNDRV_PCM_FORMAT_S16_LE) {
spin_unlock_irqrestore(&korg1212->lock, flags);
return -EINVAL;
}
korg1212
->
periodsize
=
K1212_BLOCK_SIZE
;
*/
korg1212
->
channels
=
params_channels
(
params
);
korg1212
->
periodsize
=
K1212_PERIOD_BYTES
;
spin_unlock_irqrestore
(
&
korg1212
->
lock
,
flags
);
...
...
@@ -1398,6 +1509,7 @@ static int snd_korg1212_prepare(snd_pcm_substream_t *substream)
{
korg1212_t
*
korg1212
=
_snd_pcm_substream_chip
(
substream
);
unsigned
long
flags
;
int
rc
;
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_prepare [%s]
\n
"
,
stateName
[
korg1212
->
cardState
]);
...
...
@@ -1405,18 +1517,19 @@ static int snd_korg1212_prepare(snd_pcm_substream_t *substream)
spin_lock_irqsave
(
&
korg1212
->
lock
,
flags
);
snd_korg1212_SetupForPlay
(
korg1212
);
korg1212
->
currentBuffer
=
-
1
;
rc
=
snd_korg1212_SetupForPlay
(
korg1212
);
korg1212
->
currentBuffer
=
0
;
spin_unlock_irqrestore
(
&
korg1212
->
lock
,
flags
);
return
0
;
return
rc
?
-
EINVAL
:
0
;
}
static
int
snd_korg1212_trigger
(
snd_pcm_substream_t
*
substream
,
int
cmd
)
{
korg1212_t
*
korg1212
=
_snd_pcm_substream_chip
(
substream
);
int
rc
;
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_trigger [%s] cmd=%d
\n
"
,
stateName
[
korg1212
->
cardState
],
cmd
);
...
...
@@ -1424,72 +1537,82 @@ static int snd_korg1212_trigger(snd_pcm_substream_t *substream,
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
korg1212
->
running
=
1
;
snd_korg1212_TriggerPlay
(
korg1212
);
/*
if (korg1212->running) {
#if K1212_DEBUG_LEVEL > 1
K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_trigger: Already running?\n");
#endif
break;
}
*/
korg1212
->
running
++
;
rc
=
snd_korg1212_TriggerPlay
(
korg1212
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
korg1212
->
running
=
0
;
snd_korg1212_StopPlay
(
korg1212
);
/*
if (!korg1212->running) {
#if K1212_DEBUG_LEVEL > 1
K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_trigger: Already stopped?\n");
#endif
break;
}
*/
korg1212
->
running
--
;
rc
=
snd_korg1212_StopPlay
(
korg1212
);
break
;
default:
return
-
EINVAL
;
rc
=
1
;
break
;
}
return
0
;
return
rc
?
-
EINVAL
:
0
;
}
static
snd_pcm_uframes_t
snd_korg1212_pointer
(
snd_pcm_substream_t
*
substream
)
static
snd_pcm_uframes_t
snd_korg1212_p
layback_p
ointer
(
snd_pcm_substream_t
*
substream
)
{
korg1212_t
*
korg1212
=
_snd_pcm_substream_chip
(
substream
);
snd_pcm_uframes_t
pos
;
if
(
korg1212
->
currentBuffer
<
0
)
return
0
;
pos
=
korg1212
->
currentBuffer
*
kPlayBufferFrames
;
#if K1212_DEBUG_LEVEL > 1
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_pointer [%s] %ld
\n
"
,
stateName
[
korg1212
->
cardState
],
pos
);
#if K1212_DEBUG_LEVEL > 2
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_playback_pointer [%s] %ld
\n
"
,
stateName
[
korg1212
->
cardState
],
pos
);
#endif
return
pos
;
}
static
int
snd_korg1212_playback_copy
(
snd_pcm_substream_t
*
substream
,
int
channel
,
/* not used (interleaved data) */
snd_pcm_uframes_t
pos
,
void
*
src
,
snd_pcm_uframes_t
count
)
static
snd_pcm_uframes_t
snd_korg1212_capture_pointer
(
snd_pcm_substream_t
*
substream
)
{
korg1212_t
*
korg1212
=
_snd_pcm_substream_chip
(
substream
);
KorgAudioFrame
*
dst
=
korg1212
->
playDataBufsPtr
[
0
].
bufferData
+
pos
;
snd_pcm_uframes_t
pos
;
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_playback_copy [%s] %ld %ld
\n
"
,
stateName
[
korg1212
->
cardState
],
pos
,
count
);
pos
=
korg1212
->
currentBuffer
*
kPlayBufferFrames
;
#if K1212_DEBUG_LEVEL > 2
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_capture_pointer [%s] %ld
\n
"
,
stateName
[
korg1212
->
cardState
],
pos
);
#endif
snd_assert
(
pos
+
count
<=
K1212_MAX_SAMPLES
,
return
-
EINVAL
);
return
copy_from_user
(
dst
,
src
,
count
*
K1212_FRAME_SIZE
)
?
-
EFAULT
:
0
;
return
pos
;
}
static
int
snd_korg1212_
capture
_copy
(
snd_pcm_substream_t
*
substream
,
static
int
snd_korg1212_
playback
_copy
(
snd_pcm_substream_t
*
substream
,
int
channel
,
/* not used (interleaved data) */
snd_pcm_uframes_t
pos
,
void
*
dst
,
void
*
src
,
snd_pcm_uframes_t
count
)
{
korg1212_t
*
korg1212
=
_snd_pcm_substream_chip
(
substream
);
KorgAudioFrame
*
src
=
korg1212
->
recordDataBufsPtr
[
0
].
bufferData
+
pos
;
#if K1212_DEBUG_LEVEL >
0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_
capture
_copy [%s] %ld %ld
\n
"
,
stateName
[
korg1212
->
cardState
],
pos
,
count
);
#if K1212_DEBUG_LEVEL >
2
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_
playback
_copy [%s] %ld %ld
\n
"
,
stateName
[
korg1212
->
cardState
],
pos
,
count
);
#endif
return
snd_korg1212_copy_from
(
korg1212
,
src
,
pos
,
count
,
0
,
korg1212
->
channels
*
2
);
snd_assert
(
pos
+
count
<=
K1212_MAX_SAMPLES
,
return
-
EINVAL
);
return
copy_to_user
(
dst
,
src
,
count
*
K1212_FRAME_SIZE
)
?
-
EFAULT
:
0
;
}
static
int
snd_korg1212_playback_silence
(
snd_pcm_substream_t
*
substream
,
...
...
@@ -1498,17 +1621,27 @@ static int snd_korg1212_playback_silence(snd_pcm_substream_t *substream,
snd_pcm_uframes_t
count
)
{
korg1212_t
*
korg1212
=
_snd_pcm_substream_chip
(
substream
);
KorgAudioFrame
*
dst
=
korg1212
->
playDataBufsPtr
[
0
].
bufferData
+
pos
;
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_playback_silence [%s]
\n
"
,
stateName
[
korg1212
->
cardState
]);
#endif
snd_assert
(
pos
+
count
<=
K1212_MAX_SAMPLES
,
return
-
EINVAL
);
return
snd_korg1212_silence
(
korg1212
,
pos
,
count
,
0
,
korg1212
->
channels
*
2
);
}
memset
(
dst
,
0
,
count
*
K1212_FRAME_SIZE
);
static
int
snd_korg1212_capture_copy
(
snd_pcm_substream_t
*
substream
,
int
channel
,
/* not used (interleaved data) */
snd_pcm_uframes_t
pos
,
void
*
dst
,
snd_pcm_uframes_t
count
)
{
korg1212_t
*
korg1212
=
_snd_pcm_substream_chip
(
substream
);
return
0
;
#if K1212_DEBUG_LEVEL > 2
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: snd_korg1212_capture_copy [%s] %ld %ld
\n
"
,
stateName
[
korg1212
->
cardState
],
pos
,
count
);
#endif
return
snd_korg1212_copy_to
(
korg1212
,
dst
,
pos
,
count
,
0
,
korg1212
->
channels
*
2
);
}
static
snd_pcm_ops_t
snd_korg1212_playback_ops
=
{
...
...
@@ -1518,7 +1651,7 @@ static snd_pcm_ops_t snd_korg1212_playback_ops = {
.
hw_params
=
snd_korg1212_hw_params
,
.
prepare
=
snd_korg1212_prepare
,
.
trigger
=
snd_korg1212_trigger
,
.
pointer
=
snd_korg1212_pointer
,
.
pointer
=
snd_korg1212_p
layback_p
ointer
,
.
copy
=
snd_korg1212_playback_copy
,
.
silence
=
snd_korg1212_playback_silence
,
};
...
...
@@ -1530,7 +1663,7 @@ static snd_pcm_ops_t snd_korg1212_capture_ops = {
.
hw_params
=
snd_korg1212_hw_params
,
.
prepare
=
snd_korg1212_prepare
,
.
trigger
=
snd_korg1212_trigger
,
.
pointer
=
snd_korg1212_pointer
,
.
pointer
=
snd_korg1212_
capture_
pointer
,
.
copy
=
snd_korg1212_capture_copy
,
};
...
...
@@ -1555,7 +1688,7 @@ static int snd_korg1212_control_phase_get(snd_kcontrol_t *kcontrol, snd_ctl_elem
u
->
value
.
integer
.
value
[
0
]
=
korg1212
->
volumePhase
[
i
];
if
(
i
>=
8
)
if
(
i
>=
8
)
u
->
value
.
integer
.
value
[
1
]
=
korg1212
->
volumePhase
[
i
+
1
];
spin_unlock_irqrestore
(
&
korg1212
->
lock
,
flags
);
...
...
@@ -1703,13 +1836,13 @@ static int snd_korg1212_control_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem
i
=
kcontrol
->
private_value
;
if
(
u
->
value
.
enumerated
.
item
[
0
]
!=
(
unsigned
int
)
korg1212
->
sharedBufferPtr
->
volumeData
[
i
])
{
if
(
u
->
value
.
enumerated
.
item
[
0
]
!=
(
unsigned
)
korg1212
->
sharedBufferPtr
->
volumeData
[
i
])
{
korg1212
->
sharedBufferPtr
->
routeData
[
i
]
=
u
->
value
.
enumerated
.
item
[
0
];
change
=
1
;
}
if
(
i
>=
8
)
{
if
(
u
->
value
.
enumerated
.
item
[
1
]
!=
(
unsigned
int
)
korg1212
->
sharedBufferPtr
->
volumeData
[
i
+
1
])
{
if
(
u
->
value
.
enumerated
.
item
[
1
]
!=
(
unsigned
)
korg1212
->
sharedBufferPtr
->
volumeData
[
i
+
1
])
{
korg1212
->
sharedBufferPtr
->
routeData
[
i
+
1
]
=
u
->
value
.
enumerated
.
item
[
1
];
change
=
1
;
}
...
...
@@ -1720,7 +1853,7 @@ static int snd_korg1212_control_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem
return
change
;
}
static
int
snd_korg1212_control_
analog_
info
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_info_t
*
uinfo
)
static
int
snd_korg1212_control_info
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_info_t
*
uinfo
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
uinfo
->
count
=
2
;
...
...
@@ -1729,7 +1862,7 @@ static int snd_korg1212_control_analog_info(snd_kcontrol_t *kcontrol, snd_ctl_el
return
0
;
}
static
int
snd_korg1212_control_
analog_
get
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
u
)
static
int
snd_korg1212_control_get
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
u
)
{
korg1212_t
*
korg1212
=
_snd_kcontrol_chip
(
kcontrol
);
unsigned
long
flags
;
...
...
@@ -1744,7 +1877,7 @@ static int snd_korg1212_control_analog_get(snd_kcontrol_t *kcontrol, snd_ctl_ele
return
0
;
}
static
int
snd_korg1212_control_
analog_
put
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
u
)
static
int
snd_korg1212_control_put
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
u
)
{
korg1212_t
*
korg1212
=
_snd_kcontrol_chip
(
kcontrol
);
unsigned
long
flags
;
...
...
@@ -1855,9 +1988,9 @@ static snd_kcontrol_new_t snd_korg1212_controls[] = {
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
|
SNDRV_CTL_ELEM_ACCESS_WRITE
,
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"ADC Attenuation"
,
.
info
=
snd_korg1212_control_
analog_
info
,
.
get
=
snd_korg1212_control_
analog_
get
,
.
put
=
snd_korg1212_control_
analog_
put
,
.
info
=
snd_korg1212_control_info
,
.
get
=
snd_korg1212_control_get
,
.
put
=
snd_korg1212_control_put
,
}
};
...
...
@@ -1875,7 +2008,7 @@ static void snd_korg1212_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *b
snd_iprintf
(
buffer
,
korg1212
->
card
->
longname
);
snd_iprintf
(
buffer
,
" (index #%d)
\n
"
,
korg1212
->
card
->
number
+
1
);
snd_iprintf
(
buffer
,
"
\n
General settings
\n
"
);
snd_iprintf
(
buffer
,
" period size: %d bytes
\n
"
,
K1212_
BLOCK_SIZE
);
snd_iprintf
(
buffer
,
" period size: %d bytes
\n
"
,
K1212_
PERIOD_BYTES
);
snd_iprintf
(
buffer
,
" clock mode: %s
\n
"
,
clockSourceName
[
korg1212
->
clkSrcRate
]
);
snd_iprintf
(
buffer
,
" left ADC Sens: %d
\n
"
,
korg1212
->
leftADCInSens
);
snd_iprintf
(
buffer
,
" right ADC Sens: %d
\n
"
,
korg1212
->
rightADCInSens
);
...
...
@@ -1901,19 +2034,132 @@ static void __devinit snd_korg1212_proc_init(korg1212_t *korg1212)
snd_info_set_text_ops
(
entry
,
korg1212
,
snd_korg1212_proc_read
);
}
static
int
__devinit
snd_korg1212_create
(
korg1212_t
*
korg1212
)
static
int
snd_korg1212_free
(
korg1212_t
*
korg1212
)
{
snd_korg1212_TurnOffIdleMonitor
(
korg1212
);
if
(
korg1212
->
irq
>=
0
)
{
synchronize_irq
(
korg1212
->
irq
);
snd_korg1212_DisableCardInterrupts
(
korg1212
);
free_irq
(
korg1212
->
irq
,
(
void
*
)
korg1212
);
korg1212
->
irq
=
-
1
;
}
if
(
korg1212
->
iobase
!=
0
)
{
iounmap
((
void
*
)
korg1212
->
iobase
);
korg1212
->
iobase
=
0
;
}
if
(
korg1212
->
res_iomem
!=
NULL
)
{
release_resource
(
korg1212
->
res_iomem
);
kfree_nocheck
(
korg1212
->
res_iomem
);
korg1212
->
res_iomem
=
NULL
;
}
if
(
korg1212
->
res_ioport
!=
NULL
)
{
release_resource
(
korg1212
->
res_ioport
);
kfree_nocheck
(
korg1212
->
res_ioport
);
korg1212
->
res_ioport
=
NULL
;
}
if
(
korg1212
->
res_iomem2
!=
NULL
)
{
release_resource
(
korg1212
->
res_iomem2
);
kfree_nocheck
(
korg1212
->
res_iomem2
);
korg1212
->
res_iomem2
=
NULL
;
}
// ----------------------------------------------------
// free up memory resources used for the DSP download.
// ----------------------------------------------------
if
(
korg1212
->
dspMemPtr
)
{
snd_free_pci_pages
(
korg1212
->
pci
,
korg1212
->
dspCodeSize
,
korg1212
->
dspMemPtr
,
(
dma_addr_t
)
korg1212
->
dspMemPhy
);
korg1212
->
dspMemPhy
=
0
;
korg1212
->
dspMemPtr
=
0
;
korg1212
->
dspCodeSize
=
0
;
}
#ifndef K1212_LARGEALLOC
// ------------------------------------------------------
// free up memory resources used for the Play/Rec Buffers
// ------------------------------------------------------
if
(
korg1212
->
playDataBufsPtr
)
{
snd_free_pci_pages
(
korg1212
->
pci
,
korg1212
->
DataBufsSize
,
korg1212
->
playDataBufsPtr
,
(
dma_addr_t
)
korg1212
->
PlayDataPhy
);
korg1212
->
PlayDataPhy
=
0
;
korg1212
->
playDataBufsPtr
=
NULL
;
}
if
(
korg1212
->
recordDataBufsPtr
)
{
snd_free_pci_pages
(
korg1212
->
pci
,
korg1212
->
DataBufsSize
,
korg1212
->
recordDataBufsPtr
,
(
dma_addr_t
)
korg1212
->
RecDataPhy
);
korg1212
->
RecDataPhy
=
0
;
korg1212
->
recordDataBufsPtr
=
NULL
;
}
#endif
// ----------------------------------------------------
// free up memory resources used for the Shared Buffers
// ----------------------------------------------------
if
(
korg1212
->
sharedBufferPtr
)
{
snd_free_pci_pages
(
korg1212
->
pci
,
(
u32
)
sizeof
(
KorgSharedBuffer
),
korg1212
->
sharedBufferPtr
,
(
dma_addr_t
)
korg1212
->
sharedBufferPhy
);
korg1212
->
sharedBufferPhy
=
0
;
korg1212
->
sharedBufferPtr
=
NULL
;
}
snd_magic_kfree
(
korg1212
);
return
0
;
}
static
int
snd_korg1212_dev_free
(
snd_device_t
*
device
)
{
korg1212_t
*
korg1212
=
snd_magic_cast
(
korg1212_t
,
device
->
device_data
,
return
-
ENXIO
);
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: Freeing device
\n
"
);
#endif
return
snd_korg1212_free
(
korg1212
);
}
static
int
__devinit
snd_korg1212_create
(
snd_card_t
*
card
,
struct
pci_dev
*
pci
,
korg1212_t
**
rchip
)
{
struct
pci_dev
*
pci
=
korg1212
->
pci
;
int
err
;
unsigned
int
i
;
unsigned
ioport_size
,
iomem_size
,
iomem2_size
;
dma_addr_t
phys_addr
;
korg1212_t
*
korg1212
;
static
snd_device_ops_t
ops
=
{
.
dev_free
=
snd_korg1212_dev_free
,
};
*
rchip
=
NULL
;
if
((
err
=
pci_enable_device
(
pci
))
<
0
)
return
err
;
korg1212
=
snd_magic_kcalloc
(
korg1212_t
,
0
,
GFP_KERNEL
);
if
(
korg1212
==
NULL
)
return
-
ENOMEM
;
korg1212
->
card
=
card
;
korg1212
->
pci
=
pci
;
init_waitqueue_head
(
&
korg1212
->
wait
);
spin_lock_init
(
&
korg1212
->
lock
);
korg1212
->
irq
=
-
1
;
korg1212
->
clkSource
=
K1212_CLKIDX_Local
;
korg1212
->
clkRate
=
44100
;
korg1212
->
inIRQ
=
0
;
korg1212
->
running
=
0
;
korg1212
->
opencnt
=
0
;
korg1212
->
playcnt
=
0
;
korg1212
->
setcnt
=
0
;
snd_korg1212_setCardState
(
korg1212
,
K1212_STATE_UNINITIALIZED
);
korg1212
->
idleMonitorOn
=
0
;
korg1212
->
clkSrcRate
=
K1212_CLKIDX_LocalAt44_1K
;
...
...
@@ -1923,9 +2169,6 @@ static int __devinit snd_korg1212_create(korg1212_t *korg1212)
for
(
i
=
0
;
i
<
kAudioChannels
;
i
++
)
korg1212
->
volumePhase
[
i
]
=
0
;
if
((
err
=
pci_enable_device
(
pci
))
<
0
)
return
err
;
korg1212
->
iomem
=
pci_resource_start
(
korg1212
->
pci
,
0
);
korg1212
->
ioport
=
pci_resource_start
(
korg1212
->
pci
,
1
);
korg1212
->
iomem2
=
pci_resource_start
(
korg1212
->
pci
,
2
);
...
...
@@ -1948,27 +2191,27 @@ static int __devinit snd_korg1212_create(korg1212_t *korg1212)
korg1212
->
res_iomem
=
request_mem_region
(
korg1212
->
iomem
,
iomem_size
,
"korg1212"
);
if
(
korg1212
->
res_iomem
==
NULL
)
{
snd_printk
(
"unable to grab region 0x%lx-0x%lx
\n
"
,
snd_printk
(
KERN_ERR
"unable to grab region 0x%lx-0x%lx
\n
"
,
korg1212
->
iomem
,
korg1212
->
iomem
+
iomem_size
-
1
);
return
-
EBUSY
;
}
korg1212
->
res_ioport
=
request_region
(
korg1212
->
ioport
,
ioport_size
,
"korg1212"
);
if
(
korg1212
->
res_ioport
==
NULL
)
{
snd_printk
(
"unable to grab region 0x%lx-0x%lx
\n
"
,
snd_printk
(
KERN_ERR
"unable to grab region 0x%lx-0x%lx
\n
"
,
korg1212
->
ioport
,
korg1212
->
ioport
+
ioport_size
-
1
);
return
-
EBUSY
;
}
korg1212
->
res_iomem2
=
request_mem_region
(
korg1212
->
iomem2
,
iomem2_size
,
"korg1212"
);
if
(
korg1212
->
res_iomem2
==
NULL
)
{
snd_printk
(
"unable to grab region 0x%lx-0x%lx
\n
"
,
snd_printk
(
KERN_ERR
"unable to grab region 0x%lx-0x%lx
\n
"
,
korg1212
->
iomem2
,
korg1212
->
iomem2
+
iomem2_size
-
1
);
return
-
EBUSY
;
}
if
((
korg1212
->
iobase
=
(
unsigned
long
)
ioremap
(
korg1212
->
iomem
,
iomem_size
))
==
0
)
{
snd_printk
(
"unable to remap memory region 0x%lx-0x%lx
\n
"
,
korg1212
->
iobase
,
snd_printk
(
KERN_ERR
"unable to remap memory region 0x%lx-0x%lx
\n
"
,
korg1212
->
iobase
,
korg1212
->
iobase
+
iomem_size
-
1
);
return
-
EBUSY
;
}
...
...
@@ -1978,14 +2221,12 @@ static int __devinit snd_korg1212_create(korg1212_t *korg1212)
"korg1212"
,
(
void
*
)
korg1212
);
if
(
err
)
{
snd_printk
(
"unable to grab IRQ %d
\n
"
,
pci
->
irq
);
snd_printk
(
KERN_ERR
"unable to grab IRQ %d
\n
"
,
pci
->
irq
);
return
-
EBUSY
;
}
korg1212
->
irq
=
pci
->
irq
;
init_waitqueue_head
(
&
korg1212
->
wait
);
spin_lock_init
(
&
korg1212
->
lock
);
pci_set_master
(
korg1212
->
pci
);
korg1212
->
statusRegPtr
=
(
u32
*
)
(
korg1212
->
iobase
+
STATUS_REG_OFFSET
);
...
...
@@ -2029,7 +2270,7 @@ static int __devinit snd_korg1212_create(korg1212_t *korg1212)
korg1212
->
sharedBufferPhy
=
(
unsigned
long
)
phys_addr
;
if
(
korg1212
->
sharedBufferPtr
==
NULL
)
{
snd_printk
(
"can not allocate shared buffer memory (%d bytes)
\n
"
,
sizeof
(
KorgSharedBuffer
));
snd_printk
(
KERN_ERR
"can not allocate shared buffer memory (%d bytes)
\n
"
,
sizeof
(
KorgSharedBuffer
));
return
-
ENOMEM
;
}
...
...
@@ -2045,7 +2286,7 @@ static int __devinit snd_korg1212_create(korg1212_t *korg1212)
korg1212
->
PlayDataPhy
=
(
u32
)
phys_addr
;
if
(
korg1212
->
playDataBufsPtr
==
NULL
)
{
snd_printk
(
"can not allocate play data buffer memory (%d bytes)
\n
"
,
korg1212
->
DataBufsSize
);
snd_printk
(
KERN_ERR
"can not allocate play data buffer memory (%d bytes)
\n
"
,
korg1212
->
DataBufsSize
);
return
-
ENOMEM
;
}
...
...
@@ -2058,7 +2299,7 @@ static int __devinit snd_korg1212_create(korg1212_t *korg1212)
korg1212
->
RecDataPhy
=
(
u32
)
phys_addr
;
if
(
korg1212
->
recordDataBufsPtr
==
NULL
)
{
snd_printk
(
"can not allocate record data buffer memory (%d bytes)
\n
"
,
korg1212
->
DataBufsSize
);
snd_printk
(
KERN_ERR
"can not allocate record data buffer memory (%d bytes)
\n
"
,
korg1212
->
DataBufsSize
);
return
-
ENOMEM
;
}
...
...
@@ -2086,7 +2327,7 @@ static int __devinit snd_korg1212_create(korg1212_t *korg1212)
korg1212
->
dspMemPhy
=
(
u32
)
phys_addr
;
if
(
korg1212
->
dspMemPtr
==
NULL
)
{
snd_printk
(
"can not allocate dsp code memory (%d bytes)
\n
"
,
korg1212
->
dspCodeSize
);
snd_printk
(
KERN_ERR
"can not allocate dsp code memory (%d bytes)
\n
"
,
korg1212
->
dspCodeSize
);
return
-
ENOMEM
;
}
...
...
@@ -2106,7 +2347,7 @@ static int __devinit snd_korg1212_create(korg1212_t *korg1212)
mdelay
(
CARD_BOOT_DELAY_IN_MS
);
if
(
snd_korg1212_downloadDSPCode
(
korg1212
))
if
(
snd_korg1212_downloadDSPCode
(
korg1212
))
return
-
EBUSY
;
printk
(
KERN_INFO
"dspMemPhy = %08x U[%08x]
\n
"
...
...
@@ -2122,17 +2363,21 @@ static int __devinit snd_korg1212_create(korg1212_t *korg1212)
korg1212
->
RoutingTablePhy
,
LowerWordSwap
(
korg1212
->
RoutingTablePhy
),
korg1212
->
AdatTimeCodePhy
,
LowerWordSwap
(
korg1212
->
AdatTimeCodePhy
));
if
((
err
=
snd_pcm_new
(
korg1212
->
card
,
"korg1212"
,
0
,
1
,
1
,
&
korg1212
->
pcm
16
))
<
0
)
if
((
err
=
snd_pcm_new
(
korg1212
->
card
,
"korg1212"
,
0
,
1
,
1
,
&
korg1212
->
pcm
))
<
0
)
return
err
;
korg1212
->
pcm16
->
private_data
=
korg1212
;
korg1212
->
pcm16
->
private_free
=
snd_korg1212_free_pcm
;
strcpy
(
korg1212
->
pcm16
->
name
,
"korg1212"
);
korg1212
->
pcm
->
private_data
=
korg1212
;
korg1212
->
pcm
->
private_free
=
snd_korg1212_free_pcm
;
strcpy
(
korg1212
->
pcm
->
name
,
"korg1212"
);
snd_pcm_set_ops
(
korg1212
->
pcm
,
SNDRV_PCM_STREAM_PLAYBACK
,
&
snd_korg1212_playback_ops
);
snd_pcm_set_ops
(
korg1212
->
pcm
,
SNDRV_PCM_STREAM_CAPTURE
,
&
snd_korg1212_capture_ops
);
snd_pcm_set_ops
(
korg1212
->
pcm16
,
SNDRV_PCM_STREAM_PLAYBACK
,
&
snd_korg1212_playback_ops
);
snd_pcm_set_ops
(
korg1212
->
pcm16
,
SNDRV_PCM_STREAM_CAPTURE
,
&
snd_korg1212_capture_ops
);
korg1212
->
pcm
->
info_flags
=
SNDRV_PCM_INFO_JOINT_DUPLEX
;
korg1212
->
pcm16
->
info_flags
=
SNDRV_PCM_INFO_JOINT_DUPLEX
;
//snd_pcm_lib_preallocate_pages_for_all(korg1212->pcm,
// K1212_MAX_BUF_SIZE, K1212_MAX_BUF_SIZE, GFP_KERNEL);
for
(
i
=
0
;
i
<
K1212_CONTROL_ELEMENTS
;
i
++
)
{
err
=
snd_ctl_add
(
korg1212
->
card
,
snd_ctl_new1
(
&
snd_korg1212_controls
[
i
],
korg1212
));
...
...
@@ -2141,103 +2386,21 @@ static int __devinit snd_korg1212_create(korg1212_t *korg1212)
}
snd_korg1212_proc_init
(
korg1212
);
return
0
;
}
static
void
snd_korg1212_free
(
void
*
private_data
)
{
korg1212_t
*
korg1212
=
(
korg1212_t
*
)
private_data
;
if
(
korg1212
==
NULL
)
{
return
;
}
snd_korg1212_TurnOffIdleMonitor
(
korg1212
);
snd_korg1212_DisableCardInterrupts
(
korg1212
);
if
(
korg1212
->
irq
>=
0
)
{
free_irq
(
korg1212
->
irq
,
(
void
*
)
korg1212
);
korg1212
->
irq
=
-
1
;
}
if
(
korg1212
->
iobase
!=
0
)
{
iounmap
((
void
*
)
korg1212
->
iobase
);
korg1212
->
iobase
=
0
;
}
if
(
korg1212
->
res_iomem
!=
NULL
)
{
release_resource
(
korg1212
->
res_iomem
);
kfree_nocheck
(
korg1212
->
res_iomem
);
korg1212
->
res_iomem
=
NULL
;
}
if
(
korg1212
->
res_ioport
!=
NULL
)
{
release_resource
(
korg1212
->
res_ioport
);
kfree_nocheck
(
korg1212
->
res_ioport
);
korg1212
->
res_ioport
=
NULL
;
}
if
(
korg1212
->
res_iomem2
!=
NULL
)
{
release_resource
(
korg1212
->
res_iomem2
);
kfree_nocheck
(
korg1212
->
res_iomem2
);
korg1212
->
res_iomem2
=
NULL
;
}
// ----------------------------------------------------
// free up memory resources used for the DSP download.
// ----------------------------------------------------
if
(
korg1212
->
dspMemPtr
)
{
snd_free_pci_pages
(
korg1212
->
pci
,
korg1212
->
dspCodeSize
,
korg1212
->
dspMemPtr
,
(
dma_addr_t
)
korg1212
->
dspMemPhy
);
korg1212
->
dspMemPhy
=
0
;
korg1212
->
dspMemPtr
=
0
;
korg1212
->
dspCodeSize
=
0
;
}
#ifndef K1212_LARGEALLOC
// ------------------------------------------------------
// free up memory resources used for the Play/Rec Buffers
// ------------------------------------------------------
if
(
korg1212
->
playDataBufsPtr
)
{
snd_free_pci_pages
(
korg1212
->
pci
,
korg1212
->
DataBufsSize
,
korg1212
->
playDataBufsPtr
,
(
dma_addr_t
)
korg1212
->
PlayDataPhy
);
korg1212
->
PlayDataPhy
=
0
;
korg1212
->
playDataBufsPtr
=
NULL
;
}
if
(
korg1212
->
recordDataBufsPtr
)
{
snd_free_pci_pages
(
korg1212
->
pci
,
korg1212
->
DataBufsSize
,
korg1212
->
recordDataBufsPtr
,
(
dma_addr_t
)
korg1212
->
RecDataPhy
);
korg1212
->
RecDataPhy
=
0
;
korg1212
->
recordDataBufsPtr
=
NULL
;
if
((
err
=
snd_device_new
(
card
,
SNDRV_DEV_LOWLEVEL
,
korg1212
,
&
ops
))
<
0
)
{
snd_korg1212_free
(
korg1212
);
return
err
;
}
*
rchip
=
korg1212
;
return
0
;
#endif
// ----------------------------------------------------
// free up memory resources used for the Shared Buffers
// ----------------------------------------------------
if
(
korg1212
->
sharedBufferPtr
)
{
snd_free_pci_pages
(
korg1212
->
pci
,
(
u32
)
sizeof
(
KorgSharedBuffer
),
korg1212
->
sharedBufferPtr
,
(
dma_addr_t
)
korg1212
->
sharedBufferPhy
);
korg1212
->
sharedBufferPhy
=
0
;
korg1212
->
sharedBufferPtr
=
NULL
;
}
}
/*
* Card initialisation
*/
static
void
snd_korg1212_card_free
(
snd_card_t
*
card
)
{
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK
(
"K1212_DEBUG: Freeing card
\n
"
);
#endif
snd_korg1212_free
(
card
->
private_data
);
}
static
int
__devinit
snd_korg1212_probe
(
struct
pci_dev
*
pci
,
const
struct
pci_device_id
*
pci_id
)
...
...
@@ -2254,16 +2417,11 @@ snd_korg1212_probe(struct pci_dev *pci,
dev
++
;
return
-
ENOENT
;
}
if
((
card
=
snd_card_new
(
index
[
dev
],
id
[
dev
],
THIS_MODULE
,
sizeof
(
korg1212_t
)))
==
NULL
)
card
=
snd_card_new
(
index
[
dev
],
id
[
dev
],
THIS_MODULE
,
0
);
if
(
card
==
NULL
)
return
-
ENOMEM
;
card
->
private_free
=
snd_korg1212_card_free
;
korg1212
=
(
korg1212_t
*
)
card
->
private_data
;
korg1212
->
card
=
card
;
korg1212
->
pci
=
pci
;
if
((
err
=
snd_korg1212_create
(
korg1212
))
<
0
)
{
if
((
err
=
snd_korg1212_create
(
card
,
pci
,
&
korg1212
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
...
...
@@ -2281,22 +2439,23 @@ snd_korg1212_probe(struct pci_dev *pci,
snd_card_free
(
card
);
return
err
;
}
pci_set_drvdata
(
pci
,
card
);
pci_set_drvdata
(
pci
,
korg1212
);
dev
++
;
return
0
;
}
static
void
__devexit
snd_korg1212_remove
(
struct
pci_dev
*
pci
)
{
snd_card_free
(
pci_get_drvdata
(
pci
));
korg1212_t
*
korg1212
=
pci_get_drvdata
(
pci
);
snd_card_free
(
korg1212
->
card
);
pci_set_drvdata
(
pci
,
NULL
);
}
static
struct
pci_driver
driver
=
{
.
name
=
"korg1212"
,
.
name
=
"korg1212"
,
.
id_table
=
snd_korg1212_ids
,
.
probe
=
snd_korg1212_probe
,
.
remove
=
__devexit_p
(
snd_korg1212_remove
),
.
probe
=
snd_korg1212_probe
,
.
remove
=
__devexit_p
(
snd_korg1212_remove
),
};
static
int
__init
alsa_card_korg1212_init
(
void
)
...
...
sound/pci/via82xx.c
View file @
74521715
...
...
@@ -820,6 +820,7 @@ static int snd_via686_playback_prepare(snd_pcm_substream_t *substream)
snd_pcm_runtime_t
*
runtime
=
substream
->
runtime
;
snd_ac97_set_rate
(
chip
->
ac97
,
AC97_PCM_FRONT_DAC_RATE
,
runtime
->
rate
);
snd_ac97_set_rate
(
chip
->
ac97
,
AC97_SPDIF
,
runtime
->
rate
);
via686_setup_format
(
chip
,
viadev
,
runtime
);
return
0
;
}
...
...
@@ -909,18 +910,37 @@ static int snd_via8233_multi_prepare(snd_pcm_substream_t *substream)
snd_via82xx_channel_reset
(
chip
,
viadev
);
snd_via82xx_set_table_ptr
(
chip
,
viadev
);
/* FIXME: a more generic solutions would be better */
if
(
chip
->
chip_type
==
TYPE_VIA8233A
)
{
/* VIA8233A cannot change the slot mapping, so we need
* to swap the RL/RR with C/L.
*/
#define AC97_ID_ALC650 0x414c4720
if
(
chip
->
ac97
->
id
==
AC97_ID_ALC650
)
{
unsigned
short
val
;
if
(
runtime
->
channels
>
4
)
/* slot mapping: 3,4,7,8 */
val
=
0
;
else
/* slot mapping: 3,4,6,9,7,8 */
val
=
0x4000
;
snd_ac97_update_bits
(
chip
->
ac97
,
AC97_ALC650_MULTICH
,
0xc000
,
val
);
}
}
fmt
=
(
runtime
->
format
==
SNDRV_PCM_FORMAT_S16_LE
)
?
VIA_REG_MULTPLAY_FMT_16BIT
:
VIA_REG_MULTPLAY_FMT_8BIT
;
fmt
|=
runtime
->
channels
<<
4
;
outb
(
fmt
,
VIADEV_REG
(
viadev
,
OFS_MULTPLAY_FORMAT
));
/* set sample number to slot 3, 4, 7, 8, 6, 9 */
/* set sample number to slot 3, 4, 7, 8, 6, 9
(for VIA8233/C,8235)
*/
/* corresponding to FL, FR, RL, RR, C, LFE ?? */
switch
(
runtime
->
channels
)
{
case
1
:
slots
=
(
1
<<
0
)
|
(
1
<<
4
);
break
;
case
2
:
slots
=
(
1
<<
0
)
|
(
2
<<
4
);
break
;
case
3
:
slots
=
(
1
<<
0
)
|
(
2
<<
4
)
|
(
5
<<
8
);
break
;
case
4
:
slots
=
(
1
<<
0
)
|
(
2
<<
4
)
|
(
3
<<
8
)
|
(
4
<<
12
);
break
;
case
5
:
slots
=
(
1
<<
0
)
|
(
2
<<
4
)
|
(
5
<<
8
)
|
(
3
<<
12
)
|
(
4
<<
16
);
break
;
case
6
:
slots
=
(
1
<<
0
)
|
(
2
<<
4
)
|
(
5
<<
8
)
|
(
6
<<
12
)
|
(
3
<<
16
)
|
(
4
<<
20
);
break
;
case
5
:
slots
=
(
1
<<
0
)
|
(
2
<<
4
)
|
(
3
<<
8
)
|
(
4
<<
12
)
|
(
5
<<
16
);
break
;
case
6
:
slots
=
(
1
<<
0
)
|
(
2
<<
4
)
|
(
3
<<
8
)
|
(
4
<<
12
)
|
(
5
<<
16
)
|
(
6
<<
20
);
break
;
default:
slots
=
0
;
break
;
}
/* STOP index is never reached */
...
...
@@ -1438,7 +1458,7 @@ static void snd_via82xx_mixer_free_ac97(ac97_t *ac97)
}
static
struct
ac97_quirk
ac97_quirks
[]
=
{
{
0x1106
,
0x4161
,
AC97_TUNE_HP_ONLY
},
/* ASRock K7VT2 */
{
0x1106
,
0x4161
,
"ASRock K7VT2"
,
AC97_TUNE_HP_ONLY
},
{
}
/* terminator */
};
...
...
@@ -1457,7 +1477,7 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip)
if
((
err
=
snd_ac97_mixer
(
chip
->
card
,
&
ac97
,
&
chip
->
ac97
))
<
0
)
return
err
;
snd_ac97_tune_hardware
(
&
chip
->
ac97
,
chip
->
pci
,
ac97_quirks
);
snd_ac97_tune_hardware
(
chip
->
ac97
,
chip
->
pci
,
ac97_quirks
);
if
(
chip
->
chip_type
!=
TYPE_VIA686
)
{
/* use slot 10/11 */
...
...
sound/usb/usbaudio.c
View file @
74521715
...
...
@@ -1051,7 +1051,7 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
}
/* create a data pipe */
ep
=
get_endpoint
(
alts
,
0
)
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
;
ep
=
fmt
->
endpoint
&
USB_ENDPOINT_NUMBER_MASK
;
if
(
is_playback
)
subs
->
datapipe
=
usb_sndisocpipe
(
dev
,
ep
);
else
...
...
@@ -1062,9 +1062,16 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
subs
->
fill_max
=
0
;
/* we need a sync pipe in async OUT or adaptive IN mode */
attr
=
get_endpoint
(
alts
,
0
)
->
bmAttributes
&
EP_ATTR_MASK
;
attr
=
fmt
->
ep_attr
&
EP_ATTR_MASK
;
if
((
is_playback
&&
attr
==
EP_ATTR_ASYNC
)
||
(
!
is_playback
&&
attr
==
EP_ATTR_ADAPTIVE
))
{
/*
* QUIRK: plantronics headset has adaptive-in
* although it's really not...
*/
if
(
dev
->
descriptor
.
idVendor
==
0x047f
&&
dev
->
descriptor
.
idProduct
==
0x0ca1
)
goto
_ok
;
/* check endpoint */
if
(
altsd
->
bNumEndpoints
<
2
||
get_endpoint
(
alts
,
1
)
->
bmAttributes
!=
0x01
||
...
...
@@ -1088,6 +1095,7 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
subs
->
syncinterval
=
get_endpoint
(
alts
,
1
)
->
bRefresh
;
}
_ok:
if
((
err
=
init_usb_pitch
(
dev
,
subs
->
interface
,
alts
,
fmt
))
<
0
||
(
err
=
init_usb_sample_rate
(
dev
,
subs
->
interface
,
alts
,
fmt
,
runtime
->
rate
))
<
0
)
...
...
@@ -1651,7 +1659,7 @@ static void proc_dump_substream_formats(snd_usb_substream_t *subs, snd_info_buff
fp
->
endpoint
&
USB_DIR_IN
?
"IN"
:
"OUT"
,
sync_types
[(
fp
->
ep_attr
&
EP_ATTR_MASK
)
>>
2
]);
if
(
fp
->
rates
&
SNDRV_PCM_RATE_CONTINUOUS
)
{
snd_iprintf
(
buffer
,
" Rates: %d - %d (continous)
\n
"
,
snd_iprintf
(
buffer
,
" Rates: %d - %d (contin
u
ous)
\n
"
,
fp
->
rate_min
,
fp
->
rate_max
);
}
else
{
unsigned
int
i
;
...
...
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