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 _