25-akpm/Documentation/sound/alsa/ALSA-Configuration.txt | 39
25-akpm/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 46
25-akpm/include/sound/ac97_codec.h | 15
25-akpm/include/sound/ad1848.h | 10
25-akpm/include/sound/asequencer.h | 11
25-akpm/include/sound/asound.h | 3
25-akpm/include/sound/core.h | 3
25-akpm/include/sound/cs8427.h | 2
25-akpm/include/sound/emu10k1.h | 5
25-akpm/include/sound/hdsp.h | 1
25-akpm/include/sound/info.h | 9
25-akpm/include/sound/pcm_oss.h | 4
25-akpm/include/sound/seq_midi_event.h | 16
25-akpm/include/sound/soundfont.h | 1
25-akpm/include/sound/version.h | 4
25-akpm/include/sound/ymfpci.h | 8
25-akpm/scripts/MAKEDEV.snd | 161 +
25-akpm/sound/core/control.c | 4
25-akpm/sound/core/info.c | 10
25-akpm/sound/core/ioctl32/ioctl32.c | 6
25-akpm/sound/core/memalloc.c | 81
25-akpm/sound/core/oss/pcm_oss.c | 203 ++
25-akpm/sound/core/oss/pcm_plugin.c | 23
25-akpm/sound/core/oss/pcm_plugin.h | 1
25-akpm/sound/core/oss/plugin_ops.h | 2
25-akpm/sound/core/oss/rate.c | 22
25-akpm/sound/core/oss/route.c | 4
25-akpm/sound/core/pcm_lib.c | 9
25-akpm/sound/core/pcm_memory.c | 16
25-akpm/sound/core/pcm_native.c | 12
25-akpm/sound/core/rawmidi.c | 26
25-akpm/sound/core/rtctimer.c | 14
25-akpm/sound/core/seq/seq_clientmgr.c | 56
25-akpm/sound/core/seq/seq_midi_event.c | 55
25-akpm/sound/core/seq/seq_ports.c | 14
25-akpm/sound/core/seq/seq_ports.h | 3
25-akpm/sound/core/sound.c | 18
25-akpm/sound/core/sound_oss.c | 2
25-akpm/sound/core/timer.c | 20
25-akpm/sound/drivers/dummy.c | 26
25-akpm/sound/drivers/opl3/opl3_lib.c | 2
25-akpm/sound/drivers/opl4/opl4_lib.c | 5
25-akpm/sound/drivers/opl4/opl4_local.h | 2
25-akpm/sound/drivers/opl4/opl4_synth.c | 22
25-akpm/sound/drivers/vx/vx_core.c | 6
25-akpm/sound/i2c/cs8427.c | 6
25-akpm/sound/i2c/other/ak4xxx-adda.c | 2
25-akpm/sound/isa/ad1848/ad1848.c | 19
25-akpm/sound/isa/ad1848/ad1848_lib.c | 108 +
25-akpm/sound/isa/cmi8330.c | 2
25-akpm/sound/isa/cs423x/cs4231_lib.c | 4
25-akpm/sound/isa/es18xx.c | 2
25-akpm/sound/isa/gus/gus_main.c | 4
25-akpm/sound/isa/opl3sa2.c | 3
25-akpm/sound/isa/sb/emu8000.c | 2
25-akpm/sound/isa/sb/sb16.c | 18
25-akpm/sound/isa/sscape.c | 2
25-akpm/sound/pci/ac97/Makefile | 2
25-akpm/sound/pci/ac97/ac97_codec.c | 823 ----------
25-akpm/sound/pci/ac97/ac97_local.h | 42
25-akpm/sound/pci/ac97/ac97_patch.c | 618 +++++++
25-akpm/sound/pci/ac97/ac97_patch.h | 3
25-akpm/sound/pci/ac97/ac97_proc.c | 295 +++
25-akpm/sound/pci/ali5451/ali5451.c | 52
25-akpm/sound/pci/cmipci.c | 4
25-akpm/sound/pci/cs4281.c | 74
25-akpm/sound/pci/cs46xx/cs46xx.c | 13
25-akpm/sound/pci/cs46xx/cs46xx_lib.c | 29
25-akpm/sound/pci/emu10k1/emu10k1.c | 10
25-akpm/sound/pci/emu10k1/emu10k1_main.c | 8
25-akpm/sound/pci/emu10k1/emufx.c | 59
25-akpm/sound/pci/emu10k1/emumixer.c | 82
25-akpm/sound/pci/emu10k1/irq.c | 45
25-akpm/sound/pci/ens1370.c | 10
25-akpm/sound/pci/es1938.c | 6
25-akpm/sound/pci/es1968.c | 48
25-akpm/sound/pci/ice1712/ak4xxx.c | 14
25-akpm/sound/pci/ice1712/aureon.c | 2
25-akpm/sound/pci/ice1712/ews.c | 16
25-akpm/sound/pci/ice1712/ice1712.h | 8
25-akpm/sound/pci/ice1712/ice1724.c | 4
25-akpm/sound/pci/intel8x0.c | 356 ++--
25-akpm/sound/pci/maestro3.c | 100 -
25-akpm/sound/pci/nm256/nm256.c | 13
25-akpm/sound/pci/rme96.c | 18
25-akpm/sound/pci/rme9652/Makefile | 5
25-akpm/sound/pci/rme9652/hammerfall_mem.c | 251 ---
25-akpm/sound/pci/rme9652/hdsp.c | 417 +++--
25-akpm/sound/pci/rme9652/rme9652.c | 79
25-akpm/sound/pci/sonicvibes.c | 6
25-akpm/sound/pci/trident/trident.c | 15
25-akpm/sound/pci/trident/trident_main.c | 17
25-akpm/sound/pci/via82xx.c | 6
25-akpm/sound/pci/ymfpci/ymfpci.c | 15
25-akpm/sound/pci/ymfpci/ymfpci_main.c | 131 +
25-akpm/sound/pcmcia/vx/vxpocket.c | 1
25-akpm/sound/ppc/awacs.c | 29
25-akpm/sound/ppc/burgundy.c | 25
25-akpm/sound/ppc/pmac.c | 2
25-akpm/sound/ppc/pmac.h | 5
25-akpm/sound/ppc/tumbler.c | 28
25-akpm/sound/synth/emux/soundfont.c | 18
25-akpm/sound/usb/usbaudio.c | 230 +-
25-akpm/sound/usb/usbaudio.h | 8
25-akpm/sound/usb/usbmidi.c | 3
25-akpm/sound/usb/usbmixer.c | 2
25-akpm/sound/usb/usbmixer_maps.c | 23
25-akpm/sound/usb/usbquirks.h | 36
108 files changed, 3160 insertions(+), 2120 deletions(-)
diff -puN Documentation/sound/alsa/ALSA-Configuration.txt~alsa-bk-2003-07-28 Documentation/sound/alsa/ALSA-Configuration.txt
--- 25/Documentation/sound/alsa/ALSA-Configuration.txt~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/Documentation/sound/alsa/ALSA-Configuration.txt Tue Jul 29 12:11:32 2003
@@ -27,6 +27,13 @@ the card supports). You don't need to c
isapnptools.
+Creating ALSA devices
+=====================
+
+Use the MAKEDEV.snd script located in the directory named scripts
+in the linux kernel tree.
+
+
Module parameters
=================
@@ -92,7 +99,7 @@ Module parameters
amidi_map - MIDI device number maps assigned to the 2st OSS device.
(default: 1)
- Global parameters for top soundcard modules
+ Common parameters for top soundcard modules
-------------------------------------------
Each of top-level soundcard module takes some general options,
@@ -518,6 +525,15 @@ Module parameters
Module supports up to 8 cards.
+ Note: you need to load the firmware via hdsploader utility included
+ in alsa-tools package.
+
+ Note: snd-page-alloc module does the job which snd-hammerfall-mem
+ module did formerly. It will allocate the buffers in advance
+ when any HDSP cards are found. To make the buffer
+ allocation sure, load snd-page-alloc module in the early
+ stage of boot sequence.
+
Module snd-ice1712
------------------
@@ -549,6 +565,7 @@ Module parameters
Module for Envy24HT (VT/ICE1724) based PCI soundcards.
* MidiMan M Audio Revolution 7.1
* AMP Ltd AUDIO2000
+ * TerraTec Aureon Sky-5.1, Space-7.1
Module supports up to 8 cards and autoprobe.
@@ -790,6 +807,12 @@ Module parameters
Module supports up to 8 cards.
+ Note: snd-page-alloc module does the job which snd-hammerfall-mem
+ module did formerly. It will allocate the buffers in advance
+ when any RME9652 cards are found. To make the buffer
+ allocation sure, load snd-page-alloc module in the early
+ stage of boot sequence.
+
Module snd-sa11xx-uda1341 (on arm only)
---------------------------------------
@@ -983,12 +1006,15 @@ Module parameters
Note: VIA8233/5 (not VIA8233A) can support DXS (direct sound)
channels as the first PCM. With this device, up to 4
- streams can be played at the same time. If the playback on
- this PCM is noisy, try to specify dxs_channels option to 2
- or 3.
+ streams can be played at the same time. On some motherboards,
+ these channels don't work properly due to the bug of BIOS.
+ If you experience that the playback on this PCM is noisy,
+ try to specify dxs_support option to 2 or 3. In most cases
+ dxs_support=3 would suffice, so you can keep the multi-play
+ capability.
Note: for the MPU401 on VIA823x, use snd-mpu401 driver
- additonally.
+ additonally. The mpu_port option is for VIA686 chips only.
Module snd-virmidi
------------------
@@ -1284,6 +1310,9 @@ Proc interfaces (/proc/asound)
- direct don't use plugins
- block force block mode (rvplayer)
- non-block force non-block mode
+ - whole-frag write only whole fragments (optimization affecting
+ playback only)
+ - no-silence do not fill silence ahead to avoid clicks
Example: echo "x11amp 128 16384" > /proc/asound/card0/pcm0p/oss
echo "squake 0 0 disable" > /proc/asound/card0/pcm0c/oss
diff -puN Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl~alsa-bk-2003-07-28 Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
--- 25/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl Tue Jul 29 12:11:31 2003
@@ -239,8 +239,10 @@
drivers directory
- This directory contains the non-architecture-specific
- codes. For example, the dummy pcm driver and the serial MIDI
+ This directory contains the codes shared among different drivers
+ on the different architectures. They are hence supposed not to be
+ architecture-specific.
+ For example, the dummy pcm driver and the serial MIDI
driver are found in this directory. In the sub-directories,
there are the codes for components which are independent from
bus and cpu architectures.
@@ -254,9 +256,9 @@
- drivers/opl3
+ drivers/opl3 and opl4
- The OPL3 FM-synth stuff is found here.
+ The OPL3 and OPL4 FM-synth stuff is found here.
@@ -268,9 +270,9 @@
- Although there is a standard i2c layer on Linux, ALSA uses its
+ Although there is a standard i2c layer on Linux, ALSA has its
own i2c codes for some cards, because the soundcard needs only a
- simple operation and the standard API is too complicated for
+ simple operation and the standard i2c API is too complicated for
such a purpose.
@@ -298,7 +300,7 @@
pci directory
This and its sub-directories hold the top-level card modules
- for PCI soundcards.
+ for PCI soundcards and the codes specific to the PCI BUS.
@@ -320,7 +322,7 @@
arm, ppc, and sparc directories
These are for the top-level card modules which are
- architecture specific.
+ specific to each given architecture.
@@ -3283,13 +3285,6 @@ struct _snd_pcm_runtime {
udelay() or mdelay().
-
- This atomicity problem appears also in the initialization of the
- hardware when the power-management is supported. The functions
- for suspending and resuming the chip must be atomic, i.e. no
- mutex nor sleep can be used in them.
-
-
Constraints
@@ -4079,8 +4074,7 @@ struct _snd_pcm_runtime {
- These callbacks are non-atomic like the callbacks of control API
- unless they are called during suspend/resume phase.
+ These callbacks are non-atomic like the callbacks of control API.
@@ -4094,8 +4088,6 @@ struct _snd_pcm_runtime {
The reset callback is used to reset
the codec. If the chip requires a special way of reset, you can
define this callback.
- This callback must be atomic when it's called in the suspend
- mode.
@@ -5212,6 +5204,13 @@ struct _snd_pcm_runtime {
+ For keeping the readability of 2.5 source code, it's recommended to
+ separate the above ifdef condition as the patch file in alsa-driver
+ directory.
+ See alsa-driver/pci/ali5451.c for example.
+
+
+
The scheme of the real suspend job is as following.
@@ -5383,15 +5382,6 @@ struct _snd_pcm_runtime {
-
- Last but not least: Please keep in mind that you cannot call
- schedule() during the suspend and the resume
- callbacks. If any delay is necessary, you have to use
- mdelay() or udelay()
- instead of schedule_timeout()!
- Of course, semaphores cannot be used, too, which will invoke sleep
- inside.
-
diff -puN include/sound/ac97_codec.h~alsa-bk-2003-07-28 include/sound/ac97_codec.h
--- 25/include/sound/ac97_codec.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/ac97_codec.h Tue Jul 29 12:11:31 2003
@@ -229,6 +229,13 @@
#define AC97_CM9739_SPDIF_IN_STATUS 0x68 /* 32bit */
#define AC97_CM9739_SPDIF_CTRL 0x6c
+/* specific - wolfson */
+#define AC97_WM97XX_FMIXER_VOL 0x72
+#define AC97_WM9704_RMIXER_VOL 0x74
+#define AC97_WM9704_TEST 0x5a
+#define AC97_WM9704_RPCM_VOL 0x70
+#define AC97_WM9711_OUT3VOL 0x16
+
/* ac97->scaps */
#define AC97_SCAP_AUDIO (1<<0) /* audio AC'97 codec */
@@ -256,12 +263,20 @@
typedef struct _snd_ac97 ac97_t;
+struct snd_ac97_build_ops {
+ int (*build_3d) (ac97_t *ac97);
+ int (*build_specific) (ac97_t *ac97);
+ int (*build_spdif) (ac97_t *ac97);
+ int (*build_post_spdif) (ac97_t *ac97);
+};
+
struct _snd_ac97 {
void (*reset) (ac97_t *ac97);
void (*write) (ac97_t *ac97, unsigned short reg, unsigned short val);
unsigned short (*read) (ac97_t *ac97, unsigned short reg);
void (*wait) (ac97_t *ac97);
void (*init) (ac97_t *ac97);
+ struct snd_ac97_build_ops * build_ops;
void *private_data;
void (*private_free) (ac97_t *ac97);
/* --- */
diff -puN include/sound/ad1848.h~alsa-bk-2003-07-28 include/sound/ad1848.h
--- 25/include/sound/ad1848.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/ad1848.h Tue Jul 29 12:11:31 2003
@@ -120,6 +120,12 @@
#define AD1848_HW_AD1848 0x0002 /* AD1848 chip */
#define AD1848_HW_CS4248 0x0003 /* CS4248 chip */
#define AD1848_HW_CMI8330 0x0004 /* CMI8330 chip */
+#define AD1848_HW_THINKPAD 0x0005 /* Thinkpad 360/750/755 */
+
+/* IBM Thinkpad specific stuff */
+#define AD1848_THINKPAD_CTL_PORT1 0x15e8
+#define AD1848_THINKPAD_CTL_PORT2 0x15e9
+#define AD1848_THINKPAD_CS4248_ENABLE_BIT 0x02
struct _snd_ad1848 {
unsigned long port; /* i/o port */
@@ -140,6 +146,10 @@ struct _snd_ad1848 {
int mce_bit;
int calibrate_mute;
int dma_size;
+ int thinkpad_flag; /* Thinkpad CS4248 needs some extra help */
+#ifdef CONFIG_PM
+ struct pm_dev *thinkpad_pmstate;
+#endif
spinlock_t reg_lock;
struct semaphore open_mutex;
diff -puN include/sound/asequencer.h~alsa-bk-2003-07-28 include/sound/asequencer.h
--- 25/include/sound/asequencer.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/asequencer.h Tue Jul 29 12:11:31 2003
@@ -29,7 +29,7 @@
#include
/** version of the sequencer */
-#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 0)
+#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1)
/**
* definition of sequencer event types
@@ -57,8 +57,8 @@
#define SNDRV_SEQ_EVENT_CHANPRESS 12
#define SNDRV_SEQ_EVENT_PITCHBEND 13 /**< from -8192 to 8191 */
#define SNDRV_SEQ_EVENT_CONTROL14 14 /**< 14 bit controller value */
-#define SNDRV_SEQ_EVENT_NONREGPARAM 15 /**< 14 bit NRPN */
-#define SNDRV_SEQ_EVENT_REGPARAM 16 /**< 14 bit RPN */
+#define SNDRV_SEQ_EVENT_NONREGPARAM 15 /**< 14 bit NRPN address + 14 bit unsigned value */
+#define SNDRV_SEQ_EVENT_REGPARAM 16 /**< 14 bit RPN address + 14 bit unsigned value */
/** synchronisation messages
* event data type = #sndrv_seq_ev_ctrl
@@ -604,6 +604,8 @@ struct sndrv_seq_remove_events {
/* misc. conditioning flags */
#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT (1<<0)
+#define SNDRV_SEQ_PORT_FLG_TIMESTAMP (1<<1)
+#define SNDRV_SEQ_PORT_FLG_TIME_REAL (1<<1)
struct sndrv_seq_port_info {
struct sndrv_seq_addr addr; /* client/port numbers */
@@ -620,7 +622,8 @@ struct sndrv_seq_port_info {
void *kernel; /* reserved for kernel use (must be NULL) */
unsigned int flags; /* misc. conditioning */
- char reserved[60]; /* for future use */
+ unsigned char time_queue; /* queue # for timestamping */
+ char reserved[59]; /* for future use */
};
diff -puN include/sound/asound.h~alsa-bk-2003-07-28 include/sound/asound.h
--- 25/include/sound/asound.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/asound.h Tue Jul 29 12:11:31 2003
@@ -105,9 +105,10 @@ enum sndrv_hwdep_iface {
SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */
SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */
SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */
+ SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */
/* Don't forget to change the following: */
- SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_VX,
+ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_MIXART,
};
struct sndrv_hwdep_info {
diff -puN include/sound/core.h~alsa-bk-2003-07-28 include/sound/core.h
--- 25/include/sound/core.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/core.h Tue Jul 29 12:11:31 2003
@@ -222,9 +222,6 @@ typedef struct _snd_minor snd_minor_t;
/* sound.c */
extern int snd_ecards_limit;
-extern int device_mode;
-extern int device_gid;
-extern int device_uid;
void snd_request_card(int card);
diff -puN include/sound/cs8427.h~alsa-bk-2003-07-28 include/sound/cs8427.h
--- 25/include/sound/cs8427.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/cs8427.h Tue Jul 29 12:11:31 2003
@@ -189,6 +189,8 @@
int snd_cs8427_detect(snd_i2c_bus_t *bus, unsigned char addr);
int snd_cs8427_create(snd_i2c_bus_t *bus, unsigned char addr, snd_i2c_device_t **r_cs8427);
void snd_cs8427_reset(snd_i2c_device_t *cs8427);
+int snd_cs8427_reg_write(snd_i2c_device_t *device, unsigned char reg, unsigned char val);
+int snd_cs8427_reg_read(snd_i2c_device_t *device, unsigned char reg);
int snd_cs8427_iec958_build(snd_i2c_device_t *cs8427, snd_pcm_substream_t *playback_substream, snd_pcm_substream_t *capture_substream);
int snd_cs8427_iec958_active(snd_i2c_device_t *cs8427, int active);
int snd_cs8427_iec958_pcm(snd_i2c_device_t *cs8427, unsigned int rate);
diff -puN include/sound/emu10k1.h~alsa-bk-2003-07-28 include/sound/emu10k1.h
--- 25/include/sound/emu10k1.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/emu10k1.h Tue Jul 29 12:11:31 2003
@@ -931,6 +931,7 @@ struct _snd_emu10k1 {
unsigned long port; /* I/O port number */
struct resource *res_port;
int APS: 1, /* APS flag */
+ no_ac97: 1, /* no AC'97 */
tos_link: 1; /* tos link detected */
unsigned int audigy; /* is Audigy? */
unsigned int revision; /* chip revision */
@@ -1346,10 +1347,10 @@ typedef struct {
#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, emu10k1_fx8010_info_t)
#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, emu10k1_fx8010_code_t)
-#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOW ('H', 0x12, emu10k1_fx8010_code_t)
+#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, emu10k1_fx8010_code_t)
#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int)
#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, emu10k1_fx8010_tram_t)
-#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOR ('H', 0x22, emu10k1_fx8010_tram_t)
+#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, emu10k1_fx8010_tram_t)
#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, emu10k1_fx8010_pcm_t)
#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, emu10k1_fx8010_pcm_t)
#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80)
diff -puN include/sound/hdsp.h~alsa-bk-2003-07-28 include/sound/hdsp.h
--- 25/include/sound/hdsp.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/hdsp.h Tue Jul 29 12:11:31 2003
@@ -24,6 +24,7 @@
typedef enum {
Digiface,
Multiface,
+ H9652,
Undefined,
} HDSP_IO_Type;
diff -puN include/sound/info.h~alsa-bk-2003-07-28 include/sound/info.h
--- 25/include/sound/info.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/info.h Tue Jul 29 12:11:31 2003
@@ -38,7 +38,6 @@ typedef struct snd_info_buffer snd_info_
#define SNDRV_INFO_CONTENT_TEXT 0
#define SNDRV_INFO_CONTENT_DATA 1
-#define SNDRV_INFO_CONTENT_DEVICE 2
struct snd_info_entry;
@@ -118,10 +117,6 @@ snd_info_entry_t *snd_info_create_card_e
const char *name,
snd_info_entry_t * parent);
void snd_info_free_entry(snd_info_entry_t * entry);
-snd_info_entry_t *snd_info_create_device(const char *name,
- unsigned int number,
- unsigned int mode);
-void snd_info_free_device(snd_info_entry_t * entry);
int snd_info_store_text(snd_info_entry_t * entry);
int snd_info_restore_text(snd_info_entry_t * entry);
@@ -163,10 +158,6 @@ static inline char *snd_info_get_str(cha
static inline snd_info_entry_t *snd_info_create_module_entry(struct module * module, const char *name, snd_info_entry_t * parent) { return NULL; }
static inline snd_info_entry_t *snd_info_create_card_entry(snd_card_t * card, const char *name, snd_info_entry_t * parent) { return NULL; }
static inline void snd_info_free_entry(snd_info_entry_t * entry) { ; }
-static inline snd_info_entry_t *snd_info_create_device(const char *name,
- unsigned int number,
- unsigned int mode) { return NULL; }
-static inline void snd_info_free_device(snd_info_entry_t * entry) { ; }
static inline int snd_info_card_create(snd_card_t * card) { return 0; }
static inline int snd_info_card_register(snd_card_t * card) { return 0; }
diff -puN include/sound/pcm_oss.h~alsa-bk-2003-07-28 include/sound/pcm_oss.h
--- 25/include/sound/pcm_oss.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/pcm_oss.h Tue Jul 29 12:11:31 2003
@@ -30,7 +30,9 @@ struct _snd_pcm_oss_setup {
unsigned int disable:1,
direct:1,
block:1,
- nonblock:1;
+ nonblock:1,
+ wholefrag:1,
+ nosilence:1;
unsigned int periods;
unsigned int period_size;
snd_pcm_oss_setup_t *next;
diff -puN include/sound/seq_midi_event.h~alsa-bk-2003-07-28 include/sound/seq_midi_event.h
--- 25/include/sound/seq_midi_event.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/seq_midi_event.h Tue Jul 29 12:11:31 2003
@@ -30,18 +30,16 @@ typedef struct snd_midi_event_t snd_midi
/* midi status */
struct snd_midi_event_t {
- int qlen; /* queue length */
- int read; /* chars read */
- int type; /* current event type */
- unsigned char lastcmd;
- unsigned char nostat;
- int bufsize;
- unsigned char *buf; /* input buffer */
+ int qlen; /* queue length */
+ int read; /* chars read */
+ int type; /* current event type */
+ unsigned char lastcmd; /* last command (for MIDI state handling) */
+ unsigned char nostat; /* no state flag */
+ int bufsize; /* allocated buffer size */
+ unsigned char *buf; /* input buffer */
spinlock_t lock;
};
-#define SND_MIDI_EVENT_NOSTATUS (1<<0) /* don't encode MIDI status */
-
int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev);
int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize);
void snd_midi_event_free(snd_midi_event_t *dev);
diff -puN include/sound/soundfont.h~alsa-bk-2003-07-28 include/sound/soundfont.h
--- 25/include/sound/soundfont.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/soundfont.h Tue Jul 29 12:11:31 2003
@@ -95,7 +95,6 @@ typedef struct snd_sf_list {
int zone_locked; /* locked time for zone */
int sample_locked; /* locked time for sample */
snd_sf_callback_t callback; /* callback functions */
- char sf_locked; /* font lock flag */
struct semaphore presets_mutex;
spinlock_t lock;
snd_util_memhdr_t *memhdr;
diff -puN include/sound/version.h~alsa-bk-2003-07-28 include/sound/version.h
--- 25/include/sound/version.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/version.h Tue Jul 29 12:11:31 2003
@@ -1,3 +1,3 @@
/* include/version.h. Generated by configure. */
-#define CONFIG_SND_VERSION "0.9.4"
-#define CONFIG_SND_DATE " (Mon Jun 09 12:01:18 2003 UTC)"
+#define CONFIG_SND_VERSION "0.9.6"
+#define CONFIG_SND_DATE " (Mon Jul 28 11:08:42 2003 UTC)"
diff -puN include/sound/ymfpci.h~alsa-bk-2003-07-28 include/sound/ymfpci.h
--- 25/include/sound/ymfpci.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/include/sound/ymfpci.h Tue Jul 29 12:11:31 2003
@@ -25,6 +25,7 @@
#include "pcm.h"
#include "rawmidi.h"
#include "ac97_codec.h"
+#include
#ifndef PCI_VENDOR_ID_YAMAHA
#define PCI_VENDOR_ID_YAMAHA 0x1073
@@ -309,7 +310,12 @@ struct _snd_ymfpci {
struct resource *mpu_res;
unsigned short old_legacy_ctrl;
+#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
unsigned int joystick_port;
+ struct semaphore joystick_mutex;
+ struct resource *joystick_res;
+ struct gameport gameport;
+#endif
void *work_ptr;
dma_addr_t work_ptr_addr;
@@ -383,7 +389,9 @@ int snd_ymfpci_pcm2(ymfpci_t *chip, int
int snd_ymfpci_pcm_spdif(ymfpci_t *chip, int device, snd_pcm_t **rpcm);
int snd_ymfpci_pcm_4ch(ymfpci_t *chip, int device, snd_pcm_t **rpcm);
int snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch);
+#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
int snd_ymfpci_joystick(ymfpci_t *chip);
+#endif
int snd_ymfpci_voice_alloc(ymfpci_t *chip, ymfpci_voice_type_t type, int pair, ymfpci_voice_t **rvoice);
int snd_ymfpci_voice_free(ymfpci_t *chip, ymfpci_voice_t *pvoice);
diff -puN /dev/null scripts/MAKEDEV.snd
--- /dev/null Thu Apr 11 07:25:15 2002
+++ 25-akpm/scripts/MAKEDEV.snd Tue Jul 29 12:11:32 2003
@@ -0,0 +1,161 @@
+#!/bin/bash
+#
+# This script creates the proper /dev/ entries for ALSA devices.
+# See ../Documentation/sound/alsa/ALSA-Configuration.txt for more
+# information.
+
+MAJOR=116
+OSSMAJOR=14
+MAX_CARDS=4
+PERM=666
+OWNER=root.root
+
+if [ "`grep -w -E "^audio" /etc/group`x" != x ]; then
+ PERM=660
+ OWNER=root.audio
+fi
+
+function create_odevice () {
+ rm -f $1
+ echo -n "Creating $1..."
+ mknod -m $PERM $1 c $OSSMAJOR $2
+ chown $OWNER $1
+ echo " done"
+}
+
+function create_odevices () {
+ tmp=0
+ tmp1=0
+ rm -f $1 $1?
+ echo -n "Creating $1?..."
+ while [ $tmp1 -lt $MAX_CARDS ]; do
+ minor=$[ $2 + $tmp ]
+ mknod -m $PERM $1$tmp1 c $OSSMAJOR $minor
+ chown $OWNER $1$tmp1
+ tmp=$[ $tmp + 16 ]
+ tmp1=$[ $tmp1 + 1 ]
+ done
+ echo " done"
+}
+
+function create_device1 () {
+ rm -f $1
+ minor=$2
+ echo -n "Creating $1..."
+ mknod -m $PERM $1 c $MAJOR $minor
+ chown $OWNER $1
+ echo " done"
+}
+
+function create_devices () {
+ tmp=0
+ rm -f $1 $1?
+ echo -n "Creating $1?..."
+ while [ $tmp -lt $MAX_CARDS ]; do
+ minor=$[ $tmp * 32 ]
+ minor=$[ $2 + $minor ]
+ mknod -m $PERM "${1}C${tmp}" c $MAJOR $minor
+ chown $OWNER "${1}C${tmp}"
+ tmp=$[ $tmp + 1 ]
+ done
+ echo " done"
+}
+
+function create_devices2 () {
+ tmp=0
+ rm -f $1 $1?
+ echo -n "Creating $1??..."
+ while [ $tmp -lt $MAX_CARDS ]; do
+ tmp1=0
+ while [ $tmp1 -lt $3 ]; do
+ minor=$[ $tmp * 32 ]
+ minor=$[ $2 + $minor + $tmp1 ]
+ mknod -m $PERM "${1}C${tmp}D${tmp1}" c $MAJOR $minor
+ chown $OWNER "${1}C${tmp}D${tmp1}"
+ tmp1=$[ $tmp1 + 1 ]
+ done
+ tmp=$[ $tmp + 1 ]
+ done
+ echo " done"
+}
+
+function create_devices3 () {
+ tmp=0
+ rm -f $1 $1?
+ echo -n "Creating $1??$4..."
+ while [ $tmp -lt $MAX_CARDS ]; do
+ tmp1=0
+ while [ $tmp1 -lt $3 ]; do
+ minor=$[ $tmp * 32 ]
+ minor=$[ $2 + $minor + $tmp1 ]
+ mknod -m $PERM "${1}C${tmp}D${tmp1}${4}" c $MAJOR $minor
+ chown $OWNER "${1}C${tmp}D${tmp1}${4}"
+ tmp1=$[ $tmp1 + 1 ]
+ done
+ tmp=$[ $tmp + 1 ]
+ done
+ echo " done"
+}
+
+if test "$1" = "-?" || test "$1" = "-h" || test "$1" = "--help"; then
+ echo "Usage: snddevices [max]"
+ exit
+fi
+
+if test "$1" = "max"; then
+ DSP_MINOR=19
+fi
+
+# OSS (Lite) compatible devices...
+
+if test $OSSMAJOR -eq 14; then
+ create_odevices /dev/mixer 0
+ create_odevice /dev/sequencer 1
+ create_odevices /dev/midi 2
+ create_odevices /dev/dsp 3
+ create_odevices /dev/audio 4
+ create_odevice /dev/sndstat 6
+ create_odevice /dev/music 8
+ create_odevices /dev/dmmidi 9
+ create_odevices /dev/dmfm 10
+ create_odevices /dev/amixer 11 # alternate mixer
+ create_odevices /dev/adsp 12 # alternate dsp
+ create_odevices /dev/amidi 13 # alternate midi
+ create_odevices /dev/admmidi 14 # alternate direct midi
+ # create symlinks
+ ln -svf /dev/mixer0 /dev/mixer
+ ln -svf /dev/midi0 /dev/midi
+ ln -svf /dev/dsp0 /dev/dsp
+ ln -svf /dev/audio0 /dev/audio
+ ln -svf /dev/music /dev/sequencer2
+ ln -svf /dev/adsp0 /dev/adsp
+ ln -svf /dev/amidi0 /dev/amidi
+fi
+
+# Remove old devices
+
+mv -f /dev/sndstat /dev/1sndstat
+rm -f /dev/snd*
+mv -f /dev/1sndstat /dev/sndstat
+if [ -d /dev/snd ]; then
+ rm -f /dev/snd/*
+ rmdir /dev/snd
+fi
+
+# Create new ones
+
+mkdir -p /dev/snd
+create_devices /dev/snd/control 0
+create_device1 /dev/snd/seq 1
+create_device1 /dev/snd/timer 33
+create_devices2 /dev/snd/hw 4 4
+create_devices2 /dev/snd/midi 8 8
+create_devices3 /dev/snd/pcm 16 8 p
+create_devices3 /dev/snd/pcm 24 8 c
+
+# Loader devices
+
+echo "ALSA loader devices"
+rm -f /dev/aload*
+create_devices /dev/aload 0
+create_device1 /dev/aloadSEQ 1
diff -puN sound/core/control.c~alsa-bk-2003-07-28 sound/core/control.c
--- 25/sound/core/control.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/control.c Tue Jul 29 12:11:31 2003
@@ -504,8 +504,10 @@ static int snd_ctl_elem_list(snd_card_t
offset = 0;
}
up_read(&card->controls_rwsem);
- if (list.used > 0 && copy_to_user(list.pids, dst, list.used * sizeof(snd_ctl_elem_id_t)))
+ if (list.used > 0 && copy_to_user(list.pids, dst, list.used * sizeof(snd_ctl_elem_id_t))) {
+ vfree(dst);
return -EFAULT;
+ }
vfree(dst);
} else {
down_read(&card->controls_rwsem);
diff -puN sound/core/info.c~alsa-bk-2003-07-28 sound/core/info.c
--- 25/sound/core/info.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/info.c Tue Jul 29 12:11:31 2003
@@ -115,7 +115,7 @@ int snd_iprintf(snd_info_buffer_t * buff
*/
-struct proc_dir_entry *snd_proc_root = NULL;
+static struct proc_dir_entry *snd_proc_root = NULL;
snd_info_entry_t *snd_seq_root = NULL;
#ifdef CONFIG_SND_OSSEMUL
snd_info_entry_t *snd_oss_root = NULL;
@@ -278,18 +278,16 @@ static int snd_info_entry_open(struct in
if ((entry->content == SNDRV_INFO_CONTENT_TEXT &&
!entry->c.text.read_size) ||
(entry->content == SNDRV_INFO_CONTENT_DATA &&
- entry->c.ops->read == NULL) ||
- entry->content == SNDRV_INFO_CONTENT_DEVICE) {
+ entry->c.ops->read == NULL)) {
err = -ENODEV;
goto __error;
}
}
if (mode == O_WRONLY || mode == O_RDWR) {
if ((entry->content == SNDRV_INFO_CONTENT_TEXT &&
- !entry->c.text.write_size) ||
+ !entry->c.text.write_size) ||
(entry->content == SNDRV_INFO_CONTENT_DATA &&
- entry->c.ops->write == NULL) ||
- entry->content == SNDRV_INFO_CONTENT_DEVICE) {
+ entry->c.ops->write == NULL)) {
err = -ENODEV;
goto __error;
}
diff -puN sound/core/ioctl32/ioctl32.c~alsa-bk-2003-07-28 sound/core/ioctl32/ioctl32.c
--- 25/sound/core/ioctl32/ioctl32.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/ioctl32/ioctl32.c Tue Jul 29 12:11:31 2003
@@ -419,13 +419,13 @@ extern struct ioctl32_mapper pcm_mappers
extern struct ioctl32_mapper rawmidi_mappers[];
extern struct ioctl32_mapper timer_mappers[];
extern struct ioctl32_mapper hwdep_mappers[];
-#ifdef CONFIG_SND_SEQUENCER
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
extern struct ioctl32_mapper seq_mappers[];
#endif
static void snd_ioctl32_done(void)
{
-#ifdef CONFIG_SND_SEQUENCER
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
snd_ioctl32_unregister(seq_mappers);
#endif
snd_ioctl32_unregister(hwdep_mappers);
@@ -442,7 +442,7 @@ static int __init snd_ioctl32_init(void)
snd_ioctl32_register(rawmidi_mappers);
snd_ioctl32_register(timer_mappers);
snd_ioctl32_register(hwdep_mappers);
-#ifdef CONFIG_SND_SEQUENCER
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
snd_ioctl32_register(seq_mappers);
#endif
return 0;
diff -puN sound/core/memalloc.c~alsa-bk-2003-07-28 sound/core/memalloc.c
--- 25/sound/core/memalloc.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/memalloc.c Tue Jul 29 12:11:31 2003
@@ -37,18 +37,12 @@ MODULE_DESCRIPTION("Memory allocator for
MODULE_LICENSE("GPL");
-/* so far, pre-defined allocation is only for hammerfall cards... */
-/* #define ENABLE_PREALLOC */
-
-
-#ifdef ENABLE_PREALLOC
#ifndef SNDRV_CARDS
#define SNDRV_CARDS 8
#endif
static int enable[8] = {[0 ... (SNDRV_CARDS-1)] = 1};
MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(enable, "Enable cards to allocate buffers.");
-#endif
/*
@@ -154,6 +148,7 @@ static int compare_device(const struct s
return a->dev.flags == b->dev.flags;
#ifdef CONFIG_PCI
case SNDRV_DMA_TYPE_PCI:
+ case SNDRV_DMA_TYPE_PCI_SG:
return a->dev.pci == b->dev.pci;
#endif
#ifdef CONFIG_SBUS
@@ -336,7 +331,7 @@ int snd_dma_free_reserved(const struct s
* and replaced with the new one.
*
* When NULL buffer pointer or zero buffer size is given, the existing
- * release buffer is released and the entry is removed.
+ * buffer is released and the entry is removed.
*
* Returns zero if successful, or a negative code at error.
*/
@@ -785,7 +780,6 @@ void snd_free_sbus_pages(struct sbus_dev
#endif /* CONFIG_SBUS */
-#ifdef ENABLE_PREALLOC
/*
* allocation of buffers for pre-defined devices
*/
@@ -861,7 +855,6 @@ static void __init preallocate_cards(voi
}
}
}
-#endif
#ifdef CONFIG_PROC_FS
@@ -873,9 +866,56 @@ static int snd_mem_proc_read(char *page,
{
int len = 0;
long pages = snd_allocated_pages >> (PAGE_SHIFT-12);
+ struct list_head *p;
+ struct snd_mem_list *mem;
+ int devno;
+ down(&list_mutex);
len += sprintf(page + len, "pages : %li bytes (%li pages per %likB)\n",
pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
+ devno = 0;
+ list_for_each(p, &mem_list_head) {
+ mem = list_entry(p, struct snd_mem_list, list);
+ devno++;
+ len += sprintf(page + len, "buffer %d : ", devno);
+ if (mem->dev.id == SNDRV_DMA_DEVICE_UNUSED)
+ len += sprintf(page + len, "UNUSED");
+ else
+ len += sprintf(page + len, "ID %08x", mem->dev.id);
+ len += sprintf(page + len, " : type ");
+ switch (mem->dev.type) {
+ case SNDRV_DMA_TYPE_CONTINUOUS:
+ len += sprintf(page + len, "CONT [%x]", mem->dev.dev.flags);
+ break;
+#ifdef CONFIG_PCI
+ case SNDRV_DMA_TYPE_PCI:
+ case SNDRV_DMA_TYPE_PCI_SG:
+ if (mem->dev.dev.pci) {
+ len += sprintf(page + len, "PCI [%04x:%04x]",
+ mem->dev.dev.pci->vendor,
+ mem->dev.dev.pci->device);
+ }
+ break;
+#endif
+#ifdef CONFIG_ISA
+ case SNDRV_DMA_TYPE_ISA:
+ len += sprintf(page + len, "ISA [%x]", mem->dev.dev.flags);
+ break;
+#endif
+#ifdef CONFIG_SBUS
+ case SNDRV_DMA_TYPE_SBUS:
+ len += sprintf(page + len, "SBUS [%x]", mem->dev.dev.sbus->slot);
+ break;
+#endif
+ default:
+ len += sprintf(page + len, "UNKNOWN");
+ break;
+ }
+ len += sprintf(page + len, "\n addr = 0x%lx, size = %d bytes, used = %s\n",
+ (unsigned long)mem->buffer.addr, (int)mem->buffer.bytes,
+ mem->used ? "yes" : "no");
+ }
+ up(&list_mutex);
return len;
}
#endif /* CONFIG_PROC_FS */
@@ -886,10 +926,10 @@ static int snd_mem_proc_read(char *page,
static int __init snd_mem_init(void)
{
+#ifdef CONFIG_PROC_FS
create_proc_read_entry("driver/snd-page-alloc", 0, 0, snd_mem_proc_read, NULL);
-#ifdef ENABLE_PREALLOC
- preallocate_cards();
#endif
+ preallocate_cards();
return 0;
}
@@ -906,6 +946,25 @@ module_init(snd_mem_init)
module_exit(snd_mem_exit)
+#ifndef MODULE
+
+/* format is: snd-page-alloc=enable */
+
+static int __init snd_mem_setup(char *str)
+{
+ static unsigned __initdata nr_dev = 0;
+
+ if (nr_dev >= SNDRV_CARDS)
+ return 0;
+ (void)(get_option(&str,&enable[nr_dev]) == 2);
+ nr_dev++;
+ return 1;
+}
+
+__setup("snd-page-alloc=", snd_mem_setup);
+
+#endif
+
/*
* exports
*/
diff -puN sound/core/oss/pcm_oss.c~alsa-bk-2003-07-28 sound/core/oss/pcm_oss.c
--- 25/sound/core/oss/pcm_oss.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/oss/pcm_oss.c Tue Jul 29 12:11:31 2003
@@ -22,6 +22,9 @@
#if 0
#define PLUGIN_DEBUG
#endif
+#if 0
+#define OSS_DEBUG
+#endif
#include
#include
@@ -442,7 +445,7 @@ static int snd_pcm_oss_change_params(snd
} else {
sw_params->start_threshold = runtime->boundary;
}
- if (atomic_read(&runtime->mmap_count))
+ if (atomic_read(&runtime->mmap_count) || substream->stream == SNDRV_PCM_STREAM_CAPTURE)
sw_params->stop_threshold = runtime->boundary;
else
sw_params->stop_threshold = runtime->buffer_size;
@@ -451,8 +454,18 @@ static int snd_pcm_oss_change_params(snd
sw_params->sleep_min = 0;
sw_params->avail_min = runtime->period_size;
sw_params->xfer_align = 1;
- sw_params->silence_threshold = 0;
- sw_params->silence_size = 0;
+ if (atomic_read(&runtime->mmap_count) ||
+ (substream->oss.setup && substream->oss.setup->nosilence)) {
+ sw_params->silence_threshold = 0;
+ sw_params->silence_size = 0;
+ } else {
+ snd_pcm_uframes_t frames;
+ frames = runtime->period_size + 16;
+ if (frames > runtime->buffer_size)
+ frames = runtime->buffer_size;
+ sw_params->silence_threshold = frames;
+ sw_params->silence_size = frames;
+ }
if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) {
snd_printd("SW_PARAMS failed: %i\n", err);
@@ -567,6 +580,31 @@ static int snd_pcm_oss_make_ready(snd_pc
return 0;
}
+static int snd_pcm_oss_capture_position_fixup(snd_pcm_substream_t *substream, snd_pcm_sframes_t *delay)
+{
+ snd_pcm_runtime_t *runtime;
+ snd_pcm_uframes_t frames;
+ int err = 0;
+
+ while (1) {
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, delay);
+ if (err < 0)
+ break;
+ runtime = substream->runtime;
+ if (*delay <= (snd_pcm_sframes_t)runtime->buffer_size)
+ break;
+ /* in case of overrun, skip whole periods like OSS/Linux driver does */
+ /* until avail(delay) <= buffer_size */
+ frames = (*delay - runtime->buffer_size) + runtime->period_size - 1;
+ frames /= runtime->period_size;
+ frames *= runtime->period_size;
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_FORWARD, &frames);
+ if (err < 0)
+ break;
+ }
+ return err;
+}
+
snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel)
{
snd_pcm_runtime_t *runtime = substream->runtime;
@@ -574,6 +612,12 @@ snd_pcm_sframes_t snd_pcm_oss_write3(snd
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
+#ifdef OSS_DEBUG
+ if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
+ printk("pcm_oss: write: recovering from XRUN\n");
+ else
+ printk("pcm_oss: write: recovering from SUSPEND\n");
+#endif
ret = snd_pcm_oss_prepare(substream);
if (ret < 0)
break;
@@ -599,10 +643,17 @@ snd_pcm_sframes_t snd_pcm_oss_write3(snd
snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel)
{
snd_pcm_runtime_t *runtime = substream->runtime;
+ snd_pcm_sframes_t delay;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
+#ifdef OSS_DEBUG
+ if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
+ printk("pcm_oss: read: recovering from XRUN\n");
+ else
+ printk("pcm_oss: read: recovering from SUSPEND\n");
+#endif
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, 0);
if (ret < 0)
break;
@@ -611,6 +662,9 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_
if (ret < 0)
break;
}
+ ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
+ if (ret < 0)
+ break;
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
@@ -640,6 +694,12 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(sn
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
+#ifdef OSS_DEBUG
+ if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
+ printk("pcm_oss: writev: recovering from XRUN\n");
+ else
+ printk("pcm_oss: writev: recovering from SUSPEND\n");
+#endif
ret = snd_pcm_oss_prepare(substream);
if (ret < 0)
break;
@@ -670,6 +730,12 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(snd
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
+#ifdef OSS_DEBUG
+ if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
+ printk("pcm_oss: readv: recovering from XRUN\n");
+ else
+ printk("pcm_oss: readv: recovering from SUSPEND\n");
+#endif
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, 0);
if (ret < 0)
break;
@@ -746,8 +812,9 @@ static ssize_t snd_pcm_oss_write1(snd_pc
buf += tmp;
bytes -= tmp;
xfer += tmp;
- if (runtime->oss.buffer_used == runtime->oss.period_bytes) {
- tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
+ if (substream->oss.setup == NULL || !substream->oss.setup->wholefrag ||
+ runtime->oss.buffer_used == runtime->oss.period_bytes) {
+ tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer, runtime->oss.buffer_used, 1);
if (tmp <= 0)
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
runtime->oss.bytes += tmp;
@@ -855,6 +922,22 @@ static int snd_pcm_oss_reset(snd_pcm_oss
return 0;
}
+static int snd_pcm_oss_post(snd_pcm_oss_file_t *pcm_oss_file)
+{
+ snd_pcm_substream_t *substream;
+ int err;
+
+ substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
+ if (substream != NULL) {
+ if ((err = snd_pcm_oss_make_ready(substream)) < 0)
+ return err;
+ snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_START, 0);
+ }
+ /* note: all errors from the start action are ignored */
+ /* OSS apps do not know, how to handle them */
+ return 0;
+}
+
static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file)
{
int err = 0;
@@ -1188,6 +1271,10 @@ static int snd_pcm_oss_set_trigger(snd_p
snd_pcm_runtime_t *runtime;
snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL;
int err, cmd;
+
+#ifdef OSS_DEBUG
+ printk("pcm_oss: trigger = 0x%x\n", trigger);
+#endif
psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
@@ -1288,7 +1375,7 @@ static int snd_pcm_oss_get_ptr(snd_pcm_o
{
snd_pcm_substream_t *substream;
snd_pcm_runtime_t *runtime;
- snd_pcm_status_t status;
+ snd_pcm_sframes_t delay;
struct count_info info;
int err;
@@ -1306,14 +1393,17 @@ static int snd_pcm_oss_get_ptr(snd_pcm_o
return -EFAULT;
return 0;
}
- memset(&status, 0, sizeof(status));
- err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_STATUS, &status);
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
+ } else {
+ err = snd_pcm_oss_capture_position_fixup(substream, &delay);
+ }
if (err < 0)
return err;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- info.bytes = runtime->oss.bytes - snd_pcm_oss_bytes(substream, runtime->buffer_size - status.avail);
+ info.bytes = runtime->oss.bytes - snd_pcm_oss_bytes(substream, delay);
} else {
- info.bytes = runtime->oss.bytes + snd_pcm_oss_bytes(substream, status.avail);
+ info.bytes = runtime->oss.bytes + snd_pcm_oss_bytes(substream, delay);
}
info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size);
if (atomic_read(&runtime->mmap_count)) {
@@ -1326,10 +1416,7 @@ static int snd_pcm_oss_get_ptr(snd_pcm_o
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
snd_pcm_oss_simulate_fill(substream);
} else {
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- info.blocks = (runtime->buffer_size - status.avail) / runtime->period_size;
- else
- info.blocks = status.avail / runtime->period_size;
+ info.blocks = delay / runtime->period_size;
}
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
@@ -1340,7 +1427,7 @@ static int snd_pcm_oss_get_space(snd_pcm
{
snd_pcm_substream_t *substream;
snd_pcm_runtime_t *runtime;
- snd_pcm_status_t status;
+ snd_pcm_sframes_t avail;
struct audio_buf_info info;
int err;
@@ -1357,7 +1444,6 @@ static int snd_pcm_oss_get_space(snd_pcm
info.fragsize = runtime->oss.period_bytes;
info.fragstotal = runtime->periods;
- memset(&status, 0, sizeof(status));
if (runtime->oss.prepare) {
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
info.bytes = runtime->oss.period_bytes * runtime->periods;
@@ -1367,21 +1453,21 @@ static int snd_pcm_oss_get_space(snd_pcm
info.fragments = 0;
}
} else {
- err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_STATUS, &status);
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &avail);
+ avail = runtime->buffer_size - avail;
+ } else {
+ err = snd_pcm_oss_capture_position_fixup(substream, &avail);
+ }
if (err < 0)
return err;
- info.bytes = snd_pcm_oss_bytes(substream, status.avail);
- info.fragments = status.avail / runtime->period_size;
+ info.bytes = snd_pcm_oss_bytes(substream, avail);
+ info.fragments = avail / runtime->period_size;
}
-#if 0
- /* very experimental stuff to get Quake2 working */
- runtime->oss.period = (info.periods - 1) << 16;
- for (tmp = info.fragsize; tmp > 1; tmp >>= 1)
- runtime->oss.period++;
- runtime->oss.subdivision = 1; /* disable SUBDIVIDE */
+#ifdef OSS_DEBUG
+ printk("pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.fragments, info.fragstotal, info.fragsize);
#endif
- // printk("space: bytes = %i, periods = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.periods, info.fragstotal, info.fragsize);
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
return 0;
@@ -1727,6 +1813,9 @@ static int snd_pcm_oss_ioctl(struct inod
#endif
if (((cmd >> 8) & 0xff) != 'P')
return -EINVAL;
+#ifdef OSS_DEBUG
+ printk("pcm_oss: ioctl = 0x%x\n", cmd);
+#endif
switch (cmd) {
case SNDCTL_DSP_RESET:
return snd_pcm_oss_reset(pcm_oss_file);
@@ -1782,8 +1871,8 @@ static int snd_pcm_oss_ioctl(struct inod
case SOUND_PCM_WRITE_FILTER:
case SOUND_PCM_READ_FILTER:
return -EIO;
- case SNDCTL_DSP_POST: /* to do */
- return 0;
+ case SNDCTL_DSP_POST:
+ return snd_pcm_oss_post(pcm_oss_file);
case SNDCTL_DSP_SUBDIVIDE:
if (get_user(res, (int *)arg))
return -EFAULT;
@@ -1866,7 +1955,15 @@ static ssize_t snd_pcm_oss_read(struct f
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
if (substream == NULL)
return -ENXIO;
+#ifndef OSS_DEBUG
return snd_pcm_oss_read1(substream, buf, count);
+#else
+ {
+ ssize_t res = snd_pcm_oss_read1(substream, buf, count);
+ printk("pcm_oss: read %li bytes (returned %li bytes)\n", (long)count, (long)res);
+ return res;
+ }
+#endif
}
static ssize_t snd_pcm_oss_write(struct file *file, const char *buf, size_t count, loff_t *offset)
@@ -1882,6 +1979,9 @@ static ssize_t snd_pcm_oss_write(struct
up(&file->f_dentry->d_inode->i_sem);
result = snd_pcm_oss_write1(substream, buf, count);
down(&file->f_dentry->d_inode->i_sem);
+#ifdef OSS_DEBUG
+ printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result);
+#endif
return result;
}
@@ -1927,12 +2027,20 @@ static unsigned int snd_pcm_oss_poll(str
}
if (csubstream != NULL) {
snd_pcm_runtime_t *runtime = csubstream->runtime;
+ enum sndrv_pcm_state ostate;
poll_wait(file, &runtime->sleep, wait);
snd_pcm_stream_lock_irq(csubstream);
- if (runtime->status->state != SNDRV_PCM_STATE_RUNNING ||
+ if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING ||
snd_pcm_oss_capture_ready(csubstream))
mask |= POLLIN | POLLRDNORM;
snd_pcm_stream_unlock_irq(csubstream);
+ if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
+ snd_pcm_oss_file_t ofile;
+ memset(&ofile, 0, sizeof(ofile));
+ ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
+ runtime->oss.trigger = 0;
+ snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
+ }
}
return mask;
@@ -1945,6 +2053,9 @@ static int snd_pcm_oss_mmap(struct file
snd_pcm_runtime_t *runtime;
int err;
+#ifdef OSS_DEBUG
+ printk("pcm_oss: mmap begin\n");
+#endif
pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
switch ((area->vm_flags & (VM_READ | VM_WRITE))) {
case VM_READ | VM_WRITE:
@@ -1988,6 +2099,9 @@ static int snd_pcm_oss_mmap(struct file
if (err < 0)
return err;
runtime->oss.mmap_bytes = area->vm_end - area->vm_start;
+#ifdef OSS_DEBUG
+ printk("pcm_oss: mmap ok, bytes = 0x%x\n", runtime->oss.mmap_bytes);
+#endif
/* In mmap mode we never stop */
runtime->stop_threshold = runtime->boundary;
@@ -2005,14 +2119,16 @@ static void snd_pcm_oss_proc_read(snd_in
snd_pcm_oss_setup_t *setup = pstr->oss.setup_list;
down(&pstr->oss.setup_mutex);
while (setup) {
- snd_iprintf(buffer, "%s %u %u%s%s%s%s\n",
+ snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
setup->task_name,
setup->periods,
setup->period_size,
setup->disable ? " disable" : "",
setup->direct ? " direct" : "",
setup->block ? " block" : "",
- setup->nonblock ? " non-block" : "");
+ setup->nonblock ? " non-block" : "",
+ setup->wholefrag ? " whole-frag" : "",
+ setup->nosilence ? " no-silence" : "");
setup = setup->next;
}
up(&pstr->oss.setup_mutex);
@@ -2078,6 +2194,10 @@ static void snd_pcm_oss_proc_write(snd_i
template.block = 1;
} else if (!strcmp(str, "non-block")) {
template.nonblock = 1;
+ } else if (!strcmp(str, "whole-frag")) {
+ template.wholefrag = 1;
+ } else if (!strcmp(str, "no-silence")) {
+ template.nosilence = 1;
}
} while (*str);
if (setup == NULL) {
@@ -2269,3 +2389,24 @@ static void __exit alsa_pcm_oss_exit(voi
module_init(alsa_pcm_oss_init)
module_exit(alsa_pcm_oss_exit)
+
+#ifndef MODULE
+
+/* format is: snd-pcm-oss=dsp_map,adsp_map[,nonblock_open] */
+
+static int __init alsa_pcm_oss_setup(char *str)
+{
+ static unsigned __initdata nr_dev = 0;
+
+ if (nr_dev >= SNDRV_CARDS)
+ return 0;
+ (void)(get_option(&str,&dsp_map[nr_dev]) == 2 &&
+ get_option(&str,&adsp_map[nr_dev]) == 2);
+ (void)(get_option(&str,&nonblock_open) == 2);
+ nr_dev++;
+ return 1;
+}
+
+__setup("snd-pcm-oss=", alsa_pcm_oss_setup);
+
+#endif /* !MODULE */
diff -puN sound/core/oss/pcm_plugin.c~alsa-bk-2003-07-28 sound/core/oss/pcm_plugin.c
--- 25/sound/core/oss/pcm_plugin.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/oss/pcm_plugin.c Tue Jul 29 12:11:31 2003
@@ -56,6 +56,17 @@ static int snd_pcm_plugin_dst_channels_m
return 0;
}
+/*
+ * because some cards might have rates "very close", we ignore
+ * all "resampling" requests within +-5%
+ */
+static int rate_match(unsigned int src_rate, unsigned int dst_rate)
+{
+ unsigned int low = (src_rate * 95) / 100;
+ unsigned int high = (src_rate * 105) / 100;
+ return dst_rate >= low && dst_rate <= high;
+}
+
static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t frames)
{
snd_pcm_plugin_format_t *format;
@@ -80,11 +91,14 @@ static int snd_pcm_plugin_alloc(snd_pcm_
plugin->buf = vmalloc(size);
plugin->buf_frames = frames;
}
- if (!plugin->buf)
+ if (!plugin->buf) {
+ plugin->buf_frames = 0;
return -ENOMEM;
+ }
c = plugin->buf_channels;
if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
for (channel = 0; channel < format->channels; channel++, c++) {
+ c->frames = frames;
c->enabled = 1;
c->wanted = 0;
c->area.addr = plugin->buf;
@@ -95,6 +109,7 @@ static int snd_pcm_plugin_alloc(snd_pcm_
snd_assert((size % format->channels) == 0,);
size /= format->channels;
for (channel = 0; channel < format->channels; channel++, c++) {
+ c->frames = frames;
c->enabled = 1;
c->wanted = 0;
c->area.addr = plugin->buf + (channel * size);
@@ -420,7 +435,7 @@ int snd_pcm_plug_format_plugins(snd_pcm_
/* Format change (linearization) */
if ((srcformat.format != dstformat.format ||
- srcformat.rate != dstformat.rate ||
+ !rate_match(srcformat.rate, dstformat.rate) ||
srcformat.channels != dstformat.channels) &&
!snd_pcm_format_linear(srcformat.format)) {
if (snd_pcm_format_linear(dstformat.format))
@@ -468,7 +483,7 @@ int snd_pcm_plug_format_plugins(snd_pcm_
ttable[v * sv + v] = FULL;
}
tmpformat.channels = dstformat.channels;
- if (srcformat.rate == dstformat.rate &&
+ if (rate_match(srcformat.rate, dstformat.rate) &&
snd_pcm_format_linear(dstformat.format))
tmpformat.format = dstformat.format;
err = snd_pcm_plugin_build_route(plug,
@@ -490,7 +505,7 @@ int snd_pcm_plug_format_plugins(snd_pcm_
}
/* rate resampling */
- if (srcformat.rate != dstformat.rate) {
+ if (!rate_match(srcformat.rate, dstformat.rate)) {
tmpformat.rate = dstformat.rate;
if (srcformat.channels == dstformat.channels &&
snd_pcm_format_linear(dstformat.format))
diff -puN sound/core/oss/pcm_plugin.h~alsa-bk-2003-07-28 sound/core/oss/pcm_plugin.h
--- 25/sound/core/oss/pcm_plugin.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/oss/pcm_plugin.h Tue Jul 29 12:11:31 2003
@@ -106,6 +106,7 @@ typedef struct _snd_pcm_channel_area {
typedef struct _snd_pcm_plugin_channel {
void *aptr; /* pointer to the allocated area */
snd_pcm_channel_area_t area;
+ snd_pcm_uframes_t frames; /* allocated frames */
unsigned int enabled:1; /* channel need to be processed */
unsigned int wanted:1; /* channel is wanted */
} snd_pcm_plugin_channel_t;
diff -puN sound/core/oss/plugin_ops.h~alsa-bk-2003-07-28 sound/core/oss/plugin_ops.h
--- 25/sound/core/oss/plugin_ops.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/oss/plugin_ops.h Tue Jul 29 12:11:31 2003
@@ -323,7 +323,7 @@ get_s16_1234_xxC3: sample = swab16(as_u3
#ifdef PUT_S16_LABELS
/* dst_wid dst_endswap unsigned */
-static void *put_s16_labels[4 * 2 * 2 * 4 * 2] = {
+static void *put_s16_labels[4 * 2 * 2] = {
&&put_s16_xx12_xxx1, /* 16h -> 8h */
&&put_s16_xx12_xxx9, /* 16h ^> 8h */
&&put_s16_xx12_xxx1, /* 16h -> 8s */
diff -puN sound/core/oss/rate.c~alsa-bk-2003-07-28 sound/core/oss/rate.c
--- 25/sound/core/oss/rate.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/oss/rate.c Tue Jul 29 12:11:31 2003
@@ -85,11 +85,7 @@ static void resample_expand(snd_pcm_plug
#undef PUT_S16_LABELS
void *get = get_s16_labels[data->get];
void *put = put_s16_labels[data->put];
- void *get_s16_end = 0;
signed short sample = 0;
-#define GET_S16_END *get_s16_end
-#include "plugin_ops.h"
-#undef GET_S16_END
for (channel = 0; channel < plugin->src_format.channels; channel++) {
pos = data->pos;
@@ -108,24 +104,16 @@ static void resample_expand(snd_pcm_plug
dst_step = dst_channels[channel].area.step / 8;
src_frames1 = src_frames;
dst_frames1 = dst_frames;
- if (pos & ~R_MASK) {
- get_s16_end = &&after_get1;
- goto *get;
- after_get1:
- pos &= R_MASK;
- S1 = S2;
- S2 = sample;
- src += src_step;
- src_frames1--;
- }
while (dst_frames1-- > 0) {
if (pos & ~R_MASK) {
pos &= R_MASK;
S1 = S2;
if (src_frames1-- > 0) {
- get_s16_end = &&after_get2;
goto *get;
- after_get2:
+#define GET_S16_END after_get
+#include "plugin_ops.h"
+#undef GET_S16_END
+ after_get:
S2 = sample;
src += src_step;
}
@@ -318,6 +306,8 @@ static snd_pcm_sframes_t rate_transfer(s
#endif
dst_frames = rate_dst_frames(plugin, frames);
+ if (dst_frames > dst_channels[0].frames)
+ dst_frames = dst_channels[0].frames;
data = (rate_t *)plugin->extra_data;
data->func(plugin, src_channels, dst_channels, frames, dst_frames);
return dst_frames;
diff -puN sound/core/oss/route.c~alsa-bk-2003-07-28 sound/core/oss/route.c
--- 25/sound/core/oss/route.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/oss/route.c Tue Jul 29 12:11:31 2003
@@ -518,6 +518,10 @@ int getput_index(int format)
int sign, width, endian;
sign = !snd_pcm_format_signed(format);
width = snd_pcm_format_width(format) / 8 - 1;
+ if (width < 0 || width > 3) {
+ snd_printk(KERN_ERR "snd-pcm-oss: invalid format %d\n", format);
+ width = 0;
+ }
#ifdef SNDRV_LITTLE_ENDIAN
endian = snd_pcm_format_big_endian(format);
#else
diff -puN sound/core/pcm_lib.c~alsa-bk-2003-07-28 sound/core/pcm_lib.c
--- 25/sound/core/pcm_lib.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/pcm_lib.c Tue Jul 29 12:11:31 2003
@@ -60,7 +60,7 @@ void snd_pcm_playback_silence(snd_pcm_su
return;
snd_assert(runtime->silence_filled <= runtime->buffer_size, return);
noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled;
- if (noise_dist > (snd_pcm_sframes_t) runtime->silence_threshold)
+ if (noise_dist >= (snd_pcm_sframes_t) runtime->silence_threshold)
return;
frames = runtime->silence_threshold - noise_dist;
if (frames > runtime->silence_size)
@@ -84,10 +84,9 @@ void snd_pcm_playback_silence(snd_pcm_su
if ((snd_pcm_sframes_t)runtime->silence_start < 0)
runtime->silence_start += runtime->boundary;
}
- frames = runtime->buffer_size;
+ frames = runtime->buffer_size - runtime->silence_filled;
}
- snd_assert(frames >= runtime->silence_filled, return);
- frames -= runtime->silence_filled;
+ snd_assert(frames <= runtime->buffer_size, return);
if (frames == 0)
return;
ofs = (runtime->silence_start + runtime->silence_filled) % runtime->buffer_size;
@@ -1932,7 +1931,7 @@ void snd_pcm_tick_prepare(snd_pcm_substr
if (runtime->silence_size >= runtime->boundary) {
frames = 1;
} else if (runtime->silence_size > 0 &&
- runtime->silence_filled < runtime->buffer_size) {
+ runtime->silence_filled < runtime->buffer_size) {
snd_pcm_sframes_t noise_dist;
noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled;
snd_assert(noise_dist <= (snd_pcm_sframes_t)runtime->silence_threshold, );
diff -puN sound/core/pcm_memory.c~alsa-bk-2003-07-28 sound/core/pcm_memory.c
--- 25/sound/core/pcm_memory.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/pcm_memory.c Tue Jul 29 12:11:31 2003
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -568,3 +569,18 @@ struct page *snd_pcm_sgbuf_ops_page(snd_
}
#endif /* CONFIG_PCI */
+
+#ifndef MODULE
+
+/* format is: snd-pcm=preallocate_dma,maximum_substreams */
+
+static int __init alsa_pcm_setup(char *str)
+{
+ (void)(get_option(&str,&preallocate_dma) == 2 &&
+ get_option(&str,&maximum_substreams) == 2);
+ return 1;
+}
+
+__setup("snd-pcm=", alsa_pcm_setup);
+
+#endif /* ifndef MODULE */
diff -puN sound/core/pcm_native.c~alsa-bk-2003-07-28 sound/core/pcm_native.c
--- 25/sound/core/pcm_native.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/pcm_native.c Tue Jul 29 12:11:31 2003
@@ -461,9 +461,15 @@ static int snd_pcm_sw_params(snd_pcm_sub
if (params->xfer_align == 0 ||
params->xfer_align % runtime->min_align != 0)
return -EINVAL;
- if ((params->silence_threshold != 0 || params->silence_size < runtime->boundary) &&
- (params->silence_threshold + params->silence_size > runtime->buffer_size))
- return -EINVAL;
+ if (params->silence_size >= runtime->boundary) {
+ if (params->silence_threshold != 0)
+ return -EINVAL;
+ } else {
+ if (params->silence_size > params->silence_threshold)
+ return -EINVAL;
+ if (params->silence_threshold > runtime->buffer_size)
+ return -EINVAL;
+ }
snd_pcm_stream_lock_irq(substream);
runtime->tstamp_mode = params->tstamp_mode;
runtime->sleep_min = params->sleep_min;
diff -puN sound/core/rawmidi.c~alsa-bk-2003-07-28 sound/core/rawmidi.c
--- 25/sound/core/rawmidi.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/rawmidi.c Tue Jul 29 12:11:31 2003
@@ -1437,7 +1437,7 @@ static int snd_rawmidi_dev_free(snd_devi
return snd_rawmidi_free(rmidi);
}
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
static void snd_rawmidi_dev_seq_free(snd_seq_device_t *device)
{
snd_rawmidi_t *rmidi = snd_magic_cast(snd_rawmidi_t, device->private_data, return);
@@ -1513,7 +1513,7 @@ static int snd_rawmidi_dev_register(snd_
}
}
rmidi->proc_entry = entry;
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (!rmidi->ops || !rmidi->ops->dev_register) { /* own registration mechanism */
if (snd_seq_device_new(rmidi->card, rmidi->device, SNDRV_SEQ_DEV_ID_MIDISYNTH, 0, &rmidi->seq_dev) >= 0) {
rmidi->seq_dev->private_data = rmidi;
@@ -1568,7 +1568,7 @@ static int snd_rawmidi_dev_unregister(sn
rmidi->ops->dev_unregister(rmidi);
snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
up(®ister_mutex);
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (rmidi->seq_dev) {
snd_device_free(rmidi->card, rmidi->seq_dev);
rmidi->seq_dev = NULL;
@@ -1630,6 +1630,26 @@ static void __exit alsa_rawmidi_exit(voi
module_init(alsa_rawmidi_init)
module_exit(alsa_rawmidi_exit)
+#ifndef MODULE
+#ifdef CONFIG_SND_OSSEMUL
+/* format is: snd-rawmidi=midi_map,amidi_map */
+
+static int __init alsa_rawmidi_setup(char *str)
+{
+ static unsigned __initdata nr_dev = 0;
+
+ if (nr_dev >= SNDRV_CARDS)
+ return 0;
+ (void)(get_option(&str,&midi_map[nr_dev]) == 2 &&
+ get_option(&str,&amidi_map[nr_dev]) == 2);
+ nr_dev++;
+ return 1;
+}
+
+__setup("snd-rawmidi=", alsa_rawmidi_setup);
+#endif /* CONFIG_SND_OSSEMUL */
+#endif /* ifndef MODULE */
+
EXPORT_SYMBOL(snd_rawmidi_output_params);
EXPORT_SYMBOL(snd_rawmidi_input_params);
EXPORT_SYMBOL(snd_rawmidi_drop_output);
diff -puN sound/core/rtctimer.c~alsa-bk-2003-07-28 sound/core/rtctimer.c
--- 25/sound/core/rtctimer.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/rtctimer.c Tue Jul 29 12:11:31 2003
@@ -57,7 +57,7 @@ static struct _snd_timer_hardware rtc_hw
.stop = rtctimer_stop,
};
-int rtctimer_freq = RTC_FREQ; /* frequency */
+static int rtctimer_freq = RTC_FREQ; /* frequency */
static snd_timer_t *rtctimer;
static atomic_t rtc_inc = ATOMIC_INIT(0);
static rtc_task_t rtc_task;
@@ -182,4 +182,16 @@ MODULE_PARM_DESC(rtctimer_freq, "timer f
MODULE_LICENSE("GPL");
+#ifndef MODULE
+/* format is: snd-rtctimer=freq */
+
+static int __init rtctimer_setup(char *str)
+{
+ (void)(get_option(&str,&rtctimer_freq) == 2);
+ return 1;
+}
+
+__setup("snd-rtctimer=", rtctimer_setup);
+#endif /* ifndef MODULE */
+
#endif /* CONFIG_RTC || CONFIG_RTC_MODULE */
diff -puN sound/core/seq/seq_clientmgr.c~alsa-bk-2003-07-28 sound/core/seq/seq_clientmgr.c
--- 25/sound/core/seq/seq_clientmgr.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/seq/seq_clientmgr.c Tue Jul 29 12:11:31 2003
@@ -521,6 +521,32 @@ static int bounce_error_event(client_t *
/*
+ * rewrite the time-stamp of the event record with the curren time
+ * of the given queue.
+ * return non-zero if updated.
+ */
+static int update_timestamp_of_queue(snd_seq_event_t *event, int queue, int real_time)
+{
+ queue_t *q;
+
+ q = queueptr(queue);
+ if (! q)
+ return 0;
+ event->queue = queue;
+ event->flags &= ~SNDRV_SEQ_TIME_STAMP_MASK;
+ if (real_time) {
+ event->time.time = snd_seq_timer_get_cur_time(q->timer);
+ event->flags |= SNDRV_SEQ_TIME_STAMP_REAL;
+ } else {
+ event->time.tick = snd_seq_timer_get_cur_tick(q->timer);
+ event->flags |= SNDRV_SEQ_TIME_STAMP_TICK;
+ }
+ queuefree(q);
+ return 1;
+}
+
+
+/*
* deliver an event to the specified destination.
* if filter is non-zero, client filter bitmap is tested.
*
@@ -551,6 +577,10 @@ static int snd_seq_deliver_single_event(
goto __skip;
}
+ if (dest_port->timestamping)
+ update_timestamp_of_queue(event, dest_port->time_queue,
+ dest_port->time_real);
+
/* expand the quoted event */
if (event->type == SNDRV_SEQ_EVENT_KERNEL_QUOTE) {
quoted = 1;
@@ -597,27 +627,6 @@ static int snd_seq_deliver_single_event(
}
-static void snd_seq_subs_update_event_header(subscribers_t *subs, snd_seq_event_t *event)
-{
- if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) {
- /* convert time according to flag with subscription */
- queue_t *q;
- q = queueptr(subs->info.queue);
- if (q) {
- event->queue = subs->info.queue;
- event->flags &= ~SNDRV_SEQ_TIME_STAMP_MASK;
- if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL) {
- event->time.time = snd_seq_timer_get_cur_time(q->timer);
- event->flags |= SNDRV_SEQ_TIME_STAMP_REAL;
- } else {
- event->time.tick = snd_seq_timer_get_cur_tick(q->timer);
- event->flags |= SNDRV_SEQ_TIME_STAMP_TICK;
- }
- queuefree(q);
- }
- }
-}
-
/*
* send the event to all subscribers:
*/
@@ -647,7 +656,10 @@ static int deliver_to_subscribers(client
list_for_each(p, &grp->list_head) {
subs = list_entry(p, subscribers_t, src_list);
event->dest = subs->info.dest;
- snd_seq_subs_update_event_header(subs, event);
+ if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
+ /* convert time according to flag with subscription */
+ update_timestamp_of_queue(event, subs->info.queue,
+ subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL);
err = snd_seq_deliver_single_event(client, event,
0, atomic, hop);
if (err < 0)
diff -puN sound/core/seq/seq_midi_event.c~alsa-bk-2003-07-28 sound/core/seq/seq_midi_event.c
--- 25/sound/core/seq/seq_midi_event.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/seq/seq_midi_event.c Tue Jul 29 12:11:31 2003
@@ -98,14 +98,15 @@ static struct status_event_list_t {
};
static int extra_decode_ctrl14(snd_midi_event_t *dev, unsigned char *buf, int len, snd_seq_event_t *ev);
+static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int count, snd_seq_event_t *ev);
static struct extra_event_list_t {
int event;
int (*decode)(snd_midi_event_t *dev, unsigned char *buf, int len, snd_seq_event_t *ev);
} extra_event[] = {
{SNDRV_SEQ_EVENT_CONTROL14, extra_decode_ctrl14},
- /*{SNDRV_SEQ_EVENT_NONREGPARAM, extra_decode_nrpn},*/
- /*{SNDRV_SEQ_EVENT_REGPARAM, extra_decode_rpn},*/
+ {SNDRV_SEQ_EVENT_NONREGPARAM, extra_decode_xrpn},
+ {SNDRV_SEQ_EVENT_REGPARAM, extra_decode_xrpn},
};
/*
@@ -441,12 +442,12 @@ static int extra_decode_ctrl14(snd_midi_
unsigned char cmd;
int idx = 0;
- if (ev->data.control.param < 32) {
+ cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
+ if (ev->data.control.param < 0x20) {
if (count < 4)
return -ENOMEM;
if (dev->nostat && count < 6)
return -ENOMEM;
- cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
if (cmd != dev->lastcmd || dev->nostat) {
if (count < 5)
return -ENOMEM;
@@ -456,13 +457,11 @@ static int extra_decode_ctrl14(snd_midi_
buf[idx++] = (ev->data.control.value >> 7) & 0x7f;
if (dev->nostat)
buf[idx++] = cmd;
- buf[idx++] = ev->data.control.param + 32;
+ buf[idx++] = ev->data.control.param + 0x20;
buf[idx++] = ev->data.control.value & 0x7f;
- return idx;
} else {
if (count < 2)
return -ENOMEM;
- cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
if (cmd != dev->lastcmd || dev->nostat) {
if (count < 3)
return -ENOMEM;
@@ -470,8 +469,48 @@ static int extra_decode_ctrl14(snd_midi_
}
buf[idx++] = ev->data.control.param & 0x7f;
buf[idx++] = ev->data.control.value & 0x7f;
- return idx;
}
+ return idx;
+}
+
+/* decode reg/nonreg param */
+static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int count, snd_seq_event_t *ev)
+{
+ unsigned char cmd;
+ char *cbytes;
+ static char cbytes_nrpn[4] = { MIDI_CTL_NONREG_PARM_NUM_MSB,
+ MIDI_CTL_NONREG_PARM_NUM_LSB,
+ MIDI_CTL_MSB_DATA_ENTRY,
+ MIDI_CTL_LSB_DATA_ENTRY };
+ static char cbytes_rpn[4] = { MIDI_CTL_REGIST_PARM_NUM_MSB,
+ MIDI_CTL_REGIST_PARM_NUM_LSB,
+ MIDI_CTL_MSB_DATA_ENTRY,
+ MIDI_CTL_LSB_DATA_ENTRY };
+ unsigned char bytes[4];
+ int idx = 0, i;
+
+ if (count < 8)
+ return -ENOMEM;
+ if (dev->nostat && count < 12)
+ return -ENOMEM;
+ cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
+ bytes[0] = ev->data.control.param & 0x007f;
+ bytes[1] = (ev->data.control.param & 0x3f80) >> 7;
+ bytes[2] = ev->data.control.value & 0x007f;
+ bytes[3] = (ev->data.control.value & 0x3f80) >> 7;
+ if (cmd != dev->lastcmd && !dev->nostat) {
+ if (count < 9)
+ return -ENOMEM;
+ buf[idx++] = dev->lastcmd = cmd;
+ }
+ cbytes = ev->type == SNDRV_SEQ_EVENT_NONREGPARAM ? cbytes_nrpn : cbytes_rpn;
+ for (i = 0; i < 4; i++) {
+ if (dev->nostat)
+ buf[idx++] = dev->lastcmd = cmd;
+ buf[idx++] = cbytes[i];
+ buf[idx++] = bytes[i];
+ }
+ return idx;
}
/*
diff -puN sound/core/seq/seq_ports.c~alsa-bk-2003-07-28 sound/core/seq/seq_ports.c
--- 25/sound/core/seq/seq_ports.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/seq/seq_ports.c Tue Jul 29 12:11:31 2003
@@ -352,6 +352,11 @@ int snd_seq_set_port_info(client_port_t
port->midi_voices = info->midi_voices;
port->synth_voices = info->synth_voices;
+ /* timestamping */
+ port->timestamping = (info->flags & SNDRV_SEQ_PORT_FLG_TIMESTAMP) ? 1 : 0;
+ port->time_real = (info->flags & SNDRV_SEQ_PORT_FLG_TIME_REAL) ? 1 : 0;
+ port->time_queue = info->time_queue;
+
return 0;
}
@@ -378,6 +383,15 @@ int snd_seq_get_port_info(client_port_t
info->read_use = port->c_src.count;
info->write_use = port->c_dest.count;
+ /* timestamping */
+ info->flags = 0;
+ if (port->timestamping) {
+ info->flags |= SNDRV_SEQ_PORT_FLG_TIMESTAMP;
+ if (port->time_real)
+ info->flags |= SNDRV_SEQ_PORT_FLG_TIME_REAL;
+ info->time_queue = port->time_queue;
+ }
+
return 0;
}
diff -puN sound/core/seq/seq_ports.h~alsa-bk-2003-07-28 sound/core/seq/seq_ports.h
--- 25/sound/core/seq/seq_ports.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/seq/seq_ports.h Tue Jul 29 12:11:31 2003
@@ -74,6 +74,9 @@ typedef struct client_port_t {
void *private_data;
unsigned int callback_all : 1;
unsigned int closing : 1;
+ unsigned int timestamping: 1;
+ unsigned int time_real: 1;
+ int time_queue;
/* capability, inport, output, sync */
unsigned int capability; /* port capability bits */
diff -puN sound/core/sound.c~alsa-bk-2003-07-28 sound/core/sound.c
--- 25/sound/core/sound.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/sound.c Tue Jul 29 12:11:31 2003
@@ -389,6 +389,24 @@ static void __exit alsa_sound_exit(void)
module_init(alsa_sound_init)
module_exit(alsa_sound_exit)
+#ifndef MODULE
+
+/* format is: snd=major,cards_limit[,device_mode] */
+
+static int __init alsa_sound_setup(char *str)
+{
+ (void)(get_option(&str,&major) == 2 &&
+ get_option(&str,&cards_limit) == 2);
+#ifdef CONFIG_DEVFS_FS
+ (void)(get_option(&str,&device_mode) == 2);
+#endif
+ return 1;
+}
+
+__setup("snd=", alsa_sound_setup);
+
+#endif /* ifndef MODULE */
+
/* sound.c */
EXPORT_SYMBOL(snd_major);
EXPORT_SYMBOL(snd_ecards_limit);
diff -puN sound/core/sound_oss.c~alsa-bk-2003-07-28 sound/core/sound_oss.c
--- 25/sound/core/sound_oss.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/sound_oss.c Tue Jul 29 12:11:31 2003
@@ -23,7 +23,7 @@
#ifdef CONFIG_SND_OSSEMUL
-#if !defined(CONFIG_SOUND) && !defined(CONFIG_SOUND_MODULE)
+#if !defined(CONFIG_SOUND) && !(defined(MODULE) && defined(CONFIG_SOUND_MODULE))
#error "Enable the OSS soundcore multiplexer (CONFIG_SOUND) in the kernel."
#endif
diff -puN sound/core/timer.c~alsa-bk-2003-07-28 sound/core/timer.c
--- 25/sound/core/timer.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/core/timer.c Tue Jul 29 12:11:31 2003
@@ -41,7 +41,7 @@
#define DEFAULT_TIMER_LIMIT 2
#endif
-int timer_limit = DEFAULT_TIMER_LIMIT;
+static int timer_limit = DEFAULT_TIMER_LIMIT;
MODULE_AUTHOR("Jaroslav Kysela , Takashi Iwai ");
MODULE_DESCRIPTION("ALSA timer interface");
MODULE_LICENSE("GPL");
@@ -458,12 +458,14 @@ static int _snd_timer_stop(snd_timer_ins
return -EINVAL;
spin_lock_irqsave(&timer->lock, flags);
list_del_init(&timeri->ack_list);
+#if 0 /* FIXME: this causes dead lock with the sequencer timer */
/* wait until the callback is finished */
while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
spin_unlock_irqrestore(&timer->lock, flags);
udelay(10);
spin_lock_irqsave(&timer->lock, flags);
}
+#endif
list_del_init(&timeri->active_list);
if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) &&
!(timeri->flags & SNDRV_TIMER_IFLG_SLAVE) &&
@@ -1688,10 +1690,11 @@ static ssize_t snd_timer_user_read(struc
break;
}
}
- spin_unlock_irq(&tu->qlock);
if (err < 0)
break;
+ spin_unlock_irq(&tu->qlock);
+
if (tu->tread) {
if (copy_to_user(buffer, &tu->tqueue[tu->qhead++], sizeof(snd_timer_tread_t))) {
err = -EFAULT;
@@ -1712,6 +1715,7 @@ static ssize_t snd_timer_user_read(struc
spin_lock_irq(&tu->qlock);
tu->qused--;
}
+ spin_unlock_irq(&tu->qlock);
return result > 0 ? result : err;
}
@@ -1802,6 +1806,18 @@ static void __exit alsa_timer_exit(void)
module_init(alsa_timer_init)
module_exit(alsa_timer_exit)
+#ifndef MODULE
+/* format is: snd-timer=timer_limit */
+
+static int __init alsa_timer_setup(char *str)
+{
+ (void)(get_option(&str,&timer_limit) == 2);
+ return 1;
+}
+
+__setup("snd-timer=", alsa_timer_setup);
+#endif /* ifndef MODULE */
+
EXPORT_SYMBOL(snd_timer_open);
EXPORT_SYMBOL(snd_timer_close);
EXPORT_SYMBOL(snd_timer_resolution);
diff -puN sound/drivers/dummy.c~alsa-bk-2003-07-28 sound/drivers/dummy.c
--- 25/sound/drivers/dummy.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/drivers/dummy.c Tue Jul 29 12:11:31 2003
@@ -69,6 +69,15 @@ MODULE_DEVICES("{{ALSA,Dummy soundcard}}
#define USE_PERIODS_MAX 255
#endif
+#if 0 /* simple AC97 bridge (intel8x0) with 48kHz AC97 only codec */
+#define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE
+#define USE_CHANNELS_MIN 2
+#define USE_CHANNELS_MAX 2
+#define USE_RATE SNDRV_PCM_RATE_48000
+#define USE_RATE_MIN 48000
+#define USE_RATE_MAX 48000
+#endif
+
/* defaults */
#ifndef MAX_BUFFER_SIZE
@@ -77,6 +86,11 @@ MODULE_DEVICES("{{ALSA,Dummy soundcard}}
#ifndef USE_FORMATS
#define USE_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
#endif
+#ifndef USE_RATE
+#define USE_RATE SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000
+#define USE_RATE_MIN 5500
+#define USE_RATE_MAX 48000
+#endif
#ifndef USE_CHANNELS_MIN
#define USE_CHANNELS_MIN 1
#endif
@@ -271,9 +285,9 @@ static snd_pcm_hardware_t snd_card_dummy
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = USE_FORMATS,
- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
- .rate_min = 5500,
- .rate_max = 48000,
+ .rates = USE_RATE,
+ .rate_min = USE_RATE_MIN,
+ .rate_max = USE_RATE_MAX,
.channels_min = USE_CHANNELS_MIN,
.channels_max = USE_CHANNELS_MAX,
.buffer_bytes_max = MAX_BUFFER_SIZE,
@@ -289,9 +303,9 @@ static snd_pcm_hardware_t snd_card_dummy
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = USE_FORMATS,
- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
- .rate_min = 5500,
- .rate_max = 48000,
+ .rates = USE_RATE,
+ .rate_min = USE_RATE_MIN,
+ .rate_max = USE_RATE_MAX,
.channels_min = USE_CHANNELS_MIN,
.channels_max = USE_CHANNELS_MAX,
.buffer_bytes_max = MAX_BUFFER_SIZE,
diff -puN sound/drivers/opl3/opl3_lib.c~alsa-bk-2003-07-28 sound/drivers/opl3/opl3_lib.c
--- 25/sound/drivers/opl3/opl3_lib.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/drivers/opl3/opl3_lib.c Tue Jul 29 12:11:31 2003
@@ -538,7 +538,7 @@ int snd_opl3_hwdep_new(opl3_t * opl3,
hw->ops.release = snd_opl3_release;
opl3->seq_dev_num = seq_device;
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3,
sizeof(opl3_t*), &opl3->seq_dev) >= 0) {
strcpy(opl3->seq_dev->name, hw->name);
diff -puN sound/drivers/opl4/opl4_lib.c~alsa-bk-2003-07-28 sound/drivers/opl4/opl4_lib.c
--- 25/sound/drivers/opl4/opl4_lib.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/drivers/opl4/opl4_lib.c Tue Jul 29 12:11:31 2003
@@ -20,6 +20,7 @@
#include "opl4_local.h"
#include
#include
+#include
#include
MODULE_AUTHOR("Clemens Ladisch ");
@@ -137,7 +138,7 @@ static int snd_opl4_detect(opl4_t *opl4)
return 0;
}
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
static void snd_opl4_seq_dev_free(snd_seq_device_t *seq_dev)
{
opl4_t *opl4 = snd_magic_cast(opl4_t, seq_dev->private_data, return);
@@ -243,7 +244,7 @@ int snd_opl4_create(snd_card_t *card,
snd_opl4_create_proc(opl4);
#endif
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
opl4->seq_client = -1;
if (opl4->hardware < OPL3_HW_OPL4_ML)
snd_opl4_create_seq_dev(opl4, seq_device);
diff -puN sound/drivers/opl4/opl4_local.h~alsa-bk-2003-07-28 sound/drivers/opl4/opl4_local.h
--- 25/sound/drivers/opl4/opl4_local.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/drivers/opl4/opl4_local.h Tue Jul 29 12:11:31 2003
@@ -163,8 +163,10 @@ typedef struct opl4_voice {
int note;
int velocity;
const opl4_sound_t *sound;
+ u8 level_direct;
u8 reg_f_number;
u8 reg_misc;
+ u8 reg_lfo_vibrato;
} opl4_voice_t;
struct opl4 {
diff -puN sound/drivers/opl4/opl4_synth.c~alsa-bk-2003-07-28 sound/drivers/opl4/opl4_synth.c
--- 25/sound/drivers/opl4/opl4_synth.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/drivers/opl4/opl4_synth.c Tue Jul 29 12:11:31 2003
@@ -267,11 +267,6 @@ static unsigned char snd_opl4_volume_tab
2, 2, 2, 1, 1, 0, 0, 0
};
-static void snd_opl4_write_mask(opl4_t *opl4, u8 reg, u8 mask, u8 value)
-{
- snd_opl4_write(opl4, reg, ((snd_opl4_read(opl4, reg)) & ~mask) | (value & mask));
-}
-
/*
* Initializes all voices.
*/
@@ -302,7 +297,8 @@ void snd_opl4_synth_shutdown(opl4_t *opl
int i;
for (i = 0; i < OPL4_MAX_VOICES; i++)
- snd_opl4_write_mask(opl4, OPL4_REG_MISC + i, OPL4_KEY_ON_BIT, 0);
+ snd_opl4_write(opl4, OPL4_REG_MISC + i,
+ opl4->voices[i].reg_misc & ~OPL4_KEY_ON_BIT);
}
/*
@@ -378,7 +374,9 @@ static void snd_opl4_update_volume(opl4_
att = 0;
else if (att > 0x7e)
att = 0x7e;
- snd_opl4_write(opl4, OPL4_REG_LEVEL + voice->number, att << 1);
+ snd_opl4_write(opl4, OPL4_REG_LEVEL + voice->number,
+ (att << 1) | voice->level_direct);
+ voice->level_direct = 0;
}
static void snd_opl4_update_pan(opl4_t *opl4, opl4_voice_t *voice)
@@ -405,8 +403,10 @@ static void snd_opl4_update_vibrato_dept
depth = (7 - voice->sound->vibrato)
* (voice->chan->control[MIDI_CTL_VIBRATO_DEPTH] & 0x7f);
depth = (depth >> 7) + voice->sound->vibrato;
- snd_opl4_write_mask(opl4, OPL4_REG_LFO_VIBRATO + voice->number,
- OPL4_VIBRATO_DEPTH_MASK, depth);
+ voice->reg_lfo_vibrato &= ~OPL4_VIBRATO_DEPTH_MASK;
+ voice->reg_lfo_vibrato |= depth & OPL4_VIBRATO_DEPTH_MASK;
+ snd_opl4_write(opl4, OPL4_REG_LFO_VIBRATO + voice->number,
+ voice->reg_lfo_vibrato);
}
static void snd_opl4_update_pitch(opl4_t *opl4, opl4_voice_t *voice)
@@ -441,8 +441,6 @@ static void snd_opl4_update_pitch(opl4_t
static void snd_opl4_update_tone_parameters(opl4_t *opl4, opl4_voice_t *voice)
{
- snd_opl4_write(opl4, OPL4_REG_LFO_VIBRATO + voice->number,
- voice->sound->reg_lfo_vibrato);
snd_opl4_write(opl4, OPL4_REG_ATTACK_DECAY1 + voice->number,
voice->sound->reg_attack_decay1);
snd_opl4_write(opl4, OPL4_REG_LEVEL_DECAY2 + voice->number,
@@ -521,6 +519,7 @@ void snd_opl4_note_on(void *private_data
voice[i]->reg_misc = OPL4_LFO_RESET_BIT;
snd_opl4_update_pan(opl4, voice[i]);
snd_opl4_update_pitch(opl4, voice[i]);
+ voice[i]->level_direct = OPL4_LEVEL_DIRECT_BIT;
snd_opl4_update_volume(opl4, voice[i]);
}
@@ -530,6 +529,7 @@ void snd_opl4_note_on(void *private_data
/* set remaining parameters */
for (i = 0; i < voices; i++) {
snd_opl4_update_tone_parameters(opl4, voice[i]);
+ voice[i]->reg_lfo_vibrato = voice[i]->sound->reg_lfo_vibrato;
snd_opl4_update_vibrato_depth(opl4, voice[i]);
}
diff -puN sound/drivers/vx/vx_core.c~alsa-bk-2003-07-28 sound/drivers/vx/vx_core.c
--- 25/sound/drivers/vx/vx_core.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/drivers/vx/vx_core.c Tue Jul 29 12:11:31 2003
@@ -44,8 +44,7 @@ MODULE_LICENSE("GPL");
*/
void snd_vx_delay(vx_core_t *chip, int xmsec)
{
- if (! (chip->chip_status & VX_STAT_IN_SUSPEND) && ! in_interrupt() &&
- xmsec >= 1000 / HZ) {
+ if (! in_interrupt() && xmsec >= 1000 / HZ) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((xmsec * HZ + 999) / 1000);
} else {
@@ -632,6 +631,9 @@ static void vx_proc_read(snd_info_entry_
snd_iprintf(buffer, "Frequency: %d\n", chip->freq);
snd_iprintf(buffer, "Detected Frequency: %d\n", chip->freq_detected);
snd_iprintf(buffer, "Detected UER type: %s\n", uer_type[chip->uer_detected]);
+ snd_iprintf(buffer, "Min/Max/Cur IBL: %d/%d/%d (granularity=%d)\n",
+ chip->ibl.min_size, chip->ibl.max_size, chip->ibl.size,
+ chip->ibl.granularity);
}
static void vx_proc_init(vx_core_t *chip)
diff -puN sound/i2c/cs8427.c~alsa-bk-2003-07-28 sound/i2c/cs8427.c
--- 25/sound/i2c/cs8427.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/i2c/cs8427.c Tue Jul 29 12:11:31 2003
@@ -75,7 +75,7 @@ int snd_cs8427_detect(snd_i2c_bus_t *bus
return res;
}
-static int snd_cs8427_reg_write(snd_i2c_device_t *device, unsigned char reg, unsigned char val)
+int snd_cs8427_reg_write(snd_i2c_device_t *device, unsigned char reg, unsigned char val)
{
int err;
unsigned char buf[2];
@@ -89,7 +89,7 @@ static int snd_cs8427_reg_write(snd_i2c_
return 0;
}
-static int snd_cs8427_reg_read(snd_i2c_device_t *device, unsigned char reg)
+int snd_cs8427_reg_read(snd_i2c_device_t *device, unsigned char reg)
{
int err;
unsigned char buf;
@@ -561,6 +561,8 @@ int snd_cs8427_iec958_pcm(snd_i2c_device
EXPORT_SYMBOL(snd_cs8427_detect);
EXPORT_SYMBOL(snd_cs8427_create);
EXPORT_SYMBOL(snd_cs8427_reset);
+EXPORT_SYMBOL(snd_cs8427_reg_write);
+EXPORT_SYMBOL(snd_cs8427_reg_read);
EXPORT_SYMBOL(snd_cs8427_iec958_build);
EXPORT_SYMBOL(snd_cs8427_iec958_active);
EXPORT_SYMBOL(snd_cs8427_iec958_pcm);
diff -puN sound/i2c/other/ak4xxx-adda.c~alsa-bk-2003-07-28 sound/i2c/other/ak4xxx-adda.c
--- 25/sound/i2c/other/ak4xxx-adda.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/i2c/other/ak4xxx-adda.c Tue Jul 29 12:11:31 2003
@@ -41,7 +41,7 @@ void snd_akm4xxx_write(akm4xxx_t *ak, in
/* save the data */
if (ak->type == SND_AK4524 || ak->type == SND_AK4528) {
- if ((reg != 0x04 && reg != 0x05) || (reg & 0x80) == 0)
+ if ((reg != 0x04 && reg != 0x05) || (val & 0x80) == 0)
snd_akm4xxx_set(ak, chip, reg, val);
else
snd_akm4xxx_set_ipga(ak, chip, reg, val);
diff -puN sound/isa/ad1848/ad1848.c~alsa-bk-2003-07-28 sound/isa/ad1848/ad1848.c
--- 25/sound/isa/ad1848/ad1848.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/isa/ad1848/ad1848.c Tue Jul 29 12:11:31 2003
@@ -46,6 +46,7 @@ static int enable[SNDRV_CARDS] = SNDRV_D
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */
static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
+static int thinkpad[SNDRV_CARDS]; /* Thinkpad special case */
MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(index, "Index value for AD1848 soundcard.");
@@ -65,6 +66,9 @@ MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
MODULE_PARM(dma1, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(dma1, "DMA1 # for AD1848 driver.");
MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
+MODULE_PARM(thinkpad, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series.");
+MODULE_PARM_SYNTAX(thinkpad, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
static snd_card_t *snd_ad1848_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
@@ -77,15 +81,15 @@ static int __init snd_card_ad1848_probe(
int err;
if (port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify port\n");
+ snd_printk(KERN_ERR "ad1848: specify port\n");
return -EINVAL;
}
if (irq[dev] == SNDRV_AUTO_IRQ) {
- snd_printk("specify irq\n");
+ snd_printk(KERN_ERR "ad1848: specify irq\n");
return -EINVAL;
}
if (dma1[dev] == SNDRV_AUTO_DMA) {
- snd_printk("specify dma1\n");
+ snd_printk(KERN_ERR "ad1848: specify dma1\n");
return -EINVAL;
}
@@ -96,7 +100,7 @@ static int __init snd_card_ad1848_probe(
if ((err = snd_ad1848_create(card, port[dev],
irq[dev],
dma1[dev],
- AD1848_HW_DETECT,
+ thinkpad[dev] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT,
&chip)) < 0) {
snd_card_free(card);
return err;
@@ -116,6 +120,10 @@ static int __init snd_card_ad1848_probe(
sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
pcm->name, chip->port, irq[dev], dma1[dev]);
+ if (thinkpad[dev]) {
+ strcat(card->longname, " [Thinkpad]");
+ }
+
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
return err;
@@ -168,7 +176,8 @@ static int __init alsa_card_ad1848_setup
get_id(&str,&id[nr_dev]) == 2 &&
get_option(&str,(int *)&port[nr_dev]) == 2 &&
get_option(&str,&irq[nr_dev]) == 2 &&
- get_option(&str,&dma1[nr_dev]) == 2);
+ get_option(&str,&dma1[nr_dev]) == 2 &&
+ get_option(&str,&thinkpad[nr_dev]) == 2);
nr_dev++;
return 1;
}
diff -puN sound/isa/ad1848/ad1848_lib.c~alsa-bk-2003-07-28 sound/isa/ad1848/ad1848_lib.c
--- 25/sound/isa/ad1848/ad1848_lib.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/isa/ad1848/ad1848_lib.c Tue Jul 29 12:11:31 2003
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -625,6 +626,95 @@ static snd_pcm_uframes_t snd_ad1848_capt
*/
+static void snd_ad1848_thinkpad_twiddle(ad1848_t *chip, int on) {
+
+ int tmp;
+
+ if (!chip->thinkpad_flag) return;
+
+ outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
+ tmp = inb(AD1848_THINKPAD_CTL_PORT2);
+
+ if (on)
+ /* turn it on */
+ tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
+ else
+ /* turn it off */
+ tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
+
+ outb(tmp, AD1848_THINKPAD_CTL_PORT2);
+
+}
+
+#ifdef CONFIG_PM
+static void snd_ad1848_suspend(ad1848_t *chip) {
+
+ snd_card_t *card = chip->card;
+
+ if (card->power_state == SNDRV_CTL_POWER_D3hot)
+ return;
+
+ snd_pcm_suspend_all(chip->pcm);
+ /* FIXME: save registers? */
+
+ if (chip->thinkpad_flag)
+ snd_ad1848_thinkpad_twiddle(chip, 0);
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+}
+
+static void snd_ad1848_resume(ad1848_t *chip) {
+
+ snd_card_t *card = chip->card;
+
+ if (card->power_state == SNDRV_CTL_POWER_D0)
+ return;
+
+ if (chip->thinkpad_flag)
+ snd_ad1848_thinkpad_twiddle(chip, 1);
+
+ /* FIXME: restore registers? */
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+}
+
+/* callback for control API */
+static int snd_ad1848_set_power_state(snd_card_t *card, unsigned int power_state)
+{
+ ad1848_t *chip = (ad1848_t *) card->power_state_private_data;
+ switch (power_state) {
+ case SNDRV_CTL_POWER_D0:
+ case SNDRV_CTL_POWER_D1:
+ case SNDRV_CTL_POWER_D2:
+ snd_ad1848_resume(chip);
+ break;
+ case SNDRV_CTL_POWER_D3hot:
+ case SNDRV_CTL_POWER_D3cold:
+ snd_ad1848_suspend(chip);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int snd_ad1848_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+ ad1848_t *chip = snd_magic_cast(ad1848_t, dev->data, return 0);
+
+ switch (rqst) {
+ case PM_SUSPEND:
+ snd_ad1848_suspend(chip);
+ break;
+ case PM_RESUME:
+ snd_ad1848_resume(chip);
+ break;
+ }
+ return 0;
+}
+
+#endif /* CONFIG_PM */
+
static int snd_ad1848_probe(ad1848_t * chip)
{
unsigned long flags;
@@ -799,6 +889,10 @@ static int snd_ad1848_capture_close(snd_
static int snd_ad1848_free(ad1848_t *chip)
{
+#ifdef CONFIG_PM
+ if (chip->thinkpad_pmstate)
+ pm_unregister(chip->thinkpad_pmstate);
+#endif
if (chip->res_port) {
release_resource(chip->res_port);
kfree_nocheck(chip->res_port);
@@ -870,6 +964,20 @@ int snd_ad1848_create(snd_card_t * card,
}
chip->dma = dma;
+ if (hardware == AD1848_HW_THINKPAD) {
+ chip->thinkpad_flag = 1;
+ chip->hardware = AD1848_HW_DETECT; /* reset */
+ snd_ad1848_thinkpad_twiddle(chip, 1);
+#ifdef CONFIG_PM
+ chip->thinkpad_pmstate = pm_register(PM_ISA_DEV, 0, snd_ad1848_pm_callback);
+ if (chip->thinkpad_pmstate) {
+ chip->thinkpad_pmstate->data = chip;
+ card->set_power_state = snd_ad1848_set_power_state; /* callback */
+ card->power_state_private_data = chip;
+ }
+#endif
+ }
+
if (snd_ad1848_probe(chip) < 0) {
snd_ad1848_free(chip);
return -ENODEV;
diff -puN sound/isa/cmi8330.c~alsa-bk-2003-07-28 sound/isa/cmi8330.c
--- 25/sound/isa/cmi8330.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/isa/cmi8330.c Tue Jul 29 12:11:31 2003
@@ -293,7 +293,7 @@ static int __devinit snd_cmi8330_pnp(int
const struct pnp_card_device_id *id)
{
struct pnp_dev *pdev;
- struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_ATOMIC);
+ struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
int err;
acard->cap = pnp_request_card_device(card, id->devs[0].id, NULL);
diff -puN sound/isa/cs423x/cs4231_lib.c~alsa-bk-2003-07-28 sound/isa/cs423x/cs4231_lib.c
--- 25/sound/isa/cs423x/cs4231_lib.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/isa/cs423x/cs4231_lib.c Tue Jul 29 12:11:31 2003
@@ -1401,8 +1401,10 @@ static int snd_cs4231_pm_callback(struct
switch (rqst) {
case PM_SUSPEND:
- if (chip->suspend)
+ if (chip->suspend) {
+ snd_pcm_suspend_all(chip->pcm);
(*chip->suspend)(chip);
+ }
break;
case PM_RESUME:
if (chip->resume)
diff -puN sound/isa/es18xx.c~alsa-bk-2003-07-28 sound/isa/es18xx.c
--- 25/sound/isa/es18xx.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/isa/es18xx.c Tue Jul 29 12:11:31 2003
@@ -1966,7 +1966,7 @@ static int __devinit snd_audiodrive_pnp(
const struct pnp_card_device_id *id)
{
struct pnp_dev *pdev;
- struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_ATOMIC);
+ struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
int err;
if (!cfg)
diff -puN sound/isa/gus/gus_main.c~alsa-bk-2003-07-28 sound/isa/gus/gus_main.c
--- 25/sound/isa/gus/gus_main.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/isa/gus/gus_main.c Tue Jul 29 12:11:31 2003
@@ -106,7 +106,7 @@ static int snd_gus_free(snd_gus_card_t *
{
if (gus->gf1.res_port2 == NULL)
goto __hw_end;
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (gus->seq_dev) {
snd_device_free(gus->card, gus->seq_dev);
gus->seq_dev = NULL;
@@ -434,7 +434,7 @@ int snd_gus_initialize(snd_gus_card_t *g
}
if ((err = snd_gus_init_dma_irq(gus, 1)) < 0)
return err;
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (snd_seq_device_new(gus->card, 1, SNDRV_SEQ_DEV_ID_GUS,
sizeof(snd_gus_card_t*), &gus->seq_dev) >= 0) {
strcpy(gus->seq_dev->name, "GUS");
diff -puN sound/isa/opl3sa2.c~alsa-bk-2003-07-28 sound/isa/opl3sa2.c
--- 25/sound/isa/opl3sa2.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/isa/opl3sa2.c Tue Jul 29 12:11:31 2003
@@ -552,9 +552,8 @@ static void snd_opl3sa2_suspend(opl3sa2_
if (card->power_state == SNDRV_CTL_POWER_D3hot)
return;
- /* FIXME: is this order ok? */
+ snd_pcm_suspend_all(chip->cs4231->pcm); /* stop before saving regs */
chip->cs4231_suspend(chip->cs4231);
- snd_pcm_suspend_all(chip->cs4231->pcm);
/* power down */
snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3);
diff -puN sound/isa/sb/emu8000.c~alsa-bk-2003-07-28 sound/isa/sb/emu8000.c
--- 25/sound/isa/sb/emu8000.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/isa/sb/emu8000.c Tue Jul 29 12:11:31 2003
@@ -1138,7 +1138,7 @@ snd_emu8000_new(snd_card_t *card, int in
snd_emu8000_free(hw);
return err;
}
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
sizeof(emu8000_t*), &awe) >= 0) {
strcpy(awe->name, "EMU-8000");
diff -puN sound/isa/sb/sb16.c~alsa-bk-2003-07-28 sound/isa/sb/sb16.c
--- 25/sound/isa/sb/sb16.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/isa/sb/sb16.c Tue Jul 29 12:11:31 2003
@@ -66,7 +66,7 @@ MODULE_DEVICES("{{Creative Labs,SB AWE 3
#define SNDRV_DEBUG_IRQ
#endif
-#if defined(SNDRV_SBAWE) && (defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE))
+#if defined(SNDRV_SBAWE) && (defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)))
#define SNDRV_SBAWE_EMU8000
#endif
@@ -350,6 +350,18 @@ __wt_error:
#endif /* CONFIG_PNP */
+static void snd_sb16_free(snd_card_t *card)
+{
+ struct snd_card_sb16 *acard = (struct snd_card_sb16 *)card->private_data;
+
+ if (acard == NULL)
+ return;
+ if (acard->fm_res) {
+ release_resource(acard->fm_res);
+ kfree_nocheck(acard->fm_res);
+ }
+}
+
static int __init snd_sb16_probe(int dev,
struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
@@ -374,6 +386,7 @@ static int __init snd_sb16_probe(int dev
if (card == NULL)
return -ENOMEM;
acard = (struct snd_card_sb16 *) card->private_data;
+ card->private_free = snd_sb16_free;
#ifdef CONFIG_PNP
if (isapnp[dev]) {
if ((err = snd_card_sb16_pnp(dev, acard, pcard, pid))) {
@@ -464,7 +477,8 @@ static int __init snd_sb16_probe(int dev
if (fm_port[dev] > 0) {
if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2,
- OPL3_HW_OPL3, fm_port[dev] == port[dev],
+ OPL3_HW_OPL3,
+ fm_port[dev] == port[dev] || fm_port[dev] == 0x388,
&opl3) < 0) {
snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n",
fm_port[dev], fm_port[dev] + 2);
diff -puN sound/isa/sscape.c~alsa-bk-2003-07-28 sound/isa/sscape.c
--- 25/sound/isa/sscape.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/isa/sscape.c Tue Jul 29 12:11:31 2003
@@ -809,7 +809,7 @@ static snd_kcontrol_new_t midi_mixer_ctl
*/
static unsigned __devinit get_irq_config(int irq)
{
- static const int valid_irq[] __devinitdata = { 9, 5, 7, 10 };
+ static const int valid_irq[] = { 9, 5, 7, 10 };
unsigned cfg;
for (cfg = 0; cfg < ARRAY_SIZE(valid_irq); ++cfg) {
diff -puN sound/pci/ac97/ac97_codec.c~alsa-bk-2003-07-28 sound/pci/ac97/ac97_codec.c
--- 25/sound/pci/ac97/ac97_codec.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/ac97/ac97_codec.c Tue Jul 29 12:11:31 2003
@@ -32,6 +32,7 @@
#include
#include
#include
+#include "ac97_local.h"
#include "ac97_id.h"
#include "ac97_patch.h"
@@ -51,8 +52,6 @@ MODULE_PARM_SYNTAX(enable_loopback, SNDR
*/
-static void snd_ac97_proc_init(snd_card_t * card, ac97_t * ac97, const char *prefix);
-
typedef struct {
unsigned int id;
unsigned int mask;
@@ -114,7 +113,7 @@ static const ac97_codec_id_t snd_ac97_co
{ 0x414c4740, 0xfffffff0, "ALC202", NULL, NULL },
{ 0x414c4750, 0xfffffff0, "ALC250", NULL, NULL },
{ 0x414c4770, 0xfffffff0, "ALC203", NULL, NULL },
-{ 0x434d4941, 0xffffffff, "CMI9738", NULL, NULL },
+{ 0x434d4941, 0xffffffff, "CMI9738", patch_cm9738, NULL },
{ 0x434d4961, 0xffffffff, "CMI9739", patch_cm9739, NULL },
{ 0x43525900, 0xfffffff8, "CS4297", NULL, NULL },
{ 0x43525910, 0xfffffff8, "CS4297A", patch_cirrus_spdif, NULL },
@@ -134,8 +133,8 @@ static const ac97_codec_id_t snd_ac97_co
{ 0x49434501, 0xffffffff, "ICE1230", NULL, NULL },
{ 0x49434511, 0xffffffff, "ICE1232", NULL, NULL }, // alias VIA VT1611A?
{ 0x49434514, 0xffffffff, "ICE1232A", NULL, NULL },
-{ 0x49434551, 0xffffffff, "VT1616", NULL, NULL },
-{ 0x49434552, 0xffffffff, "VT1616i", NULL, NULL }, // VT1616 compatible (chipset integrated)
+{ 0x49434551, 0xffffffff, "VT1616", patch_vt1616, NULL },
+{ 0x49434552, 0xffffffff, "VT1616i", patch_vt1616, NULL }, // VT1616 compatible (chipset integrated)
{ 0x49544520, 0xffffffff, "IT2226E", NULL, NULL },
{ 0x4e534300, 0xffffffff, "LM4540/43/45/46/48", NULL, NULL }, // only guess --jk
{ 0x4e534331, 0xffffffff, "LM4549", NULL, NULL },
@@ -158,7 +157,7 @@ static const ac97_codec_id_t snd_ac97_co
{ 0x594d4800, 0xffffffff, "YMF743", NULL, NULL },
{ 0x594d4802, 0xffffffff, "YMF752", NULL, NULL },
{ 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL },
-{ 0x83847600, 0xffffffff, "STAC9700/83/84", NULL, NULL },
+{ 0x83847600, 0xffffffff, "STAC9700/83/84", patch_sigmatel_stac9700, NULL },
{ 0x83847604, 0xffffffff, "STAC9701/3/4/5", NULL, NULL },
{ 0x83847605, 0xffffffff, "STAC9704", NULL, NULL },
{ 0x83847608, 0xffffffff, "STAC9708/11", patch_sigmatel_stac9708, NULL },
@@ -171,7 +170,7 @@ static const ac97_codec_id_t snd_ac97_co
{ 0, 0, NULL, NULL, NULL }
};
-static const char *snd_ac97_stereo_enhancements[] =
+const char *snd_ac97_stereo_enhancements[] =
{
/* 0 */ "No 3D Stereo Enhancement",
/* 1 */ "Analog Devices Phat Stereo",
@@ -310,21 +309,6 @@ void snd_ac97_write_cache(ac97_t *ac97,
set_bit(reg, ac97->reg_accessed);
}
-static void snd_ac97_write_cache_test(ac97_t *ac97, unsigned short reg, unsigned short value)
-{
-#if 0
- if (!snd_ac97_valid_reg(ac97, reg))
- return;
- //spin_lock(&ac97->reg_lock);
- ac97->write(ac97, reg, value);
- ac97->regs[reg] = ac97->read(ac97, reg);
- if (value != ac97->regs[reg])
- snd_printk("AC97 reg=%02x val=%04x real=%04x\n", reg, value, ac97->regs[reg]);
- //spin_unlock(&ac97->reg_lock);
-#endif
- snd_ac97_write_cache(ac97, reg, value);
-}
-
/**
* snd_ac97_update - update the value on the given register
* @ac97: the ac97 instance
@@ -518,12 +502,7 @@ static int snd_ac97_put_enum_double(snd_
return snd_ac97_update_bits(ac97, reg, 1 << shift, val << shift);
}
-#define AC97_SINGLE(xname, reg, shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \
- .get = snd_ac97_get_single, .put = snd_ac97_put_single, \
- .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-
-static int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -534,7 +513,7 @@ static int snd_ac97_info_single(snd_kcon
return 0;
}
-static int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
@@ -548,7 +527,7 @@ static int snd_ac97_get_single(snd_kcont
return 0;
}
-static int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
@@ -718,7 +697,7 @@ AC97_ENUM_DOUBLE("Mic Select", AC97_GENE
AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)
};
-static const snd_kcontrol_new_t snd_ac97_controls_3d[2] = {
+const snd_kcontrol_new_t snd_ac97_controls_3d[2] = {
AC97_SINGLE("3D Control - Center", AC97_3D_CONTROL, 8, 15, 0),
AC97_SINGLE("3D Control - Depth", AC97_3D_CONTROL, 0, 15, 0)
};
@@ -743,21 +722,9 @@ AC97_SINGLE("Sigmatel Surround Playback
AC97_DOUBLE("Sigmatel Surround Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1)
};
-static const snd_kcontrol_new_t snd_ac97_sigmatel_controls[] = {
-AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),
-AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)
-};
-
static const snd_kcontrol_new_t snd_ac97_control_eapd =
AC97_SINGLE("External Amplifier Power Down", AC97_POWERDOWN, 15, 1, 0);
-static const snd_kcontrol_new_t snd_ac97_controls_vt1616[] = {
-AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
-AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
-AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
-AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
-};
-
static int snd_ac97_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
@@ -892,7 +859,7 @@ static int snd_ac97_put_spsa(snd_kcontro
return 0;
}
-static const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = {
+const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = {
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -916,7 +883,6 @@ static const snd_kcontrol_new_t snd_ac97
},
AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),AC97_EXTENDED_STATUS, 2, 1, 0),
- // AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA",AC97_EXTENDED_STATUS, 4, 3, 0)
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA",
@@ -927,15 +893,6 @@ static const snd_kcontrol_new_t snd_ac97
},
};
-static const snd_kcontrol_new_t snd_ac97_cirrus_controls_spdif[2] = {
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0),
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE, 0, 3, 0)
-};
-
-static const snd_kcontrol_new_t snd_ac97_conexant_controls_spdif[2] = {
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1, 0),
-};
-
#define AD18XX_PCM_BITS(xname, codec, shift, mask) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_ad18xx_pcm_info_bits, \
.get = snd_ac97_ad18xx_pcm_get_bits, .put = snd_ac97_ad18xx_pcm_put_bits, \
@@ -1031,325 +988,6 @@ static const snd_kcontrol_new_t snd_ac97
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
- */
-static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
- AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
- AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
- AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
- AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
- /* 4: Analog Input To Surround */
- /* 5: Analog Input To Center/LFE */
- /* 6: Independent Master Volume Right */
- /* 7: Independent Master Volume Left */
- /* 8: reserved */
- AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
- AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0),
-#if 0 /* always set in patch_alc650 */
- AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
- AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
- AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1),
- AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1),
- AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
- AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
-#endif
-};
-
-static const snd_kcontrol_new_t snd_ac97_control_alc650_mic =
-AC97_SINGLE("Mic As Center/LFE", AC97_ALC650_MULTICH, 10, 1, 0);
-
-
-static int snd_ac97_alc650_mic_gpio_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
- return 0;
-}
-
-static int snd_ac97_alc650_mic_gpio_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- int change;
- change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
- ucontrol->value.integer.value[0] ? (1 << 10) : 0);
- if (change) {
- /* GPIO0 write for mic */
- snd_ac97_update_bits(ac97, 0x76, 0x01,
- ucontrol->value.integer.value[0] ? 0 : 0x01);
- /* GPIO0 high for mic */
- snd_ac97_update_bits(ac97, 0x78, 0x100,
- ucontrol->value.integer.value[0] ? 0 : 0x100);
- }
- return change;
-}
-
-static const snd_kcontrol_new_t snd_ac97_control_alc650_mic_gpio = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Mic As Center/LFE",
- .info = snd_ac97_info_single,
- .get = snd_ac97_alc650_mic_gpio_get,
- .put = snd_ac97_alc650_mic_gpio_put,
- .private_value = (1 << 16), /* for info */
-};
-
-static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
- AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0),
- AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
- AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0),
-};
-
-/* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
-
-/* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
-static int snd_ac97_ymf753_info_speaker(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[3] = {
- "Standard", "Small", "Smaller"
- };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 3;
- if (uinfo->value.enumerated.item > 2)
- uinfo->value.enumerated.item = 2;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_ac97_ymf753_get_speaker(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short val;
-
- val = ac97->regs[AC97_YMF753_3D_MODE_SEL];
- val = (val >> 10) & 3;
- if (val > 0) /* 0 = invalid */
- val--;
- ucontrol->value.enumerated.item[0] = val;
- return 0;
-}
-
-static int snd_ac97_ymf753_put_speaker(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] > 2)
- return -EINVAL;
- val = (ucontrol->value.enumerated.item[0] + 1) << 10;
- return snd_ac97_update(ac97, AC97_YMF753_3D_MODE_SEL, val);
-}
-
-static const snd_kcontrol_new_t snd_ac97_ymf753_controls_speaker =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "3D Control - Speaker",
- .info = snd_ac97_ymf753_info_speaker,
- .get = snd_ac97_ymf753_get_speaker,
- .put = snd_ac97_ymf753_put_speaker,
-};
-
-/* It is possible to indicate to the Yamaha YMF753 the source to direct to the S/PDIF output. */
-static int snd_ac97_ymf753_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_ymf753_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_YMF753_DIT_CTRL2];
- ucontrol->value.enumerated.item[0] = (val >> 1) & 1;
- return 0;
-}
-
-static int snd_ac97_ymf753_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] << 1;
- return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0002, val);
-}
-
-/* The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
- The YMF753 will output 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)
-{
- static char *texts[3] = { "Disabled", "Pin 43", "Pin 48" };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 3;
- if (uinfo->value.enumerated.item > 2)
- uinfo->value.enumerated.item = 2;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_ac97_ymf753_spdif_output_pin_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_YMF753_DIT_CTRL2];
- ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0;
- return 0;
-}
-
-static int snd_ac97_ymf753_spdif_output_pin_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] > 2)
- return -EINVAL;
- val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 :
- (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0;
- return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0028, val);
- /* The following can be used to direct S/PDIF output to pin 47 (EAPD).
- snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */
-}
-
-static const snd_kcontrol_new_t snd_ac97_ymf753_controls_spdif[3] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
- .info = snd_ac97_ymf753_spdif_source_info,
- .get = snd_ac97_ymf753_spdif_source_get,
- .put = snd_ac97_ymf753_spdif_source_put,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Output Pin",
- .info = snd_ac97_ymf753_spdif_output_pin_info,
- .get = snd_ac97_ymf753_spdif_output_pin_get,
- .put = snd_ac97_ymf753_spdif_output_pin_put,
- },
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",NONE,NONE) "Mute", AC97_YMF753_DIT_CTRL2, 2, 1, 1)
-};
-
-
-/*
- * C-Media codecs
- */
-
-static int snd_ac97_cmedia_spdif_playback_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[] = { "Analog", "Digital" };
-
- 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_cmedia_spdif_playback_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_CM9739_SPDIF_CTRL];
- ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;
- return 0;
-}
-
-static int snd_ac97_cmedia_spdif_playback_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
- return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL,
- 0x01 << 1,
- (ucontrol->value.enumerated.item[0] & 0x01) << 1);
-}
-
-static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = {
- /* BIT 0: SPDI_EN - always true */
- { /* BIT 1: SPDIFS */
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
- .info = snd_ac97_cmedia_spdif_playback_source_info,
- .get = snd_ac97_cmedia_spdif_playback_source_get,
- .put = snd_ac97_cmedia_spdif_playback_source_put,
- },
- /* BIT 2: IG_SPIV */
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9739_SPDIF_CTRL, 2, 1, 0),
- /* BIT 3: SPI2F */
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9739_SPDIF_CTRL, 3, 1, 0),
- /* BIT 4: SPI2SDI */
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL, 4, 1, 0),
- /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
-};
-
-static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = {
- AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0),
-};
-
-static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {
- AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),
- AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
-};
-
/*
*
*/
@@ -1414,7 +1052,7 @@ static int snd_ac97_try_volume_mix(ac97_
if (!(val & mask)) {
/* nothing seems to be here - mute flag is not set */
/* try another test */
- snd_ac97_write_cache_test(ac97, reg, val | mask);
+ snd_ac97_write_cache(ac97, reg, val | mask);
val = snd_ac97_read(ac97, reg);
if (!(val & mask))
return 0; /* nothing here */
@@ -1422,7 +1060,7 @@ static int snd_ac97_try_volume_mix(ac97_
return 1; /* success, useable */
}
-static int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit)
+int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit)
{
unsigned short mask, val, orig, res;
@@ -1491,7 +1129,7 @@ static inline int printable(unsigned int
return x;
}
-static snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97)
+snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97)
{
snd_kcontrol_new_t template;
memcpy(&template, _template, sizeof(template));
@@ -1500,8 +1138,9 @@ static snd_kcontrol_t *snd_ac97_cnew(con
return snd_ctl_new1(&template, ac97);
}
-static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97)
+static int snd_ac97_mixer_build(ac97_t * ac97)
{
+ snd_card_t *card = ac97->card;
snd_kcontrol_t *kctl;
const snd_kcontrol_new_t *knew;
int err;
@@ -1751,39 +1390,9 @@ static int snd_ac97_mixer_build(snd_card
snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0x0000);
/* build 3D controls */
- switch (ac97->id) {
- case AC97_ID_STAC9708:
- if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
- return err;
- strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
- kctl->private_value = AC97_3D_CONTROL | (3 << 16);
- if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
- return err;
- strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
- kctl->private_value = AC97_3D_CONTROL | (2 << 8) | (3 << 16);
- snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
- break;
- case AC97_ID_STAC9700:
- case AC97_ID_STAC9721:
- case AC97_ID_STAC9744:
- case AC97_ID_STAC9756:
- if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
- return err;
- strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
- kctl->private_value = AC97_3D_CONTROL | (3 << 16);
- snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
- break;
- case AC97_ID_YMF753:
- if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
- return err;
- strcpy(kctl->id.name, "3D Control - Wide");
- kctl->private_value = AC97_3D_CONTROL | (9 << 8) | (7 << 16);
- snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0)
- return err;
- snd_ac97_write_cache(ac97, AC97_YMF753_3D_MODE_SEL, 0x0c00);
- break;
- default:
+ if (ac97->build_ops && ac97->build_ops->build_3d) {
+ ac97->build_ops->build_3d(ac97);
+ } else {
if (snd_ac97_try_volume_mix(ac97, AC97_3D_CONTROL)) {
unsigned short val;
val = 0x0707;
@@ -1801,115 +1410,31 @@ static int snd_ac97_mixer_build(snd_card
snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
}
}
-
+
/* build S/PDIF controls */
if (ac97->ext_id & AC97_EI_SPDIF) {
- if (ac97->flags & AC97_CS_SPDIF) {
- for (idx = 0; idx < 3; idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)
- return err;
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_cirrus_controls_spdif[0], ac97))) < 0)
+ if (ac97->build_ops && ac97->build_ops->build_spdif) {
+ if ((err = ac97->build_ops->build_spdif(ac97)) < 0)
return err;
- switch (ac97->id & AC97_ID_CS_MASK) {
- case AC97_ID_CS4205:
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_cirrus_controls_spdif[1], ac97))) < 0)
- return err;
- break;
- }
- /* set default PCM S/PDIF params */
- /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
- snd_ac97_write_cache(ac97, AC97_CSR_SPDIF, 0x0a20);
- } else if (ac97->flags & AC97_CX_SPDIF) {
- for (idx = 0; idx < 3; idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)
- return err;
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_conexant_controls_spdif[0], ac97))) < 0)
- return err;
- /* set default PCM S/PDIF params */
- /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
- snd_ac97_write_cache(ac97, AC97_CXR_AUDIO_MISC,
- snd_ac97_read(ac97, AC97_CXR_AUDIO_MISC) & ~(AC97_CXR_SPDIFEN|AC97_CXR_COPYRGT|AC97_CXR_SPDIF_MASK));
-
} else {
for (idx = 0; idx < 5; idx++)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)
return err;
- switch (ac97->id) {
- case AC97_ID_YMF753:
- 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;
- break;
- case AC97_ID_AD1980:
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_ad1980_spdif_source, ac97))) < 0)
+ if (ac97->build_ops && ac97->build_ops->build_post_spdif) {
+ if ((err = ac97->build_ops->build_post_spdif(ac97)) < 0)
return err;
- break;
- case AC97_ID_CM9739:
- for (idx = 0; idx < ARRAY_SIZE(snd_ac97_cm9739_controls_spdif); idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_cm9739_controls_spdif[idx], ac97))) < 0)
- return err;
- break;
}
/* set default PCM S/PDIF params */
/* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
snd_ac97_write_cache(ac97, AC97_SPDIF, 0x2a20);
}
-
ac97->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
}
/* build chip specific controls */
- switch (ac97->id) {
- case AC97_ID_STAC9700:
- case AC97_ID_STAC9708:
- case AC97_ID_STAC9721:
- case AC97_ID_STAC9744:
- case AC97_ID_STAC9756:
- snd_ac97_write_cache_test(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003);
- if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1))
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_sigmatel_controls[0], ac97))) < 0)
- return err;
- if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0))
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_sigmatel_controls[1], ac97))) < 0)
- return err;
- break;
- case AC97_ID_ALC650:
- /* detect ALC650 rev.E of later */
- for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_alc650); idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_alc650[idx], ac97))) < 0)
- return err;
- if ((err = snd_ctl_add(card, snd_ac97_cnew(ac97->spec.dev_flags ?
- &snd_ac97_control_alc650_mic :
- &snd_ac97_control_alc650_mic_gpio, ac97))) < 0)
- return err;
- if (ac97->ext_id & AC97_EI_SPDIF) {
- for (idx = 0; idx < ARRAY_SIZE(snd_ac97_spdif_controls_alc650); idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_spdif_controls_alc650[idx], ac97))) < 0)
- return err;
- }
- break;
- case AC97_ID_VT1616:
- if (snd_ac97_try_bit(ac97, 0x5a, 9))
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_vt1616[0], ac97))) < 0)
- return err;
- for (idx = 1; idx < ARRAY_SIZE(snd_ac97_controls_vt1616); idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_vt1616[idx], ac97))) < 0)
- return err;
- break;
- case AC97_ID_CM9739:
- for (idx = 1; idx < ARRAY_SIZE(snd_ac97_cm9739_controls); idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_cm9739_controls[idx], ac97))) < 0)
- return err;
- break;
- case AC97_ID_CM9738:
- for (idx = 1; idx < ARRAY_SIZE(snd_ac97_cm9738_controls); idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_cm9738_controls[idx], ac97))) < 0)
- return err;
- break;
- default:
- /* nothing */
- break;
- }
+ if (ac97->build_ops && ac97->build_ops->build_specific)
+ if ((err = ac97->build_ops->build_specific(ac97)) < 0)
+ return err;
if (snd_ac97_try_bit(ac97, AC97_POWERDOWN, 15)) {
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_eapd, ac97))) < 0)
@@ -1931,7 +1456,7 @@ static int snd_ac97_test_rate(ac97_t *ac
unsigned int tmp;
tmp = ((unsigned int)rate * ac97->clock) / 48000;
- snd_ac97_write_cache_test(ac97, reg, tmp & 0xffff);
+ snd_ac97_write_cache(ac97, reg, tmp & 0xffff);
val = snd_ac97_read(ac97, reg);
return val == (tmp & 0xffff);
}
@@ -1961,7 +1486,7 @@ static void snd_ac97_determine_rates(ac9
*r_result = result;
}
-static void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)
+void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)
{
const ac97_codec_id_t *pid;
@@ -2138,12 +1663,12 @@ int snd_ac97_mixer(snd_card_t * card, ac
/* FIXME: add powerdown control */
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 */
+ snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
+ snd_ac97_write_cache(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);
+ snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
+ snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0);
end_time = jiffies + (HZ / 10);
do {
if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)
@@ -2212,10 +1737,10 @@ int snd_ac97_mixer(snd_card_t * card, ac
snd_ac97_free(ac97);
return err;
}
- }
- if (ac97_is_audio(ac97) && snd_ac97_mixer_build(card, ac97) < 0) {
- snd_ac97_free(ac97);
- return -ENOMEM;
+ if (snd_ac97_mixer_build(ac97) < 0) {
+ snd_ac97_free(ac97);
+ return -ENOMEM;
+ }
}
snd_ac97_proc_init(card, ac97, "ac97");
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ac97, &ops)) < 0) {
@@ -2357,21 +1882,21 @@ int snd_ac97_modem(snd_card_t * card, ac
/* note: it's important to set the rate at first */
tmp = AC97_MEA_GPIO;
if (ac97->ext_mid & AC97_MEI_LINE1) {
- snd_ac97_write_cache_test(ac97, AC97_LINE1_RATE, 12000);
+ snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 12000);
tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1;
}
if (ac97->ext_mid & AC97_MEI_LINE2) {
- snd_ac97_write_cache_test(ac97, AC97_LINE2_RATE, 12000);
+ snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 12000);
tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2;
}
if (ac97->ext_mid & AC97_MEI_HANDSET) {
- snd_ac97_write_cache_test(ac97, AC97_HANDSET_RATE, 12000);
+ snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 12000);
tmp |= AC97_MEA_HADC | AC97_MEA_HDAC;
}
- snd_ac97_write_cache_test(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
+ snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
udelay(100);
/* nothing should be in powerdown mode */
- snd_ac97_write_cache_test(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
+ snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
end_time = jiffies + (HZ / 10);
do {
if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)
@@ -2422,270 +1947,6 @@ int snd_ac97_modem(snd_card_t * card, ac
}
/*
- * proc interface
- */
-
-static void snd_ac97_proc_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, int subidx)
-{
- char name[64];
- unsigned int id;
- unsigned short val, tmp, ext, mext;
- static const char *spdif_slots[4] = { " SPDIF=3/4", " SPDIF=7/8", " SPDIF=6/9", " SPDIF=res" };
- static const char *spdif_rates[4] = { " Rate=44.1kHz", " Rate=res", " Rate=48kHz", " Rate=32kHz" };
- static const char *spdif_rates_cs4205[4] = { " Rate=48kHz", " Rate=44.1kHz", " Rate=res", " Rate=res" };
-
- id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16;
- id |= snd_ac97_read(ac97, AC97_VENDOR_ID2);
- 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;
-
- // val = snd_ac97_read(ac97, AC97_RESET);
- val = ac97->caps;
- snd_iprintf(buffer, "Capabilities :%s%s%s%s%s%s\n",
- val & AC97_BC_DEDICATED_MIC ? " -dedicated MIC PCM IN channel-" : "",
- val & AC97_BC_RESERVED1 ? " -reserved1-" : "",
- val & AC97_BC_BASS_TREBLE ? " -bass & treble-" : "",
- val & AC97_BC_SIM_STEREO ? " -simulated stereo-" : "",
- val & AC97_BC_HEADPHONE ? " -headphone out-" : "",
- val & AC97_BC_LOUDNESS ? " -loudness-" : "");
- tmp = ac97->caps & AC97_BC_DAC_MASK;
- snd_iprintf(buffer, "DAC resolution : %s%s%s%s\n",
- tmp == AC97_BC_16BIT_DAC ? "16-bit" : "",
- tmp == AC97_BC_18BIT_DAC ? "18-bit" : "",
- tmp == AC97_BC_20BIT_DAC ? "20-bit" : "",
- tmp == AC97_BC_DAC_MASK ? "???" : "");
- tmp = ac97->caps & AC97_BC_ADC_MASK;
- snd_iprintf(buffer, "ADC resolution : %s%s%s%s\n",
- tmp == AC97_BC_16BIT_ADC ? "16-bit" : "",
- tmp == AC97_BC_18BIT_ADC ? "18-bit" : "",
- tmp == AC97_BC_20BIT_ADC ? "20-bit" : "",
- tmp == AC97_BC_ADC_MASK ? "???" : "");
- snd_iprintf(buffer, "3D enhancement : %s\n",
- snd_ac97_stereo_enhancements[(val >> 10) & 0x1f]);
- snd_iprintf(buffer, "\nCurrent setup\n");
- val = snd_ac97_read(ac97, AC97_MIC);
- snd_iprintf(buffer, "Mic gain : %s [%s]\n", val & 0x0040 ? "+20dB" : "+0dB", ac97->regs[AC97_MIC] & 0x0040 ? "+20dB" : "+0dB");
- val = snd_ac97_read(ac97, AC97_GENERAL_PURPOSE);
- snd_iprintf(buffer, "POP path : %s 3D\n"
- "Sim. stereo : %s\n"
- "3D enhancement : %s\n"
- "Loudness : %s\n"
- "Mono output : %s\n"
- "Mic select : %s\n"
- "ADC/DAC loopback : %s\n",
- val & 0x8000 ? "post" : "pre",
- val & 0x4000 ? "on" : "off",
- val & 0x2000 ? "on" : "off",
- val & 0x1000 ? "on" : "off",
- val & 0x0200 ? "Mic" : "MIX",
- val & 0x0100 ? "Mic2" : "Mic1",
- val & 0x0080 ? "on" : "off");
-
- ext = snd_ac97_read(ac97, AC97_EXTENDED_ID);
- if (ext == 0)
- goto __modem;
-
- snd_iprintf(buffer, "Extended ID : codec=%i rev=%i%s%s%s%s DSA=%i%s%s%s%s\n",
- (ext & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT,
- (ext & AC97_EI_REV_MASK) >> AC97_EI_REV_SHIFT,
- ext & AC97_EI_AMAP ? " AMAP" : "",
- ext & AC97_EI_LDAC ? " LDAC" : "",
- ext & AC97_EI_SDAC ? " SDAC" : "",
- ext & AC97_EI_CDAC ? " CDAC" : "",
- (ext & AC97_EI_DACS_SLOT_MASK) >> AC97_EI_DACS_SLOT_SHIFT,
- ext & AC97_EI_VRM ? " VRM" : "",
- ext & AC97_EI_SPDIF ? " SPDIF" : "",
- ext & AC97_EI_DRA ? " DRA" : "",
- ext & AC97_EI_VRA ? " VRA" : "");
- val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
- snd_iprintf(buffer, "Extended status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
- val & AC97_EA_PRL ? " PRL" : "",
- val & AC97_EA_PRK ? " PRK" : "",
- val & AC97_EA_PRJ ? " PRJ" : "",
- val & AC97_EA_PRI ? " PRI" : "",
- val & AC97_EA_SPCV ? " SPCV" : "",
- val & AC97_EA_MDAC ? " MADC" : "",
- val & AC97_EA_LDAC ? " LDAC" : "",
- val & AC97_EA_SDAC ? " SDAC" : "",
- val & AC97_EA_CDAC ? " CDAC" : "",
- ext & AC97_EI_SPDIF ? spdif_slots[(val & AC97_EA_SPSA_SLOT_MASK) >> AC97_EA_SPSA_SLOT_SHIFT] : "",
- val & AC97_EA_VRM ? " VRM" : "",
- val & AC97_EA_SPDIF ? " SPDIF" : "",
- val & AC97_EA_DRA ? " DRA" : "",
- val & AC97_EA_VRA ? " VRA" : "");
- if (ext & AC97_EI_VRA) { /* VRA */
- val = snd_ac97_read(ac97, AC97_PCM_FRONT_DAC_RATE);
- snd_iprintf(buffer, "PCM front DAC : %iHz\n", val);
- if (ext & AC97_EI_SDAC) {
- val = snd_ac97_read(ac97, AC97_PCM_SURR_DAC_RATE);
- snd_iprintf(buffer, "PCM Surr DAC : %iHz\n", val);
- }
- if (ext & AC97_EI_LDAC) {
- val = snd_ac97_read(ac97, AC97_PCM_LFE_DAC_RATE);
- snd_iprintf(buffer, "PCM LFE DAC : %iHz\n", val);
- }
- val = snd_ac97_read(ac97, AC97_PCM_LR_ADC_RATE);
- snd_iprintf(buffer, "PCM ADC : %iHz\n", val);
- }
- if (ext & AC97_EI_VRM) {
- val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE);
- snd_iprintf(buffer, "PCM MIC ADC : %iHz\n", val);
- }
- if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF)) {
- if (ac97->flags & AC97_CS_SPDIF)
- val = snd_ac97_read(ac97, AC97_CSR_SPDIF);
- else
- val = snd_ac97_read(ac97, AC97_SPDIF);
-
- snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n",
- val & AC97_SC_PRO ? " PRO" : " Consumer",
- val & AC97_SC_NAUDIO ? " Non-audio" : " PCM",
- val & AC97_SC_COPY ? " Copyright" : "",
- val & AC97_SC_PRE ? " Preemph50/15" : "",
- (val & AC97_SC_CC_MASK) >> AC97_SC_CC_SHIFT,
- (val & AC97_SC_L) >> 11,
- (ac97->flags & AC97_CS_SPDIF) ?
- spdif_rates_cs4205[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT] :
- spdif_rates[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT],
- (ac97->flags & AC97_CS_SPDIF) ?
- (val & AC97_SC_DRS ? " Validity" : "") :
- (val & AC97_SC_DRS ? " DRS" : ""),
- (ac97->flags & AC97_CS_SPDIF) ?
- (val & AC97_SC_V ? " Enabled" : "") :
- (val & AC97_SC_V ? " Validity" : ""));
- }
-
- __modem:
- mext = snd_ac97_read(ac97, AC97_EXTENDED_MID);
- if (mext == 0)
- return;
-
- snd_iprintf(buffer, "Extended modem ID: codec=%i%s%s%s%s%s\n",
- (mext & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT,
- mext & AC97_MEI_CID2 ? " CID2" : "",
- mext & AC97_MEI_CID1 ? " CID1" : "",
- mext & AC97_MEI_HANDSET ? " HSET" : "",
- mext & AC97_MEI_LINE2 ? " LIN2" : "",
- mext & AC97_MEI_LINE1 ? " LIN1" : "");
- val = snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS);
- snd_iprintf(buffer, "Modem status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
- val & AC97_MEA_GPIO ? " GPIO" : "",
- val & AC97_MEA_MREF ? " MREF" : "",
- val & AC97_MEA_ADC1 ? " ADC1" : "",
- val & AC97_MEA_DAC1 ? " DAC1" : "",
- val & AC97_MEA_ADC2 ? " ADC2" : "",
- val & AC97_MEA_DAC2 ? " DAC2" : "",
- val & AC97_MEA_HADC ? " HADC" : "",
- val & AC97_MEA_HDAC ? " HDAC" : "",
- val & AC97_MEA_PRA ? " PRA(GPIO)" : "",
- val & AC97_MEA_PRB ? " PRB(res)" : "",
- val & AC97_MEA_PRC ? " PRC(ADC1)" : "",
- val & AC97_MEA_PRD ? " PRD(DAC1)" : "",
- val & AC97_MEA_PRE ? " PRE(ADC2)" : "",
- val & AC97_MEA_PRF ? " PRF(DAC2)" : "",
- val & AC97_MEA_PRG ? " PRG(HADC)" : "",
- val & AC97_MEA_PRH ? " PRH(HDAC)" : "");
- if (mext & AC97_MEI_LINE1) {
- val = snd_ac97_read(ac97, AC97_LINE1_RATE);
- snd_iprintf(buffer, "Line1 rate : %iHz\n", val);
- }
- if (mext & AC97_MEI_LINE2) {
- val = snd_ac97_read(ac97, AC97_LINE2_RATE);
- snd_iprintf(buffer, "Line2 rate : %iHz\n", val);
- }
- if (mext & AC97_MEI_HANDSET) {
- val = snd_ac97_read(ac97, AC97_HANDSET_RATE);
- snd_iprintf(buffer, "Headset rate : %iHz\n", val);
- }
-}
-
-static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
-{
- ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
-
- if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86
- int idx;
- down(&ac97->spec.ad18xx.mutex);
- for (idx = 0; idx < 3; idx++)
- if (ac97->spec.ad18xx.id[idx]) {
- /* select single codec */
- snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
- snd_ac97_proc_read_main(ac97, buffer, idx);
- snd_iprintf(buffer, "\n\n");
- }
- /* select all codecs */
- snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000);
- up(&ac97->spec.ad18xx.mutex);
-
- snd_iprintf(buffer, "\nAD18XX configuration\n");
- snd_iprintf(buffer, "Unchained : 0x%04x,0x%04x,0x%04x\n",
- ac97->spec.ad18xx.unchained[0],
- ac97->spec.ad18xx.unchained[1],
- ac97->spec.ad18xx.unchained[2]);
- snd_iprintf(buffer, "Chained : 0x%04x,0x%04x,0x%04x\n",
- ac97->spec.ad18xx.chained[0],
- ac97->spec.ad18xx.chained[1],
- ac97->spec.ad18xx.chained[2]);
- } else {
- snd_ac97_proc_read_main(ac97, buffer, 0);
- }
-}
-
-static void snd_ac97_proc_regs_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, int subidx)
-{
- int reg, val;
-
- for (reg = 0; reg < 0x80; reg += 2) {
- val = snd_ac97_read(ac97, reg);
- snd_iprintf(buffer, "%i:%02x = %04x\n", subidx, reg, val);
- }
-}
-
-static void snd_ac97_proc_regs_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
-{
- ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
-
- if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86
-
- int idx;
- down(&ac97->spec.ad18xx.mutex);
- for (idx = 0; idx < 3; idx++)
- if (ac97->spec.ad18xx.id[idx]) {
- /* select single codec */
- snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
- snd_ac97_proc_regs_read_main(ac97, buffer, idx);
- }
- /* select all codecs */
- snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000);
- up(&ac97->spec.ad18xx.mutex);
- } else {
- snd_ac97_proc_regs_read_main(ac97, buffer, 0);
- }
-}
-
-static void snd_ac97_proc_init(snd_card_t * card, ac97_t * ac97, const char *prefix)
-{
- snd_info_entry_t *entry;
- char name[32];
-
- if (ac97->num)
- sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num);
- else
- sprintf(name, "%s#%d", prefix, ac97->addr);
- if (! snd_card_proc_new(card, name, &entry))
- snd_info_set_text_ops(entry, ac97, snd_ac97_proc_read);
- if (ac97->num)
- sprintf(name, "%s#%d-%dregs", prefix, ac97->addr, ac97->num);
- else
- sprintf(name, "%s#%dregs", prefix, ac97->addr);
- if (! snd_card_proc_new(card, name, &entry))
- snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read);
-}
-
-/*
* PCM support
*/
diff -puN /dev/null sound/pci/ac97/ac97_local.h
--- /dev/null Thu Apr 11 07:25:15 2002
+++ 25-akpm/sound/pci/ac97/ac97_local.h Tue Jul 29 12:11:31 2003
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) by Jaroslav Kysela
+ * Universal interface for Audio Codec '97
+ *
+ * For more details look to AC '97 component specification revision 2.2
+ * by Intel Corporation (http://developer.intel.com).
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define AC97_SINGLE(xname, reg, shift, mask, invert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \
+ .get = snd_ac97_get_single, .put = snd_ac97_put_single, \
+ .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
+
+/* ac97_codec.c */
+extern const char *snd_ac97_stereo_enhancements[];
+extern const snd_kcontrol_new_t snd_ac97_controls_3d[];
+extern const snd_kcontrol_new_t snd_ac97_controls_spdif[];
+snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97);
+void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem);
+int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
+int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit);
+
+/* ac97_proc.c */
+void snd_ac97_proc_init(snd_card_t * card, ac97_t * ac97, const char *prefix);
diff -puN sound/pci/ac97/ac97_patch.c~alsa-bk-2003-07-28 sound/pci/ac97/ac97_patch.c
--- 25/sound/pci/ac97/ac97_patch.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/ac97/ac97_patch.c Tue Jul 29 12:11:31 2003
@@ -3,7 +3,8 @@
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.2
- * by Intel Corporation (http://developer.intel.com).
+ * by Intel Corporation (http://developer.intel.com) and to datasheets
+ * for specific codecs.
*
*
* This program is free software; you can redistribute it and/or modify
@@ -28,15 +29,203 @@
#include
#include
#include
+#include
#include
-#include
-#include
#include "ac97_patch.h"
+#include "ac97_id.h"
+#include "ac97_local.h"
+
+#define chip_t ac97_t
/*
* Chip specific initialization
*/
+static int patch_build_controls(ac97_t * ac97, const snd_kcontrol_new_t *controls, int count)
+{
+ int idx, err;
+
+ for (idx = 0; idx < count; idx++)
+ if ((err = snd_ctl_add(ac97->card, snd_ac97_cnew(&controls[idx], ac97))) < 0)
+ return err;
+ return 0;
+}
+
+/* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
+
+/* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
+static int snd_ac97_ymf753_info_speaker(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[3] = {
+ "Standard", "Small", "Smaller"
+ };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 3;
+ if (uinfo->value.enumerated.item > 2)
+ uinfo->value.enumerated.item = 2;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_ac97_ymf753_get_speaker(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned short val;
+
+ val = ac97->regs[AC97_YMF753_3D_MODE_SEL];
+ val = (val >> 10) & 3;
+ if (val > 0) /* 0 = invalid */
+ val--;
+ ucontrol->value.enumerated.item[0] = val;
+ return 0;
+}
+
+static int snd_ac97_ymf753_put_speaker(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] > 2)
+ return -EINVAL;
+ val = (ucontrol->value.enumerated.item[0] + 1) << 10;
+ return snd_ac97_update(ac97, AC97_YMF753_3D_MODE_SEL, val);
+}
+
+static const snd_kcontrol_new_t snd_ac97_ymf753_controls_speaker =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "3D Control - Speaker",
+ .info = snd_ac97_ymf753_info_speaker,
+ .get = snd_ac97_ymf753_get_speaker,
+ .put = snd_ac97_ymf753_put_speaker,
+};
+
+/* It is possible to indicate to the Yamaha YMF753 the source to direct to the S/PDIF output. */
+static int snd_ac97_ymf753_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_ymf753_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_YMF753_DIT_CTRL2];
+ ucontrol->value.enumerated.item[0] = (val >> 1) & 1;
+ return 0;
+}
+
+static int snd_ac97_ymf753_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] << 1;
+ return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0002, val);
+}
+
+/* The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
+ The YMF753 will output 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)
+{
+ static char *texts[3] = { "Disabled", "Pin 43", "Pin 48" };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 3;
+ if (uinfo->value.enumerated.item > 2)
+ uinfo->value.enumerated.item = 2;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_ac97_ymf753_spdif_output_pin_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_YMF753_DIT_CTRL2];
+ ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0;
+ return 0;
+}
+
+static int snd_ac97_ymf753_spdif_output_pin_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] > 2)
+ return -EINVAL;
+ val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 :
+ (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0;
+ return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0028, val);
+ /* The following can be used to direct S/PDIF output to pin 47 (EAPD).
+ snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */
+}
+
+static const snd_kcontrol_new_t snd_ac97_ymf753_controls_spdif[3] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
+ .info = snd_ac97_ymf753_spdif_source_info,
+ .get = snd_ac97_ymf753_spdif_source_get,
+ .put = snd_ac97_ymf753_spdif_source_put,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Output Pin",
+ .info = snd_ac97_ymf753_spdif_output_pin_info,
+ .get = snd_ac97_ymf753_spdif_output_pin_get,
+ .put = snd_ac97_ymf753_spdif_output_pin_put,
+ },
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",NONE,NONE) "Mute", AC97_YMF753_DIT_CTRL2, 2, 1, 1)
+};
+
+static int patch_yamaha_ymf753_3d(ac97_t * ac97)
+{
+ snd_kcontrol_t *kctl;
+ int err;
+
+ if ((err = snd_ctl_add(ac97->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
+ return err;
+ strcpy(kctl->id.name, "3D Control - Wide");
+ kctl->private_value = AC97_3D_CONTROL | (9 << 8) | (7 << 16);
+ snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
+ if ((err = snd_ctl_add(ac97->card, snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0)
+ return err;
+ snd_ac97_write_cache(ac97, AC97_YMF753_3D_MODE_SEL, 0x0c00);
+ return 0;
+}
+
+static int patch_yamaha_ymf753_post_spdif(ac97_t * ac97)
+{
+ int err;
+
+ if ((err = patch_build_controls(ac97, snd_ac97_ymf753_controls_spdif, ARRAY_SIZE(snd_ac97_ymf753_controls_spdif))) < 0)
+ return err;
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_yamaha_ymf753_ops = {
+ .build_3d = patch_yamaha_ymf753_3d,
+ .build_post_spdif = patch_yamaha_ymf753_post_spdif
+};
+
int patch_yamaha_ymf753(ac97_t * ac97)
{
/* Patch for Yamaha YMF753, Copyright (c) by David Shust, dshust@shustring.com.
@@ -46,6 +235,7 @@ int patch_yamaha_ymf753(ac97_t * ac97)
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.
*/
+ ac97->build_ops = &patch_yamaha_ymf753_ops;
ac97->caps |= AC97_BC_BASS_TREBLE;
ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */
return 0;
@@ -57,12 +247,6 @@ int patch_yamaha_ymf753(ac97_t * ac97)
* added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
*/
-#define AC97_WM97XX_FMIXER_VOL 0x72
-#define AC97_WM9704_RMIXER_VOL 0x74
-#define AC97_WM9704_TEST 0x5a
-#define AC97_WM9704_RPCM_VOL 0x70
-#define AC97_WM9711_OUT3VOL 0x16
-
int patch_wolfson03(ac97_t * ac97)
{
/* This is known to work for the ViewSonic ViewPad 1000
@@ -117,10 +301,89 @@ int patch_tritech_tr28028(ac97_t * ac97)
return 0;
}
+static int patch_sigmatel_stac9700_3d(ac97_t * ac97)
+{
+ snd_kcontrol_t *kctl;
+ int err;
+
+ if ((err = snd_ctl_add(ac97->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
+ return err;
+ strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
+ kctl->private_value = AC97_3D_CONTROL | (3 << 16);
+ snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
+ return 0;
+}
+
+static int patch_sigmatel_stac9708_3d(ac97_t * ac97)
+{
+ snd_kcontrol_t *kctl;
+ int err;
+
+ if ((err = snd_ctl_add(ac97->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
+ return err;
+ strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
+ kctl->private_value = AC97_3D_CONTROL | (3 << 16);
+ if ((err = snd_ctl_add(ac97->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
+ return err;
+ strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
+ kctl->private_value = AC97_3D_CONTROL | (2 << 8) | (3 << 16);
+ snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
+ return 0;
+}
+
+static const snd_kcontrol_new_t snd_ac97_sigmatel_4speaker =
+AC97_SINGLE("Sigmatel 4-Speaker Stereo Playback Switch", AC97_SIGMATEL_DAC2INVERT, 2, 1, 0);
+
+static const snd_kcontrol_new_t snd_ac97_sigmatel_phaseinvert =
+AC97_SINGLE("Sigmatel Surround Phase Inversion Playback Switch", AC97_SIGMATEL_DAC2INVERT, 3, 1, 0);
+
+static const snd_kcontrol_new_t snd_ac97_sigmatel_controls[] = {
+AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),
+AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)
+};
+
+static int patch_sigmatel_stac97xx_specific(ac97_t * ac97)
+{
+ int err;
+
+ snd_ac97_write_cache(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003);
+ if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1))
+ if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[0], 1)) < 0)
+ return err;
+ if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0))
+ if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[1], 1)) < 0)
+ return err;
+ if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2))
+ if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_4speaker, 1)) < 0)
+ return err;
+ if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3))
+ if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_phaseinvert, 1)) < 0)
+ return err;
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = {
+ .build_3d = patch_sigmatel_stac9700_3d,
+ .build_specific = patch_sigmatel_stac97xx_specific
+};
+
+static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
+ .build_3d = patch_sigmatel_stac9708_3d,
+ .build_specific = patch_sigmatel_stac97xx_specific
+};
+
+int patch_sigmatel_stac9700(ac97_t * ac97)
+{
+ ac97->build_ops = &patch_sigmatel_stac9700_ops;
+ return 0;
+}
+
int patch_sigmatel_stac9708(ac97_t * ac97)
{
unsigned int codec72, codec6c;
+ ac97->build_ops = &patch_sigmatel_stac9708_ops;
+
codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000;
codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG);
@@ -142,6 +405,7 @@ int patch_sigmatel_stac9708(ac97_t * ac9
int patch_sigmatel_stac9721(ac97_t * ac97)
{
+ ac97->build_ops = &patch_sigmatel_stac9700_ops;
if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) {
// patch for SigmaTel
snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
@@ -156,6 +420,7 @@ int patch_sigmatel_stac9721(ac97_t * ac9
int patch_sigmatel_stac9744(ac97_t * ac97)
{
// patch for SigmaTel
+ ac97->build_ops = &patch_sigmatel_stac9700_ops;
snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
@@ -167,6 +432,7 @@ int patch_sigmatel_stac9744(ac97_t * ac9
int patch_sigmatel_stac9756(ac97_t * ac97)
{
// patch for SigmaTel
+ ac97->build_ops = &patch_sigmatel_stac9700_ops;
snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
@@ -175,6 +441,35 @@ int patch_sigmatel_stac9756(ac97_t * ac9
return 0;
}
+static const snd_kcontrol_new_t snd_ac97_cirrus_controls_spdif[2] = {
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0),
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE, 0, 3, 0)
+};
+
+static int patch_cirrus_build_spdif(ac97_t * ac97)
+{
+ int err;
+
+ if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
+ return err;
+ if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1)) < 0)
+ return err;
+ switch (ac97->id & AC97_ID_CS_MASK) {
+ case AC97_ID_CS4205:
+ if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[1], 1)) < 0)
+ return err;
+ break;
+ }
+ /* set default PCM S/PDIF params */
+ /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
+ snd_ac97_write_cache(ac97, AC97_CSR_SPDIF, 0x0a20);
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_cirrus_ops = {
+ .build_spdif = patch_cirrus_build_spdif
+};
+
int patch_cirrus_spdif(ac97_t * ac97)
{
/* Basically, the cs4201/cs4205/cs4297a has non-standard sp/dif registers.
@@ -188,6 +483,7 @@ int patch_cirrus_spdif(ac97_t * ac97)
- sp/dif ssource select is in 0x5e bits 0,1.
*/
+ ac97->build_ops = &patch_cirrus_ops;
ac97->flags |= AC97_CS_SPDIF;
ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000;
ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
@@ -203,8 +499,32 @@ int patch_cirrus_cs4299(ac97_t * ac97)
return patch_cirrus_spdif(ac97);
}
+static const snd_kcontrol_new_t snd_ac97_conexant_controls_spdif[1] = {
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1, 0),
+};
+
+static int patch_conexant_build_spdif(ac97_t * ac97)
+{
+ int err;
+
+ if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
+ return err;
+ if ((err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1)) < 0)
+ return err;
+ /* set default PCM S/PDIF params */
+ /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
+ snd_ac97_write_cache(ac97, AC97_CXR_AUDIO_MISC,
+ snd_ac97_read(ac97, AC97_CXR_AUDIO_MISC) & ~(AC97_CXR_SPDIFEN|AC97_CXR_COPYRGT|AC97_CXR_SPDIF_MASK));
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_conexant_ops = {
+ .build_spdif = patch_conexant_build_spdif
+};
+
int patch_conexant(ac97_t * ac97)
{
+ ac97->build_ops = &patch_conexant_ops;
ac97->flags |= AC97_CX_SPDIF;
ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
return 0;
@@ -330,6 +650,26 @@ int patch_ad1881(ac97_t * ac97)
return 0;
}
+static const snd_kcontrol_new_t snd_ac97_controls_ad1885[] = {
+ AC97_SINGLE("Digital Mono Direct", AC97_AD_MISC, 11, 1, 0),
+ AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0),
+ AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0),
+ AC97_SINGLE("Zero Fill DAC", AC97_AD_MISC, 15, 1, 0),
+};
+
+static int patch_ad1885_specific(ac97_t * ac97)
+{
+ int err;
+
+ if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0)
+ return err;
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_ad1885_build_ops = {
+ .build_specific = &patch_ad1885_specific
+};
+
int patch_ad1885(ac97_t * ac97)
{
unsigned short jack;
@@ -341,6 +681,8 @@ int patch_ad1885(ac97_t * ac97)
/* turn off jack sense bits D8 & D9 */
jack = snd_ac97_read(ac97, AC97_AD_JACK_SPDIF);
snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, jack | 0x0300);
+
+ ac97->build_ops = &patch_ad1885_build_ops;
return 0;
}
@@ -353,11 +695,63 @@ int patch_ad1886(ac97_t * ac97)
return 0;
}
+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,
+};
+
+static int patch_ad1980_post_spdif(ac97_t * ac97)
+{
+ return patch_build_controls(ac97, &snd_ac97_ad1980_spdif_source, 1);
+}
+
+static struct snd_ac97_build_ops patch_ad1980_build_ops = {
+ .build_post_spdif = &patch_ad1980_post_spdif
+};
+
int patch_ad1980(ac97_t * ac97)
{
unsigned short misc;
patch_ad1881(ac97);
+ ac97->build_ops = &patch_ad1980_build_ops;
/* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */
/* it seems that most vendors connect line-out connector to headphone out of AC'97 */
misc = snd_ac97_read(ac97, AC97_AD_MISC);
@@ -365,6 +759,92 @@ int patch_ad1980(ac97_t * ac97)
return 0;
}
+static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
+ AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
+ AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
+ AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
+ AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
+ /* 4: Analog Input To Surround */
+ /* 5: Analog Input To Center/LFE */
+ /* 6: Independent Master Volume Right */
+ /* 7: Independent Master Volume Left */
+ /* 8: reserved */
+ AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
+ AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0),
+#if 0 /* always set in patch_alc650 */
+ AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
+ AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
+ AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1),
+ AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1),
+ AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
+ AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
+#endif
+};
+
+static const snd_kcontrol_new_t snd_ac97_control_alc650_mic =
+AC97_SINGLE("Mic As Center/LFE", AC97_ALC650_MULTICH, 10, 1, 0);
+
+static int snd_ac97_alc650_mic_gpio_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
+ return 0;
+}
+
+static int snd_ac97_alc650_mic_gpio_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ int change;
+ change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
+ ucontrol->value.integer.value[0] ? (1 << 10) : 0);
+ if (change) {
+ /* GPIO0 write for mic */
+ snd_ac97_update_bits(ac97, 0x76, 0x01,
+ ucontrol->value.integer.value[0] ? 0 : 0x01);
+ /* GPIO0 high for mic */
+ snd_ac97_update_bits(ac97, 0x78, 0x100,
+ ucontrol->value.integer.value[0] ? 0 : 0x100);
+ }
+ return change;
+}
+
+static const snd_kcontrol_new_t snd_ac97_control_alc650_mic_gpio = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic As Center/LFE",
+ .info = snd_ac97_info_single,
+ .get = snd_ac97_alc650_mic_gpio_get,
+ .put = snd_ac97_alc650_mic_gpio_put,
+ .private_value = (1 << 16), /* for info */
+};
+
+static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
+ AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0),
+ AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
+ AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0),
+};
+
+static int patch_alc650_specific(ac97_t * ac97)
+{
+ int err;
+
+ if ((err = patch_build_controls(ac97, snd_ac97_controls_alc650, ARRAY_SIZE(snd_ac97_controls_alc650))) < 0)
+ return err;
+ if ((err = patch_build_controls(ac97,
+ ac97->spec.dev_flags ?
+ &snd_ac97_control_alc650_mic :
+ &snd_ac97_control_alc650_mic_gpio, 1)) < 0)
+ return err;
+ if (ac97->ext_id & AC97_EI_SPDIF) {
+ if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0)
+ return err;
+ }
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_alc650_ops = {
+ .build_specific = patch_alc650_specific
+};
+
int patch_alc650(ac97_t * ac97)
{
unsigned short val;
@@ -374,6 +854,7 @@ int patch_alc650(ac97_t * ac97)
* this is used for switching mic and center/lfe, which needs
* resetting GPIO0 level on the older revision.
*/
+ ac97->build_ops = &patch_alc650_ops;
ac97->spec.dev_flags = 0;
/* check spdif (should be only on rev.E) */
@@ -417,10 +898,101 @@ int patch_alc650(ac97_t * ac97)
return 0;
}
+static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {
+ AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),
+ AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
+};
+
+static int patch_cm9738_specific(ac97_t * ac97)
+{
+ return patch_build_controls(ac97, snd_ac97_cm9738_controls, ARRAY_SIZE(snd_ac97_cm9738_controls));
+}
+
+static struct snd_ac97_build_ops patch_cm9738_ops = {
+ .build_specific = patch_cm9738_specific
+};
+
+int patch_cm9738(ac97_t * ac97)
+{
+ ac97->build_ops = &patch_cm9738_ops;
+ return 0;
+}
+
+static int snd_ac97_cmedia_spdif_playback_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[] = { "Analog", "Digital" };
+
+ 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_cmedia_spdif_playback_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_CM9739_SPDIF_CTRL];
+ ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;
+ return 0;
+}
+
+static int snd_ac97_cmedia_spdif_playback_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+ return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL,
+ 0x01 << 1,
+ (ucontrol->value.enumerated.item[0] & 0x01) << 1);
+}
+
+static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = {
+ /* BIT 0: SPDI_EN - always true */
+ { /* BIT 1: SPDIFS */
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
+ .info = snd_ac97_cmedia_spdif_playback_source_info,
+ .get = snd_ac97_cmedia_spdif_playback_source_get,
+ .put = snd_ac97_cmedia_spdif_playback_source_put,
+ },
+ /* BIT 2: IG_SPIV */
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9739_SPDIF_CTRL, 2, 1, 0),
+ /* BIT 3: SPI2F */
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9739_SPDIF_CTRL, 3, 1, 0),
+ /* BIT 4: SPI2SDI */
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL, 4, 1, 0),
+ /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
+};
+
+static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = {
+ AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0),
+};
+
+static int patch_cm9739_specific(ac97_t * ac97)
+{
+ return patch_build_controls(ac97, snd_ac97_cm9739_controls, ARRAY_SIZE(snd_ac97_cm9739_controls));
+}
+
+static int patch_cm9739_post_spdif(ac97_t * ac97)
+{
+ return patch_build_controls(ac97, snd_ac97_cm9739_controls_spdif, ARRAY_SIZE(snd_ac97_cm9739_controls_spdif));
+}
+
+static struct snd_ac97_build_ops patch_cm9739_ops = {
+ .build_specific = patch_cm9739_specific,
+ .build_post_spdif = patch_cm9739_post_spdif
+};
+
int patch_cm9739(ac97_t * ac97)
{
unsigned short val;
+ ac97->build_ops = &patch_cm9739_ops;
+
/* check spdif */
val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
if (val & AC97_EA_SPCV) {
@@ -444,3 +1016,31 @@ int patch_cm9739(ac97_t * ac97)
return 0;
}
+static const snd_kcontrol_new_t snd_ac97_controls_vt1616[] = {
+AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
+AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
+AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
+AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
+};
+
+static int patch_vt1616_specific(ac97_t * ac97)
+{
+ int err;
+
+ if (snd_ac97_try_bit(ac97, 0x5a, 9))
+ if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[0], 1)) < 0)
+ return err;
+ if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1)) < 0)
+ return err;
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_vt1616_ops = {
+ .build_specific = patch_vt1616_specific
+};
+
+int patch_vt1616(ac97_t * ac97)
+{
+ ac97->build_ops = &patch_vt1616_ops;
+ return 0;
+}
diff -puN sound/pci/ac97/ac97_patch.h~alsa-bk-2003-07-28 sound/pci/ac97/ac97_patch.h
--- 25/sound/pci/ac97/ac97_patch.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/ac97/ac97_patch.h Tue Jul 29 12:11:31 2003
@@ -29,6 +29,7 @@ int patch_wolfson04(ac97_t * ac97);
int patch_wolfson05(ac97_t * ac97);
int patch_wolfson11(ac97_t * ac97);
int patch_tritech_tr28028(ac97_t * ac97);
+int patch_sigmatel_stac9700(ac97_t * ac97);
int patch_sigmatel_stac9708(ac97_t * ac97);
int patch_sigmatel_stac9721(ac97_t * ac97);
int patch_sigmatel_stac9744(ac97_t * ac97);
@@ -42,4 +43,6 @@ int patch_ad1885(ac97_t * ac97);
int patch_ad1886(ac97_t * ac97);
int patch_ad1980(ac97_t * ac97);
int patch_alc650(ac97_t * ac97);
+int patch_cm9738(ac97_t * ac97);
int patch_cm9739(ac97_t * ac97);
+int patch_vt1616(ac97_t * ac97);
diff -puN /dev/null sound/pci/ac97/ac97_proc.c
--- /dev/null Thu Apr 11 07:25:15 2002
+++ 25-akpm/sound/pci/ac97/ac97_proc.c Tue Jul 29 12:11:31 2003
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) by Jaroslav Kysela
+ * Universal interface for Audio Codec '97
+ *
+ * For more details look to AC '97 component specification revision 2.2
+ * by Intel Corporation (http://developer.intel.com).
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include "ac97_local.h"
+#include "ac97_id.h"
+
+/*
+ * proc interface
+ */
+
+static void snd_ac97_proc_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, int subidx)
+{
+ char name[64];
+ unsigned int id;
+ unsigned short val, tmp, ext, mext;
+ static const char *spdif_slots[4] = { " SPDIF=3/4", " SPDIF=7/8", " SPDIF=6/9", " SPDIF=res" };
+ static const char *spdif_rates[4] = { " Rate=44.1kHz", " Rate=res", " Rate=48kHz", " Rate=32kHz" };
+ static const char *spdif_rates_cs4205[4] = { " Rate=48kHz", " Rate=44.1kHz", " Rate=res", " Rate=res" };
+
+ id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16;
+ id |= snd_ac97_read(ac97, AC97_VENDOR_ID2);
+ 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;
+
+ // val = snd_ac97_read(ac97, AC97_RESET);
+ val = ac97->caps;
+ snd_iprintf(buffer, "Capabilities :%s%s%s%s%s%s\n",
+ val & AC97_BC_DEDICATED_MIC ? " -dedicated MIC PCM IN channel-" : "",
+ val & AC97_BC_RESERVED1 ? " -reserved1-" : "",
+ val & AC97_BC_BASS_TREBLE ? " -bass & treble-" : "",
+ val & AC97_BC_SIM_STEREO ? " -simulated stereo-" : "",
+ val & AC97_BC_HEADPHONE ? " -headphone out-" : "",
+ val & AC97_BC_LOUDNESS ? " -loudness-" : "");
+ tmp = ac97->caps & AC97_BC_DAC_MASK;
+ snd_iprintf(buffer, "DAC resolution : %s%s%s%s\n",
+ tmp == AC97_BC_16BIT_DAC ? "16-bit" : "",
+ tmp == AC97_BC_18BIT_DAC ? "18-bit" : "",
+ tmp == AC97_BC_20BIT_DAC ? "20-bit" : "",
+ tmp == AC97_BC_DAC_MASK ? "???" : "");
+ tmp = ac97->caps & AC97_BC_ADC_MASK;
+ snd_iprintf(buffer, "ADC resolution : %s%s%s%s\n",
+ tmp == AC97_BC_16BIT_ADC ? "16-bit" : "",
+ tmp == AC97_BC_18BIT_ADC ? "18-bit" : "",
+ tmp == AC97_BC_20BIT_ADC ? "20-bit" : "",
+ tmp == AC97_BC_ADC_MASK ? "???" : "");
+ snd_iprintf(buffer, "3D enhancement : %s\n",
+ snd_ac97_stereo_enhancements[(val >> 10) & 0x1f]);
+ snd_iprintf(buffer, "\nCurrent setup\n");
+ val = snd_ac97_read(ac97, AC97_MIC);
+ snd_iprintf(buffer, "Mic gain : %s [%s]\n", val & 0x0040 ? "+20dB" : "+0dB", ac97->regs[AC97_MIC] & 0x0040 ? "+20dB" : "+0dB");
+ val = snd_ac97_read(ac97, AC97_GENERAL_PURPOSE);
+ snd_iprintf(buffer, "POP path : %s 3D\n"
+ "Sim. stereo : %s\n"
+ "3D enhancement : %s\n"
+ "Loudness : %s\n"
+ "Mono output : %s\n"
+ "Mic select : %s\n"
+ "ADC/DAC loopback : %s\n",
+ val & 0x8000 ? "post" : "pre",
+ val & 0x4000 ? "on" : "off",
+ val & 0x2000 ? "on" : "off",
+ val & 0x1000 ? "on" : "off",
+ val & 0x0200 ? "Mic" : "MIX",
+ val & 0x0100 ? "Mic2" : "Mic1",
+ val & 0x0080 ? "on" : "off");
+
+ ext = snd_ac97_read(ac97, AC97_EXTENDED_ID);
+ if (ext == 0)
+ goto __modem;
+
+ snd_iprintf(buffer, "Extended ID : codec=%i rev=%i%s%s%s%s DSA=%i%s%s%s%s\n",
+ (ext & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT,
+ (ext & AC97_EI_REV_MASK) >> AC97_EI_REV_SHIFT,
+ ext & AC97_EI_AMAP ? " AMAP" : "",
+ ext & AC97_EI_LDAC ? " LDAC" : "",
+ ext & AC97_EI_SDAC ? " SDAC" : "",
+ ext & AC97_EI_CDAC ? " CDAC" : "",
+ (ext & AC97_EI_DACS_SLOT_MASK) >> AC97_EI_DACS_SLOT_SHIFT,
+ ext & AC97_EI_VRM ? " VRM" : "",
+ ext & AC97_EI_SPDIF ? " SPDIF" : "",
+ ext & AC97_EI_DRA ? " DRA" : "",
+ ext & AC97_EI_VRA ? " VRA" : "");
+ val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
+ snd_iprintf(buffer, "Extended status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ val & AC97_EA_PRL ? " PRL" : "",
+ val & AC97_EA_PRK ? " PRK" : "",
+ val & AC97_EA_PRJ ? " PRJ" : "",
+ val & AC97_EA_PRI ? " PRI" : "",
+ val & AC97_EA_SPCV ? " SPCV" : "",
+ val & AC97_EA_MDAC ? " MADC" : "",
+ val & AC97_EA_LDAC ? " LDAC" : "",
+ val & AC97_EA_SDAC ? " SDAC" : "",
+ val & AC97_EA_CDAC ? " CDAC" : "",
+ ext & AC97_EI_SPDIF ? spdif_slots[(val & AC97_EA_SPSA_SLOT_MASK) >> AC97_EA_SPSA_SLOT_SHIFT] : "",
+ val & AC97_EA_VRM ? " VRM" : "",
+ val & AC97_EA_SPDIF ? " SPDIF" : "",
+ val & AC97_EA_DRA ? " DRA" : "",
+ val & AC97_EA_VRA ? " VRA" : "");
+ if (ext & AC97_EI_VRA) { /* VRA */
+ val = snd_ac97_read(ac97, AC97_PCM_FRONT_DAC_RATE);
+ snd_iprintf(buffer, "PCM front DAC : %iHz\n", val);
+ if (ext & AC97_EI_SDAC) {
+ val = snd_ac97_read(ac97, AC97_PCM_SURR_DAC_RATE);
+ snd_iprintf(buffer, "PCM Surr DAC : %iHz\n", val);
+ }
+ if (ext & AC97_EI_LDAC) {
+ val = snd_ac97_read(ac97, AC97_PCM_LFE_DAC_RATE);
+ snd_iprintf(buffer, "PCM LFE DAC : %iHz\n", val);
+ }
+ val = snd_ac97_read(ac97, AC97_PCM_LR_ADC_RATE);
+ snd_iprintf(buffer, "PCM ADC : %iHz\n", val);
+ }
+ if (ext & AC97_EI_VRM) {
+ val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE);
+ snd_iprintf(buffer, "PCM MIC ADC : %iHz\n", val);
+ }
+ if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF)) {
+ if (ac97->flags & AC97_CS_SPDIF)
+ val = snd_ac97_read(ac97, AC97_CSR_SPDIF);
+ else
+ val = snd_ac97_read(ac97, AC97_SPDIF);
+
+ snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n",
+ val & AC97_SC_PRO ? " PRO" : " Consumer",
+ val & AC97_SC_NAUDIO ? " Non-audio" : " PCM",
+ val & AC97_SC_COPY ? " Copyright" : "",
+ val & AC97_SC_PRE ? " Preemph50/15" : "",
+ (val & AC97_SC_CC_MASK) >> AC97_SC_CC_SHIFT,
+ (val & AC97_SC_L) >> 11,
+ (ac97->flags & AC97_CS_SPDIF) ?
+ spdif_rates_cs4205[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT] :
+ spdif_rates[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT],
+ (ac97->flags & AC97_CS_SPDIF) ?
+ (val & AC97_SC_DRS ? " Validity" : "") :
+ (val & AC97_SC_DRS ? " DRS" : ""),
+ (ac97->flags & AC97_CS_SPDIF) ?
+ (val & AC97_SC_V ? " Enabled" : "") :
+ (val & AC97_SC_V ? " Validity" : ""));
+ }
+
+ __modem:
+ mext = snd_ac97_read(ac97, AC97_EXTENDED_MID);
+ if (mext == 0)
+ return;
+
+ snd_iprintf(buffer, "Extended modem ID: codec=%i%s%s%s%s%s\n",
+ (mext & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT,
+ mext & AC97_MEI_CID2 ? " CID2" : "",
+ mext & AC97_MEI_CID1 ? " CID1" : "",
+ mext & AC97_MEI_HANDSET ? " HSET" : "",
+ mext & AC97_MEI_LINE2 ? " LIN2" : "",
+ mext & AC97_MEI_LINE1 ? " LIN1" : "");
+ val = snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS);
+ snd_iprintf(buffer, "Modem status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ val & AC97_MEA_GPIO ? " GPIO" : "",
+ val & AC97_MEA_MREF ? " MREF" : "",
+ val & AC97_MEA_ADC1 ? " ADC1" : "",
+ val & AC97_MEA_DAC1 ? " DAC1" : "",
+ val & AC97_MEA_ADC2 ? " ADC2" : "",
+ val & AC97_MEA_DAC2 ? " DAC2" : "",
+ val & AC97_MEA_HADC ? " HADC" : "",
+ val & AC97_MEA_HDAC ? " HDAC" : "",
+ val & AC97_MEA_PRA ? " PRA(GPIO)" : "",
+ val & AC97_MEA_PRB ? " PRB(res)" : "",
+ val & AC97_MEA_PRC ? " PRC(ADC1)" : "",
+ val & AC97_MEA_PRD ? " PRD(DAC1)" : "",
+ val & AC97_MEA_PRE ? " PRE(ADC2)" : "",
+ val & AC97_MEA_PRF ? " PRF(DAC2)" : "",
+ val & AC97_MEA_PRG ? " PRG(HADC)" : "",
+ val & AC97_MEA_PRH ? " PRH(HDAC)" : "");
+ if (mext & AC97_MEI_LINE1) {
+ val = snd_ac97_read(ac97, AC97_LINE1_RATE);
+ snd_iprintf(buffer, "Line1 rate : %iHz\n", val);
+ }
+ if (mext & AC97_MEI_LINE2) {
+ val = snd_ac97_read(ac97, AC97_LINE2_RATE);
+ snd_iprintf(buffer, "Line2 rate : %iHz\n", val);
+ }
+ if (mext & AC97_MEI_HANDSET) {
+ val = snd_ac97_read(ac97, AC97_HANDSET_RATE);
+ snd_iprintf(buffer, "Headset rate : %iHz\n", val);
+ }
+}
+
+static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+{
+ ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
+
+ if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86
+ int idx;
+ down(&ac97->spec.ad18xx.mutex);
+ for (idx = 0; idx < 3; idx++)
+ if (ac97->spec.ad18xx.id[idx]) {
+ /* select single codec */
+ snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
+ snd_ac97_proc_read_main(ac97, buffer, idx);
+ snd_iprintf(buffer, "\n\n");
+ }
+ /* select all codecs */
+ snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000);
+ up(&ac97->spec.ad18xx.mutex);
+
+ snd_iprintf(buffer, "\nAD18XX configuration\n");
+ snd_iprintf(buffer, "Unchained : 0x%04x,0x%04x,0x%04x\n",
+ ac97->spec.ad18xx.unchained[0],
+ ac97->spec.ad18xx.unchained[1],
+ ac97->spec.ad18xx.unchained[2]);
+ snd_iprintf(buffer, "Chained : 0x%04x,0x%04x,0x%04x\n",
+ ac97->spec.ad18xx.chained[0],
+ ac97->spec.ad18xx.chained[1],
+ ac97->spec.ad18xx.chained[2]);
+ } else {
+ snd_ac97_proc_read_main(ac97, buffer, 0);
+ }
+}
+
+static void snd_ac97_proc_regs_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, int subidx)
+{
+ int reg, val;
+
+ for (reg = 0; reg < 0x80; reg += 2) {
+ val = snd_ac97_read(ac97, reg);
+ snd_iprintf(buffer, "%i:%02x = %04x\n", subidx, reg, val);
+ }
+}
+
+static void snd_ac97_proc_regs_read(snd_info_entry_t *entry,
+ snd_info_buffer_t * buffer)
+{
+ ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
+
+ if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86
+
+ int idx;
+ down(&ac97->spec.ad18xx.mutex);
+ for (idx = 0; idx < 3; idx++)
+ if (ac97->spec.ad18xx.id[idx]) {
+ /* select single codec */
+ snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
+ snd_ac97_proc_regs_read_main(ac97, buffer, idx);
+ }
+ /* select all codecs */
+ snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000);
+ up(&ac97->spec.ad18xx.mutex);
+ } else {
+ snd_ac97_proc_regs_read_main(ac97, buffer, 0);
+ }
+}
+
+void snd_ac97_proc_init(snd_card_t * card, ac97_t * ac97, const char *prefix)
+{
+ snd_info_entry_t *entry;
+ char name[32];
+
+ if (ac97->num)
+ sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num);
+ else
+ sprintf(name, "%s#%d", prefix, ac97->addr);
+ if (! snd_card_proc_new(card, name, &entry))
+ snd_info_set_text_ops(entry, ac97, snd_ac97_proc_read);
+ if (ac97->num)
+ sprintf(name, "%s#%d-%dregs", prefix, ac97->addr, ac97->num);
+ else
+ sprintf(name, "%s#%dregs", prefix, ac97->addr);
+ if (! snd_card_proc_new(card, name, &entry))
+ snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read);
+}
diff -puN sound/pci/ac97/Makefile~alsa-bk-2003-07-28 sound/pci/ac97/Makefile
--- 25/sound/pci/ac97/Makefile~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/ac97/Makefile Tue Jul 29 12:11:31 2003
@@ -3,7 +3,7 @@
# Copyright (c) 2001 by Jaroslav Kysela
#
-snd-ac97-codec-objs := ac97_codec.o ac97_patch.o
+snd-ac97-codec-objs := ac97_codec.o ac97_proc.o ac97_patch.o
snd-ak4531-codec-objs := ak4531_codec.o
# Toplevel Module Dependency
diff -puN sound/pci/ali5451/ali5451.c~alsa-bk-2003-07-28 sound/pci/ali5451/ali5451.c
--- 25/sound/pci/ali5451/ali5451.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/ali5451/ali5451.c Tue Jul 29 12:11:31 2003
@@ -1891,27 +1891,14 @@ static int __devinit snd_ali_mixer(ali_t
}
#ifdef CONFIG_PM
-#ifndef PCI_OLD_SUSPEND
-static int snd_ali_suspend(struct pci_dev *dev, u32 state)
-#else
-static void snd_ali_suspend(struct pci_dev *dev)
-#endif
+static void ali_suspend(ali_t *chip)
{
-#ifndef PCI_OLD_SUSPEND
- ali_t *chip = snd_magic_cast(ali_t, pci_get_drvdata(dev), return -ENXIO);
-#else
- ali_t *chip = snd_magic_cast(ali_t, pci_get_drvdata(dev), return);
-#endif
ali_image_t *im;
int i, j;
im = chip->image;
if (! im)
-#ifndef PCI_OLD_SUSPEND
- return -ENXIO;
-#else
return;
-#endif
spin_lock_irq(&chip->reg_lock);
@@ -1938,32 +1925,16 @@ static void snd_ali_suspend(struct pci_d
outl(0xffffffff, ALI_REG(chip, ALI_STOP));
spin_unlock_irq(&chip->reg_lock);
-#ifndef PCI_OLD_SUSPEND
- return 0;
-#endif
}
-#ifndef PCI_OLD_SUSPEND
-static int snd_ali_resume(struct pci_dev *dev)
-#else
-static void snd_ali_resume(struct pci_dev *dev)
-#endif
+static void ali_resume(ali_t *chip)
{
-#ifndef PCI_OLD_SUSPEND
- ali_t *chip = snd_magic_cast(ali_t, pci_get_drvdata(dev), return -ENXIO);
-#else
- ali_t *chip = snd_magic_cast(ali_t, pci_get_drvdata(dev), return);
-#endif
ali_image_t *im;
int i, j;
im = chip->image;
if (! im)
-#ifndef PCI_OLD_SUSPEND
- return -ENXIO;
-#else
return;
-#endif
pci_enable_device(chip->pci);
@@ -1989,11 +1960,22 @@ static void snd_ali_resume(struct pci_de
outl(im->regs[ALI_MISCINT >> 2], ALI_REG(chip, ALI_MISCINT));
spin_unlock_irq(&chip->reg_lock);
-#ifndef PCI_OLD_SUSPEND
+ return;
+}
+
+static int snd_ali_suspend(struct pci_dev *dev, u32 state)
+{
+ ali_t *chip = snd_magic_cast(ali_t, pci_get_drvdata(dev), return -ENXIO);
+ ali_suspend(chip);
return 0;
-#endif
}
-#endif
+static int snd_ali_resume(struct pci_dev *dev)
+{
+ ali_t *chip = snd_magic_cast(ali_t, pci_get_drvdata(dev), return -ENXIO);
+ ali_resume(chip);
+ return 0;
+}
+#endif /* CONFIG_PM */
static int snd_ali_free(ali_t * codec)
{
@@ -2181,7 +2163,7 @@ static int __devinit snd_ali_create(snd_
/* M7101: power management */
pci_dev = pci_find_device(0x10b9, 0x7101, NULL);
codec->pci_m7101 = pci_dev;
- if (! codec->pci_m7101) {
+ if (! codec->pci_m7101 && codec->revision == ALI_5451_V02) {
snd_printk(KERN_ERR "ali5451: cannot find ALi 7101 chip.\n");
snd_ali_free(codec);
return -ENODEV;
diff -puN sound/pci/cmipci.c~alsa-bk-2003-07-28 sound/pci/cmipci.c
--- 25/sound/pci/cmipci.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/cmipci.c Tue Jul 29 12:11:31 2003
@@ -1186,7 +1186,7 @@ static int snd_cmipci_ac3_copy(snd_pcm_s
#ifndef USE_AES_IEC958
u16 *srcp = src, val;
#else
- char buf[1920]; /* bits can be divided by 20, 24, 16 */
+ char buf[480]; /* bits can be divided by 20, 24, 16 */
size_t bytes = frames_to_bytes(runtime, count);
#endif
@@ -1245,7 +1245,7 @@ static int snd_cmipci_ac3_silence(snd_pc
snd_pcm_uframes_t offset;
snd_pcm_runtime_t *runtime = subs->runtime;
# ifdef USE_AES_IEC958
- char buf[1920]; /* bits can be divided by 20, 24, 16 */
+ char buf[480]; /* bits can be divided by 20, 24, 16 */
size_t bytes = frames_to_bytes(runtime, count);
# endif
if (! cm->channel[CM_CH_PLAY].ac3_shift)
diff -puN sound/pci/cs4281.c~alsa-bk-2003-07-28 sound/pci/cs4281.c
--- 25/sound/pci/cs4281.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/cs4281.c Tue Jul 29 12:11:31 2003
@@ -530,36 +530,27 @@ MODULE_DEVICE_TABLE(pci, snd_cs4281_ids)
* common I/O routines
*/
-static void snd_cs4281_delay(unsigned int delay, int can_schedule)
+static void snd_cs4281_delay(unsigned int delay)
{
if (delay > 999) {
- if (can_schedule) {
- unsigned long end_time;
- delay = (delay * HZ) / 1000000;
- if (delay < 1)
- delay = 1;
- end_time = jiffies + delay;
- do {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- } while (time_after_eq(end_time, jiffies));
- } else {
- delay += 999;
- delay /= 1000;
- mdelay(delay > 0 ? delay : 1);
- }
+ unsigned long end_time;
+ delay = (delay * HZ) / 1000000;
+ if (delay < 1)
+ delay = 1;
+ end_time = jiffies + delay;
+ do {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(1);
+ } while (time_after_eq(end_time, jiffies));
} else {
udelay(delay);
}
}
-inline static void snd_cs4281_delay_long(int can_schedule)
+inline static void snd_cs4281_delay_long(void)
{
- if (can_schedule) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- } else
- mdelay(10);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(1);
}
static inline void snd_cs4281_pokeBA0(cs4281_t *chip, unsigned long offset, unsigned int val)
@@ -1267,7 +1258,7 @@ static void __devinit snd_cs4281_proc_in
* joystick support
*/
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
typedef struct snd_cs4281_gameport {
struct gameport info;
@@ -1359,7 +1350,7 @@ static void __devinit snd_cs4281_gamepor
#else
#define snd_cs4281_gameport(chip) /*NOP*/
-#endif /* CONFIG_GAMEPORT || CONFIG_GAMEPORT_MODULE */
+#endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */
/*
@@ -1368,7 +1359,7 @@ static void __devinit snd_cs4281_gamepor
static int snd_cs4281_free(cs4281_t *chip)
{
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
if (chip->gameport) {
gameport_unregister_port(&chip->gameport->info);
kfree(chip->gameport);
@@ -1411,7 +1402,7 @@ static int snd_cs4281_dev_free(snd_devic
return snd_cs4281_free(chip);
}
-static int snd_cs4281_chip_init(cs4281_t *chip, int can_schedule); /* defined below */
+static int snd_cs4281_chip_init(cs4281_t *chip); /* defined below */
#ifdef CONFIG_PM
static int snd_cs4281_set_power_state(snd_card_t *card, unsigned int power_state);
#endif
@@ -1471,7 +1462,7 @@ static int __devinit snd_cs4281_create(s
return -ENOMEM;
}
- tmp = snd_cs4281_chip_init(chip, 1);
+ tmp = snd_cs4281_chip_init(chip);
if (tmp) {
snd_cs4281_free(chip);
return tmp;
@@ -1493,7 +1484,7 @@ static int __devinit snd_cs4281_create(s
return 0;
}
-static int snd_cs4281_chip_init(cs4281_t *chip, int can_schedule)
+static int snd_cs4281_chip_init(cs4281_t *chip)
{
unsigned int tmp;
int timeout;
@@ -1547,7 +1538,7 @@ static int snd_cs4281_chip_init(cs4281_t
snd_cs4281_pokeBA0(chip, BA0_SPMC, 0);
udelay(50);
snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN);
- snd_cs4281_delay(50000, can_schedule);
+ snd_cs4281_delay(50000);
if (chip->dual_codec)
snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN | BA0_SPMC_ASDI2E);
@@ -1563,7 +1554,7 @@ static int snd_cs4281_chip_init(cs4281_t
* Start the DLL Clock logic.
*/
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, BA0_CLKCR1_DLLP);
- snd_cs4281_delay(50000, can_schedule);
+ snd_cs4281_delay(50000);
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, BA0_CLKCR1_SWCE | BA0_CLKCR1_DLLP);
/*
@@ -1577,7 +1568,7 @@ static int snd_cs4281_chip_init(cs4281_t
*/
if (snd_cs4281_peekBA0(chip, BA0_CLKCR1) & BA0_CLKCR1_DLLRDY)
goto __ok0;
- snd_cs4281_delay_long(can_schedule);
+ snd_cs4281_delay_long();
} while (timeout-- > 0);
snd_printk(KERN_ERR "DLLRDY not seen\n");
@@ -1603,7 +1594,7 @@ static int snd_cs4281_chip_init(cs4281_t
*/
if (snd_cs4281_peekBA0(chip, BA0_ACSTS) & BA0_ACSTS_CRDY)
goto __ok1;
- snd_cs4281_delay_long(can_schedule);
+ snd_cs4281_delay_long();
} while (timeout-- > 0);
snd_printk(KERN_ERR "never read codec ready from AC'97 (0x%x)\n", snd_cs4281_peekBA0(chip, BA0_ACSTS));
@@ -1615,7 +1606,7 @@ static int snd_cs4281_chip_init(cs4281_t
do {
if (snd_cs4281_peekBA0(chip, BA0_ACSTS2) & BA0_ACSTS_CRDY)
goto __codec2_ok;
- snd_cs4281_delay_long(can_schedule);
+ snd_cs4281_delay_long();
} while (timeout-- > 0);
snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n");
chip->dual_codec = 0;
@@ -1642,7 +1633,7 @@ static int snd_cs4281_chip_init(cs4281_t
*/
if ((snd_cs4281_peekBA0(chip, BA0_ACISV) & (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) == (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4)))
goto __ok2;
- snd_cs4281_delay_long(can_schedule);
+ snd_cs4281_delay_long();
} while (timeout-- > 0);
snd_printk(KERN_ERR "never read ISV3 and ISV4 from AC'97\n");
@@ -2109,7 +2100,7 @@ static void cs4281_resume(cs4281_t *chip
ulCLK |= CLKCR1_CKRA;
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
- snd_cs4281_chip_init(chip, 0);
+ snd_cs4281_chip_init(chip);
/* restore the status registers */
for (i = 0; i < number_of(saved_regs); i++)
@@ -2128,7 +2119,6 @@ static void cs4281_resume(cs4281_t *chip
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
}
-#ifndef PCI_OLD_SUSPEND
static int snd_cs4281_suspend(struct pci_dev *dev, u32 state)
{
cs4281_t *chip = snd_magic_cast(cs4281_t, pci_get_drvdata(dev), return -ENXIO);
@@ -2141,18 +2131,6 @@ static int snd_cs4281_resume(struct pci_
cs4281_resume(chip);
return 0;
}
-#else
-static void snd_cs4281_suspend(struct pci_dev *dev)
-{
- cs4281_t *chip = snd_magic_cast(cs4281_t, pci_get_drvdata(dev), return);
- cs4281_suspend(chip);
-}
-static void snd_cs4281_resume(struct pci_dev *dev)
-{
- cs4281_t *chip = snd_magic_cast(cs4281_t, pci_get_drvdata(dev), return);
- cs4281_resume(chip);
-}
-#endif
/* callback */
static int snd_cs4281_set_power_state(snd_card_t *card, unsigned int power_state)
diff -puN sound/pci/cs46xx/cs46xx.c~alsa-bk-2003-07-28 sound/pci/cs46xx/cs46xx.c
--- 25/sound/pci/cs46xx/cs46xx.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/cs46xx/cs46xx.c Tue Jul 29 12:11:31 2003
@@ -163,7 +163,6 @@ static int __devinit snd_card_cs46xx_pro
}
#ifdef CONFIG_PM
-#ifndef PCI_OLD_SUSPEND
static int snd_card_cs46xx_suspend(struct pci_dev *pci, u32 state)
{
cs46xx_t *chip = snd_magic_cast(cs46xx_t, pci_get_drvdata(pci), return -ENXIO);
@@ -176,18 +175,6 @@ static int snd_card_cs46xx_resume(struct
snd_cs46xx_resume(chip);
return 0;
}
-#else
-static void snd_card_cs46xx_suspend(struct pci_dev *pci)
-{
- cs46xx_t *chip = snd_magic_cast(cs46xx_t, pci_get_drvdata(pci), return);
- snd_cs46xx_suspend(chip);
-}
-static void snd_card_cs46xx_resume(struct pci_dev *pci)
-{
- cs46xx_t *chip = snd_magic_cast(cs46xx_t, pci_get_drvdata(pci), return);
- snd_cs46xx_resume(chip);
-}
-#endif
#endif
static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci)
diff -puN sound/pci/cs46xx/cs46xx_lib.c~alsa-bk-2003-07-28 sound/pci/cs46xx/cs46xx_lib.c
--- 25/sound/pci/cs46xx/cs46xx_lib.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/cs46xx/cs46xx_lib.c Tue Jul 29 12:11:31 2003
@@ -2743,7 +2743,7 @@ int __devinit snd_cs46xx_midi(cs46xx_t *
* gameport interface
*/
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
typedef struct snd_cs46xx_gameport {
struct gameport info;
@@ -2960,7 +2960,7 @@ static int snd_cs46xx_free(cs46xx_t *chi
if (chip->active_ctrl)
chip->active_ctrl(chip, 1);
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
if (chip->gameport) {
gameport_unregister_port(&chip->gameport->info);
kfree(chip->gameport);
@@ -3010,7 +3010,7 @@ static int snd_cs46xx_dev_free(snd_devic
/*
* initialize chip
*/
-static int snd_cs46xx_chip_init(cs46xx_t *chip, int busywait)
+static int snd_cs46xx_chip_init(cs46xx_t *chip)
{
int timeout;
@@ -3090,7 +3090,8 @@ static int snd_cs46xx_chip_init(cs46xx_t
/*
* Wait until the PLL has stabilized.
*/
- mdelay(100); /* FIXME: schedule? */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ/10); /* 100ms */
/*
* Turn on clocking of the core so that we can setup the serial ports.
@@ -3143,12 +3144,8 @@ static int snd_cs46xx_chip_init(cs46xx_t
*/
if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY)
goto ok1;
- if (busywait)
- mdelay(10);
- else {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout((HZ+99)/100);
- }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout((HZ+99)/100);
}
@@ -3197,12 +3194,8 @@ static int snd_cs46xx_chip_init(cs46xx_t
*/
if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
goto ok2;
- if (busywait)
- mdelay(10);
- else {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout((HZ+99)/100);
- }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout((HZ+99)/100);
}
#ifndef CONFIG_SND_CS46XX_NEW_DSP
@@ -3811,7 +3804,7 @@ void snd_cs46xx_resume(cs46xx_t *chip)
chip->amplifier = 0;
chip->active_ctrl(chip, 1); /* force to on */
- snd_cs46xx_chip_init(chip, 1);
+ snd_cs46xx_chip_init(chip);
#if 0
snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE,
@@ -3992,7 +3985,7 @@ int __devinit snd_cs46xx_create(snd_card
}
#endif
- err = snd_cs46xx_chip_init(chip, 0);
+ err = snd_cs46xx_chip_init(chip);
if (err < 0) {
snd_cs46xx_free(chip);
return err;
diff -puN sound/pci/emu10k1/emu10k1.c~alsa-bk-2003-07-28 sound/pci/emu10k1/emu10k1.c
--- 25/sound/pci/emu10k1/emu10k1.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/emu10k1/emu10k1.c Tue Jul 29 12:11:31 2003
@@ -35,7 +35,7 @@ MODULE_CLASSES("{sound}");
MODULE_DEVICES("{{Creative Labs,SB Live!/PCI512/E-mu APS},"
"{Creative Labs,SB Audigy}}");
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
#define ENABLE_SYNTH
#include
#endif
@@ -135,11 +135,9 @@ static int __devinit snd_card_emu10k1_pr
snd_card_free(card);
return err;
}
- if (!emu->APS) { /* APS board has not an AC97 mixer */
- if ((err = snd_emu10k1_mixer(emu)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_emu10k1_mixer(emu)) < 0) {
+ snd_card_free(card);
+ return err;
}
if (emu->audigy) {
if ((err = snd_emu10k1_audigy_midi(emu)) < 0) {
diff -puN sound/pci/emu10k1/emu10k1_main.c~alsa-bk-2003-07-28 sound/pci/emu10k1/emu10k1_main.c
--- 25/sound/pci/emu10k1/emu10k1_main.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/emu10k1/emu10k1_main.c Tue Jul 29 12:11:31 2003
@@ -674,6 +674,14 @@ int __devinit snd_emu10k1_create(snd_car
if (emu->serial == 0x40011102) {
emu->card_type = EMU10K1_CARD_EMUAPS;
emu->APS = 1;
+ emu->no_ac97 = 1; /* APS has no AC97 chip */
+ }
+ else if (emu->revision == 4 && emu->serial == 0x10051102) {
+ /* Audigy 2 EX has apparently no effective AC97 controls
+ * (for both input and output), so we skip the AC97 detections
+ */
+ snd_printdd(KERN_INFO "Audigy2 EX is detected. skpping ac97.\n");
+ emu->no_ac97 = 1;
}
emu->fx8010.fxbus_mask = 0x303f;
diff -puN sound/pci/emu10k1/emufx.c~alsa-bk-2003-07-28 sound/pci/emu10k1/emufx.c
--- 25/sound/pci/emu10k1/emufx.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/emu10k1/emufx.c Tue Jul 29 12:11:31 2003
@@ -945,12 +945,15 @@ static void snd_emu10k1_add_controls(emu
snd_emu10k1_fx8010_ctl_t *ctl, nctl;
snd_kcontrol_new_t knew;
snd_kcontrol_t *kctl;
- snd_ctl_elem_value_t val;
+ snd_ctl_elem_value_t *val;
+ val = (snd_ctl_elem_value_t *)kmalloc(sizeof(*val), GFP_KERNEL);
+ if (!val)
+ return;
for (i = 0, _gctl = icode->gpr_add_controls;
i < icode->gpr_add_control_count; i++, _gctl++) {
if (copy_from_user(&gctl, _gctl, sizeof(gctl)))
- return;
+ break;
snd_runtime_check(gctl.id.iface == SNDRV_CTL_ELEM_IFACE_MIXER ||
gctl.id.iface == SNDRV_CTL_ELEM_IFACE_PCM, continue);
snd_runtime_check(gctl.id.name[0] != '\0', continue);
@@ -970,7 +973,7 @@ static void snd_emu10k1_add_controls(emu
for (j = 0; j < 32; j++) {
nctl.gpr[j] = gctl.gpr[j];
nctl.value[j] = ~gctl.value[j]; /* inverted, we want to write new value in gpr_ctl_put() */
- val.value.integer.value[j] = gctl.value[j];
+ val->value.integer.value[j] = gctl.value[j];
}
nctl.min = gctl.min;
nctl.max = gctl.max;
@@ -996,8 +999,9 @@ static void snd_emu10k1_add_controls(emu
snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE |
SNDRV_CTL_EVENT_MASK_INFO, &ctl->kcontrol->id);
}
- snd_emu10k1_gpr_ctl_put(ctl->kcontrol, &val);
+ snd_emu10k1_gpr_ctl_put(ctl->kcontrol, val);
}
+ kfree(val);
}
static void snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
@@ -1234,7 +1238,10 @@ static void __devinit snd_emu10k1_init_s
static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
{
- int err, i, z, gpr, tmp, playback, capture, nctl;
+ int err, i, z, gpr, nctl;
+ const int playback = 10;
+ const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
+ const int tmp = 0x88;
u32 ptr;
emu10k1_fx8010_code_t *icode;
emu10k1_fx8010_control_gpr_t *controls, *ctl;
@@ -1257,19 +1264,15 @@ static int __devinit _snd_emu10k1_audigy
strcpy(icode->name, "Audigy DSP code for ALSA");
ptr = 0;
nctl = 0;
- playback = 10;
- capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
gpr = capture + 10;
- tmp = 0x88;
/* stop FX processor */
snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
- /* Wave Playback */
+ /* Wave Playback Volume */
A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
- snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr,
- emu->revision == 4 ? 50 : 100);
+ snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100);
gpr += 2;
/* Wave Surround Playback */
@@ -1493,6 +1496,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_G
snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "Tone Control - Switch", gpr, 0);
gpr += 2;
+ /* Master volume for audigy2 */
+ if (emu->revision == 4) {
+ A_OP(icode, &ptr, iMAC0, A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS));
+ A_OP(icode, &ptr, iMAC0, A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr+1), A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS));
+ snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0);
+ gpr += 2;
+ }
+
/* digital outputs */
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);
@@ -1500,7 +1511,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_G
A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
/* analog speakers */
- if (emu->audigy && emu->revision == 4) { /* audigy2 */
+ if (emu->revision == 4) { /* audigy2 */
A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
} else {
A_PUT_STEREO_OUTPUT(A_EXTOUT_AC97_L, A_EXTOUT_AC97_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
@@ -2227,7 +2238,7 @@ static int snd_emu10k1_fx8010_info(emu10
static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
{
emu10k1_t *emu = snd_magic_cast(emu10k1_t, hw->private_data, return -ENXIO);
- emu10k1_fx8010_info_t info;
+ emu10k1_fx8010_info_t *info;
emu10k1_fx8010_code_t *icode;
emu10k1_fx8010_pcm_t *ipcm;
unsigned int addr;
@@ -2235,10 +2246,18 @@ static int snd_emu10k1_fx8010_ioctl(snd_
switch (cmd) {
case SNDRV_EMU10K1_IOCTL_INFO:
- if ((res = snd_emu10k1_fx8010_info(emu, &info)) < 0)
+ info = (emu10k1_fx8010_info_t *)kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ if ((res = snd_emu10k1_fx8010_info(emu, info)) < 0) {
+ kfree(info);
return res;
- if (copy_to_user((void *)arg, &info, sizeof(info)))
+ }
+ if (copy_to_user((void *)arg, info, sizeof(*info))) {
+ kfree(info);
return -EFAULT;
+ }
+ kfree(info);
return 0;
case SNDRV_EMU10K1_IOCTL_CODE_POKE:
if (!capable(CAP_SYS_ADMIN))
@@ -2271,9 +2290,13 @@ static int snd_emu10k1_fx8010_ioctl(snd_
case SNDRV_EMU10K1_IOCTL_PCM_POKE:
if (emu->audigy)
return -EINVAL;
- ipcm = (emu10k1_fx8010_pcm_t *)snd_kcalloc(sizeof(*ipcm), GFP_KERNEL);
+ ipcm = (emu10k1_fx8010_pcm_t *)kmalloc(sizeof(*ipcm), GFP_KERNEL);
if (ipcm == NULL)
return -ENOMEM;
+ if (copy_from_user(ipcm, (void *)arg, sizeof(*ipcm))) {
+ kfree(ipcm);
+ return -EFAULT;
+ }
res = snd_emu10k1_ipcm_poke(emu, ipcm);
kfree(ipcm);
return res;
@@ -2283,6 +2306,10 @@ static int snd_emu10k1_fx8010_ioctl(snd_
ipcm = (emu10k1_fx8010_pcm_t *)snd_kcalloc(sizeof(*ipcm), GFP_KERNEL);
if (ipcm == NULL)
return -ENOMEM;
+ if (copy_from_user(ipcm, (void *)arg, sizeof(*ipcm))) {
+ kfree(ipcm);
+ return -EFAULT;
+ }
res = snd_emu10k1_ipcm_peek(emu, ipcm);
if (res == 0 && copy_to_user((void *)arg, ipcm, sizeof(*ipcm))) {
kfree(ipcm);
diff -puN sound/pci/emu10k1/emumixer.c~alsa-bk-2003-07-28 sound/pci/emu10k1/emumixer.c
--- 25/sound/pci/emu10k1/emumixer.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/emu10k1/emumixer.c Tue Jul 29 12:11:31 2003
@@ -423,6 +423,36 @@ static void snd_emu10k1_mixer_free_ac97(
emu->ac97 = NULL;
}
+/*
+ */
+static int remove_ctl(snd_card_t *card, 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(card, &id);
+}
+
+static snd_kcontrol_t *ctl_find(snd_card_t *card, const char *name)
+{
+ snd_ctl_elem_id_t sid;
+ memset(&sid, 0, sizeof(sid));
+ strcpy(sid.name, name);
+ sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ return snd_ctl_find_id(card, &sid);
+}
+
+static int rename_ctl(snd_card_t *card, const char *src, const char *dst)
+{
+ snd_kcontrol_t *kctl = ctl_find(card, src);
+ if (kctl) {
+ strcpy(kctl->id.name, dst);
+ return 0;
+ }
+ return -ENOENT;
+}
+
int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
{
ac97_t ac97;
@@ -430,7 +460,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_
snd_kcontrol_t *kctl;
snd_card_t *card = emu->card;
- if (!emu->APS) {
+ if (!emu->no_ac97) {
memset(&ac97, 0, sizeof(ac97));
ac97.write = snd_emu10k1_ac97_write;
ac97.read = snd_emu10k1_ac97_read;
@@ -438,8 +468,33 @@ int __devinit snd_emu10k1_mixer(emu10k1_
ac97.private_free = snd_emu10k1_mixer_free_ac97;
if ((err = snd_ac97_mixer(emu->card, &ac97, &emu->ac97)) < 0)
return err;
+ if (emu->audigy && emu->revision == 4) {
+ /* Master/PCM controls on ac97 of Audigy2 has no effect */
+ /* FIXME: keep master volume/switch to be sure.
+ * once after we check that they play really no roles,
+ * they shall be removed.
+ */
+ rename_ctl(card, "Master Playback Switch", "AC97 Master Playback Switch");
+ rename_ctl(card, "Master Playback Volume", "AC97 Master Playback Volume");
+ /* pcm controls are removed */
+ remove_ctl(card, "PCM Playback Switch");
+ remove_ctl(card, "PCM Playback Volume");
+ }
} else {
- strcpy(emu->card->mixername, "EMU APS");
+ if (emu->APS)
+ strcpy(emu->card->mixername, "EMU APS");
+ else if (emu->audigy)
+ strcpy(emu->card->mixername, "SB Audigy");
+ else
+ strcpy(emu->card->mixername, "Emu10k1");
+ }
+
+ if (emu->audigy && emu->revision == 4) {
+ /* Audigy2 and Audigy2 EX */
+ /* use the conventional names */
+ rename_ctl(card, "Wave Playback Volume", "PCM Playback Volume");
+ rename_ctl(card, "Wave Playback Volume", "PCM Capture Volume");
+ rename_ctl(card, "Wave Master Playback Volume", "Master Playback Volume");
}
if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
@@ -455,6 +510,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_
if ((err = snd_ctl_add(card, kctl)))
return err;
+ /* intiailize the routing and volume table for each pcm playback stream */
for (pcm = 0; pcm < 32; pcm++) {
emu10k1_pcm_mixer_t *mix;
int v;
@@ -474,21 +530,25 @@ int __devinit snd_emu10k1_mixer(emu10k1_
mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
}
- if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
+ if (! emu->APS) { /* FIXME: APS has these controls? */
+ /* sb live! and audigy */
+ if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+ if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+ }
if (emu->audigy) {
if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
- } else {
+ } else if (! emu->APS) {
+ /* sb live! */
if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
diff -puN sound/pci/emu10k1/irq.c~alsa-bk-2003-07-28 sound/pci/emu10k1/irq.c
--- 25/sound/pci/emu10k1/irq.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/emu10k1/irq.c Tue Jul 29 12:11:31 2003
@@ -55,15 +55,13 @@ irqreturn_t snd_emu10k1_interrupt(int ir
if (status & IPR_CHANNELLOOP) {
int voice;
int voice_max = status & IPR_CHANNELNUMBERMASK;
- int voice_max_l;
u32 val;
emu10k1_voice_t *pvoice = emu->voices;
val = snd_emu10k1_ptr_read(emu, CLIPL, 0);
- voice_max_l = voice_max;
- if (voice_max_l >= 0x20)
- voice_max_l = 0x1f;
- for (voice = 0; voice <= voice_max_l; voice++) {
+ for (voice = 0; voice <= voice_max; voice++) {
+ if (voice == 0x20)
+ val = snd_emu10k1_ptr_read(emu, CLIPH, 0);
if (val & 1) {
if (pvoice->use && pvoice->interrupt != NULL) {
pvoice->interrupt(emu, pvoice);
@@ -75,21 +73,6 @@ irqreturn_t snd_emu10k1_interrupt(int ir
val >>= 1;
pvoice++;
}
- if (voice_max > 0x1f) {
- val = snd_emu10k1_ptr_read(emu, CLIPH, 0);
- for (; voice <= voice_max; voice++) {
- if(val & 1) {
- if (pvoice->use && pvoice->interrupt != NULL) {
- pvoice->interrupt(emu, pvoice);
- snd_emu10k1_voice_intr_ack(emu, voice);
- } else {
- snd_emu10k1_voice_intr_disable(emu, voice);
- }
- }
- val >>= 1;
- pvoice++;
- }
- }
status &= ~IPR_CHANNELLOOP;
}
status &= ~IPR_CHANNELNUMBERMASK;
@@ -150,9 +133,27 @@ irqreturn_t snd_emu10k1_interrupt(int ir
status &= ~IPR_FXDSP;
}
if (status) {
- snd_printd(KERN_WARNING "emu10k1: unhandled interrupt: 0x%08x\n", status);
+ unsigned int bits;
+ snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
+ //make sure any interrupts we don't handle are disabled:
+ bits = INTE_FXDSPENABLE |
+ INTE_PCIERRORENABLE |
+ INTE_VOLINCRENABLE |
+ INTE_VOLDECRENABLE |
+ INTE_MUTEENABLE |
+ INTE_MICBUFENABLE |
+ INTE_ADCBUFENABLE |
+ INTE_EFXBUFENABLE |
+ INTE_GPSPDIFENABLE |
+ INTE_CDSPDIFENABLE |
+ INTE_INTERVALTIMERENB |
+ INTE_MIDITXENABLE |
+ INTE_MIDIRXENABLE;
+ if (emu->audigy)
+ bits |= INTE_A_MIDITXENABLE2 | INTE_A_MIDIRXENABLE2;
+ snd_emu10k1_intr_disable(emu, bits);
}
- outl(orig_status, emu->port + IPR); /* ack */
+ outl(orig_status, emu->port + IPR); /* ack all */
}
return IRQ_RETVAL(handled);
}
diff -puN sound/pci/ens1370.c~alsa-bk-2003-07-28 sound/pci/ens1370.c
--- 25/sound/pci/ens1370.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/ens1370.c Tue Jul 29 12:11:31 2003
@@ -409,7 +409,7 @@ struct _snd_ensoniq {
dma_addr_t bugbuf_addr;
#endif
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
struct gameport gameport;
struct semaphore joy_sem; // gameport configuration semaphore
#endif
@@ -1559,7 +1559,7 @@ static int snd_ensoniq_1371_mixer(ensoni
#endif /* CHIP1371 */
/* generic control callbacks for ens1370 and for joystick */
-#if defined(CHIP1370) || defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CHIP1370) || defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#define ENSONIQ_CONTROL(xname, mask) \
{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = xname, .info = snd_ensoniq_control_info, \
.get = snd_ensoniq_control_get, .put = snd_ensoniq_control_put, \
@@ -1657,7 +1657,7 @@ static int __devinit snd_ensoniq_1370_mi
* General Switches...
*/
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
/* MQ: gameport driver connectivity */
#define ENSONIQ_JOY_CONTROL(xname, mask) \
{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = xname, .info = snd_ensoniq_control_info, \
@@ -1814,7 +1814,7 @@ static void __devinit snd_ensoniq_proc_i
static int snd_ensoniq_free(ensoniq_t *ensoniq)
{
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
if (ensoniq->ctrl & ES_JYSTK_EN)
snd_ensoniq_joy_disable(ensoniq);
#endif
@@ -2012,7 +2012,7 @@ static int __devinit snd_ensoniq_create(
outb(ensoniq->uartc = 0x00, ES_REG(ensoniq, UART_CONTROL));
outb(0x00, ES_REG(ensoniq, UART_RES));
outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
init_MUTEX(&ensoniq->joy_sem);
#ifdef CHIP1371
snd_ctl_add(card, snd_ctl_new1(&snd_es1371_joystick_addr, ensoniq));
diff -puN sound/pci/es1938.c~alsa-bk-2003-07-28 sound/pci/es1938.c
--- 25/sound/pci/es1938.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/es1938.c Tue Jul 29 12:11:31 2003
@@ -244,7 +244,7 @@ struct _snd_es1938 {
spinlock_t mixer_lock;
snd_info_entry_t *proc_entry;
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
struct gameport gameport;
#endif
};
@@ -1346,7 +1346,7 @@ static int snd_es1938_free(es1938_t *chi
{
/*if (chip->rmidi)
snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0);*/
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
if (chip->gameport.io)
gameport_unregister_port(&chip->gameport);
#endif
@@ -1663,7 +1663,7 @@ static int __devinit snd_es1938_probe(st
} /*else
snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0x40);*/
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
chip->gameport.io = chip->game_port;
gameport_register_port(&chip->gameport);
#endif
diff -puN sound/pci/es1968.c~alsa-bk-2003-07-28 sound/pci/es1968.c
--- 25/sound/pci/es1968.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/es1968.c Tue Jul 29 12:11:31 2003
@@ -654,6 +654,11 @@ inline static u16 maestro_read(es1968_t
return result;
}
+#define big_mdelay(msec) do {\
+ set_current_state(TASK_UNINTERRUPTIBLE);\
+ schedule_timeout(((msec) * HZ + 999) / 1000);\
+} while (0)
+
/* Wait for the codec bus to be free */
static int snd_es1968_ac97_wait(es1968_t *chip)
{
@@ -2109,7 +2114,7 @@ static void snd_es1968_ac97_reset(es1968
outw(0x0000, ioaddr + 0x60); /* write 0 to gpio 0 */
udelay(20);
outw(0x0001, ioaddr + 0x60); /* write 1 to gpio 1 */
- mdelay(20);
+ big_mdelay(20);
outw(save_68 | 0x1, ioaddr + 0x68); /* now restore .. */
outw((inw(ioaddr + 0x38) & 0xfffc) | 0x1, ioaddr + 0x38);
@@ -2125,7 +2130,7 @@ static void snd_es1968_ac97_reset(es1968
outw(0x0001, ioaddr + 0x60); /* write 1 to gpio */
udelay(20);
outw(0x0009, ioaddr + 0x60); /* write 9 to gpio */
- mdelay(500); /* .. ouch.. */
+ big_mdelay(500);
//outw(inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38);
outw(inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a);
outw(inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c);
@@ -2151,7 +2156,7 @@ static void snd_es1968_ac97_reset(es1968
if (w > 10000) {
outb(inb(ioaddr + 0x37) | 0x08, ioaddr + 0x37); /* do a software reset */
- mdelay(500); /* oh my.. */
+ big_mdelay(500); /* oh my.. */
outb(inb(ioaddr + 0x37) & ~0x08,
ioaddr + 0x37);
udelay(1);
@@ -2340,11 +2345,6 @@ static void snd_es1968_chip_init(es1968_
outb(3, iobase + ASSP_CONTROL_A); /* M: Reserved bits... */
outb(0, iobase + ASSP_CONTROL_C); /* M: Disable ASSP, ASSP IRQ's and FM Port */
- /* Enable IRQ's */
- w = ESM_HIRQ_DSIE | ESM_HIRQ_MPU401 | ESM_HIRQ_HW_VOLUME;
- outw(w, iobase + ESM_PORT_HOST_IRQ);
-
-
/*
* set up wavecache
*/
@@ -2414,6 +2414,14 @@ static void snd_es1968_chip_init(es1968_
}
}
+/* Enable IRQ's */
+static void snd_es1968_start_irq(es1968_t *chip)
+{
+ unsigned short w;
+ w = ESM_HIRQ_DSIE | ESM_HIRQ_MPU401 | ESM_HIRQ_HW_VOLUME;
+ outw(w, chip->io_port + ESM_PORT_HOST_IRQ);
+}
+
#ifdef CONFIG_PM
/*
* PM support
@@ -2453,16 +2461,18 @@ static void es1968_resume(es1968_t *chip
wave_set_register(chip, 0x01FC, chip->dma.addr >> 12);
}
+ snd_es1968_start_irq(chip);
+
/* restore ac97 state */
snd_ac97_resume(chip->ac97);
/* start timer again */
if (atomic_read(&chip->bobclient))
snd_es1968_bob_start(chip);
+
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
}
-#ifndef PCI_OLD_SUSPEND
static int snd_es1968_suspend(struct pci_dev *dev, u32 state)
{
es1968_t *chip = snd_magic_cast(es1968_t, pci_get_drvdata(dev), return -ENXIO);
@@ -2475,18 +2485,6 @@ static int snd_es1968_resume(struct pci_
es1968_resume(chip);
return 0;
}
-#else
-static void snd_es1968_suspend(struct pci_dev *dev)
-{
- es1968_t *chip = snd_magic_cast(es1968_t, pci_get_drvdata(dev), return);
- es1968_suspend(chip);
-}
-static void snd_es1968_resume(struct pci_dev *dev)
-{
- es1968_t *chip = snd_magic_cast(es1968_t, pci_get_drvdata(dev), return);
- es1968_resume(chip);
-}
-#endif
/* callback */
static int snd_es1968_set_power_state(snd_card_t *card, unsigned int power_state)
@@ -2612,9 +2610,9 @@ static int __devinit snd_es1968_create(s
/* disable power-management if not maestro2e or
* if not on the whitelist
*/
- unsigned int vend;
- pci_read_config_dword(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, &vend);
- if (chip->type != TYPE_MAESTRO2E || (vend & 0xffff) != 0x1028) {
+ unsigned short vend;
+ pci_read_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, &vend);
+ if (chip->type != TYPE_MAESTRO2E || (vend != 0x1028 && vend != 0x1179)) {
printk(KERN_INFO "es1968: not attempting power management.\n");
do_pm = 0;
}
@@ -2769,6 +2767,8 @@ static int __devinit snd_es1968_probe(st
}
}
+ snd_es1968_start_irq(chip);
+
chip->clock = clock[dev];
if (! chip->clock)
es1968_measure_clock(chip);
diff -puN sound/pci/ice1712/ak4xxx.c~alsa-bk-2003-07-28 sound/pci/ice1712/ak4xxx.c
--- 25/sound/pci/ice1712/ak4xxx.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/ice1712/ak4xxx.c Tue Jul 29 12:11:31 2003
@@ -27,8 +27,14 @@
#include
#include
#include
+#include
#include "ice1712.h"
+MODULE_AUTHOR("Jaroslav Kysela ");
+MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface");
+MODULE_LICENSE("GPL");
+MODULE_CLASSES("{sound}");
+
static void snd_ice1712_akm4xxx_lock(akm4xxx_t *ak, int chip)
{
ice1712_t *ice = ak->private_data[0];
@@ -116,8 +122,8 @@ static void snd_ice1712_akm4xxx_write(ak
/*
* initialize the akm4xxx_t record with the template
*/
-int __devinit snd_ice1712_akm4xxx_init(akm4xxx_t *ak, const akm4xxx_t *temp,
- const struct snd_ak4xxx_private *_priv, ice1712_t *ice)
+int snd_ice1712_akm4xxx_init(akm4xxx_t *ak, const akm4xxx_t *temp,
+ const struct snd_ak4xxx_private *_priv, ice1712_t *ice)
{
struct snd_ak4xxx_private *priv;
@@ -139,7 +145,7 @@ int __devinit snd_ice1712_akm4xxx_init(a
return 0;
}
-void __devexit snd_ice1712_akm4xxx_free(ice1712_t *ice)
+void snd_ice1712_akm4xxx_free(ice1712_t *ice)
{
unsigned int akidx;
if (ice->akm == NULL)
@@ -155,7 +161,7 @@ void __devexit snd_ice1712_akm4xxx_free(
/*
* build AK4xxx controls
*/
-int __devinit snd_ice1712_akm4xxx_build_controls(ice1712_t *ice)
+int snd_ice1712_akm4xxx_build_controls(ice1712_t *ice)
{
unsigned int akidx;
int err;
diff -puN sound/pci/ice1712/aureon.c~alsa-bk-2003-07-28 sound/pci/ice1712/aureon.c
--- 25/sound/pci/ice1712/aureon.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/ice1712/aureon.c Tue Jul 29 12:11:31 2003
@@ -449,7 +449,7 @@ static int __devinit aureon_init(ice1712
/*
- * Aureon board don't provide the EEPROM data except for the vendor IDs.
+ * Aureon boards don't provide the EEPROM data except for the vendor IDs.
* hence the driver needs to sets up it properly.
*/
diff -puN sound/pci/ice1712/ews.c~alsa-bk-2003-07-28 sound/pci/ice1712/ews.c
--- 25/sound/pci/ice1712/ews.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/ice1712/ews.c Tue Jul 29 12:11:31 2003
@@ -389,6 +389,14 @@ static struct snd_ak4xxx_private akm_6fi
* initialize the chip
*/
+/* 6fire specific */
+#define PCF9554_REG_INPUT 0
+#define PCF9554_REG_OUTPUT 1
+#define PCF9554_REG_POLARITY 2
+#define PCF9554_REG_CONFIG 3
+
+static int snd_ice1712_6fire_write_pca(ice1712_t *ice, unsigned char reg, unsigned char data);
+
static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
{
int err;
@@ -425,6 +433,7 @@ static int __devinit snd_ice1712_ews_ini
snd_printk("PCF9554 initialization failed\n");
return err;
}
+ snd_ice1712_6fire_write_pca(ice, PCF9554_REG_CONFIG, 0x80);
break;
case ICE1712_SUBDEVICE_EWS88MT:
case ICE1712_SUBDEVICE_EWS88MT_NEW:
@@ -449,10 +458,12 @@ static int __devinit snd_ice1712_ews_ini
case ICE1712_SUBDEVICE_EWX2496:
if ((err = snd_ice1712_init_cs8427(ice, CS8427_BASE_ADDR)) < 0)
return err;
+ snd_cs8427_reg_write(ice->cs8427, CS8427_REG_RECVERRMASK, CS8427_UNLOCK | CS8427_CONF | CS8427_BIP | CS8427_PAR);
break;
case ICE1712_SUBDEVICE_DMX6FIRE:
if ((err = snd_ice1712_init_cs8427(ice, ICE1712_6FIRE_CS8427_ADDR)) < 0)
return err;
+ snd_cs8427_reg_write(ice->cs8427, CS8427_REG_RECVERRMASK, CS8427_UNLOCK | CS8427_CONF | CS8427_BIP | CS8427_PAR);
break;
case ICE1712_SUBDEVICE_EWS88MT:
case ICE1712_SUBDEVICE_EWS88MT_NEW:
@@ -750,11 +761,6 @@ static snd_kcontrol_new_t snd_ice1712_ew
* DMX 6Fire specific controls
*/
-#define PCF9554_REG_INPUT 0
-#define PCF9554_REG_OUTPUT 1
-#define PCF9554_REG_POLARITY 2
-#define PCF9554_REG_CONFIG 3
-
static int snd_ice1712_6fire_read_pca(ice1712_t *ice, unsigned char reg)
{
unsigned char byte;
diff -puN sound/pci/ice1712/ice1712.h~alsa-bk-2003-07-28 sound/pci/ice1712/ice1712.h
--- 25/sound/pci/ice1712/ice1712.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/ice1712/ice1712.h Tue Jul 29 12:11:31 2003
@@ -86,8 +86,8 @@
* Indirect registers
*/
-#define ICE1712_IREG_PBK_COUNT_HI 0x00
-#define ICE1712_IREG_PBK_COUNT_LO 0x01
+#define ICE1712_IREG_PBK_COUNT_LO 0x00
+#define ICE1712_IREG_PBK_COUNT_HI 0x01
#define ICE1712_IREG_PBK_CTRL 0x02
#define ICE1712_IREG_PBK_LEFT 0x03 /* left volume */
#define ICE1712_IREG_PBK_RIGHT 0x04 /* right volume */
@@ -95,8 +95,8 @@
#define ICE1712_IREG_PBK_RATE_LO 0x06
#define ICE1712_IREG_PBK_RATE_MID 0x07
#define ICE1712_IREG_PBK_RATE_HI 0x08
-#define ICE1712_IREG_CAP_COUNT_HI 0x10
-#define ICE1712_IREG_CAP_COUNT_LO 0x11
+#define ICE1712_IREG_CAP_COUNT_LO 0x10
+#define ICE1712_IREG_CAP_COUNT_HI 0x11
#define ICE1712_IREG_CAP_CTRL 0x12
#define ICE1712_IREG_GPIO_DATA 0x20
#define ICE1712_IREG_GPIO_WRITE_MASK 0x21
diff -puN sound/pci/ice1712/ice1724.c~alsa-bk-2003-07-28 sound/pci/ice1712/ice1724.c
--- 25/sound/pci/ice1712/ice1724.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/ice1712/ice1724.c Tue Jul 29 12:11:31 2003
@@ -1583,8 +1583,8 @@ static int __devinit snd_vt1724_read_eep
struct snd_ice1712_card_info **tbl, *c;
if ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_EEPROM) == 0) {
- snd_printk("ICE1724 has not detected EEPROM\n");
- return -EIO;
+ snd_printk(KERN_WARNING "ICE1724 has not detected EEPROM\n");
+ // return -EIO;
}
ice->eeprom.subvendor = (snd_vt1724_read_i2c(ice, dev, 0x00) << 0) |
(snd_vt1724_read_i2c(ice, dev, 0x01) << 8) |
diff -puN sound/pci/intel8x0.c~alsa-bk-2003-07-28 sound/pci/intel8x0.c
--- 25/sound/pci/intel8x0.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/intel8x0.c Tue Jul 29 12:11:31 2003
@@ -254,8 +254,13 @@ DEFINE_REGSET(AL_PI, 0x40); /* ALi PCM i
DEFINE_REGSET(AL_PO, 0x50); /* Ali PCM out */
DEFINE_REGSET(AL_MC, 0x60); /* Ali Mic in */
DEFINE_REGSET(AL_CDC_SPO, 0x70); /* Ali Codec SPDIF out */
+DEFINE_REGSET(AL_CENTER, 0x80); /* Ali center out */
+DEFINE_REGSET(AL_LFE, 0x90); /* Ali center out */
DEFINE_REGSET(AL_CLR_SPI, 0xa0); /* Ali Controller SPDIF in */
DEFINE_REGSET(AL_CLR_SPO, 0xb0); /* Ali Controller SPDIF out */
+DEFINE_REGSET(AL_I2S, 0xc0); /* Ali I2S in */
+DEFINE_REGSET(AL_PI2, 0xd0); /* Ali PCM2 in */
+DEFINE_REGSET(AL_MC2, 0xe0); /* Ali Mic2 in */
enum {
ICH_REG_ALI_SCR = 0x00, /* System Control Register */
@@ -275,32 +280,61 @@ enum {
ICH_REG_ALI_RTSR = 0x34, /* Receive Tag Slot Register */
ICH_REG_ALI_CSPSR = 0x38, /* Command/Status Port Status Register */
ICH_REG_ALI_CAS = 0x3c, /* Codec Write Semaphore Register */
+ ICH_REG_ALI_HWVOL = 0xf0, /* hardware volume control/status */
+ ICH_REG_ALI_I2SCR = 0xf4, /* I2S control/status */
ICH_REG_ALI_SPDIFCSR = 0xf8, /* spdif channel status register */
- ICH_REG_ALI_SPDIFICS = 0xfc /* spdif interface control/status */
+ ICH_REG_ALI_SPDIFICS = 0xfc, /* spdif interface control/status */
};
#define ALI_CAS_SEM_BUSY 0x80000000
-#define ALI_CSPSR_CODEC_READY 0x08
+#define ALI_CPR_ADDR_SECONDARY 0x100
#define ALI_CPR_ADDR_READ 0x80
+#define ALI_CSPSR_CODEC_READY 0x08
#define ALI_CSPSR_READ_OK 0x02
#define ALI_CSPSR_WRITE_OK 0x01
/* interrupts for the whole chip by interrupt status register finish */
+#define ALI_INT_MICIN2 (1<<26)
+#define ALI_INT_PCMIN2 (1<<25)
+#define ALI_INT_I2SIN (1<<24)
#define ALI_INT_SPDIFOUT (1<<23) /* controller spdif out INTERRUPT */
#define ALI_INT_SPDIFIN (1<<22)
+#define ALI_INT_LFEOUT (1<<21)
+#define ALI_INT_CENTEROUT (1<<20)
#define ALI_INT_CODECSPDIFOUT (1<<19)
#define ALI_INT_MICIN (1<<18)
#define ALI_INT_PCMOUT (1<<17)
#define ALI_INT_PCMIN (1<<16)
-#define ALI_INT_CPRAIS (1<<7)
-#define ALI_INT_SPRAIS (1<<5)
+#define ALI_INT_CPRAIS (1<<7) /* command port available */
+#define ALI_INT_SPRAIS (1<<5) /* status port available */
#define ALI_INT_GPIO (1<<1)
#define ALI_INT_MASK (ALI_INT_SPDIFOUT|ALI_INT_CODECSPDIFOUT|ALI_INT_MICIN|ALI_INT_PCMOUT|ALI_INT_PCMIN)
-#define ALI_PCM_CH4 0x100
-#define ALI_PCM_CH6 0x200
-#define ALI_PCM_MASK (ALI_PCM_CH4 | ALI_PCM_CH6)
+#define ICH_ALI_SC_RESET (1<<31) /* master reset */
+#define ICH_ALI_SC_AC97_DBL (1<<30)
+#define ICH_ALI_SC_CODEC_SPDF (3<<20) /* 1=7/8, 2=6/9, 3=10/11 */
+#define ICH_ALI_SC_IN_BITS (3<<18)
+#define ICH_ALI_SC_OUT_BITS (3<<16)
+#define ICH_ALI_SC_6CH_CFG (3<<14)
+#define ICH_ALI_SC_PCM_4 (1<<8)
+#define ICH_ALI_SC_PCM_6 (2<<8)
+#define ICH_ALI_SC_PCM_246_MASK (3<<8)
+
+#define ICH_ALI_SS_SEC_ID (3<<5)
+#define ICH_ALI_SS_PRI_ID (3<<3)
+
+#define ICH_ALI_IF_AC97SP (1<<21)
+#define ICH_ALI_IF_MC (1<<20)
+#define ICH_ALI_IF_PI (1<<19)
+#define ICH_ALI_IF_MC2 (1<<18)
+#define ICH_ALI_IF_PI2 (1<<17)
+#define ICH_ALI_IF_LINE_SRC (1<<15) /* 0/1 = slot 3/6 */
+#define ICH_ALI_IF_MIC_SRC (1<<14) /* 0/1 = slot 3/6 */
+#define ICH_ALI_IF_SPDF_SRC (3<<12) /* 00 = PCM, 01 = AC97-in, 10 = spdif-in, 11 = i2s */
+#define ICH_ALI_IF_AC97_OUT (3<<8) /* 00 = PCM, 10 = spdif-in, 11 = i2s */
+#define ICH_ALI_IF_PO_SPDF (1<<3)
+#define ICH_ALI_IF_PO (1<<1)
/*
*
@@ -336,11 +370,6 @@ typedef struct {
ac97_t *ac97;
unsigned short ac97_rate_regs[3];
int ac97_rates_idx;
-#ifdef CONFIG_PM
- unsigned char civ_saved;
- unsigned char piv_saved;
- unsigned short picb_saved;
-#endif
} ichdev_t;
typedef struct _snd_intel8x0 intel8x0_t;
@@ -603,31 +632,29 @@ static int snd_intel8x0_ali_codec_semaph
int time = 100;
while (time-- && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY))
udelay(1);
+ if (! time)
+ snd_printk(KERN_WARNING "ali_codec_semaphore timeout\n");
return snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_CODEC_READY);
}
static unsigned short snd_intel8x0_ali_codec_read(ac97_t *ac97, unsigned short reg)
{
intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return ~0);
- unsigned short data, reg2;
+ unsigned short data = 0xffff;
spin_lock(&chip->ac97_lock);
if (snd_intel8x0_ali_codec_semaphore(chip))
goto __err;
- iputword(chip, ICHREG(ALI_CPR_ADDR), reg | ALI_CPR_ADDR_READ);
+ reg |= ALI_CPR_ADDR_READ;
+ if (ac97->num)
+ reg |= ALI_CPR_ADDR_SECONDARY;
+ iputword(chip, ICHREG(ALI_CPR_ADDR), reg);
if (snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_READ_OK))
goto __err;
data = igetword(chip, ICHREG(ALI_SPR));
- reg2 = igetword(chip, ICHREG(ALI_SPR_ADDR));
- if (reg != reg2) {
- snd_printd(KERN_WARNING "intel8x0: AC97 read not completed? 0x%x != 0x%x\n", reg, reg2);
- // goto __err;
- }
- spin_unlock(&chip->ac97_lock);
- return data;
__err:
spin_unlock(&chip->ac97_lock);
- return 0xffff;
+ return data;
}
static void snd_intel8x0_ali_codec_write(ac97_t *ac97, unsigned short reg, unsigned short val)
@@ -640,7 +667,9 @@ static void snd_intel8x0_ali_codec_write
return;
}
iputword(chip, ICHREG(ALI_CPR), val);
- iputbyte(chip, ICHREG(ALI_CPR_ADDR), reg);
+ if (ac97->num)
+ reg |= ALI_CPR_ADDR_SECONDARY;
+ iputword(chip, ICHREG(ALI_CPR_ADDR), reg);
snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_WRITE_OK);
spin_unlock(&chip->ac97_lock);
}
@@ -680,6 +709,7 @@ static void snd_intel8x0_setup_periods(i
ichdev->frags = ichdev->size / ichdev->fragsize;
}
iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi = ICH_REG_LVI_MASK);
+ iputbyte(chip, port + ICH_REG_OFF_CIV, 0);
ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags;
ichdev->position = 0;
#if 0
@@ -728,6 +758,8 @@ static irqreturn_t snd_intel8x0_interrup
spin_lock(&chip->reg_lock);
status = igetdword(chip, chip->int_sta_reg);
if ((status & chip->int_sta_mask) == 0) {
+ if (status)
+ iputdword(chip, chip->int_sta_reg, status);
spin_unlock(&chip->reg_lock);
return IRQ_NONE;
}
@@ -776,8 +808,9 @@ static int snd_intel8x0_pcm_trigger(snd_
}
iputbyte(chip, port + ICH_REG_OFF_CR, val);
if (cmd == SNDRV_PCM_TRIGGER_STOP) {
- /* reset whole DMA things */
+ /* wait until DMA stopped */
while (!(igetbyte(chip, port + ichdev->roff_sr) & ICH_DCH)) ;
+ /* reset whole DMA things */
iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS);
}
return 0;
@@ -788,31 +821,40 @@ static int snd_intel8x0_ali_trigger(snd_
intel8x0_t *chip = snd_pcm_substream_chip(substream);
ichdev_t *ichdev = get_ichdev(substream);
unsigned long port = ichdev->reg_offset;
+ static int fiforeg[] = { ICHREG(ALI_FIFOCR1), ICHREG(ALI_FIFOCR2), ICHREG(ALI_FIFOCR3) };
+ unsigned int val, fifo;
+ val = igetdword(chip, ICHREG(ALI_DMACR));
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /* clear FIFO for synchronization of channels */
+ fifo = igetdword(chip, fiforeg[ichdev->ali_slot / 4]);
+ fifo &= ~(0xff << (ichdev->ali_slot % 4));
+ fifo |= 0x83 << (ichdev->ali_slot % 4);
+ iputdword(chip, fiforeg[ichdev->ali_slot / 4], fifo);
+ }
iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE);
- iputbyte(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot);
+ val &= ~(1 << (ichdev->ali_slot + 16)); /* clear PAUSE flag */
+ iputdword(chip, ICHREG(ALI_DMACR), val | (1 << ichdev->ali_slot)); /* start DMA */
break;
case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
- iputbyte(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 8));
+ iputdword(chip, ICHREG(ALI_DMACR), val | (1 << (ichdev->ali_slot + 16))); /* pause */
iputbyte(chip, port + ICH_REG_OFF_CR, 0);
- /* reset whole DMA things */
- while (!(igetbyte(chip, port + ICH_REG_OFF_CR)))
+ while (igetbyte(chip, port + ICH_REG_OFF_CR))
;
+ if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)
+ break;
+ /* reset whole DMA things */
iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS);
/* clear interrupts */
iputbyte(chip, port + ICH_REG_OFF_SR, igetbyte(chip, port + ICH_REG_OFF_SR) | 0x1e);
iputdword(chip, ICHREG(ALI_INTERRUPTSR),
- igetdword(chip, ICHREG(ALI_INTERRUPTSR)) & (1 << (ichdev->ali_slot + 8)));
- break;
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- iputbyte(chip, port + ICH_REG_OFF_CR, 0);
- break;
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- iputbyte(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot);
+ igetdword(chip, ICHREG(ALI_INTERRUPTSR)) & ichdev->int_sta_mask);
break;
default:
return -EINVAL;
@@ -833,21 +875,36 @@ static int snd_intel8x0_hw_free(snd_pcm_
static void snd_intel8x0_setup_multi_channels(intel8x0_t *chip, int channels)
{
- unsigned int cnt = igetdword(chip, ICHREG(GLOB_CNT));
- if (chip->device_type == DEVICE_SIS) {
+ unsigned int cnt;
+ switch (chip->device_type) {
+ case DEVICE_ALI:
+ cnt = igetdword(chip, ICHREG(ALI_SCR));
+ cnt &= ~ICH_ALI_SC_PCM_246_MASK;
+ if (chip->multi4 && channels == 4)
+ cnt |= ICH_ALI_SC_PCM_4;
+ else if (chip->multi6 && channels == 6)
+ cnt |= ICH_ALI_SC_PCM_6;
+ iputdword(chip, ICHREG(ALI_SCR), cnt);
+ break;
+ case DEVICE_SIS:
+ cnt = igetdword(chip, ICHREG(GLOB_CNT));
cnt &= ~ICH_SIS_PCM_246_MASK;
if (chip->multi4 && channels == 4)
cnt |= ICH_SIS_PCM_4;
else if (chip->multi6 && channels == 6)
cnt |= ICH_SIS_PCM_6;
- } else {
+ iputdword(chip, ICHREG(GLOB_CNT), cnt);
+ break;
+ default:
+ cnt = igetdword(chip, ICHREG(GLOB_CNT));
cnt &= ~ICH_PCM_246_MASK;
if (chip->multi4 && channels == 4)
cnt |= ICH_PCM_4;
else if (chip->multi6 && channels == 6)
cnt |= ICH_PCM_6;
+ iputdword(chip, ICHREG(GLOB_CNT), cnt);
+ break;
}
- iputdword(chip, ICHREG(GLOB_CNT), cnt);
}
static int snd_intel8x0_pcm_prepare(snd_pcm_substream_t * substream)
@@ -860,7 +917,7 @@ static int snd_intel8x0_pcm_prepare(snd_
ichdev->physbuf = runtime->dma_addr;
ichdev->size = snd_pcm_lib_buffer_bytes(substream);
ichdev->fragsize = snd_pcm_lib_period_bytes(substream);
- if (ichdev->ichd == ICHD_PCMOUT && chip->device_type != DEVICE_ALI) {
+ if (ichdev->ichd == ICHD_PCMOUT) {
spin_lock(&chip->reg_lock);
snd_intel8x0_setup_multi_channels(chip, runtime->channels);
spin_unlock(&chip->reg_lock);
@@ -869,6 +926,9 @@ static int snd_intel8x0_pcm_prepare(snd_
for (i = 0; i < 3; i++)
if (ichdev->ac97_rate_regs[i])
snd_ac97_set_rate(ichdev->ac97, ichdev->ac97_rate_regs[i], runtime->rate);
+ /* FIXME: hack to enable spdif support */
+ if (ichdev->ichd == ICHD_PCMOUT && chip->device_type == DEVICE_SIS)
+ snd_ac97_set_rate(ichdev->ac97, AC97_SPDIF, runtime->rate);
}
snd_intel8x0_setup_periods(chip, ichdev);
return 0;
@@ -878,11 +938,16 @@ static snd_pcm_uframes_t snd_intel8x0_pc
{
intel8x0_t *chip = snd_pcm_substream_chip(substream);
ichdev_t *ichdev = get_ichdev(substream);
- size_t ptr;
+ size_t ptr1, ptr;
- ptr = ichdev->fragsize1;
- ptr -= igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << chip->pcm_pos_shift;
+ ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << chip->pcm_pos_shift;
+ if (ptr1 != 0)
+ ptr = ichdev->fragsize1 - ptr1;
+ else
+ ptr = 0;
ptr += ichdev->position;
+ if (ptr >= ichdev->size)
+ return 0;
return bytes_to_frames(substream->runtime, ptr);
}
@@ -895,7 +960,7 @@ static snd_pcm_hardware_t snd_intel8x0_s
SNDRV_PCM_INFO_RESUME),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_48000,
- .rate_min = 8000,
+ .rate_min = 48000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
@@ -935,14 +1000,23 @@ static int snd_intel8x0_pcm_open(snd_pcm
{
intel8x0_t *chip = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
+ static unsigned int i, rates[] = {
+ /* ATTENTION: these values depend on the definition in pcm.h! */
+ 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000
+ };
int err;
ichdev->substream = substream;
runtime->hw = snd_intel8x0_stream;
- if (ichdev->ac97 && ichdev->ac97_rates_idx >= 0)
+ if (ichdev->ac97 && ichdev->ac97_rates_idx >= 0) {
runtime->hw.rates = ichdev->ac97->rates[ichdev->ac97_rates_idx];
- if (!(runtime->hw.rates & SNDRV_PCM_RATE_8000))
- runtime->hw.rate_min = 48000;
+ for (i = 0; i < ARRAY_SIZE(rates); i++) {
+ if (runtime->hw.rates & (1 << i)) {
+ runtime->hw.rate_min = rates[i];
+ break;
+ }
+ }
+ }
if (chip->device_type == DEVICE_SIS) {
runtime->hw.buffer_bytes_max = 64*1024;
runtime->hw.period_bytes_max = 64*1024;
@@ -1058,6 +1132,14 @@ static int snd_intel8x0_spdif_close(snd_
static int snd_intel8x0_ali_ac97spdifout_open(snd_pcm_substream_t * substream)
{
intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ unsigned long flags;
+ unsigned int val;
+
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ val = igetdword(chip, ICHREG(ALI_INTERFACECR));
+ val |= ICH_ALI_IF_AC97SP;
+ /* also needs to set ALI_SC_CODEC_SPDF correctly */
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
return snd_intel8x0_pcm_open(substream, &chip->ichd[ALID_AC97SPDIFOUT]);
}
@@ -1065,8 +1147,15 @@ static int snd_intel8x0_ali_ac97spdifout
static int snd_intel8x0_ali_ac97spdifout_close(snd_pcm_substream_t * substream)
{
intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ unsigned long flags;
+ unsigned int val;
chip->ichd[ALID_AC97SPDIFOUT].substream = NULL;
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ val = igetdword(chip, ICHREG(ALI_INTERFACECR));
+ val &= ~ICH_ALI_IF_AC97SP;
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+
return 0;
}
@@ -1085,6 +1174,7 @@ static int snd_intel8x0_ali_spdifin_clos
return 0;
}
+#if 0 // NYI
static int snd_intel8x0_ali_spdifout_open(snd_pcm_substream_t * substream)
{
intel8x0_t *chip = snd_pcm_substream_chip(substream);
@@ -1099,6 +1189,7 @@ static int snd_intel8x0_ali_spdifout_clo
chip->ichd[ALID_SPDIFOUT].substream = NULL;
return 0;
}
+#endif
static snd_pcm_ops_t snd_intel8x0_playback_ops = {
.open = snd_intel8x0_playback_open,
@@ -1221,6 +1312,7 @@ static snd_pcm_ops_t snd_intel8x0_ali_sp
.pointer = snd_intel8x0_pcm_pointer,
};
+#if 0 // NYI
static snd_pcm_ops_t snd_intel8x0_ali_spdifout_ops = {
.open = snd_intel8x0_ali_spdifout_open,
.close = snd_intel8x0_ali_spdifout_close,
@@ -1231,6 +1323,7 @@ static snd_pcm_ops_t snd_intel8x0_ali_sp
.trigger = snd_intel8x0_pcm_trigger,
.pointer = snd_intel8x0_pcm_pointer,
};
+#endif // NYI
struct ich_pcm_table {
char *suffix;
@@ -1352,18 +1445,20 @@ static struct ich_pcm_table ali_pcms[] _
},
{
.suffix = "IEC958",
- .playback_ops = &snd_intel8x0_ali_spdifout_ops,
+ .playback_ops = &snd_intel8x0_ali_ac97spdifout_ops,
.capture_ops = &snd_intel8x0_ali_spdifin_ops,
.prealloc_size = 64 * 1024,
.prealloc_max_size = 128 * 1024,
+ .ac97_idx = ALID_AC97SPDIFOUT,
},
+#if 0 // NYI
{
- .suffix = "AC97 IEC958",
- .playback_ops = &snd_intel8x0_ali_ac97spdifout_ops,
+ .suffix = "HW IEC958",
+ .playback_ops = &snd_intel8x0_ali_spdifout_ops,
.prealloc_size = 64 * 1024,
.prealloc_max_size = 128 * 1024,
- .ac97_idx = ALID_AC97SPDIFOUT,
},
+#endif
};
static int __devinit snd_intel8x0_pcm(intel8x0_t *chip)
@@ -1442,20 +1537,30 @@ static struct _ac97_rate_regs nforce_ac9
};
static struct _ac97_rate_regs ali_ac97_rate_regs[] __devinitdata = {
+#if 0 /* FIXME: my test board doens't work well with VRA... */
{ ALID_PCMOUT, { AC97_PCM_FRONT_DAC_RATE, AC97_PCM_SURR_DAC_RATE, AC97_PCM_LFE_DAC_RATE }, AC97_RATES_FRONT_DAC },
{ ALID_PCMIN, { AC97_PCM_LR_ADC_RATE, 0, 0 }, AC97_RATES_ADC },
{ ALID_MIC, { AC97_PCM_MIC_ADC_RATE, 0, 0 }, AC97_RATES_MIC_ADC },
{ ALID_AC97SPDIFOUT, { AC97_SPDIF, 0, 0 }, AC97_RATES_SPDIF },
{ ALID_SPDIFOUT, { 0, 0, 0 }, -1 },
{ ALID_SPDIFIN, { 0, 0, 0 }, -1 },
+#else
+ { ALID_PCMOUT, { AC97_PCM_FRONT_DAC_RATE }, -1 },
+ { ALID_PCMIN, { AC97_PCM_LR_ADC_RATE }, -1 },
+ { ALID_MIC, { AC97_PCM_MIC_ADC_RATE }, -1 },
+ { ALID_AC97SPDIFOUT, { AC97_SPDIF }, -1 },
+ { ALID_SPDIFOUT, { }, -1 },
+ { ALID_SPDIFIN, { }, -1 },
+#endif
};
static struct ac97_quirk ac97_quirks[] __devinitdata = {
{ 0x1028, 0x0126, "Dell Optiplex GX260", AC97_TUNE_HP_ONLY },
{ 0x1734, 0x0088, "Fujitsu-Siemens D1522", AC97_TUNE_HP_ONLY },
{ 0x10f1, 0x2665, "Fujitsu-Siemens Celcius", AC97_TUNE_HP_ONLY },
+ { 0x110a, 0x0056, "Fujitsu-Siemens Scenic", AC97_TUNE_HP_ONLY },
{ 0x8086, 0x4d44, "Intel D850EMV2", AC97_TUNE_HP_ONLY },
- { 0x4144, 0x5360, "AMD64 Motherboard", AC97_TUNE_HP_ONLY },
+ /* { 0x4144, 0x5360, "AMD64 Motherboard", AC97_TUNE_HP_ONLY }, */ /* FIXME: this seems invalid */
{ 0x1043, 0x80b0, "ASUS P4PE Mobo", AC97_TUNE_SWAP_SURROUND },
{ } /* terminator */
};
@@ -1465,19 +1570,24 @@ static int __devinit snd_intel8x0_mixer(
ac97_t ac97, *x97;
ichdev_t *ichdev;
int err;
- unsigned int i, num, channels = 2, codecs, _codecs;
+ unsigned int i, num, codecs, _codecs;
unsigned int glob_sta = 0;
struct _ac97_rate_regs *tbl;
+ int spdif_idx = -1; /* disabled */
switch (chip->device_type) {
case DEVICE_NFORCE:
tbl = nforce_ac97_rate_regs;
+ spdif_idx = NVD_SPBAR;
break;
case DEVICE_ALI:
tbl = ali_ac97_rate_regs;
+ spdif_idx = ALID_AC97SPDIFOUT;
break;
default:
tbl = intel_ac97_rate_regs;
+ if (chip->device_type == DEVICE_INTEL_ICH4)
+ spdif_idx = ICHD_SPBAR;
break;
};
for (i = 0; i < chip->bdbars_count; i++) {
@@ -1501,10 +1611,6 @@ static int __devinit snd_intel8x0_mixer(
glob_sta = igetdword(chip, ICHREG(GLOB_STA));
ac97.write = snd_intel8x0_codec_write;
ac97.read = snd_intel8x0_codec_read;
- if (glob_sta & ICH_PCM_6)
- channels = 6;
- else if (glob_sta & ICH_PCM_4)
- channels = 4;
if (chip->device_type == DEVICE_INTEL_ICH4) {
codecs = 0;
if (glob_sta & ICH_PCR)
@@ -1527,7 +1633,6 @@ static int __devinit snd_intel8x0_mixer(
} else {
ac97.write = snd_intel8x0_ali_codec_write;
ac97.read = snd_intel8x0_ali_codec_read;
- channels = 6;
codecs = 1;
/* detect the secondary codec */
for (i = 0; i < 100; i++) {
@@ -1551,19 +1656,8 @@ static int __devinit snd_intel8x0_mixer(
if (x97->ext_id & AC97_EI_VRM)
chip->ichd[ICHD_MIC].ac97 = x97;
/* spdif */
- if (x97->ext_id & AC97_EI_SPDIF) {
- switch (chip->device_type) {
- case DEVICE_INTEL_ICH4:
- chip->ichd[ICHD_SPBAR].ac97 = x97;
- break;
- case DEVICE_NFORCE:
- chip->ichd[NVD_SPBAR].ac97 = x97;
- break;
- case DEVICE_ALI:
- chip->ichd[ALID_AC97SPDIFOUT].ac97 = x97;
- break;
- }
- }
+ if ((x97->ext_id & AC97_EI_SPDIF) && spdif_idx >= 0)
+ chip->ichd[spdif_idx].ac97 = x97;
/* make sure, that we have DACs at right slot for rev2.2 */
if (ac97_is_rev22(x97))
snd_ac97_update_bits(x97, AC97_EXTENDED_ID, AC97_EI_DACS_SLOT_MASK, 0);
@@ -1594,23 +1688,18 @@ static int __devinit snd_intel8x0_mixer(
chip->ichd[ICHD_PCM2IN].ac97 == x97)
chip->ichd[ICHD_MIC2].ac97 = x97;
}
- if (x97->ext_id & AC97_EI_SPDIF) {
- if (chip->ichd[ICHD_SPBAR].ac97 == NULL)
- chip->ichd[ICHD_SPBAR].ac97 = x97;
- }
break;
default:
if (x97->ext_id & AC97_EI_VRM) {
if (chip->ichd[ICHD_MIC].ac97 == NULL)
chip->ichd[ICHD_MIC].ac97 = x97;
}
- if ((x97->ext_id & AC97_EI_SPDIF) &&
- chip->device_type == DEVICE_NFORCE) {
- if (chip->ichd[NVD_SPBAR].ac97 == NULL)
- chip->ichd[NVD_SPBAR].ac97 = x97;
- }
break;
}
+ if ((x97->ext_id & AC97_EI_SPDIF) && spdif_idx >= 0) {
+ if (chip->ichd[spdif_idx].ac97 == NULL)
+ chip->ichd[spdif_idx].ac97 = x97;
+ }
}
__skip_secondary:
@@ -1640,22 +1729,24 @@ static int __devinit snd_intel8x0_mixer(
if (x97->scaps & AC97_SCAP_CENTER_LFE_DAC)
chip->multi6 = 1;
}
- if (codecs > 1) {
+ if (chip->device_type == DEVICE_ALI && chip->ac97[1]) {
+ /* set secondary codec id */
+ iputdword(chip, ICHREG(ALI_SSR),
+ (igetdword(chip, ICHREG(ALI_SSR)) & ~ICH_ALI_SS_SEC_ID) |
+ (chip->ac97[1]->addr << 5));
+ }
+ if (codecs > 1 && !chip->multi6) {
/* assign right slots for rev2.2 codecs */
i = 1;
- if (chip->multi4)
- goto __6ch;
- for ( ; i < codecs; i++) {
+ for ( ; i < codecs && !chip->multi4; 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;
}
}
- __6ch:
for ( ; i < codecs && chip->multi4; i++) {
x97 = chip->ac97[i];
if (!ac97_is_audio(x97))
@@ -1668,27 +1759,20 @@ static int __devinit snd_intel8x0_mixer(
}
/* ok, some older codecs might support only AMAP */
if (!chip->multi4) {
+ int cnums = 0;
for (i = 1; i < codecs; i++) {
x97 = chip->ac97[i];
if (!ac97_is_audio(x97))
continue;
if (ac97_can_amap(x97)) {
- if (x97->addr == 1) {
- chip->multi4 = 1;
- break;
- }
- }
- }
- for ( ; i < codecs && chip->multi4; i++) {
- if (!ac97_is_audio(x97))
- continue;
- if (ac97_can_amap(x97)) {
- if (x97->addr == 2) {
- chip->multi6 = 1;
- break;
- }
+ if (x97->addr > 0)
+ cnums++;
}
}
+ if (cnums >= 2)
+ chip->multi6 = 1;
+ if (cnums >= 1)
+ chip->multi4 = 1;
}
}
chip->in_ac97_init = 0;
@@ -1702,25 +1786,20 @@ static int __devinit snd_intel8x0_mixer(
static void do_ali_reset(intel8x0_t *chip)
{
- iputdword(chip, ICHREG(ALI_SCR), 0x8000000);
+ iputdword(chip, ICHREG(ALI_SCR), ICH_ALI_SC_RESET);
iputdword(chip, ICHREG(ALI_FIFOCR1), 0x83838383);
iputdword(chip, ICHREG(ALI_FIFOCR2), 0x83838383);
- iputdword(chip, ICHREG(ALI_INTERFACECR), 0x04080002); /* no spdif? */
+ iputdword(chip, ICHREG(ALI_FIFOCR3), 0x83838383);
+ iputdword(chip, ICHREG(ALI_INTERFACECR),
+ ICH_ALI_IF_MC|ICH_ALI_IF_PI|ICH_ALI_IF_PO);
iputdword(chip, ICHREG(ALI_INTERRUPTCR), 0x00000000);
iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000);
}
-static void do_delay(intel8x0_t *chip)
-{
-#ifdef CONFIG_PM
- if (chip->in_suspend) {
- mdelay((1000 + HZ - 1) / HZ);
- return;
- }
-#endif
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
-}
+#define do_delay(chip) do {\
+ set_current_state(TASK_UNINTERRUPTIBLE);\
+ schedule_timeout(1);\
+} while (0)
static int snd_intel8x0_ich_chip_init(intel8x0_t *chip)
{
@@ -1847,14 +1926,14 @@ static int snd_intel8x0_chip_init(intel8
unsigned int i;
int err;
- if (chip->device_type != DEVICE_ALI)
- err = snd_intel8x0_ich_chip_init(chip);
- else
- err = snd_intel8x0_ali_chip_init(chip);
- if (err < 0)
- return err;
-
- iagetword(chip, 0); /* clear semaphore flag */
+ if (chip->device_type != DEVICE_ALI) {
+ if ((err = snd_intel8x0_ich_chip_init(chip)) < 0)
+ return err;
+ iagetword(chip, 0); /* clear semaphore flag */
+ } else {
+ if ((err = snd_intel8x0_ali_chip_init(chip)) < 0)
+ return err;
+ }
/* disable interrupts */
for (i = 0; i < chip->bdbars_count; i++)
@@ -1939,6 +2018,7 @@ static void intel8x0_resume(intel8x0_t *
return;
pci_enable_device(chip->pci);
+ pci_set_master(chip->pci);
snd_intel8x0_chip_init(chip);
for (i = 0; i < 3; i++)
if (chip->ac97[i])
@@ -1948,7 +2028,6 @@ static void intel8x0_resume(intel8x0_t *
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
}
-#ifndef PCI_OLD_SUSPEND
static int snd_intel8x0_suspend(struct pci_dev *dev, u32 state)
{
intel8x0_t *chip = snd_magic_cast(intel8x0_t, pci_get_drvdata(dev), return -ENXIO);
@@ -1961,18 +2040,6 @@ static int snd_intel8x0_resume(struct pc
intel8x0_resume(chip);
return 0;
}
-#else
-static void snd_intel8x0_suspend(struct pci_dev *dev)
-{
- intel8x0_t *chip = snd_magic_cast(intel8x0_t, pci_get_drvdata(dev), return);
- intel8x0_suspend(chip);
-}
-static void snd_intel8x0_resume(struct pci_dev *dev)
-{
- intel8x0_t *chip = snd_magic_cast(intel8x0_t, pci_get_drvdata(dev), return);
- intel8x0_resume(chip);
-}
-#endif
/* callback */
static int snd_intel8x0_set_power_state(snd_card_t *card, unsigned int power_state)
@@ -2033,7 +2100,7 @@ static void __devinit intel8x0_measure_a
iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE | ICH_STARTBM);
else {
iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE);
- iputbyte(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot);
+ iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot);
}
do_gettimeofday(&start_time);
spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -2051,12 +2118,16 @@ static void __devinit intel8x0_measure_a
pos += ichdev->position;
do_gettimeofday(&stop_time);
/* stop */
- if (chip->device_type == DEVICE_ALI)
- iputbyte(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 8));
- iputbyte(chip, port + ICH_REG_OFF_CR, 0);
- /* reset whole DMA things */
- while (!(igetbyte(chip, port + ichdev->roff_sr) & ICH_DCH))
- ;
+ if (chip->device_type == DEVICE_ALI) {
+ iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 8));
+ iputbyte(chip, port + ICH_REG_OFF_CR, 0);
+ while (igetbyte(chip, port + ICH_REG_OFF_CR))
+ ;
+ } else {
+ iputbyte(chip, port + ICH_REG_OFF_CR, 0);
+ while (!(igetbyte(chip, port + ichdev->roff_sr) & ICH_DCH))
+ ;
+ }
iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS);
spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -2281,7 +2352,8 @@ static int __devinit snd_intel8x0_create
ichdev->roff_sr = ICH_REG_OFF_SR;
ichdev->roff_picb = ICH_REG_OFF_PICB;
}
- ichdev->ali_slot = i + 1; /* is this right for last three devices? --jk */
+ if (device_type == DEVICE_ALI)
+ ichdev->ali_slot = (ichdev->reg_offset - 0x40) / 0x10;
}
/* SIS7012 handles the pcm data in bytes, others are in words */
chip->pcm_pos_shift = (device_type == DEVICE_SIS) ? 0 : 1;
diff -puN sound/pci/maestro3.c~alsa-bk-2003-07-28 sound/pci/maestro3.c
--- 25/sound/pci/maestro3.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/maestro3.c Tue Jul 29 12:11:32 2003
@@ -43,6 +43,7 @@
#include
#include
#include
+#include
#include
#define SNDRV_GET_ID
#include
@@ -851,6 +852,9 @@ struct snd_m3 {
int external_amp;
int amp_gpio;
+ /* midi */
+ snd_rawmidi_t *rmidi;
+
/* pcm streams */
int num_substreams;
m3_dma_t *substreams;
@@ -971,6 +975,11 @@ static struct m3_quirk m3_quirk_list[] =
* lowlevel functions
*/
+#define big_mdelay(msec) do {\
+ set_current_state(TASK_UNINTERRUPTIBLE);\
+ schedule_timeout(((msec) * HZ) / 1000);\
+} while (0)
+
inline static void snd_m3_outw(m3_t *chip, u16 value, unsigned long reg)
{
outw(value, chip->iobase + reg);
@@ -1012,7 +1021,7 @@ static void snd_m3_assp_write(m3_t *chip
static void snd_m3_assp_halt(m3_t *chip)
{
chip->reset_state = snd_m3_inb(chip, DSP_PORT_CONTROL_REG_B) & ~REGB_STOP_CLOCK;
- mdelay(10);
+ big_mdelay(10);
snd_m3_outb(chip, chip->reset_state & ~REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B);
}
@@ -1526,9 +1535,14 @@ static snd_pcm_uframes_t
snd_m3_pcm_pointer(snd_pcm_substream_t * subs)
{
m3_t *chip = snd_pcm_substream_chip(subs);
+ unsigned int ptr;
m3_dma_t *s = (m3_dma_t*)subs->runtime->private_data;
snd_assert(s != NULL, return 0);
- return bytes_to_frames(subs->runtime, snd_m3_get_pointer(chip, s, subs));
+
+ spin_lock(&chip->reg_lock);
+ ptr = snd_m3_get_pointer(chip, s, subs);
+ spin_unlock(&chip->reg_lock);
+ return bytes_to_frames(subs->runtime, ptr);
}
@@ -1562,17 +1576,11 @@ snd_m3_interrupt(int irq, void *dev_id,
u8 status;
int i;
- status = inb(chip->iobase + 0x1A);
+ status = inb(chip->iobase + HOST_INT_STATUS);
if (status == 0xff)
return IRQ_NONE;
- /* presumably acking the ints? */
- outw(status, chip->iobase + 0x1A);
-
- /*if (in_suspend)
- return IRQ_NONE;*/
-
/*
* ack an assp int if its running
* and has an int pending
@@ -1595,9 +1603,13 @@ snd_m3_interrupt(int irq, void *dev_id,
}
}
- /* XXX is this needed? */
- if (status & 0x40)
- outb(0x40, chip->iobase+0x1A);
+#if 0 /* TODO: not supported yet */
+ if ((status & MPU401_INT_PENDING) && chip->rmidi)
+ snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
+#endif
+
+ /* ack ints */
+ snd_m3_outw(chip, HOST_INT_STATUS, status);
return IRQ_HANDLED;
}
@@ -1898,7 +1910,7 @@ static int snd_m3_try_read_vendor(m3_t *
return (ret == 0) || (ret == 0xffff);
}
-static void snd_m3_ac97_reset(m3_t *chip, int busywait)
+static void snd_m3_ac97_reset(m3_t *chip)
{
u16 dir;
int delay1 = 0, delay2 = 0, i;
@@ -1933,12 +1945,8 @@ static void snd_m3_ac97_reset(m3_t *chip
outw(0, io + GPIO_DATA);
outw(dir | GPO_PRIMARY_AC97, io + GPIO_DIRECTION);
- if (busywait) {
- mdelay(delay1);
- } else {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout((delay1 * HZ) / 1000);
- }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout((delay1 * HZ) / 1000);
outw(GPO_PRIMARY_AC97, io + GPIO_DATA);
udelay(5);
@@ -1946,12 +1954,9 @@ static void snd_m3_ac97_reset(m3_t *chip
outw(IO_SRAM_ENABLE | SERIAL_AC_LINK_ENABLE, io + RING_BUS_CTRL_A);
outw(~0, io + GPIO_MASK);
- if (busywait) {
- mdelay(delay2);
- } else {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout((delay2 * HZ) / 1000);
- }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout((delay2 * HZ) / 1000);
+
if (! snd_m3_try_read_vendor(chip))
break;
@@ -1968,9 +1973,9 @@ static void snd_m3_ac97_reset(m3_t *chip
*/
tmp = inw(io + RING_BUS_CTRL_A);
outw(RAC_SDFS_ENABLE|LAC_SDFS_ENABLE, io + RING_BUS_CTRL_A);
- mdelay(20);
+ big_mdelay(20);
outw(tmp, io + RING_BUS_CTRL_A);
- mdelay(50);
+ big_mdelay(50);
#endif
}
@@ -2298,8 +2303,15 @@ snd_m3_chip_init(m3_t *chip)
{
struct pci_dev *pcidev = chip->pci;
u32 n;
+ u16 w;
u8 t; /* makes as much sense as 'n', no? */
+ pci_read_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, &w);
+ w &= ~(SOUND_BLASTER_ENABLE|FM_SYNTHESIS_ENABLE|
+ MPU401_IO_ENABLE|MPU401_IRQ_ENABLE|ALIAS_10BIT_IO|
+ DISABLE_LEGACY);
+ pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w);
+
pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n);
n &= REDUCED_DEBOUNCE;
n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING;
@@ -2337,7 +2349,7 @@ snd_m3_enable_ints(m3_t *chip)
{
unsigned long io = chip->iobase;
- outw(ASSP_INT_ENABLE, io + HOST_INT_CTRL);
+ outw(ASSP_INT_ENABLE | MPU401_INT_ENABLE, io + HOST_INT_CTRL);
outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE,
io + ASSP_CONTROL_C);
}
@@ -2363,6 +2375,10 @@ static int snd_m3_free(m3_t *chip)
spin_unlock_irqrestore(&chip->reg_lock, flags);
kfree(chip->substreams);
}
+ if (chip->iobase_res) {
+ snd_m3_outw(chip, HOST_INT_CTRL, 0); /* disable ints */
+ }
+
#ifdef CONFIG_PM
if (chip->suspend_mem)
vfree(chip->suspend_mem);
@@ -2400,7 +2416,7 @@ static void m3_suspend(m3_t *chip)
snd_pcm_suspend_all(chip->pcm);
- mdelay(10); /* give the assp a chance to idle.. */
+ big_mdelay(10); /* give the assp a chance to idle.. */
snd_m3_assp_halt(chip);
@@ -2435,7 +2451,7 @@ static void m3_resume(m3_t *chip)
snd_m3_chip_init(chip);
snd_m3_assp_halt(chip);
- snd_m3_ac97_reset(chip, 1);
+ snd_m3_ac97_reset(chip);
/* restore dsp image */
index = 0;
@@ -2460,7 +2476,6 @@ static void m3_resume(m3_t *chip)
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
}
-#ifndef PCI_OLD_SUSPEND
static int snd_m3_suspend(struct pci_dev *pci, u32 state)
{
m3_t *chip = snd_magic_cast(m3_t, pci_get_drvdata(pci), return -ENXIO);
@@ -2473,18 +2488,6 @@ static int snd_m3_resume(struct pci_dev
m3_resume(chip);
return 0;
}
-#else
-static void snd_m3_suspend(struct pci_dev *pci)
-{
- m3_t *chip = snd_magic_cast(m3_t, pci_get_drvdata(pci), return);
- m3_suspend(chip);
-}
-static void snd_m3_resume(struct pci_dev *pci)
-{
- m3_t *chip = snd_magic_cast(m3_t, pci_get_drvdata(pci), return);
- m3_resume(chip);
-}
-#endif
/* callback */
static int snd_m3_set_power_state(snd_card_t *card, unsigned int power_state)
@@ -2606,7 +2609,7 @@ snd_m3_create(snd_card_t *card, struct p
snd_m3_chip_init(chip);
snd_m3_assp_halt(chip);
- snd_m3_ac97_reset(chip, 0);
+ snd_m3_ac97_reset(chip);
snd_m3_assp_init(chip);
snd_m3_amp_enable(chip, 1);
@@ -2717,6 +2720,15 @@ snd_m3_probe(struct pci_dev *pci, const
return err;
}
+#if 0 /* TODO: not supported yet */
+ /* TODO enable midi irq and i/o */
+ err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401,
+ chip->iobase + MPU401_DATA_PORT, 1,
+ chip->irq, 0, &chip->rmidi);
+ if (err < 0)
+ printk(KERN_WARNING "maestro3: no midi support.\n");
+#endif
+
pci_set_drvdata(pci, chip);
dev++;
return 0;
diff -puN sound/pci/nm256/nm256.c~alsa-bk-2003-07-28 sound/pci/nm256/nm256.c
--- 25/sound/pci/nm256/nm256.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/nm256/nm256.c Tue Jul 29 12:11:31 2003
@@ -1307,7 +1307,6 @@ static void nm256_resume(nm256_t *chip)
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
}
-#ifndef PCI_OLD_SUSPEND
static int snd_nm256_suspend(struct pci_dev *dev, u32 state)
{
nm256_t *chip = snd_magic_cast(nm256_t, pci_get_drvdata(dev), return -ENXIO);
@@ -1320,18 +1319,6 @@ static int snd_nm256_resume(struct pci_d
nm256_resume(chip);
return 0;
}
-#else
-static void snd_nm256_suspend(struct pci_dev *dev)
-{
- nm256_t *chip = snd_magic_cast(nm256_t, pci_get_drvdata(dev), return);
- nm256_suspend(chip);
-}
-static void snd_nm256_resume(struct pci_dev *dev)
-{
- nm256_t *chip = snd_magic_cast(nm256_t, pci_get_drvdata(dev), return);
- nm256_resume(chip);
-}
-#endif
/* callback */
static int snd_nm256_set_power_state(snd_card_t *card, unsigned int power_state)
diff -puN sound/pci/rme9652/hammerfall_mem.c~alsa-bk-2003-07-28 sound/pci/rme9652/hammerfall_mem.c
--- 25/sound/pci/rme9652/hammerfall_mem.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/rme9652/hammerfall_mem.c Tue Jul 29 12:11:31 2003
@@ -1,251 +0,0 @@
-/*
- ALSA memory allocation module for the RME Digi9652
-
- Copyright(c) 1999 IEM - Winfried Ritsch
- Copyright (C) 1999 Paul Barton-Davis
-
- This module is only needed if you compiled the hammerfall driver with
- the PREALLOCATE_MEMORY option. It allocates the memory need to
- run the board and holds it until the module is unloaded. Because
- we need 2 contiguous 1.6MB regions for the board, it can be
- a problem getting them once the system memory has become fairly
- fragmented.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- $Id: hammerfall_mem.c,v 1.9 2003/05/31 11:33:57 perex Exp $
-
-
- Tue Oct 17 2000 Jaroslav Kysela
- * space is allocated only for physical devices
- * added support for 2.4 kernels (pci_alloc_consistent)
-
-*/
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define HAMMERFALL_CARDS 8
-#define HAMMERFALL_CHANNEL_BUFFER_SAMPLES (16*1024)
-#define HAMMERFALL_CHANNEL_BUFFER_BYTES (4*HAMMERFALL_CHANNEL_BUFFER_SAMPLES)
-
-/* export */
-
-static int enable[8] = {1,1,1,1,1,1,1,1};
-MODULE_PARM(enable, "1-" __MODULE_STRING(HAMMERFALL_CARDS) "i");
-MODULE_PARM_DESC(enable, "Enable cards to allocate buffers for.");
-
-MODULE_AUTHOR("Winfried Ritsch, Paul Barton-Davis ");
-MODULE_DESCRIPTION("Memory allocator for RME Hammerfall");
-MODULE_CLASSES("{sound}");
-MODULE_LICENSE("GPL");
-
-/* Since we don't know at this point if we're allocating memory for a
- Hammerfall or a Hammerfall/Light, assume the worst and allocate
- space for the maximum number of channels.
-
- The extra channel is allocated because we need a 64kB-aligned
- buffer in the actual interface driver code (see rme9652.c or hdsp.c
- for details)
-*/
-
-#define TOTAL_SIZE (26+1)*(HAMMERFALL_CHANNEL_BUFFER_BYTES)
-#define NBUFS 2*HAMMERFALL_CARDS
-
-#define HAMMERFALL_BUF_ALLOCATED 0x1
-#define HAMMERFALL_BUF_USED 0x2
-
-typedef struct hammerfall_buf_stru hammerfall_buf_t;
-
-struct hammerfall_buf_stru {
- struct pci_dev *pci;
- void *buf;
- dma_addr_t addr;
- char flags;
-};
-
-static hammerfall_buf_t hammerfall_buffers[NBUFS];
-
-/* These are here so that we have absolutely no dependencies
- on any other modules. Dependencies can (1) cause us to
- lose in the rush for 2x1.6MB chunks of contiguous memory
- and (2) make driver debugging difficult because unloading
- and reloading the snd module causes us to have to do the
- same for this one. Since we can rarely if ever allocate
- memory after starting things running, that would be very
- undesirable.
-*/
-
-static void *hammerfall_malloc_pages(struct pci_dev *pci,
- unsigned long size,
- dma_addr_t *dmaaddr)
-{
- void *res;
-
- res = (void *) pci_alloc_consistent(pci, size, dmaaddr);
- if (res != NULL) {
- struct page *page = virt_to_page(res);
- struct page *last_page = page + (size + PAGE_SIZE - 1) / PAGE_SIZE;
- while (page < last_page)
- set_bit(PG_reserved, &(page++)->flags);
- }
- return res;
-}
-
-static void hammerfall_free_pages(struct pci_dev *pci, unsigned long size,
- void *ptr, dma_addr_t dmaaddr)
-{
- struct page *page, *last_page;
-
- if (ptr == NULL)
- return;
- page = virt_to_page(ptr);
- last_page = virt_to_page(ptr) + (size + PAGE_SIZE - 1) / PAGE_SIZE;
- while (page < last_page)
- clear_bit(PG_reserved, &(page++)->flags);
- pci_free_consistent(pci, size, ptr, dmaaddr);
-}
-
-void *snd_hammerfall_get_buffer (struct pci_dev *pcidev, dma_addr_t *dmaaddr)
-{
- int i;
- hammerfall_buf_t *rbuf;
-
- for (i = 0; i < NBUFS; i++) {
- rbuf = &hammerfall_buffers[i];
- if (rbuf->flags == HAMMERFALL_BUF_ALLOCATED) {
- rbuf->flags |= HAMMERFALL_BUF_USED;
- rbuf->pci = pcidev;
- *dmaaddr = rbuf->addr;
- return rbuf->buf;
- }
- }
-
- return NULL;
-}
-
-void snd_hammerfall_free_buffer (struct pci_dev *pcidev, void *addr)
-{
- int i;
- hammerfall_buf_t *rbuf;
-
- for (i = 0; i < NBUFS; i++) {
- rbuf = &hammerfall_buffers[i];
- if (rbuf->buf == addr && rbuf->pci == pcidev) {
- rbuf->flags &= ~HAMMERFALL_BUF_USED;
- return;
- }
- }
-
- printk ("Hammerfall memory allocator: unknown buffer address or PCI device ID");
-}
-
-static void hammerfall_free_buffers (void)
-
-{
- int i;
- hammerfall_buf_t *rbuf;
-
- for (i = 0; i < NBUFS; i++) {
-
- /* We rely on general module code to prevent
- us from being unloaded with buffers in use.
-
- However, not quite. Do not release memory
- if it is still marked as in use. This might
- be unnecessary.
- */
-
- rbuf = &hammerfall_buffers[i];
-
- if (rbuf->flags == HAMMERFALL_BUF_ALLOCATED) {
- hammerfall_free_pages (rbuf->pci, TOTAL_SIZE, rbuf->buf, rbuf->addr);
- rbuf->buf = NULL;
- rbuf->flags = 0;
- }
- }
-}
-
-static int __init alsa_hammerfall_mem_init(void)
-{
- int i;
- struct pci_dev *pci = NULL;
- hammerfall_buf_t *rbuf;
-
- /* make sure our buffer records are clean */
-
- for (i = 0; i < NBUFS; i++) {
- rbuf = &hammerfall_buffers[i];
- rbuf->pci = NULL;
- rbuf->buf = NULL;
- rbuf->flags = 0;
- }
-
- /* ensure sane values for the number of buffers */
-
- /* Remember: 2 buffers per card, one for capture, one for
- playback.
- */
-
- i = 0; /* card number */
- rbuf = hammerfall_buffers;
- while ((pci = pci_find_device(PCI_VENDOR_ID_XILINX, PCI_ANY_ID, pci)) != NULL) {
- int k;
-
- /* check for Hammerfall and Hammerfall DSP cards */
-
- if (pci->device != 0x3fc4 && pci->device != 0x3fc5)
- continue;
-
- if (!enable[i])
- continue;
-
- for (k = 0; k < 2; ++k) {
- rbuf->buf = hammerfall_malloc_pages(pci, TOTAL_SIZE, &rbuf->addr);
- if (rbuf->buf == NULL) {
- hammerfall_free_buffers();
- printk(KERN_ERR "Hammerfall memory allocator: no memory available for card %d buffer %d\n", i, k + 1);
- return -ENOMEM;
- }
- rbuf->flags = HAMMERFALL_BUF_ALLOCATED;
- rbuf++;
- }
- i++;
- }
-
- if (i == 0)
- printk(KERN_ERR "Hammerfall memory allocator: "
- "no Hammerfall cards found...\n");
- else
- printk(KERN_ERR "Hammerfall memory allocator: "
- "buffers allocated for %d cards\n", i);
-
- return 0;
-}
-
-static void __exit alsa_hammerfall_mem_exit(void)
-{
- hammerfall_free_buffers();
-}
-
-module_init(alsa_hammerfall_mem_init)
-module_exit(alsa_hammerfall_mem_exit)
-
-EXPORT_SYMBOL(snd_hammerfall_get_buffer);
-EXPORT_SYMBOL(snd_hammerfall_free_buffer);
diff -puN sound/pci/rme9652/hdsp.c~alsa-bk-2003-07-28 sound/pci/rme9652/hdsp.c
--- 25/sound/pci/rme9652/hdsp.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/rme9652/hdsp.c Tue Jul 29 12:11:31 2003
@@ -22,6 +22,7 @@
*/
#include
+#include
#include
#include
#include
@@ -75,6 +76,8 @@ MODULE_DEVICES("{{RME Hammerfall-DSP},"
#define DIGIFACE_DS_CHANNELS 14
#define MULTIFACE_SS_CHANNELS 18
#define MULTIFACE_DS_CHANNELS 14
+#define H9652_SS_CHANNELS 26
+#define H9652_DS_CHANNELS 14
/* Write registers. These are defined as byte-offsets from the iobase value.
*/
@@ -84,7 +87,7 @@ MODULE_DEVICES("{{RME Hammerfall-DSP},"
#define HDSP_controlRegister 64
#define HDSP_interruptConfirmation 96
#define HDSP_outputEnable 128
-#define HDSP_jtagReg 256
+#define HDSP_control2Reg 256
#define HDSP_midiDataOut0 352
#define HDSP_midiDataOut1 356
#define HDSP_fifoData 368
@@ -120,7 +123,7 @@ MODULE_DEVICES("{{RME Hammerfall-DSP},"
#define HDSP_IO_EXTENT 5192
-/* jtag register bits */
+/* control2 register bits */
#define HDSP_TMS 0x01
#define HDSP_TCK 0x02
@@ -133,6 +136,7 @@ MODULE_DEVICES("{{RME Hammerfall-DSP},"
#define HDSP_VERSION_BIT 0x100
#define HDSP_BIGENDIAN_MODE 0x200
#define HDSP_RD_MULTIPLE 0x400
+#define HDSP_9652_ENABLE_MIXER 0x800
#define HDSP_S_PROGRAM (HDSP_PROGRAM|HDSP_CONFIG_MODE_0)
#define HDSP_S_LOAD (HDSP_PROGRAM|HDSP_CONFIG_MODE_1)
@@ -358,15 +362,16 @@ struct _hdsp {
hdsp_midi_t midi[2];
struct tasklet_struct midi_tasklet;
int precise_ptr;
- u32 control_register; /* cached value */
+ u32 control_register; /* cached value */
+ u32 control2_register; /* cached value */
u32 creg_spdif;
u32 creg_spdif_stream;
- char *card_name; /* digiface/multiface */
+ char *card_name; /* digiface/multiface */
HDSP_IO_Type io_type; /* ditto, but for code use */
unsigned short firmware_rev;
unsigned short state; /* stores state bits */
u32 firmware_cache[24413]; /* this helps recover from accidental iobox power failure */
- size_t period_bytes; /* guess what this is */
+ size_t period_bytes; /* guess what this is */
unsigned char ds_channels;
unsigned char ss_channels; /* different for multiface/digiface */
void *capture_buffer_unaligned; /* original buffer addresses */
@@ -433,8 +438,39 @@ static char channel_map_ds[HDSP_MAX_CHAN
#define HDSP_PREALLOCATE_MEMORY /* via module snd-hdsp_mem */
#ifdef HDSP_PREALLOCATE_MEMORY
-extern void *snd_hammerfall_get_buffer(struct pci_dev *, dma_addr_t *dmaaddr);
-extern void snd_hammerfall_free_buffer(struct pci_dev *, void *ptr);
+static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
+{
+ struct snd_dma_device pdev;
+ struct snd_dma_buffer dmbuf;
+
+ snd_dma_device_pci(&pdev, pci, capture);
+ dmbuf.bytes = 0;
+ if (! snd_dma_get_reserved(&pdev, &dmbuf)) {
+ if (snd_dma_alloc_pages(&pdev, size, &dmbuf) < 0)
+ return NULL;
+ snd_dma_set_reserved(&pdev, &dmbuf);
+ }
+ *addrp = dmbuf.addr;
+ return dmbuf.area;
+}
+
+static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
+{
+ struct snd_dma_device dev;
+ snd_dma_device_pci(&dev, pci, capture);
+ snd_dma_free_reserved(&dev);
+}
+
+#else
+static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
+{
+ return snd_malloc_pci_pages(pci, size, addrp);
+}
+
+static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
+{
+ snd_free_pci_pages(pci, size, ptr, addr);
+}
#endif
static struct pci_device_id snd_hdsp_ids[] __devinitdata = {
@@ -452,7 +488,7 @@ MODULE_DEVICE_TABLE(pci, snd_hdsp_ids);
/* prototypes */
static int __devinit snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp);
static int __devinit snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp);
-static inline int snd_hdsp_initialize_input_enable (hdsp_t *hdsp);
+static inline int snd_hdsp_enable_io (hdsp_t *hdsp);
static inline void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp);
static inline void snd_hdsp_initialize_channels (hdsp_t *hdsp);
static inline int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout);
@@ -460,18 +496,6 @@ static int hdsp_update_simple_mixer_cont
static int hdsp_autosync_ref(hdsp_t *hdsp);
static int snd_hdsp_set_defaults(hdsp_t *hdsp);
-static inline int hdsp_is_9652 (hdsp_t *hdsp)
-{
- switch (hdsp->firmware_rev) {
- case 0x64:
- case 0x65:
- case 0x68:
- return 1;
- default:
- return 0;
- }
-}
-
static inline int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out)
{
switch (hdsp->firmware_rev) {
@@ -504,12 +528,15 @@ static inline unsigned int hdsp_read(hds
static inline int hdsp_check_for_iobox (hdsp_t *hdsp)
{
+
+ if (hdsp->io_type == H9652) return 0;
if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) {
snd_printk ("Hammerfall-DSP: no Digiface or Multiface connected!\n");
hdsp->state &= ~HDSP_FirmwareLoaded;
return -EIO;
}
return 0;
+
}
static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
@@ -521,7 +548,7 @@ static int snd_hdsp_load_firmware_from_c
snd_printk ("loading firmware\n");
- hdsp_write (hdsp, HDSP_jtagReg, HDSP_S_PROGRAM);
+ hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM);
hdsp_write (hdsp, HDSP_fifoData, 0);
if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
@@ -529,7 +556,7 @@ static int snd_hdsp_load_firmware_from_c
return -EIO;
}
- hdsp_write (hdsp, HDSP_jtagReg, HDSP_S_LOAD);
+ hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
for (i = 0; i < 24413; ++i) {
hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]);
@@ -544,7 +571,12 @@ static int snd_hdsp_load_firmware_from_c
return -EIO;
}
- hdsp_write (hdsp, HDSP_jtagReg, 0);
+#ifdef SNDRV_BIG_ENDIAN
+ hdsp->control2_register = HDSP_BIGENDIAN_MODE;
+#else
+ hdsp->control2_register = 0;
+#endif
+ hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
snd_printk ("finished firmware loading\n");
if ((1000 / HZ) < 3000) {
@@ -574,25 +606,25 @@ static inline int hdsp_get_iobox_version
return -EIO;
}
- if ((err = snd_hdsp_initialize_input_enable(hdsp)) < 0) {
+ if ((err = snd_hdsp_enable_io(hdsp)) < 0) {
return err;
}
if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
- hdsp_write (hdsp, HDSP_jtagReg, HDSP_PROGRAM);
+ hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM);
hdsp_write (hdsp, HDSP_fifoData, 0);
if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0) {
return -EIO;
}
- hdsp_write (hdsp, HDSP_jtagReg, HDSP_S_LOAD);
+ hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
hdsp_write (hdsp, HDSP_fifoData, 0);
if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT)) {
hdsp->io_type = Multiface;
- hdsp_write (hdsp, HDSP_jtagReg, HDSP_VERSION_BIT);
- hdsp_write (hdsp, HDSP_jtagReg, HDSP_S_LOAD);
+ hdsp_write (hdsp, HDSP_control2Reg, HDSP_VERSION_BIT);
+ hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT);
} else {
hdsp->io_type = Digiface;
@@ -611,6 +643,7 @@ static inline int hdsp_get_iobox_version
static inline int hdsp_check_for_firmware (hdsp_t *hdsp)
{
+ if (hdsp->io_type == H9652) return 0;
if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
snd_printk("firmware not present.\n");
hdsp->state &= ~HDSP_FirmwareLoaded;
@@ -657,36 +690,41 @@ static inline int hdsp_write_gain(hdsp_t
{
unsigned int ad;
- if (hdsp_is_9652 (hdsp)) {
+ if (addr >= HDSP_MATRIX_MIXER_SIZE)
+ return -1;
+
+ if (hdsp->io_type == H9652) {
- if ((ad = addr/2) < 676) {
+ /* from martin björnsen:
+
+ "You can only write dwords to the
+ mixer memory which contain two
+ mixer values in the low and high
+ word. So if you want to change
+ value 0 you have to read value 1
+ from the cache and write both to
+ the first dword in the mixer
+ memory."
+ */
- /* from martin björnsen:
+ hdsp->mixer_matrix[addr] = data;
- "You can only write dwords to the
- mixer memory which contain two
- mixer values in the low and high
- word. So if you want to change
- value 0 you have to read value 1
- from the cache and write both to
- the first dword in the mixer
- memory."
- */
-
- hdsp->mixer_matrix[addr] = data;
- hdsp_write (hdsp, 1024 + ad,
- (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) +
- hdsp->mixer_matrix[addr&0x7fe]);
- return 0;
- } else {
- return -1;
- }
+ /* `addr' addresses a 16-bit wide address, but
+ the address space accessed via hdsp_write
+ uses byte offsets. put another way, addr
+ varies from 0 to 1351, but to access the
+ corresponding memory location, we need
+ to access 0 to 2703 ...
+ */
+
+ hdsp_write (hdsp, 4096 + (addr*2),
+ (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) +
+ hdsp->mixer_matrix[addr&0x7fe]);
+ return 0;
} else {
- if (addr >= HDSP_MATRIX_MIXER_SIZE)
- return -1;
-
+
ad = (addr << 16) + data;
if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT)) {
@@ -829,6 +867,11 @@ static int hdsp_set_rate(hdsp_t *hdsp, i
int current_rate;
int rate_bits;
+ /* ASSUMPTION: hdsp->lock is either help, or
+ there is no need for it (e.g. during module
+ initialization).
+ */
+
if (!(hdsp->control_register & HDSP_ClockModeMaster)) {
if (called_internally) {
/* request from ctl or card initialization */
@@ -860,8 +903,6 @@ static int hdsp_set_rate(hdsp_t *hdsp, i
exists for externally-driven rate changes. All we can do
is to flag rate changes in the read/write routines. */
- spin_lock_irq(&hdsp->lock);
-
switch (rate) {
case 32000:
if (current_rate > 48000) {
@@ -900,7 +941,6 @@ static int hdsp_set_rate(hdsp_t *hdsp, i
rate_bits = HDSP_Frequency96KHz;
break;
default:
- spin_unlock_irq(&hdsp->lock);
return -EINVAL;
}
@@ -908,7 +948,6 @@ static int hdsp_set_rate(hdsp_t *hdsp, i
snd_printk ("cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n",
hdsp->capture_pid,
hdsp->playback_pid);
- spin_unlock_irq(&hdsp->lock);
return -EBUSY;
}
@@ -924,6 +963,7 @@ static int hdsp_set_rate(hdsp_t *hdsp, i
hdsp->channel_map = channel_map_mf_ss;
break;
case Digiface:
+ case H9652:
hdsp->channel_map = channel_map_df_ss;
break;
default:
@@ -938,7 +978,6 @@ static int hdsp_set_rate(hdsp_t *hdsp, i
hdsp_update_simple_mixer_controls (hdsp);
}
- spin_unlock_irq(&hdsp->lock);
return 0;
}
@@ -1131,21 +1170,19 @@ static void snd_hdsp_midi_input_trigger(
hdsp_t *hdsp;
hdsp_midi_t *hmidi;
unsigned long flags;
+ u32 ie;
hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
hdsp = hmidi->hdsp;
+ ie = hmidi->id ? HDSP_Midi1InterruptEnable : HDSP_Midi0InterruptEnable;
spin_lock_irqsave (&hdsp->lock, flags);
if (up) {
- snd_hdsp_flush_midi_input (hdsp, hmidi->id);
- if (hmidi->id)
- hdsp->control_register |= HDSP_Midi1InterruptEnable;
- else
- hdsp->control_register |= HDSP_Midi0InterruptEnable;
+ if (!(hdsp->control_register & ie)) {
+ snd_hdsp_flush_midi_input (hdsp, hmidi->id);
+ hdsp->control_register |= ie;
+ }
} else {
- if (hmidi->id)
- hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
- else
- hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
+ hdsp->control_register &= ~ie;
}
hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
@@ -2004,7 +2041,19 @@ static int snd_hdsp_info_pref_sync_ref(s
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
- uinfo->value.enumerated.items = (hdsp->io_type == Digiface) ? 6 : 4;
+
+ switch (hdsp->io_type) {
+ case Digiface:
+ case H9652:
+ uinfo->value.enumerated.items = 6;
+ break;
+ case Multiface:
+ uinfo->value.enumerated.items = 4;
+ default:
+ uinfo->value.enumerated.items = 0;
+ break;
+ }
+
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
@@ -2028,7 +2077,19 @@ static int snd_hdsp_put_pref_sync_ref(sn
if (!snd_hdsp_use_is_exclusive(hdsp))
return -EBUSY;
- max = (hdsp->io_type == Digiface) ? 6 : 4;
+
+ switch (hdsp->io_type) {
+ case Digiface:
+ case H9652:
+ max = 6;
+ break;
+ case Multiface:
+ max = 4;
+ break;
+ default:
+ return -EIO;
+ }
+
val = ucontrol->value.enumerated.item[0] % max;
spin_lock_irqsave(&hdsp->lock, flags);
change = (int)val != hdsp_pref_sync_ref(hdsp);
@@ -2496,7 +2557,22 @@ static int snd_hdsp_get_adat_sync_check(
hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
offset = ucontrol->id.index - 1;
- snd_assert(offset >= 0 || offset < ((hdsp->io_type == Digiface) ? 3 : 1), return -EINVAL);
+ snd_assert(offset >= 0);
+
+ switch (hdsp->io_type) {
+ case Digiface:
+ case H9652:
+ if (offset >= 3)
+ return -EINVAL;
+ break;
+ case Multiface:
+ if (offset >= 1)
+ return -EINVAL;
+ break;
+ default:
+ return -EIO;
+ }
+
ucontrol->value.enumerated.item[0] = hdsp_adat_sync_check(hdsp, offset);
return 0;
}
@@ -2593,8 +2669,9 @@ int snd_hdsp_create_controls(snd_card_t
snd_kcontrol_t *kctl;
for (idx = 0; idx < HDSP_CONTROLS; idx++) {
- if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0)
+ if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0) {
return err;
+ }
if (idx == 1) /* IEC958 (S/PDIF) Stream */
hdsp->spdif_ctl = kctl;
}
@@ -2602,10 +2679,18 @@ int snd_hdsp_create_controls(snd_card_t
snd_hdsp_playback_mixer.name = "Chn";
snd_hdsp_adat_sync_check.name = "ADAT Lock Status";
- if (hdsp->io_type == Digiface) {
+ switch (hdsp->io_type) {
+ case Digiface:
limit = DIGIFACE_SS_CHANNELS;
- } else {
+ break;
+ case H9652:
+ limit = H9652_SS_CHANNELS;
+ break;
+ case Multiface:
limit = MULTIFACE_SS_CHANNELS;
+ break;
+ default:
+ return -EIO;
}
/* The index values are one greater than the channel ID so that alsamixer
@@ -2627,7 +2712,7 @@ int snd_hdsp_create_controls(snd_card_t
if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) {
return err;
}
- if (hdsp->io_type == Digiface) {
+ if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
for (idx = 1; idx < 3; ++idx) {
snd_hdsp_adat_sync_check.index = idx+1;
if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) {
@@ -2681,6 +2766,7 @@ snd_hdsp_proc_read(snd_info_entry_t *ent
snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
hdsp->irq, hdsp->port, hdsp->iobase);
snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register);
+ snd_iprintf(buffer, "Control2 register: 0x%x\n", hdsp->control2_register);
snd_iprintf(buffer, "Status register: 0x%x\n", status);
snd_iprintf(buffer, "Status2 register: 0x%x\n", status2);
snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff);
@@ -2854,6 +2940,7 @@ snd_hdsp_proc_read(snd_info_entry_t *ent
switch (hdsp->io_type) {
case Digiface:
+ case H9652:
x = status & HDSP_Sync1;
if (status & HDSP_Lock1) {
snd_iprintf(buffer, "ADAT2: %s\n", x ? "Sync" : "Lock");
@@ -2913,25 +3000,15 @@ static void __devinit snd_hdsp_proc_init
static void snd_hdsp_free_buffers(hdsp_t *hdsp)
{
if (hdsp->capture_buffer_unaligned) {
-#ifndef HDSP_PREALLOCATE_MEMORY
- snd_free_pci_pages(hdsp->pci,
- HDSP_DMA_AREA_BYTES,
- hdsp->capture_buffer_unaligned,
- hdsp->capture_buffer_addr);
-#else
- snd_hammerfall_free_buffer(hdsp->pci, hdsp->capture_buffer_unaligned);
-#endif
+ snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES,
+ hdsp->capture_buffer_unaligned,
+ hdsp->capture_buffer_addr, 1);
}
if (hdsp->playback_buffer_unaligned) {
-#ifndef HDSP_PREALLOCATE_MEMORY
- snd_free_pci_pages(hdsp->pci,
- HDSP_DMA_AREA_BYTES,
- hdsp->playback_buffer_unaligned,
- hdsp->playback_buffer_addr);
-#else
- snd_hammerfall_free_buffer(hdsp->pci, hdsp->playback_buffer_unaligned);
-#endif
+ snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES,
+ hdsp->playback_buffer_unaligned,
+ hdsp->playback_buffer_addr, 0);
}
}
@@ -2941,28 +3018,15 @@ static int __devinit snd_hdsp_initialize
dma_addr_t pb_addr, cb_addr;
unsigned long pb_bus, cb_bus;
-#ifndef HDSP_PREALLOCATE_MEMORY
- cb = snd_malloc_pci_pages(hdsp->pci, HDSP_DMA_AREA_BYTES, &cb_addr);
- pb = snd_malloc_pci_pages(hdsp->pci, HDSP_DMA_AREA_BYTES, &pb_addr);
-#else
- cb = snd_hammerfall_get_buffer(hdsp->pci, &cb_addr);
- pb = snd_hammerfall_get_buffer(hdsp->pci, &pb_addr);
-#endif
+ cb = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, &cb_addr, 1);
+ pb = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, &pb_addr, 0);
if (cb == 0 || pb == 0) {
if (cb) {
-#ifdef HDSP_PREALLOCATE_MEMORY
- snd_hammerfall_free_buffer(hdsp->pci, cb);
-#else
- snd_free_pci_pages(hdsp->pci, HDSP_DMA_AREA_BYTES, cb, cb_addr);
-#endif
+ snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, cb, cb_addr, 1);
}
if (pb) {
-#ifdef HDSP_PREALLOCATE_MEMORY
- snd_hammerfall_free_buffer(hdsp->pci, pb);
-#else
- snd_free_pci_pages(hdsp->pci, HDSP_DMA_AREA_BYTES, pb, pb_addr);
-#endif
+ snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, pb, pb_addr, 0);
}
printk(KERN_ERR "%s: no buffers available\n", hdsp->card_name);
@@ -3025,13 +3089,13 @@ static int snd_hdsp_set_defaults(hdsp_t
hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN;
}
- for (i = 0; i < (hdsp_is_9652(hdsp) ? 1352 : HDSP_MATRIX_MIXER_SIZE); i++) {
+ for (i = 0; i < (hdsp->io_type == H9652 ? 1352 : HDSP_MATRIX_MIXER_SIZE); i++) {
if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN)) {
return -EIO;
}
}
- if (!hdsp_is_9652(hdsp) && line_outs_monitor[hdsp->dev]) {
+ if ((hdsp->io_type != H9652) && line_outs_monitor[hdsp->dev]) {
snd_printk ("sending all inputs and playback streams to line outs.\n");
@@ -3291,9 +3355,13 @@ static int snd_hdsp_hw_params(snd_pcm_su
/* how to make sure that the rate matches an externally-set one ?
*/
+ spin_lock_irq(&hdsp->lock);
if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) {
+ spin_unlock_irq(&hdsp->lock);
_snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
return err;
+ } else {
+ spin_unlock_irq(&hdsp->lock);
}
if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) {
@@ -3731,6 +3799,10 @@ static int snd_hdsp_hwdep_ioctl(snd_hwde
switch (cmd) {
case SNDRV_HDSP_IOCTL_GET_PEAK_RMS:
+ if (hdsp->io_type == H9652) {
+ snd_printk("hardware metering isn't supported yet for hdsp9652 cards\n");
+ return -EINVAL;
+ }
if (!(hdsp->state & HDSP_FirmwareLoaded)) {
snd_printk("firmware needs to be uploaded to the card.\n");
return -EINVAL;
@@ -3783,7 +3855,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwde
return -EFAULT;
break;
case SNDRV_HDSP_IOCTL_GET_VERSION:
- if (hdsp_is_9652(hdsp)) return -EINVAL;
+ if (hdsp->io_type == H9652) return -EINVAL;
if (hdsp->io_type == Undefined) {
if ((err = hdsp_get_iobox_version(hdsp)) < 0) {
return err;
@@ -3796,7 +3868,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwde
}
break;
case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE:
- if (hdsp_is_9652(hdsp)) return -EINVAL;
+ if (hdsp->io_type == H9652) return -EINVAL;
/* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */
if (hdsp->io_type == Undefined) return -EINVAL;
@@ -3904,7 +3976,19 @@ static int __devinit snd_hdsp_create_pcm
return 0;
}
-static inline int snd_hdsp_initialize_input_enable (hdsp_t *hdsp)
+static inline void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp)
+{
+ hdsp->control2_register |= HDSP_9652_ENABLE_MIXER;
+ hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
+}
+
+static inline void snd_hdsp_9652_disable_mixer (hdsp_t *hdsp)
+{
+ hdsp->control2_register &= ~HDSP_9652_ENABLE_MIXER;
+ hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
+}
+
+static inline int snd_hdsp_enable_io (hdsp_t *hdsp)
{
int i;
@@ -3922,14 +4006,27 @@ static inline int snd_hdsp_initialize_in
static inline void snd_hdsp_initialize_channels(hdsp_t *hdsp)
{
- if (hdsp->io_type == Digiface) {
+ switch (hdsp->io_type) {
+ case Digiface:
hdsp->card_name = "RME Hammerfall DSP + Digiface";
hdsp->ss_channels = DIGIFACE_SS_CHANNELS;
hdsp->ds_channels = DIGIFACE_DS_CHANNELS;
- } else {
+ break;
+
+ case H9652:
+ hdsp->card_name = "RME Hammerfall HDSP 9652";
+ hdsp->ss_channels = H9652_SS_CHANNELS;
+ hdsp->ds_channels = H9652_DS_CHANNELS;
+ break;
+
+ case Multiface:
hdsp->card_name = "RME Hammerfall DSP + Multiface";
hdsp->ss_channels = MULTIFACE_SS_CHANNELS;
hdsp->ds_channels = MULTIFACE_DS_CHANNELS;
+
+ default:
+ /* should never get here */
+ break;
}
}
@@ -3937,10 +4034,6 @@ static inline void snd_hdsp_initialize_m
{
snd_hdsp_flush_midi_input (hdsp, 0);
snd_hdsp_flush_midi_input (hdsp, 1);
-
-#ifdef SNDRV_BIG_ENDIAN
- hdsp_write(hdsp, HDSP_jtagReg, HDSP_BIGENDIAN_MODE);
-#endif
}
static int __devinit snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp)
@@ -4001,6 +4094,7 @@ static int __devinit snd_hdsp_create(snd
struct pci_dev *pci = hdsp->pci;
int err;
int i;
+ int is_9652 = 0;
hdsp->irq = -1;
hdsp->state = 0;
@@ -4027,23 +4121,27 @@ static int __devinit snd_hdsp_create(snd
pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
strcpy(card->driver, "H-DSP");
strcpy(card->mixername, "Xilinx FPGA");
-
+
switch (hdsp->firmware_rev & 0xff) {
case 0xa:
case 0xb:
hdsp->card_name = "RME Hammerfall DSP";
break;
+
case 0x64:
case 0x65:
case 0x68:
hdsp->card_name = "RME HDSP 9652";
+ is_9652 = 1;
break;
+
default:
return -ENODEV;
}
- if ((err = pci_enable_device(pci)) < 0)
+ if ((err = pci_enable_device(pci)) < 0) {
return err;
+ }
pci_set_master(hdsp->pci);
@@ -4071,70 +4169,53 @@ static int __devinit snd_hdsp_create(snd
return err;
}
- if (hdsp_is_9652(hdsp)) {
-
- if ((err = snd_hdsp_initialize_input_enable(hdsp)) != 0) {
+ if (!is_9652 && hdsp_check_for_iobox (hdsp)) {
+ /* no iobox connected, we defer initialization */
+ snd_printk("card initialization pending : waiting for firmware\n");
+ if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
return err;
}
-
- hdsp->io_type = Digiface;
-
- hdsp->ss_channels = DIGIFACE_SS_CHANNELS;
- hdsp->ds_channels = DIGIFACE_DS_CHANNELS;
+ return 0;
+ }
- snd_hdsp_initialize_midi_flush(hdsp);
+ if ((err = snd_hdsp_enable_io(hdsp)) != 0) {
+ return err;
+ }
+ if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
+ snd_printk("card initialization pending : waiting for firmware\n");
if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
return err;
}
-
- } else {
+ return 0;
+ }
- if (hdsp_check_for_iobox (hdsp)) {
- /* no iobox connected, we defer initialization */
- snd_printk("card initialization pending : waiting for firmware\n");
- if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
- return err;
- }
- return 0;
- }
+ snd_printk("Firmware already loaded, initializing card.\n");
+
+ if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) {
+ hdsp->io_type = Multiface;
+ } else {
+ hdsp->io_type = Digiface;
+ }
- if ((err = snd_hdsp_initialize_input_enable(hdsp)) != 0) {
- return err;
- }
-
- if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
- snd_printk("card initialization pending : waiting for firmware\n");
- if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
- return err;
- }
- return 0;
- }
-
- snd_printk("Firmware already loaded, initializing card.\n");
+ if (is_9652) {
+ hdsp->io_type = H9652;
+ snd_hdsp_9652_enable_mixer (hdsp);
+ }
- if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) {
- hdsp->io_type = Multiface;
- } else {
- hdsp->io_type = Digiface;
- }
-
- if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
- return err;
- }
-
- snd_hdsp_initialize_channels(hdsp);
-
- snd_hdsp_initialize_midi_flush(hdsp);
-
+ if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
+ return err;
}
+ snd_hdsp_initialize_channels(hdsp);
+ snd_hdsp_initialize_midi_flush(hdsp);
+
hdsp->state |= HDSP_FirmwareLoaded;
-
+
if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0) {
return err;
}
-
+
return 0;
}
@@ -4201,7 +4282,7 @@ static int __devinit snd_hdsp_probe(stru
strcpy(card->shortname, "Hammerfall DSP");
sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
hdsp->port, hdsp->irq);
-
+
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
return err;
diff -puN sound/pci/rme9652/Makefile~alsa-bk-2003-07-28 sound/pci/rme9652/Makefile
--- 25/sound/pci/rme9652/Makefile~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/rme9652/Makefile Tue Jul 29 12:11:31 2003
@@ -3,10 +3,9 @@
# Copyright (c) 2001 by Jaroslav Kysela
#
-snd-hammerfall-mem-objs := hammerfall_mem.o
snd-rme9652-objs := rme9652.o
snd-hdsp-objs := hdsp.o
# Toplevel Module Dependency
-obj-$(CONFIG_SND_RME9652) += snd-rme9652.o snd-hammerfall-mem.o
-obj-$(CONFIG_SND_HDSP) += snd-hdsp.o snd-hammerfall-mem.o
+obj-$(CONFIG_SND_RME9652) += snd-rme9652.o
+obj-$(CONFIG_SND_HDSP) += snd-hdsp.o
diff -puN sound/pci/rme9652/rme9652.c~alsa-bk-2003-07-28 sound/pci/rme9652/rme9652.c
--- 25/sound/pci/rme9652/rme9652.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/rme9652/rme9652.c Tue Jul 29 12:11:31 2003
@@ -309,10 +309,42 @@ static char channel_map_9636_ds[26] = {
#define RME9652_PREALLOCATE_MEMORY /* via module snd-hammerfall-mem */
#ifdef RME9652_PREALLOCATE_MEMORY
-extern void *snd_hammerfall_get_buffer(struct pci_dev *, dma_addr_t *dmaaddr);
-extern void snd_hammerfall_free_buffer(struct pci_dev *, void *ptr);
+static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
+{
+ struct snd_dma_device pdev;
+ struct snd_dma_buffer dmbuf;
+
+ snd_dma_device_pci(&pdev, pci, capture);
+ dmbuf.bytes = 0;
+ if (! snd_dma_get_reserved(&pdev, &dmbuf)) {
+ if (snd_dma_alloc_pages(&pdev, size, &dmbuf) < 0)
+ return NULL;
+ snd_dma_set_reserved(&pdev, &dmbuf);
+ }
+ *addrp = dmbuf.addr;
+ return dmbuf.area;
+}
+
+static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
+{
+ struct snd_dma_device dev;
+ snd_dma_device_pci(&dev, pci, capture);
+ snd_dma_free_reserved(&dev);
+}
+
+#else
+static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
+{
+ return snd_malloc_pci_pages(pci, size, addrp);
+}
+
+static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
+{
+ snd_free_pci_pages(pci, size, ptr, addr);
+}
#endif
+
static struct pci_device_id snd_rme9652_ids[] __devinitdata = {
{
.vendor = 0x10ee,
@@ -1810,25 +1842,15 @@ static void __devinit snd_rme9652_proc_i
static void snd_rme9652_free_buffers(rme9652_t *rme9652)
{
if (rme9652->capture_buffer_unaligned) {
-#ifndef RME9652_PREALLOCATE_MEMORY
- snd_free_pci_pages(rme9652->pci,
- RME9652_DMA_AREA_BYTES,
- rme9652->capture_buffer_unaligned,
- rme9652->capture_buffer_addr);
-#else
- snd_hammerfall_free_buffer(rme9652->pci, rme9652->capture_buffer_unaligned);
-#endif
+ snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES,
+ rme9652->capture_buffer_unaligned,
+ rme9652->capture_buffer_addr, 1);
}
if (rme9652->playback_buffer_unaligned) {
-#ifndef RME9652_PREALLOCATE_MEMORY
- snd_free_pci_pages(rme9652->pci,
- RME9652_DMA_AREA_BYTES,
- rme9652->playback_buffer_unaligned,
- rme9652->playback_buffer_addr);
-#else
- snd_hammerfall_free_buffer(rme9652->pci, rme9652->playback_buffer_unaligned);
-#endif
+ snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES,
+ rme9652->playback_buffer_unaligned,
+ rme9652->playback_buffer_addr, 0);
}
}
@@ -1855,28 +1877,15 @@ static int __devinit snd_rme9652_initial
dma_addr_t pb_addr, cb_addr;
unsigned long pb_bus, cb_bus;
-#ifndef RME9652_PREALLOCATE_MEMORY
- cb = snd_malloc_pci_pages(rme9652->pci, RME9652_DMA_AREA_BYTES, &cb_addr);
- pb = snd_malloc_pci_pages(rme9652->pci, RME9652_DMA_AREA_BYTES, &pb_addr);
-#else
- cb = snd_hammerfall_get_buffer(rme9652->pci, &cb_addr);
- pb = snd_hammerfall_get_buffer(rme9652->pci, &pb_addr);
-#endif
+ cb = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, &cb_addr, 1);
+ pb = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, &pb_addr, 0);
if (cb == 0 || pb == 0) {
if (cb) {
-#ifdef RME9652_PREALLOCATE_MEMORY
- snd_hammerfall_free_buffer(rme9652->pci, cb);
-#else
- snd_free_pci_pages(rme9652->pci, RME9652_DMA_AREA_BYTES, cb, cb_addr);
-#endif
+ snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, cb, cb_addr, 1);
}
if (pb) {
-#ifdef RME9652_PREALLOCATE_MEMORY
- snd_hammerfall_free_buffer(rme9652->pci, pb);
-#else
- snd_free_pci_pages(rme9652->pci, RME9652_DMA_AREA_BYTES, pb, pb_addr);
-#endif
+ snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, pb, pb_addr, 0);
}
printk(KERN_ERR "%s: no buffers available\n", rme9652->card_name);
diff -puN sound/pci/rme96.c~alsa-bk-2003-07-28 sound/pci/rme96.c
--- 25/sound/pci/rme96.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/rme96.c Tue Jul 29 12:11:31 2003
@@ -806,10 +806,12 @@ snd_rme96_setclockmode(rme96_t *rme96,
{
switch (mode) {
case RME96_CLOCKMODE_SLAVE:
+ /* AutoSync */
rme96->wcreg &= ~RME96_WCR_MASTER;
rme96->areg &= ~RME96_AR_WSEL;
break;
case RME96_CLOCKMODE_MASTER:
+ /* Internal */
rme96->wcreg |= RME96_WCR_MASTER;
rme96->areg &= ~RME96_AR_WSEL;
break;
@@ -1318,7 +1320,7 @@ snd_rme96_capture_adat_open(snd_pcm_subs
snd_pcm_set_sync(substream);
runtime->hw = snd_rme96_capture_adat_info;
- if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG) {
+ if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) {
/* makes no sense to use analog input. Note that analog
expension cards AEB4/8-I are RME96_INPUT_INTERNAL */
return -EIO;
@@ -1862,15 +1864,15 @@ snd_rme96_proc_read(snd_info_entry_t *en
snd_iprintf(buffer, " sample format: 16 bit\n");
}
if (rme96->areg & RME96_AR_WSEL) {
- snd_iprintf(buffer, " clock mode: word clock\n");
+ snd_iprintf(buffer, " sample clock source: word clock\n");
} else if (rme96->wcreg & RME96_WCR_MASTER) {
- snd_iprintf(buffer, " clock mode: master\n");
+ snd_iprintf(buffer, " sample clock source: internal\n");
} else if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) {
- snd_iprintf(buffer, " clock mode: slave (master anyway due to analog input setting)\n");
+ snd_iprintf(buffer, " sample clock source: autosync (internal anyway due to analog input setting)\n");
} else if (snd_rme96_capture_getrate(rme96, &n) < 0) {
- snd_iprintf(buffer, " clock mode: slave (master anyway due to no valid signal)\n");
+ snd_iprintf(buffer, " sample clock source: autosync (internal anyway due to no valid signal)\n");
} else {
- snd_iprintf(buffer, " clock mode: slave\n");
+ snd_iprintf(buffer, " sample clock source: autosync\n");
}
if (rme96->wcreg & RME96_WCR_PRO) {
snd_iprintf(buffer, " format: AES/EBU (professional)\n");
@@ -2095,7 +2097,7 @@ snd_rme96_put_inputtype_control(snd_kcon
static int
snd_rme96_info_clockmode_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
- static char *texts[3] = { "Slave", "Master", "Wordclock" };
+ static char *texts[3] = { "AutoSync", "Internal", "Word" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -2418,7 +2420,7 @@ static snd_kcontrol_new_t snd_rme96_cont
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = "Clock Mode",
+ .name = "Sample Clock Source",
.info = snd_rme96_info_clockmode_control,
.get = snd_rme96_get_clockmode_control,
.put = snd_rme96_put_clockmode_control
diff -puN sound/pci/sonicvibes.c~alsa-bk-2003-07-28 sound/pci/sonicvibes.c
--- 25/sound/pci/sonicvibes.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/sonicvibes.c Tue Jul 29 12:11:31 2003
@@ -254,7 +254,7 @@ struct _snd_sonicvibes {
snd_kcontrol_t *master_mute;
snd_kcontrol_t *master_volume;
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
struct gameport gameport;
#endif
};
@@ -1189,7 +1189,7 @@ SONICVIBES_SINGLE("Joystick Speed", 0, S
static int snd_sonicvibes_free(sonicvibes_t *sonic)
{
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
if (sonic->gameport.io)
gameport_unregister_port(&sonic->gameport);
#endif
@@ -1493,7 +1493,7 @@ static int __devinit snd_sonic_probe(str
snd_card_free(card);
return err;
}
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
sonic->gameport.io = sonic->game_port;
gameport_register_port(&sonic->gameport);
#endif
diff -puN sound/pci/trident/trident.c~alsa-bk-2003-07-28 sound/pci/trident/trident.c
--- 25/sound/pci/trident/trident.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/trident/trident.c Tue Jul 29 12:11:31 2003
@@ -132,7 +132,7 @@ static int __devinit snd_trident_probe(s
return err;
}
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if ((err = snd_trident_attach_synthesizer(trident)) < 0) {
snd_card_free(card);
return err;
@@ -182,7 +182,6 @@ static void __devexit snd_trident_remove
}
#ifdef CONFIG_PM
-#ifndef PCI_OLD_SUSPEND
static int snd_card_trident_suspend(struct pci_dev *pci, u32 state)
{
trident_t *chip = snd_magic_cast(trident_t, pci_get_drvdata(pci), return -ENXIO);
@@ -195,18 +194,6 @@ static int snd_card_trident_resume(struc
snd_trident_resume(chip);
return 0;
}
-#else
-static void snd_card_trident_suspend(struct pci_dev *pci)
-{
- trident_t *chip = snd_magic_cast(trident_t, pci_get_drvdata(pci), return);
- snd_trident_suspend(chip);
-}
-static void snd_card_trident_resume(struct pci_dev *pci)
-{
- trident_t *chip = snd_magic_cast(trident_t, pci_get_drvdata(pci), return);
- snd_trident_resume(chip);
-}
-#endif
#endif
static struct pci_driver driver = {
diff -puN sound/pci/trident/trident_main.c~alsa-bk-2003-07-28 sound/pci/trident/trident_main.c
--- 25/sound/pci/trident/trident_main.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/trident/trident_main.c Tue Jul 29 12:11:31 2003
@@ -3077,7 +3077,8 @@ static int __devinit snd_trident_mixer(t
/*
* gameport interface
*/
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
typedef struct snd_trident_gameport {
struct gameport info;
@@ -3173,12 +3174,6 @@ void __devinit snd_trident_gameport(trid
*/
inline static void do_delay(trident_t *chip)
{
-#ifdef CONFIG_PM
- if (chip->in_suspend) {
- mdelay((1000 + HZ - 1) / HZ);
- return;
- }
-#endif
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
@@ -3273,7 +3268,7 @@ static void snd_trident_proc_read(snd_in
snd_iprintf(buffer, "Memory Free : %d\n", snd_util_mem_avail(trident->tlb.memhdr));
}
}
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
snd_iprintf(buffer,"\nWavetable Synth\n");
snd_iprintf(buffer, "Memory Maximum : %d\n", trident->synth.max_size);
snd_iprintf(buffer, "Memory Used : %d\n", trident->synth.current_size);
@@ -3636,7 +3631,7 @@ int __devinit snd_trident_create(snd_car
int snd_trident_free(trident_t *trident)
{
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
if (trident->gameport) {
gameport_unregister_port(&trident->gameport->info);
kfree(trident->gameport);
@@ -3796,7 +3791,7 @@ static irqreturn_t snd_trident_interrupt
---------------------------------------------------------------------------*/
int snd_trident_attach_synthesizer(trident_t *trident)
{
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (snd_seq_device_new(trident->card, 1, SNDRV_SEQ_DEV_ID_TRIDENT,
sizeof(trident_t*), &trident->seq_dev) >= 0) {
strcpy(trident->seq_dev->name, "4DWave");
@@ -3808,7 +3803,7 @@ int snd_trident_attach_synthesizer(tride
int snd_trident_detach_synthesizer(trident_t *trident)
{
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (trident->seq_dev) {
snd_device_free(trident->card, trident->seq_dev);
trident->seq_dev = NULL;
diff -puN sound/pci/via82xx.c~alsa-bk-2003-07-28 sound/pci/via82xx.c
--- 25/sound/pci/via82xx.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/via82xx.c Tue Jul 29 12:11:32 2003
@@ -886,7 +886,7 @@ static int snd_via8233_playback_prepare(
snd_ac97_set_rate(chip->ac97, AC97_PCM_LFE_DAC_RATE, runtime->rate);
snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate);
}
- if (chip->chip_type == TYPE_VIA8233A)
+ if (chip->revision == VIA_REV_8233A)
rbits = 0;
else
rbits = (0xfffff / 48000) * runtime->rate + ((0xfffff % 48000) * runtime->rate) / 48000;
@@ -928,7 +928,7 @@ static int snd_via8233_multi_prepare(snd
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));
- if (chip->chip_type == TYPE_VIA8233A)
+ if (chip->revision == VIA_REV_8233A)
slots = 0;
else {
/* set sample number to slot 3, 4, 7, 8, 6, 9 (for VIA8233/C,8235) */
@@ -1108,7 +1108,7 @@ static int snd_via8233_multi_open(snd_pc
if ((err = snd_via82xx_pcm_open(chip, viadev, substream)) < 0)
return err;
substream->runtime->hw.channels_max = 6;
- if (chip->chip_type == TYPE_VIA8233A)
+ if (chip->revision == VIA_REV_8233A)
snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels);
return 0;
}
diff -puN sound/pci/ymfpci/ymfpci.c~alsa-bk-2003-07-28 sound/pci/ymfpci/ymfpci.c
--- 25/sound/pci/ymfpci/ymfpci.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/ymfpci/ymfpci.c Tue Jul 29 12:11:31 2003
@@ -229,9 +229,11 @@ static int __devinit snd_card_ymfpci_pro
return err;
}
}
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
if ((err = snd_ymfpci_joystick(chip)) < 0) {
printk(KERN_WARNING "ymfpci: cannot initialize joystick, skipping...\n");
}
+#endif
strcpy(card->driver, str);
sprintf(card->shortname, "Yamaha DS-XG PCI (%s)", str);
sprintf(card->longname, "%s at 0x%lx, irq %i",
@@ -249,7 +251,6 @@ static int __devinit snd_card_ymfpci_pro
}
#ifdef CONFIG_PM
-#ifndef PCI_OLD_SUSPEND
static int snd_card_ymfpci_suspend(struct pci_dev *pci, u32 state)
{
ymfpci_t *chip = snd_magic_cast(ymfpci_t, pci_get_drvdata(pci), return -ENXIO);
@@ -262,18 +263,6 @@ static int snd_card_ymfpci_resume(struct
snd_ymfpci_resume(chip);
return 0;
}
-#else
-static void snd_card_ymfpci_suspend(struct pci_dev *pci)
-{
- ymfpci_t *chip = snd_magic_cast(ymfpci_t, pci_get_drvdata(pci), return);
- snd_ymfpci_suspend(chip);
-}
-static void snd_card_ymfpci_resume(struct pci_dev *pci)
-{
- ymfpci_t *chip = snd_magic_cast(ymfpci_t, pci_get_drvdata(pci), return);
- snd_ymfpci_resume(chip);
-}
-#endif
#endif
static void __devexit snd_card_ymfpci_remove(struct pci_dev *pci)
diff -puN sound/pci/ymfpci/ymfpci_main.c~alsa-bk-2003-07-28 sound/pci/ymfpci/ymfpci_main.c
--- 25/sound/pci/ymfpci/ymfpci_main.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pci/ymfpci/ymfpci_main.c Tue Jul 29 12:11:31 2003
@@ -84,7 +84,7 @@ static inline void snd_ymfpci_writel(ymf
writel(val, chip->reg_area_virt + offset);
}
-static int snd_ymfpci_codec_ready(ymfpci_t *chip, int secondary, int sched)
+static int snd_ymfpci_codec_ready(ymfpci_t *chip, int secondary)
{
signed long end_time;
u32 reg = secondary ? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR;
@@ -93,10 +93,8 @@ static int snd_ymfpci_codec_ready(ymfpci
do {
if ((snd_ymfpci_readw(chip, reg) & 0x8000) == 0)
return 0;
- if (sched) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(1);
} while (end_time - (signed long)jiffies >= 0);
snd_printk("codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg));
return -EBUSY;
@@ -107,7 +105,7 @@ static void snd_ymfpci_codec_write(ac97_
ymfpci_t *chip = snd_magic_cast(ymfpci_t, ac97->private_data, return);
u32 cmd;
- snd_ymfpci_codec_ready(chip, 0, 0);
+ snd_ymfpci_codec_ready(chip, 0);
cmd = ((YDSXG_AC97WRITECMD | reg) << 16) | val;
snd_ymfpci_writel(chip, YDSXGR_AC97CMDDATA, cmd);
}
@@ -116,10 +114,10 @@ static u16 snd_ymfpci_codec_read(ac97_t
{
ymfpci_t *chip = snd_magic_cast(ymfpci_t, ac97->private_data, return -ENXIO);
- if (snd_ymfpci_codec_ready(chip, 0, 0))
+ if (snd_ymfpci_codec_ready(chip, 0))
return ~0;
snd_ymfpci_writew(chip, YDSXGR_AC97CMDADR, YDSXG_AC97READCMD | reg);
- if (snd_ymfpci_codec_ready(chip, 0, 0))
+ if (snd_ymfpci_codec_ready(chip, 0))
return ~0;
if (chip->device_id == PCI_DEVICE_ID_YAMAHA_744 && chip->rev < 2) {
int i;
@@ -1708,24 +1706,65 @@ int __devinit snd_ymfpci_mixer(ymfpci_t
* joystick support
*/
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
static int ymfpci_joystick_ports[4] = {
0x201, 0x202, 0x204, 0x205
};
+static int snd_ymfpci_get_joystick_port(ymfpci_t *chip, int index)
+{
+ if (index < 4)
+ return ymfpci_joystick_ports[index];
+ else
+ return pci_resource_start(chip->pci, 2);
+}
+
static void setup_joystick_base(ymfpci_t *chip)
{
- if (chip->pci->device >= 0x0010) /* YMF 744/754 */
+ if (chip->device_id >= 0x0010) /* YMF 744/754 */
pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE,
- ymfpci_joystick_ports[chip->joystick_port]);
+ snd_ymfpci_get_joystick_port(chip, chip->joystick_port));
else {
u16 legacy_ctrl2;
pci_read_config_word(chip->pci, PCIR_DSXG_ELEGACY, &legacy_ctrl2);
- legacy_ctrl2 &= ~(3 << 6);
+ legacy_ctrl2 &= ~YMFPCI_LEGACY2_JSIO;
legacy_ctrl2 |= chip->joystick_port << 6;
pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, legacy_ctrl2);
}
}
+static int snd_ymfpci_enable_joystick(ymfpci_t *chip)
+{
+ u16 val;
+
+ chip->gameport.io = snd_ymfpci_get_joystick_port(chip, chip->joystick_port);
+ chip->joystick_res = request_region(chip->gameport.io, 1, "YMFPCI gameport");
+ if (!chip->joystick_res) {
+ snd_printk(KERN_WARNING "gameport port %#x in use\n", chip->gameport.io);
+ return 0;
+ }
+ setup_joystick_base(chip);
+ pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY, &val);
+ val |= YMFPCI_LEGACY_JPEN;
+ pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, val);
+ gameport_register_port(&chip->gameport);
+ return 1;
+}
+
+static int snd_ymfpci_disable_joystick(ymfpci_t *chip)
+{
+ u16 val;
+
+ gameport_unregister_port(&chip->gameport);
+ pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY, &val);
+ val &= ~YMFPCI_LEGACY_JPEN;
+ pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, val);
+ release_resource(chip->joystick_res);
+ kfree_nocheck(chip->joystick_res);
+ chip->joystick_res = NULL;
+ return 1;
+}
+
static int snd_ymfpci_joystick_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -1741,36 +1780,41 @@ static int snd_ymfpci_joystick_get(snd_k
u16 val;
pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY, &val);
- ucontrol->value.integer.value[0] = (val & 0x04) ? 1 : 0;
+ ucontrol->value.integer.value[0] = (val & YMFPCI_LEGACY_JPEN) ? 1 : 0;
return 0;
}
static int snd_ymfpci_joystick_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
- u16 val, oval;
+ int enabled, change;
- pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY, &oval);
- val = oval & ~0x04;
- if (ucontrol->value.integer.value[0])
- val |= 0x04;
- if (val != oval) {
- setup_joystick_base(chip);
- pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, val);
- return 1;
+ down(&chip->joystick_mutex);
+ enabled = chip->joystick_res != NULL;
+ change = enabled != !! ucontrol->value.integer.value[0];
+ if (change) {
+ if (!enabled)
+ change = snd_ymfpci_enable_joystick(chip);
+ else
+ change = snd_ymfpci_disable_joystick(chip);
}
- return 0;
+ up(&chip->joystick_mutex);
+ return change;
}
static int snd_ymfpci_joystick_addr_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 4;
- if (uinfo->value.enumerated.item >= 4)
- uinfo->value.enumerated.item = 3;
- sprintf(uinfo->value.enumerated.name, "port 0x%x", ymfpci_joystick_ports[uinfo->value.enumerated.item]);
- return 0;
+ ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ int ports = chip->device_id >= 0x0010 ? 5 : 4;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = ports;
+ if (uinfo->value.enumerated.item >= ports)
+ uinfo->value.enumerated.item = ports - 1;
+ sprintf(uinfo->value.enumerated.name, "port 0x%x",
+ snd_ymfpci_get_joystick_port(chip, uinfo->value.enumerated.item));
+ return 0;
}
static int snd_ymfpci_joystick_addr_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
@@ -1783,13 +1827,20 @@ static int snd_ymfpci_joystick_addr_get(
static int snd_ymfpci_joystick_addr_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
- if (ucontrol->value.enumerated.item[0] != chip->joystick_port) {
- snd_assert(ucontrol->value.enumerated.item[0] >= 0 && ucontrol->value.enumerated.item[0] < 4, return -EINVAL);
+ int change, enabled;
+
+ down(&chip->joystick_mutex);
+ change = ucontrol->value.enumerated.item[0] != chip->joystick_port;
+ if (change) {
+ enabled = chip->joystick_res != NULL;
+ if (enabled)
+ snd_ymfpci_disable_joystick(chip);
chip->joystick_port = ucontrol->value.enumerated.item[0];
- setup_joystick_base(chip);
- return 1;
+ if (enabled)
+ snd_ymfpci_enable_joystick(chip);
}
- return 0;
+ up(&chip->joystick_mutex);
+ return change;
}
static snd_kcontrol_new_t snd_ymfpci_control_joystick __devinitdata = {
@@ -1819,6 +1870,7 @@ int __devinit snd_ymfpci_joystick(ymfpci
return err;
return 0;
}
+#endif /* CONFIG_GAMEPORT */
/*
@@ -2067,6 +2119,10 @@ static int snd_ymfpci_free(ymfpci_t *chi
release_resource(chip->fm_res);
kfree_nocheck(chip->fm_res);
}
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+ if (chip->joystick_res)
+ snd_ymfpci_disable_joystick(chip);
+#endif
if (chip->reg_area_virt)
iounmap((void *)chip->reg_area_virt);
if (chip->work_ptr)
@@ -2151,7 +2207,7 @@ void snd_ymfpci_resume(ymfpci_t *chip)
pci_enable_device(chip->pci);
pci_set_master(chip->pci);
snd_ymfpci_aclink_reset(chip->pci);
- snd_ymfpci_codec_ready(chip, 0, 0);
+ snd_ymfpci_codec_ready(chip, 0);
snd_ymfpci_download_image(chip);
udelay(100);
@@ -2216,6 +2272,9 @@ int __devinit snd_ymfpci_create(snd_card
spin_lock_init(&chip->voice_lock);
init_waitqueue_head(&chip->interrupt_sleep);
atomic_set(&chip->interrupt_sleep_count, 0);
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+ init_MUTEX(&chip->joystick_mutex);
+#endif
chip->card = card;
chip->pci = pci;
chip->irq = -1;
@@ -2238,7 +2297,7 @@ int __devinit snd_ymfpci_create(snd_card
chip->irq = pci->irq;
snd_ymfpci_aclink_reset(pci);
- if (snd_ymfpci_codec_ready(chip, 0, 1) < 0) {
+ if (snd_ymfpci_codec_ready(chip, 0) < 0) {
snd_ymfpci_free(chip);
return -EIO;
}
diff -puN sound/pcmcia/vx/vxpocket.c~alsa-bk-2003-07-28 sound/pcmcia/vx/vxpocket.c
--- 25/sound/pcmcia/vx/vxpocket.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/pcmcia/vx/vxpocket.c Tue Jul 29 12:11:31 2003
@@ -31,6 +31,7 @@
*/
#include
+#include
#include
#include
#include "vxpocket.h"
diff -puN sound/ppc/awacs.c~alsa-bk-2003-07-28 sound/ppc/awacs.c
--- 25/sound/ppc/awacs.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/ppc/awacs.c Tue Jul 29 12:11:31 2003
@@ -92,18 +92,9 @@ snd_pmac_awacs_write_noreg(pmac_t *chip,
snd_pmac_awacs_write(chip, val | (reg << 12));
}
-static void do_mdelay(int msec, int can_schedule)
-{
- if (can_schedule) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout((msec * HZ + 999) / 1000);
- } else
- mdelay(msec);
-}
-
#ifdef CONFIG_PMAC_PBOOK
/* Recalibrate chip */
-static void screamer_recalibrate(pmac_t *chip, int can_schedule)
+static void screamer_recalibrate(pmac_t *chip)
{
if (chip->model != PMAC_SCREAMER)
return;
@@ -114,7 +105,7 @@ static void screamer_recalibrate(pmac_t
snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);
if (chip->manufacturer == 0x1)
/* delay for broken crystal part */
- do_mdelay(750, can_schedule);
+ big_mdelay(750);
snd_pmac_awacs_write_noreg(chip, 1,
chip->awacs_reg[1] | MASK_RECALIBRATE | MASK_CMUTE | MASK_AMUTE);
snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);
@@ -122,7 +113,7 @@ static void screamer_recalibrate(pmac_t
}
#else
-#define screamer_recalibrate(chip, can_schedule) /* NOP */
+#define screamer_recalibrate(chip) /* NOP */
#endif
@@ -631,7 +622,7 @@ static int build_mixers(pmac_t *chip, in
/*
* restore all registers
*/
-static void awacs_restore_all_regs(pmac_t *chip, int can_schedule)
+static void awacs_restore_all_regs(pmac_t *chip)
{
snd_pmac_awacs_write_noreg(chip, 0, chip->awacs_reg[0]);
snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);
@@ -655,19 +646,19 @@ static void snd_pmac_awacs_resume(pmac_t
{
if (machine_is_compatible("PowerBook3,1")
|| machine_is_compatible("PowerBook3,2")) {
- do_mdelay(100, 0);
+ big_mdelay(100);
snd_pmac_awacs_write_reg(chip, 1,
chip->awacs_reg[1] & ~MASK_PAROUT);
- do_mdelay(300, 0);
+ big_mdelay(300);
}
- awacs_restore_all_regs(chip, 0);
+ awacs_restore_all_regs(chip);
if (chip->model == PMAC_SCREAMER) {
/* reset power bits in reg 6 */
mdelay(5);
snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);
}
- screamer_recalibrate(chip, 0);
+ screamer_recalibrate(chip);
#ifdef PMAC_AMP_AVAIL
if (chip->mixer_data) {
awacs_amp_t *amp = chip->mixer_data;
@@ -775,9 +766,9 @@ snd_pmac_awacs_init(pmac_t *chip)
chip->awacs_reg[7] = 0;
}
- awacs_restore_all_regs(chip, 1);
+ awacs_restore_all_regs(chip);
chip->manufacturer = (in_le32(&chip->awacs->codec_stat) >> 8) & 0xf;
- screamer_recalibrate(chip, 1);
+ screamer_recalibrate(chip);
chip->revision = (in_le32(&chip->awacs->codec_stat) >> 12) & 0xf;
#ifdef PMAC_AMP_AVAIL
diff -puN sound/ppc/burgundy.c~alsa-bk-2003-07-28 sound/ppc/burgundy.c
--- 25/sound/ppc/burgundy.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/ppc/burgundy.c Tue Jul 29 12:11:31 2003
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include
#include "pmac.h"
#include "burgundy.h"
@@ -34,17 +35,27 @@
inline static void
snd_pmac_burgundy_busy_wait(pmac_t *chip)
{
- while (in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD)
- ;
+ int timeout = 50;
+ while ((in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) && timeout--)
+ udelay(1);
+ if (! timeout)
+ printk(KERN_DEBUG "burgundy_busy_wait: timeout\n");
}
inline static void
snd_pmac_burgundy_extend_wait(pmac_t *chip)
{
- while (!(in_le32(&chip->awacs->codec_stat) & MASK_EXTEND))
- ;
- while (in_le32(&chip->awacs->codec_stat) & MASK_EXTEND)
- ;
+ int timeout;
+ timeout = 50;
+ while (!(in_le32(&chip->awacs->codec_stat) & MASK_EXTEND) && timeout--)
+ udelay(1);
+ if (! timeout)
+ printk(KERN_DEBUG "burgundy_extend_wait: timeout #1\n");
+ timeout = 50;
+ while ((in_le32(&chip->awacs->codec_stat) & MASK_EXTEND) && timeout--)
+ udelay(1);
+ if (! timeout)
+ printk(KERN_DEBUG "burgundy_extend_wait: timeout #2\n");
}
static void
@@ -66,7 +77,6 @@ snd_pmac_burgundy_rcw(pmac_t *chip, unsi
unsigned val = 0;
unsigned long flags;
- /* should have timeouts here */
spin_lock_irqsave(&chip->reg_lock, flags);
out_le32(&chip->awacs->codec_ctrl, addr + 0x100000);
@@ -107,7 +117,6 @@ snd_pmac_burgundy_rcb(pmac_t *chip, unsi
unsigned val = 0;
unsigned long flags;
- /* should have timeouts here */
spin_lock_irqsave(&chip->reg_lock, flags);
out_le32(&chip->awacs->codec_ctrl, addr + 0x100000);
diff -puN sound/ppc/pmac.c~alsa-bk-2003-07-28 sound/ppc/pmac.c
--- 25/sound/ppc/pmac.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/ppc/pmac.c Tue Jul 29 12:11:31 2003
@@ -736,7 +736,7 @@ static void snd_pmac_sound_feature(pmac_
pmu_suspend();
feature_clear(chip->node, FEATURE_Sound_power);
feature_clear(chip->node, FEATURE_Sound_CLK_enable);
- mdelay(1000); /* XXX */
+ big_mdelay(1000); /* XXX */
pmu_resume();
}
if (chip->is_pbook_3400) {
diff -puN sound/ppc/pmac.h~alsa-bk-2003-07-28 sound/ppc/pmac.h
--- 25/sound/ppc/pmac.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/ppc/pmac.h Tue Jul 29 12:11:31 2003
@@ -201,6 +201,11 @@ int snd_pmac_boolean_mono_info(snd_kcont
int snd_pmac_add_automute(pmac_t *chip);
+#define big_mdelay(msec) do {\
+ set_current_state(TASK_UNINTERRUPTIBLE);\
+ schedule_timeout(((msec) * HZ + 999) / 1000);\
+} while (0)
+
#ifndef PMAC_SUPPORT_PCM_BEEP
#define snd_pmac_attach_beep(chip) 0
#define snd_pmac_beep_stop(chip) /**/
diff -puN sound/ppc/tumbler.c~alsa-bk-2003-07-28 sound/ppc/tumbler.c
--- 25/sound/ppc/tumbler.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/ppc/tumbler.c Tue Jul 29 12:11:31 2003
@@ -27,7 +27,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -93,9 +92,6 @@ typedef struct pmac_tumbler_t {
unsigned int mix_vol[VOL_IDX_LAST_MIX][2]; /* stereo volumes for tas3004 */
int drc_range;
int drc_enable;
-#ifdef CONFIG_PMAC_PBOOK
- struct work_struct resume_workq;
-#endif
} pmac_tumbler_t;
@@ -870,23 +866,21 @@ static void tumbler_reset_audio(pmac_t *
pmac_tumbler_t *mix = chip->mixer_data;
write_audio_gpio(&mix->audio_reset, 0);
- mdelay(200);
+ big_mdelay(200);
write_audio_gpio(&mix->audio_reset, 1);
- mdelay(100);
+ big_mdelay(100);
write_audio_gpio(&mix->audio_reset, 0);
- mdelay(100);
+ big_mdelay(100);
}
#ifdef CONFIG_PMAC_PBOOK
/* resume mixer */
-/* we call the i2c transfer in a workqueue because it may need either schedule()
- * or completion from timer interrupts.
- */
-static void tumbler_resume_work(void *arg)
+static void tumbler_resume(pmac_t *chip)
{
- pmac_t *chip = (pmac_t *)arg;
pmac_tumbler_t *mix = chip->mixer_data;
+ snd_assert(mix, return);
+
tumbler_reset_audio(chip);
if (mix->i2c.client) {
if (tumbler_init_client(&mix->i2c) < 0)
@@ -910,16 +904,6 @@ static void tumbler_resume_work(void *ar
if (chip->update_automute)
chip->update_automute(chip, 0);
}
-
-static void tumbler_resume(pmac_t *chip)
-{
- pmac_tumbler_t *mix = chip->mixer_data;
- snd_assert(mix, return);
- INIT_WORK(&mix->resume_workq, tumbler_resume_work, chip);
- if (schedule_work(&mix->resume_workq))
- return;
- printk(KERN_ERR "ALSA tumbler: cannot schedule resume-workqueue.\n");
-}
#endif
/* initialize tumbler */
diff -puN sound/synth/emux/soundfont.c~alsa-bk-2003-07-28 sound/synth/emux/soundfont.c
--- 25/sound/synth/emux/soundfont.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/synth/emux/soundfont.c Tue Jul 29 12:11:32 2003
@@ -66,15 +66,11 @@ static void snd_sf_clear(snd_sf_list_t *
static int
lock_preset(snd_sf_list_t *sflist, int nonblock)
{
- unsigned long flags;
- spin_lock_irqsave(&sflist->lock, flags);
- if (sflist->sf_locked && nonblock) {
- spin_unlock_irqrestore(&sflist->lock, flags);
- return -EBUSY;
- }
- spin_unlock_irqrestore(&sflist->lock, flags);
- down(&sflist->presets_mutex);
- sflist->sf_locked = 1;
+ if (nonblock) {
+ if (down_trylock(&sflist->presets_mutex))
+ return -EBUSY;
+ } else
+ down(&sflist->presets_mutex);
return 0;
}
@@ -86,7 +82,6 @@ static void
unlock_preset(snd_sf_list_t *sflist)
{
up(&sflist->presets_mutex);
- sflist->sf_locked = 0;
}
@@ -1356,7 +1351,6 @@ snd_sf_new(snd_sf_callback_t *callback,
init_MUTEX(&sflist->presets_mutex);
spin_lock_init(&sflist->lock);
- sflist->sf_locked = 0;
sflist->memhdr = hdr;
if (callback)
@@ -1403,7 +1397,7 @@ snd_soundfont_remove_samples(snd_sf_list
/*
* Remove unlocked samples.
- * The soundcard should be silet before calling this function.
+ * The soundcard should be silent before calling this function.
*/
int
snd_soundfont_remove_unlocked(snd_sf_list_t *sflist)
diff -puN sound/usb/usbaudio.c~alsa-bk-2003-07-28 sound/usb/usbaudio.c
--- 25/sound/usb/usbaudio.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/usb/usbaudio.c Tue Jul 29 12:11:32 2003
@@ -153,6 +153,9 @@ struct snd_usb_substream {
int direction; /* playback or capture */
int interface; /* current interface */
int endpoint; /* assigned endpoint */
+ struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */
+ unsigned int cur_rate; /* current rate (for hw_params callback) */
+ unsigned int period_bytes; /* current period bytes (for hw_params callback) */
unsigned int format; /* USB data format */
unsigned int datapipe; /* the data i/o pipe */
unsigned int syncpipe; /* 1 - async out or adaptive in */
@@ -385,6 +388,7 @@ static int prepare_playback_sync_urb(snd
urb->iso_frame_desc[i].length = 3;
urb->iso_frame_desc[i].offset = offs;
}
+ urb->interval = 1;
return 0;
}
@@ -509,6 +513,7 @@ static int prepare_playback_urb(snd_usb_
spin_unlock_irqrestore(&subs->lock, flags);
urb->transfer_buffer_length = offs * stride;
ctx->transfer = offs;
+ urb->interval = 1;
return 0;
}
@@ -808,14 +813,15 @@ static void release_substream_urbs(snd_u
/*
* initialize a substream for plaback/capture
*/
-static int init_substream_urbs(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
+static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_bytes,
+ unsigned int rate, unsigned int frame_bits)
{
unsigned int maxsize, n, i;
int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
unsigned int npacks[MAX_URBS], total_packs;
/* calculate the frequency in 10.14 format */
- subs->freqn = subs->freqm = get_usb_rate(runtime->rate);
+ subs->freqn = subs->freqm = get_usb_rate(rate);
subs->freqmax = subs->freqn + (subs->freqn >> 2); /* max. allowed frequency */
subs->phase = 0;
@@ -828,7 +834,7 @@ static int init_substream_urbs(snd_usb_s
subs->unlink_mask = 0;
/* calculate the max. size of packet */
- maxsize = ((subs->freqmax + 0x3fff) * (runtime->frame_bits >> 3)) >> 14;
+ maxsize = ((subs->freqmax + 0x3fff) * (frame_bits >> 3)) >> 14;
if (subs->maxpacksize && maxsize > subs->maxpacksize) {
//snd_printd(KERN_DEBUG "maxsize %d is greater than defined size %d\n",
// maxsize, subs->maxpacksize);
@@ -839,7 +845,6 @@ static int init_substream_urbs(snd_usb_s
subs->curpacksize = subs->maxpacksize;
else
subs->curpacksize = maxsize;
- subs->curframesize = bytes_to_frames(runtime, subs->curpacksize);
/* allocate a temporary buffer for playback */
if (is_playback) {
@@ -851,7 +856,7 @@ static int init_substream_urbs(snd_usb_s
}
/* decide how many packets to be used */
- total_packs = (frames_to_bytes(runtime, runtime->period_size) + maxsize - 1) / maxsize;
+ total_packs = (period_bytes + maxsize - 1) / maxsize;
if (total_packs < 2 * MIN_PACKS_URB)
total_packs = 2 * MIN_PACKS_URB;
subs->nurbs = (total_packs + nrpacks - 1) / nrpacks;
@@ -945,7 +950,8 @@ static int init_substream_urbs(snd_usb_s
/*
* find a matching audio format
*/
-static struct audioformat *find_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
+static struct audioformat *find_format(snd_usb_substream_t *subs, unsigned int format,
+ unsigned int rate, unsigned int channels)
{
struct list_head *p;
struct audioformat *found = NULL;
@@ -953,23 +959,21 @@ static struct audioformat *find_format(s
list_for_each(p, &subs->fmt_list) {
struct audioformat *fp;
fp = list_entry(p, struct audioformat, list);
- if (fp->format != runtime->format ||
- fp->channels != runtime->channels)
+ if (fp->format != format || fp->channels != channels)
continue;
- if (runtime->rate < fp->rate_min || runtime->rate > fp->rate_max)
+ if (rate < fp->rate_min || rate > fp->rate_max)
continue;
- if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) {
- if (! found || fp->maxpacksize > found->maxpacksize)
- found = fp;
- } else {
+ if (! (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) {
unsigned int i;
for (i = 0; i < fp->nr_rates; i++)
- if (fp->rate_table[i] == runtime->rate) {
- if (! found || fp->maxpacksize > found->maxpacksize)
- found = fp;
+ if (fp->rate_table[i] == rate)
break;
- }
+ if (i >= fp->nr_rates)
+ continue;
}
+ /* find the format with the largest max. packet size */
+ if (! found || fp->maxpacksize > found->maxpacksize)
+ found = fp;
}
return found;
}
@@ -1042,30 +1046,25 @@ static int init_usb_sample_rate(struct u
/*
* find a matching format and set up the interface
*/
-static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
+static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt)
{
struct usb_device *dev = subs->dev;
struct usb_host_config *config = dev->actconfig;
struct usb_host_interface *alts;
struct usb_interface_descriptor *altsd;
struct usb_interface *iface;
- struct audioformat *fmt;
unsigned int ep, attr;
int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
int err;
- fmt = find_format(subs, runtime);
- if (! fmt) {
- snd_printd(KERN_DEBUG "cannot set format: format = %s, rate = %d, channels = %d\n",
- snd_pcm_format_name(runtime->format), runtime->rate, runtime->channels);
- return -EINVAL;
- }
-
iface = &config->interface[fmt->iface];
alts = &iface->altsetting[fmt->altset_idx];
altsd = get_iface_desc(alts);
snd_assert(altsd->bAlternateSetting == fmt->altsetting, return -EINVAL);
+ if (fmt == subs->cur_audiofmt)
+ return 0;
+
/* close the old interface */
if (subs->interface >= 0 && subs->interface != fmt->iface) {
usb_set_interface(subs->dev, subs->interface, 0);
@@ -1093,7 +1092,6 @@ static int set_format(snd_usb_substream_
subs->datapipe = usb_rcvisocpipe(dev, ep);
subs->syncpipe = subs->syncinterval = 0;
subs->maxpacksize = get_endpoint(alts, 0)->wMaxPacketSize;
- subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize);
subs->fill_max = 0;
/* we need a sync pipe in async OUT or adaptive IN mode */
@@ -1123,18 +1121,18 @@ static int set_format(snd_usb_substream_
subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
}
- if ((err = init_usb_pitch(dev, subs->interface, alts, fmt)) < 0 ||
- (err = init_usb_sample_rate(dev, subs->interface, alts, fmt,
- runtime->rate)) < 0)
- return err;
-
/* always fill max packet size */
if (fmt->attributes & EP_CS_ATTR_FILL_MAX)
subs->fill_max = 1;
+ if ((err = init_usb_pitch(dev, subs->interface, alts, fmt)) < 0)
+ return err;
+
+ subs->cur_audiofmt = fmt;
+
#if 0
printk("setting done: format = %d, rate = %d, channels = %d\n",
- runtime->format, runtime->rate, runtime->channels);
+ fmt->format, fmt->rate, fmt->channels);
printk(" datapipe = 0x%0x, syncpipe = 0x%0x\n",
subs->datapipe, subs->syncpipe);
#endif
@@ -1143,7 +1141,9 @@ static int set_format(snd_usb_substream_
}
/*
- * allocate a buffer.
+ * hw_params callback
+ *
+ * allocate a buffer and set the given audio format.
*
* so far we use a physically linear buffer although packetize transfer
* doesn't need a continuous area.
@@ -1153,33 +1153,91 @@ static int set_format(snd_usb_substream_
static int snd_usb_hw_params(snd_pcm_substream_t *substream,
snd_pcm_hw_params_t *hw_params)
{
- return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+ snd_usb_substream_t *subs = (snd_usb_substream_t *)substream->runtime->private_data;
+ struct audioformat *fmt;
+ unsigned int channels, rate, format;
+ int ret, changed;
+
+ ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+ if (ret < 0)
+ return ret;
+
+ format = params_format(hw_params);
+ rate = params_rate(hw_params);
+ channels = params_channels(hw_params);
+ fmt = find_format(subs, format, rate, channels);
+ if (! fmt) {
+ snd_printd(KERN_DEBUG "cannot set format: format = %s, rate = %d, channels = %d\n",
+ snd_pcm_format_name(format), rate, channels);
+ return -EINVAL;
+ }
+
+ changed = subs->cur_audiofmt != fmt ||
+ subs->period_bytes != params_period_bytes(hw_params) ||
+ subs->cur_rate != rate;
+ if ((ret = set_format(subs, fmt)) < 0)
+ return ret;
+
+ if (subs->cur_rate != rate) {
+ struct usb_host_config *config = subs->dev->actconfig;
+ struct usb_host_interface *alts;
+ struct usb_interface *iface;
+ iface = &config->interface[fmt->iface];
+ alts = &iface->altsetting[fmt->altset_idx];
+ ret = init_usb_sample_rate(subs->dev, subs->interface, alts, fmt, rate);
+ if (ret < 0)
+ return ret;
+ subs->cur_rate = rate;
+ }
+
+ if (changed) {
+ /* format changed */
+ release_substream_urbs(subs, 0);
+ /* influenced: period_bytes, channels, rate, format, */
+ ret = init_substream_urbs(subs, params_period_bytes(hw_params),
+ params_rate(hw_params),
+ snd_pcm_format_physical_width(params_format(hw_params)) * params_channels(hw_params));
+ }
+
+ return ret;
}
/*
- * free the buffer
+ * hw_free callback
+ *
+ * reset the audio format and release the buffer
*/
static int snd_usb_hw_free(snd_pcm_substream_t *substream)
{
+ snd_usb_substream_t *subs = (snd_usb_substream_t *)substream->runtime->private_data;
+
+ subs->cur_audiofmt = NULL;
+ subs->cur_rate = 0;
+ subs->period_bytes = 0;
+ release_substream_urbs(subs, 0);
return snd_pcm_lib_free_pages(substream);
}
/*
* prepare callback
*
- * set format and initialize urbs
+ * only a few subtle things...
*/
static int snd_usb_pcm_prepare(snd_pcm_substream_t *substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
snd_usb_substream_t *subs = (snd_usb_substream_t *)runtime->private_data;
- int err;
- release_substream_urbs(subs, 0);
- if ((err = set_format(subs, runtime)) < 0)
- return err;
+ if (! subs->cur_audiofmt) {
+ snd_printk(KERN_ERR "usbaudio: no format is specified!\n");
+ return -ENXIO;
+ }
+
+ /* some unit conversions in runtime */
+ subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize);
+ subs->curframesize = bytes_to_frames(runtime, subs->curpacksize);
- return init_substream_urbs(subs, runtime);
+ return 0;
}
static snd_pcm_hardware_t snd_usb_playback =
@@ -1536,9 +1594,10 @@ static int snd_usb_pcm_close(snd_pcm_sub
snd_usb_stream_t *as = snd_pcm_substream_chip(substream);
snd_usb_substream_t *subs = &as->substream[direction];
- release_substream_urbs(subs, 0);
- if (subs->interface >= 0)
+ if (subs->interface >= 0) {
usb_set_interface(subs->dev, subs->interface, 0);
+ subs->interface = -1;
+ }
subs->pcm_substream = NULL;
return 0;
}
@@ -2163,8 +2222,10 @@ static int parse_audio_endpoints(snd_usb
/* skip invalid one */
if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
- altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING ||
- altsd->bNumEndpoints < 1)
+ (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING &&
+ altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) ||
+ altsd->bNumEndpoints < 1 ||
+ get_endpoint(alts, 0)->wMaxPacketSize == 0)
continue;
/* must be isochronous */
if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
@@ -2236,6 +2297,14 @@ static int parse_audio_endpoints(snd_usb
*/
fp->attributes &= ~EP_CS_ATTR_SAMPLE_RATE;
}
+
+ /* workaround for M-Audio Audiophile USB */
+ if (dev->descriptor.idVendor == 0x0763 &&
+ dev->descriptor.idProduct == 0x2003) {
+ /* doesn't set the sample rate attribute, but supports it */
+ fp->attributes |= EP_CS_ATTR_SAMPLE_RATE;
+ }
+
/*
* plantronics headset and Griffin iMic have set adaptive-in
* although it's really not...
@@ -2278,6 +2347,32 @@ static int parse_audio_endpoints(snd_usb
/*
+ * disconnect streams
+ * called from snd_usb_audio_disconnect()
+ */
+static void snd_usb_stream_disconnect(struct list_head *head, struct usb_driver *driver)
+{
+ int idx;
+ snd_usb_stream_t *as;
+ snd_usb_substream_t *subs;
+ struct list_head *p;
+
+ as = list_entry(head, snd_usb_stream_t, list);
+ for (idx = 0; idx < 2; idx++) {
+ subs = &as->substream[idx];
+ if (!subs->num_formats)
+ return;
+ release_substream_urbs(subs, 1);
+ subs->interface = -1;
+ /* release interfaces */
+ list_for_each(p, &subs->fmt_list) {
+ struct audioformat *fp = list_entry(p, struct audioformat, list);
+ usb_driver_release_interface(driver, usb_ifnum_to_if(subs->dev, fp->iface));
+ }
+ }
+}
+
+/*
* parse audio control descriptor and create pcm/midi streams
*/
static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif)
@@ -2381,7 +2476,8 @@ static int create_fixed_stream_quirk(snd
* create a stream for an interface with proper descriptors
*/
static int create_standard_interface_quirk(snd_usb_audio_t *chip,
- struct usb_interface *iface)
+ struct usb_interface *iface,
+ const snd_usb_audio_quirk_t *quirk)
{
struct usb_host_interface *alts;
struct usb_interface_descriptor *altsd;
@@ -2389,19 +2485,18 @@ static int create_standard_interface_qui
alts = &iface->altsetting[0];
altsd = get_iface_desc(alts);
- switch (altsd->bInterfaceSubClass) {
- case USB_SUBCLASS_AUDIO_STREAMING:
+ switch (quirk->type) {
+ case QUIRK_AUDIO_STANDARD_INTERFACE:
err = parse_audio_endpoints(chip, altsd->bInterfaceNumber);
if (!err)
usb_set_interface(chip->dev, altsd->bInterfaceNumber, 0); /* reset the current interface */
break;
- case USB_SUBCLASS_MIDI_STREAMING:
+ case QUIRK_MIDI_STANDARD_INTERFACE:
err = snd_usb_create_midi_interface(chip, iface, NULL);
break;
default:
- snd_printk(KERN_ERR "if %d: non-supported subclass %d\n",
- altsd->bInterfaceNumber, altsd->bInterfaceSubClass);
- return -ENODEV;
+ snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
+ return -ENXIO;
}
if (err < 0) {
snd_printk(KERN_ERR "cannot setup if %d: error %d\n",
@@ -2495,8 +2590,9 @@ static int snd_usb_create_quirk(snd_usb_
return create_composite_quirk(chip, iface, quirk);
case QUIRK_AUDIO_FIXED_ENDPOINT:
return create_fixed_stream_quirk(chip, iface, quirk);
- case QUIRK_STANDARD_INTERFACE:
- return create_standard_interface_quirk(chip, iface);
+ case QUIRK_AUDIO_STANDARD_INTERFACE:
+ case QUIRK_MIDI_STANDARD_INTERFACE:
+ return create_standard_interface_quirk(chip, iface, quirk);
default:
snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
return -ENXIO;
@@ -2635,11 +2731,6 @@ static void *snd_usb_audio_probe(struct
if (quirk && quirk->ifnum != QUIRK_ANY_INTERFACE && ifnum != quirk->ifnum)
goto __err_val;
- if (usb_set_configuration(dev, get_cfg_desc(config)->bConfigurationValue) < 0) {
- snd_printk(KERN_ERR "cannot set configuration (value 0x%x)\n", get_cfg_desc(config)->bConfigurationValue);
- goto __err_val;
- }
-
/* SB Extigy needs special boot-up sequence */
/* if more models come, this will go to the quirk list. */
if (dev->descriptor.idVendor == 0x041e && dev->descriptor.idProduct == 0x3000) {
@@ -2669,6 +2760,11 @@ static void *snd_usb_audio_probe(struct
/* it's a fresh one.
* now look for an empty slot and create a new card instance
*/
+ /* first, set the current configuration for this device */
+ if (usb_set_configuration(dev, get_cfg_desc(config)->bConfigurationValue) < 0) {
+ snd_printk(KERN_ERR "cannot set configuration (value 0x%x)\n", get_cfg_desc(config)->bConfigurationValue);
+ goto __error;
+ }
for (i = 0; i < SNDRV_CARDS; i++)
if (enable[i] && ! usb_chip[i] &&
(vid[i] == -1 || vid[i] == dev->descriptor.idVendor) &&
@@ -2746,21 +2842,11 @@ static void snd_usb_audio_disconnect(str
snd_card_disconnect(card);
/* release the pcm resources */
list_for_each(p, &chip->pcm_list) {
- snd_usb_stream_t *as;
- int idx;
- as = list_entry(p, snd_usb_stream_t, list);
- for (idx = 0; idx < 2; idx++) {
- snd_usb_substream_t *subs;
- subs = &as->substream[idx];
- if (!subs->num_formats)
- continue;
- release_substream_urbs(subs, 1);
- subs->interface = -1;
- }
+ snd_usb_stream_disconnect(p, &usb_audio_driver);
}
/* release the midi resources */
list_for_each(p, &chip->midi_list) {
- snd_usbmidi_disconnect(p);
+ snd_usbmidi_disconnect(p, &usb_audio_driver);
}
up(®ister_mutex);
snd_card_free_in_thread(card);
diff -puN sound/usb/usbaudio.h~alsa-bk-2003-07-28 sound/usb/usbaudio.h
--- 25/sound/usb/usbaudio.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/usb/usbaudio.h Tue Jul 29 12:11:31 2003
@@ -28,6 +28,7 @@
#define USB_SUBCLASS_AUDIO_CONTROL 0x01
#define USB_SUBCLASS_AUDIO_STREAMING 0x02
#define USB_SUBCLASS_MIDI_STREAMING 0x03
+#define USB_SUBCLASS_VENDOR_SPEC 0xff
#define USB_DT_CS_DEVICE 0x21
#define USB_DT_CS_CONFIG 0x22
@@ -154,7 +155,8 @@ struct snd_usb_audio {
#define QUIRK_MIDI_MIDIMAN 2
#define QUIRK_COMPOSITE 3
#define QUIRK_AUDIO_FIXED_ENDPOINT 4
-#define QUIRK_STANDARD_INTERFACE 5
+#define QUIRK_AUDIO_STANDARD_INTERFACE 5
+#define QUIRK_MIDI_STANDARD_INTERFACE 6
typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t;
typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t;
@@ -184,7 +186,7 @@ struct snd_usb_midi_endpoint_info {
/* for QUIRK_AUDIO_FIXED_ENDPOINT, data points to an audioformat structure */
-/* for QUIRK_STANDARD_INTERFACE, data is NULL */
+/* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */
/*
*/
@@ -201,7 +203,7 @@ void *snd_usb_find_csint_desc(void *desc
int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif);
int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk);
-void snd_usbmidi_disconnect(struct list_head *p);
+void snd_usbmidi_disconnect(struct list_head *p, struct usb_driver *driver);
/*
* retrieve usb_interface descriptor from the host interface
diff -puN sound/usb/usbmidi.c~alsa-bk-2003-07-28 sound/usb/usbmidi.c
--- 25/sound/usb/usbmidi.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/usb/usbmidi.c Tue Jul 29 12:11:31 2003
@@ -693,12 +693,13 @@ static void snd_usbmidi_free(snd_usb_mid
/*
* Unlinks all URBs (must be done before the usb_device is deleted).
*/
-void snd_usbmidi_disconnect(struct list_head* p)
+void snd_usbmidi_disconnect(struct list_head* p, struct usb_driver *driver)
{
snd_usb_midi_t* umidi;
int i;
umidi = list_entry(p, snd_usb_midi_t, list);
+ usb_driver_release_interface(driver, umidi->iface);
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
if (ep->out && ep->out->urb)
diff -puN sound/usb/usbmixer.c~alsa-bk-2003-07-28 sound/usb/usbmixer.c
--- 25/sound/usb/usbmixer.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/usb/usbmixer.c Tue Jul 29 12:11:31 2003
@@ -96,7 +96,7 @@ enum {
USB_FEATURE_AGC,
USB_FEATURE_DELAY,
USB_FEATURE_BASSBOOST,
- FSB_FEATURE_LOUDNESS
+ USB_FEATURE_LOUDNESS
};
enum {
diff -puN sound/usb/usbmixer_maps.c~alsa-bk-2003-07-28 sound/usb/usbmixer_maps.c
--- 25/sound/usb/usbmixer_maps.c~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/usb/usbmixer_maps.c Tue Jul 29 12:11:31 2003
@@ -89,6 +89,28 @@ static struct usbmix_name_map extigy_map
{ 0 } /* terminator */
};
+/* Section "justlink_map" below added by James Courtier-Dutton
+ * sourced from Maplin Electronics (http://www.maplin.co.uk), part number A56AK
+ * Part has 2 connectors that act as a single output. (TOSLINK Optical for digital out, and 3.5mm Jack for Analogue out.)
+ * The USB Mixer publishes a Microphone and extra Volume controls for it, but none exist on the device,
+ * so this map removes all unwanted sliders from alsamixer
+ */
+
+static struct usbmix_name_map justlink_map[] = {
+ /* 1: IT pcm playback */
+ /* 2: Not present */
+ { 3, NULL}, /* IT mic (No mic input on device) */
+ /* 4: Not present */
+ /* 5: OT speacker */
+ /* 6: OT pcm capture */
+ { 7, "Master Playback" }, /* Mute/volume for speaker */
+ { 8, NULL }, /* Capture Switch (No capture inputs on device) */
+ { 9, NULL }, /* Capture Mute/volume (No capture inputs on device */
+ /* 0xa: Not present */
+ /* 0xb: MU (w/o controls) */
+ { 0xc, NULL }, /* Mic feedback Mute/volume (No capture inputs on device) */
+ { 0 } /* terminator */
+};
/*
* Control map entries
@@ -96,6 +118,7 @@ static struct usbmix_name_map extigy_map
static struct usbmix_ctl_map usbmix_ctl_maps[] = {
{ 0x41e, 0x3000, extigy_map },
+ { 0xc45, 0x1158, justlink_map },
{ 0 } /* terminator */
};
diff -puN sound/usb/usbquirks.h~alsa-bk-2003-07-28 sound/usb/usbquirks.h
--- 25/sound/usb/usbquirks.h~alsa-bk-2003-07-28 Tue Jul 29 12:11:31 2003
+++ 25-akpm/sound/usb/usbquirks.h Tue Jul 29 12:11:31 2003
@@ -453,6 +453,36 @@
}
}
},
+{ /*
+ * This quirk is for the "Advanced Driver" mode of the Edirol UA-5.
+ * If the advanced mode switch at the back of the unit is off, the
+ * UA-5 has ID 0x0582/0x0011 and is standard compliant (no quirks),
+ * but offers only 16-bit PCM.
+ * In advanced mode, the UA-5 will output S24_3LE samples (two
+ * channels) at the rate indicated on the front switch, including
+ * the 96kHz sample rate.
+ */
+ USB_DEVICE(0x0582, 0x0010),
+ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .vendor_name = "EDIROL",
+ .product_name = "UA-5",
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = & (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 1,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
{
USB_DEVICE(0x0582, 0x0012),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
@@ -520,15 +550,15 @@
.data = & (const snd_usb_audio_quirk_t[]) {
{
.ifnum = 1,
- .type = QUIRK_STANDARD_INTERFACE
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
},
{
.ifnum = 2,
- .type = QUIRK_STANDARD_INTERFACE
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
},
{
.ifnum = 3,
- .type = QUIRK_STANDARD_INTERFACE
+ .type = QUIRK_MIDI_STANDARD_INTERFACE
},
{
.ifnum = -1
_