Commit 3888039b authored by Jaroslav Kysela's avatar Jaroslav Kysela

Merge suse.cz:/home/perex/bk/linux-sound/linux-2.5

into suse.cz:/home/perex/bk/linux-sound/linux-sound
parents d8475074 f453e20d
...@@ -945,19 +945,34 @@ Module parameters ...@@ -945,19 +945,34 @@ Module parameters
Module snd-via82xx Module snd-via82xx
------------------ ------------------
Module for AC'97 motherboards based on VIA 82C686A/686B, 8233 Module for AC'97 motherboards based on VIA 82C686A/686B, 8233,
(south) bridge. 8233A, 8233C, 8235 (south) bridge.
mpu_port - 0x300,0x310,0x320,0x330, otherwise obtain BIOS setup mpu_port - 0x300,0x310,0x320,0x330, otherwise obtain BIOS setup
[VIA686A/686B only]
ac97_clock - AC'97 codec clock base (default 48000Hz) ac97_clock - AC'97 codec clock base (default 48000Hz)
dxs_support - support DXS channels,
0 = auto (default), 1 = enable, 2 = disable,
3 = 48k only
[VIA8233/C,8235 only]
Module supports autoprobe and multiple bus-master chips (max 8). Module supports autoprobe and multiple bus-master chips (max 8).
Note: on some SMP motherboards like MSI 694D the interrupts might Note: on some SMP motherboards like MSI 694D the interrupts might
not be generated properly. In such a case, please try to not be generated properly. In such a case, please try to
set the SMP (or MPS) version on BIOS to 1.1 instead of set the SMP (or MPS) version on BIOS to 1.1 instead of
default value 1.4. Then the interrupt number will be default value 1.4. Then the interrupt number will be
assigned under 15. You might also upgrade your BIOS. assigned under 15. You might also upgrade your BIOS.
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.
Note: for the MPU401 on VIA823x, use snd-mpu401 driver
additonally.
Module snd-virmidi Module snd-virmidi
------------------ ------------------
......
...@@ -249,7 +249,7 @@ control. In fact, the controls with "XXX [Playback|Capture] ...@@ -249,7 +249,7 @@ control. In fact, the controls with "XXX [Playback|Capture]
[Volume|Switch]" will be checked in addition. [Volume|Switch]" will be checked in addition.
The current assignment of these mixer elements is listed in the proc The current assignment of these mixer elements is listed in the proc
file, /proc/asound/cardX/mixer_oss, which will be like the following file, /proc/asound/cardX/oss_mixer, which will be like the following
VOLUME "Master" 0 VOLUME "Master" 0
BASS "" 0 BASS "" 0
...@@ -267,7 +267,7 @@ For changing the assignment, you can write the configuration to this ...@@ -267,7 +267,7 @@ For changing the assignment, you can write the configuration to this
proc file. For example, to map "Wave Playback" to the PCM volume, proc file. For example, to map "Wave Playback" to the PCM volume,
send the command like the following: send the command like the following:
% echo 'VOLUME "Wave Playback" 0' > /proc/asound/card0/mixer_oss % echo 'VOLUME "Wave Playback" 0' > /proc/asound/card0/oss_mixer
The command is exactly as same as listed in the proc file. You can The command is exactly as same as listed in the proc file. You can
change one or more elements, one volume per line. In the last change one or more elements, one volume per line. In the last
......
#ifndef __SOUND_AK4XXX_ADDA_H
#define __SOUND_AK4XXX_ADDA_H
/*
* ALSA driver for AK4524 / AK4528 / AK4529 / AK4355 / AK4381
* AD and DA converters
*
* Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
*
* 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
*
*/
#ifndef AK4XXX_MAX_CHIPS
#define AK4XXX_MAX_CHIPS 4
#endif
typedef struct snd_akm4xxx akm4xxx_t;
struct snd_ak4xxx_ops {
void (*lock)(akm4xxx_t *ak, int chip);
void (*unlock)(akm4xxx_t *ak, int chip);
void (*write)(akm4xxx_t *ak, int chip, unsigned char reg, unsigned char val);
// unsigned char (*read)(akm4xxx_t *ak, int chip, unsigned char reg);
void (*set_rate_val)(akm4xxx_t *ak, unsigned int rate);
};
struct snd_akm4xxx {
snd_card_t *card;
unsigned int num_adcs; /* AK4524 or AK4528 ADCs */
unsigned int num_dacs; /* AK4524 or AK4528 DACs */
unsigned char images[AK4XXX_MAX_CHIPS][16]; /* saved register image */
unsigned char ipga_gain[AK4XXX_MAX_CHIPS][2]; /* saved register image for IPGA (AK4528) */
unsigned long private_value[AK4XXX_MAX_CHIPS]; /* helper for driver */
void *private_data[AK4XXX_MAX_CHIPS]; /* helper for driver */
/* template should fill the following fields */
unsigned int idx_offset; /* control index offset */
enum {
SND_AK4524, SND_AK4528, SND_AK4529, SND_AK4355, SND_AK4381
} type;
struct snd_ak4xxx_ops ops;
};
void snd_akm4xxx_write(akm4xxx_t *ak, int chip, unsigned char reg, unsigned char val);
void snd_akm4xxx_reset(akm4xxx_t *ak, int state);
void snd_akm4xxx_init(akm4xxx_t *ak);
int snd_akm4xxx_build_controls(akm4xxx_t *ak);
#endif /* __SOUND_AK4XXX_ADDA_H */
...@@ -184,7 +184,7 @@ static inline void snd_power_unlock(snd_card_t *card) ...@@ -184,7 +184,7 @@ static inline void snd_power_unlock(snd_card_t *card)
up(&card->power_lock); up(&card->power_lock);
} }
void snd_power_wait(snd_card_t *card); int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file);
static inline unsigned int snd_power_get_state(snd_card_t *card) static inline unsigned int snd_power_get_state(snd_card_t *card)
{ {
...@@ -199,7 +199,7 @@ static inline void snd_power_change_state(snd_card_t *card, unsigned int state) ...@@ -199,7 +199,7 @@ static inline void snd_power_change_state(snd_card_t *card, unsigned int state)
#else #else
#define snd_power_lock(card) do { (void)(card); } while (0) #define snd_power_lock(card) do { (void)(card); } while (0)
#define snd_power_unlock(card) do { (void)(card); } while (0) #define snd_power_unlock(card) do { (void)(card); } while (0)
#define snd_power_wait(card) do { (void)(card); } while (0) static inline int snd_power_wait(snd_card_t *card, unsigned int state, struct file *file) { return 0; }
#define snd_power_get_state(card) SNDRV_CTL_POWER_D0 #define snd_power_get_state(card) SNDRV_CTL_POWER_D0
#define snd_power_change_state(card, state) do { (void)(card); } while (0) #define snd_power_change_state(card, state) do { (void)(card); } while (0)
#endif #endif
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#define CS8427_REG_UDATABUF 0x13 #define CS8427_REG_UDATABUF 0x13
#define CS8427_REG_QSUBCODE 0x14 /* 0x14-0x1d (10 bytes) */ #define CS8427_REG_QSUBCODE 0x14 /* 0x14-0x1d (10 bytes) */
#define CS8427_REG_OMCKRMCKRATIO 0x1e #define CS8427_REG_OMCKRMCKRATIO 0x1e
#define CS8427_REG_CORU_DATABUF 0x20 #define CS8427_REG_CORU_DATABUF 0x20 /* 24 byte buffer area */
#define CS8427_REG_ID_AND_VER 0x7f #define CS8427_REG_ID_AND_VER 0x7f
/* CS8427_REG_CONTROL1 bits */ /* CS8427_REG_CONTROL1 bits */
...@@ -188,6 +188,7 @@ ...@@ -188,6 +188,7 @@
int snd_cs8427_detect(snd_i2c_bus_t *bus, unsigned char addr); 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); 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_iec958_build(snd_i2c_device_t *cs8427, snd_pcm_substream_t *playback_substream, snd_pcm_substream_t *capture_substream); 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_active(snd_i2c_device_t *cs8427, int active);
int snd_cs8427_iec958_pcm(snd_i2c_device_t *cs8427, unsigned int rate); int snd_cs8427_iec958_pcm(snd_i2c_device_t *cs8427, unsigned int rate);
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
* *
*/ */
#include <linux/interrupt.h>
#include "rawmidi.h" #include "rawmidi.h"
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -50,8 +49,6 @@ ...@@ -50,8 +49,6 @@
#define MPU401_MODE_BIT_OUTPUT 1 #define MPU401_MODE_BIT_OUTPUT 1
#define MPU401_MODE_BIT_INPUT_TRIGGER 2 #define MPU401_MODE_BIT_INPUT_TRIGGER 2
#define MPU401_MODE_BIT_OUTPUT_TRIGGER 3 #define MPU401_MODE_BIT_OUTPUT_TRIGGER 3
#define MPU401_MODE_BIT_RX_LOOP 4
#define MPU401_MODE_BIT_TX_LOOP 5
#define MPU401_MODE_INPUT (1<<MPU401_MODE_BIT_INPUT) #define MPU401_MODE_INPUT (1<<MPU401_MODE_BIT_INPUT)
#define MPU401_MODE_OUTPUT (1<<MPU401_MODE_BIT_OUTPUT) #define MPU401_MODE_OUTPUT (1<<MPU401_MODE_BIT_OUTPUT)
...@@ -89,6 +86,9 @@ struct _snd_mpu401 { ...@@ -89,6 +86,9 @@ struct _snd_mpu401 {
spinlock_t output_lock; spinlock_t output_lock;
spinlock_t timer_lock; spinlock_t timer_lock;
atomic_t rx_loop;
atomic_t tx_loop;
struct timer_list timer; struct timer_list timer;
void (*write) (mpu401_t * mpu, unsigned char data, unsigned long addr); void (*write) (mpu401_t * mpu, unsigned char data, unsigned long addr);
......
...@@ -328,7 +328,6 @@ struct _snd_pcm_runtime { ...@@ -328,7 +328,6 @@ struct _snd_pcm_runtime {
atomic_t mmap_count; atomic_t mmap_count;
/* -- locking / scheduling -- */ /* -- locking / scheduling -- */
spinlock_t lock;
wait_queue_head_t sleep; wait_queue_head_t sleep;
struct timer_list tick_timer; struct timer_list tick_timer;
struct fasync_struct *fasync; struct fasync_struct *fasync;
...@@ -360,6 +359,11 @@ struct _snd_pcm_runtime { ...@@ -360,6 +359,11 @@ struct _snd_pcm_runtime {
#endif #endif
}; };
typedef struct _snd_pcm_group { /* keep linked substreams */
spinlock_t lock;
struct list_head substreams;
} snd_pcm_group_t;
struct _snd_pcm_substream { struct _snd_pcm_substream {
snd_pcm_t *pcm; snd_pcm_t *pcm;
snd_pcm_str_t *pstr; snd_pcm_str_t *pstr;
...@@ -383,8 +387,10 @@ struct _snd_pcm_substream { ...@@ -383,8 +387,10 @@ struct _snd_pcm_substream {
/* -- next substream -- */ /* -- next substream -- */
snd_pcm_substream_t *next; snd_pcm_substream_t *next;
/* -- linked substreams -- */ /* -- linked substreams -- */
snd_pcm_substream_t *link_next; struct list_head link_list; /* linked list member */
snd_pcm_substream_t *link_prev; snd_pcm_group_t self_group; /* fake group for non linked substream (with substream lock inside) */
snd_pcm_group_t *group; /* pointer to current group */
/* -- assigned files -- */
snd_pcm_file_t *file; snd_pcm_file_t *file;
struct file *ffile; struct file *ffile;
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
...@@ -468,6 +474,8 @@ int snd_pcm_notify(snd_pcm_notify_t *notify, int nfree); ...@@ -468,6 +474,8 @@ int snd_pcm_notify(snd_pcm_notify_t *notify, int nfree);
* Native I/O * Native I/O
*/ */
extern rwlock_t snd_pcm_link_rwlock;
int snd_pcm_info(snd_pcm_substream_t * substream, snd_pcm_info_t *info); int snd_pcm_info(snd_pcm_substream_t * substream, snd_pcm_info_t *info);
int snd_pcm_info_user(snd_pcm_substream_t * substream, snd_pcm_info_t *info); int snd_pcm_info_user(snd_pcm_substream_t * substream, snd_pcm_info_t *info);
int snd_pcm_status(snd_pcm_substream_t * substream, snd_pcm_status_t *status); int snd_pcm_status(snd_pcm_substream_t * substream, snd_pcm_status_t *status);
...@@ -568,6 +576,53 @@ static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem) ...@@ -568,6 +576,53 @@ static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem)
* PCM library * PCM library
*/ */
static inline int snd_pcm_stream_linked(snd_pcm_substream_t *substream)
{
return substream->group != &substream->self_group;
}
static inline void snd_pcm_stream_lock(snd_pcm_substream_t *substream)
{
read_lock(&snd_pcm_link_rwlock);
spin_lock(&substream->self_group.lock);
}
static inline void snd_pcm_stream_unlock(snd_pcm_substream_t *substream)
{
spin_unlock(&substream->self_group.lock);
read_unlock(&snd_pcm_link_rwlock);
}
static inline void snd_pcm_stream_lock_irq(snd_pcm_substream_t *substream)
{
read_lock_irq(&snd_pcm_link_rwlock);
spin_lock(&substream->self_group.lock);
}
static inline void snd_pcm_stream_unlock_irq(snd_pcm_substream_t *substream)
{
spin_unlock(&substream->self_group.lock);
read_unlock_irq(&snd_pcm_link_rwlock);
}
#define snd_pcm_stream_lock_irqsave(substream, flags) \
do { \
read_lock_irqsave(&snd_pcm_link_rwlock, (flags)); \
spin_lock(&substream->self_group.lock); \
} while (0)
#define snd_pcm_stream_unlock_irqrestore(substream, flags) \
do { \
spin_unlock(&substream->self_group.lock); \
read_unlock_irqrestore(&snd_pcm_link_rwlock, (flags)); \
} while (0)
#define snd_pcm_group_for_each(pos, substream) \
list_for_each(pos, &substream->group->substreams)
#define snd_pcm_group_substream_entry(pos) \
list_entry(pos, snd_pcm_substream_t, link_list)
static inline int snd_pcm_running(snd_pcm_substream_t *substream) static inline int snd_pcm_running(snd_pcm_substream_t *substream)
{ {
return (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING || return (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
......
...@@ -295,13 +295,13 @@ int snd_sbmixer_new(sb_t *chip); ...@@ -295,13 +295,13 @@ int snd_sbmixer_new(sb_t *chip);
/* sb8_init.c */ /* sb8_init.c */
int snd_sb8dsp_pcm(sb_t *chip, int device, snd_pcm_t ** rpcm); int snd_sb8dsp_pcm(sb_t *chip, int device, snd_pcm_t ** rpcm);
/* sb8.c */ /* sb8.c */
void snd_sb8dsp_interrupt(sb_t *chip); irqreturn_t snd_sb8dsp_interrupt(sb_t *chip);
int snd_sb8_playback_open(snd_pcm_substream_t *substream); int snd_sb8_playback_open(snd_pcm_substream_t *substream);
int snd_sb8_capture_open(snd_pcm_substream_t *substream); int snd_sb8_capture_open(snd_pcm_substream_t *substream);
int snd_sb8_playback_close(snd_pcm_substream_t *substream); int snd_sb8_playback_close(snd_pcm_substream_t *substream);
int snd_sb8_capture_close(snd_pcm_substream_t *substream); int snd_sb8_capture_close(snd_pcm_substream_t *substream);
/* midi8.c */ /* midi8.c */
void snd_sb8dsp_midi_interrupt(sb_t *chip); irqreturn_t snd_sb8dsp_midi_interrupt(sb_t *chip);
int snd_sb8dsp_midi(sb_t *chip, int device, snd_rawmidi_t ** rrawmidi); int snd_sb8dsp_midi(sb_t *chip, int device, snd_rawmidi_t ** rrawmidi);
/* sb16_init.c */ /* sb16_init.c */
......
...@@ -57,14 +57,8 @@ ...@@ -57,14 +57,8 @@
/* Trident chipsets have 1GB memory limit */ /* Trident chipsets have 1GB memory limit */
#ifdef __alpha__ #ifdef __alpha__
#define TRIDENT_DMA_TYPE SNDRV_DMA_TYPE_PCI_16MB #define TRIDENT_DMA_TYPE SNDRV_DMA_TYPE_PCI_16MB
#define TRIDENT_GFP_FLAGS GFP_DMA
#else #else
#define TRIDENT_DMA_TYPE SNDRV_DMA_TYPE_PCI #define TRIDENT_DMA_TYPE SNDRV_DMA_TYPE_PCI
#if defined(__i386__) && !defined(CONFIG_1GB)
#define TRIDENT_GFP_FLAGS GFP_DMA
#else
#define TRIDENT_GFP_FLAGS 0
#endif
#endif #endif
#define SNDRV_SEQ_DEV_ID_TRIDENT "trident-synth" #define SNDRV_SEQ_DEV_ID_TRIDENT "trident-synth"
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* features support * features support
*/ */
/* $Id: uda1341.h,v 1.4 2003/02/25 12:48:16 perex Exp $ */ /* $Id: uda1341.h,v 1.5 2003/04/19 13:34:32 perex Exp $ */
#define UDA1341_ALSA_NAME "snd-uda1341" #define UDA1341_ALSA_NAME "snd-uda1341"
...@@ -210,6 +210,10 @@ enum uda1341_config { ...@@ -210,6 +210,10 @@ enum uda1341_config {
CMD_IG, CMD_IG,
CMD_AGC_TIME, CMD_AGC_TIME,
CMD_AGC_LEVEL, CMD_AGC_LEVEL,
#ifdef CONFIG_PM
CMD_SUSPEND,
CMD_RESUME,
#endif
CMD_LAST, CMD_LAST,
}; };
...@@ -221,19 +225,6 @@ enum write_through { ...@@ -221,19 +225,6 @@ enum write_through {
}; };
int __init snd_chip_uda1341_mixer_new(snd_card_t *card, struct l3_client **clnt); int __init snd_chip_uda1341_mixer_new(snd_card_t *card, struct l3_client **clnt);
void __init snd_chip_uda1341_mixer_del(snd_card_t *card);
#ifdef DEBUG_MODE
#define DEBUG(format, args...) do{printk(format, ##args);}while(0)
#else
#define DEBUG(format, args...) /* nothing */
#endif
#ifdef DEBUG_FUNCTION_NAMES
#define DEBUG_NAME(format, args...) do{printk(format, ##args);}while(0)
#else
#define DEBUG_NAME(format, args...) /* nothing */
#endif
/* /*
* Local variables: * Local variables:
......
/* include/version.h. Generated by configure. */ /* include/version.h. Generated by configure. */
#define CONFIG_SND_VERSION "0.9.2" #define CONFIG_SND_VERSION "0.9.3a"
#define CONFIG_SND_DATE " (Thu Mar 20 13:31:57 2003 UTC)" #define CONFIG_SND_DATE " (Thu May 08 07:41:58 2003 UTC)"
This diff is collapsed.
...@@ -78,6 +78,7 @@ obj-$(CONFIG_SND_ES1938) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-hwd ...@@ -78,6 +78,7 @@ obj-$(CONFIG_SND_ES1938) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-hwd
obj-$(CONFIG_SND_ES1968) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o obj-$(CONFIG_SND_ES1968) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
obj-$(CONFIG_SND_FM801) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o snd-hwdep.o obj-$(CONFIG_SND_FM801) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o snd-hwdep.o
obj-$(CONFIG_SND_ICE1712) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o obj-$(CONFIG_SND_ICE1712) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
obj-$(CONFIG_SND_ICE1724) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
obj-$(CONFIG_SND_INTEL8X0) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o obj-$(CONFIG_SND_INTEL8X0) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
obj-$(CONFIG_SND_MAESTRO3) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o obj-$(CONFIG_SND_MAESTRO3) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
obj-$(CONFIG_SND_RME32) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o obj-$(CONFIG_SND_RME32) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
......
...@@ -396,10 +396,6 @@ static snd_kcontrol_t *_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id) ...@@ -396,10 +396,6 @@ static snd_kcontrol_t *_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id)
continue; continue;
if (kctl->id.index + kctl->count <= id->index) if (kctl->id.index + kctl->count <= id->index)
continue; continue;
if (kctl->id.index != id->index) {
printk("BOOOR: %i, %i, %i\n", kctl->id.index, kctl->count, id->index);
continue;
}
return kctl; return kctl;
} }
return NULL; return NULL;
......
...@@ -252,6 +252,10 @@ int snd_card_free(snd_card_t * card) ...@@ -252,6 +252,10 @@ int snd_card_free(snd_card_t * card)
snd_cards_count--; snd_cards_count--;
write_unlock(&snd_card_rwlock); write_unlock(&snd_card_rwlock);
#ifdef CONFIG_PM
wake_up(&card->power_sleep);
#endif
/* wait, until all devices are ready for the free operation */ /* wait, until all devices are ready for the free operation */
wait_event(card->shutdown_sleep, card->files == NULL); wait_event(card->shutdown_sleep, card->files == NULL);
...@@ -662,21 +666,35 @@ int snd_card_file_remove(snd_card_t *card, struct file *file) ...@@ -662,21 +666,35 @@ int snd_card_file_remove(snd_card_t *card, struct file *file)
/** /**
* snd_power_wait - wait until the power-state is changed. * snd_power_wait - wait until the power-state is changed.
* @card: soundcard structure * @card: soundcard structure
* @power_state: expected power state
* @file: file structure for the O_NONBLOCK check (optional)
* *
* Waits until the power-state is changed. * Waits until the power-state is changed.
* *
* Note: the power lock must be active before call. * Note: the power lock must be active before call.
*/ */
void snd_power_wait(snd_card_t *card) int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file)
{ {
wait_queue_t wait; wait_queue_t wait;
/* fastpath */
if (snd_power_get_state(card) == power_state)
return 0;
init_waitqueue_entry(&wait, current); init_waitqueue_entry(&wait, current);
add_wait_queue(&card->power_sleep, &wait); add_wait_queue(&card->power_sleep, &wait);
while (1) {
if (card->shutdown)
return -ENODEV;
if (snd_power_get_state(card) == power_state) {
remove_wait_queue(&card->power_sleep, &wait);
return 0;
}
if (file && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
snd_power_unlock(card); snd_power_unlock(card);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(30 * HZ); schedule_timeout(30 * HZ);
remove_wait_queue(&card->power_sleep, &wait);
snd_power_lock(card); snd_power_lock(card);
}
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/compat.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include "ioctl32.h" #include "ioctl32.h"
...@@ -137,10 +136,15 @@ struct sndrv_pcm_channel_info32 { ...@@ -137,10 +136,15 @@ struct sndrv_pcm_channel_info32 {
COPY(step);\ COPY(step);\
} }
struct timeval32 {
s32 tv_sec;
s32 tv_usec;
} __attribute__((packed));
struct sndrv_pcm_status32 { struct sndrv_pcm_status32 {
s32 state; s32 state;
struct compat_timespec trigger_tstamp; struct timeval32 trigger_tstamp;
struct compat_timespec tstamp; struct timeval32 tstamp;
u32 appl_ptr; u32 appl_ptr;
u32 hw_ptr; u32 hw_ptr;
s32 delay; s32 delay;
...@@ -155,9 +159,9 @@ struct sndrv_pcm_status32 { ...@@ -155,9 +159,9 @@ struct sndrv_pcm_status32 {
{\ {\
COPY(state);\ COPY(state);\
COPY(trigger_tstamp.tv_sec);\ COPY(trigger_tstamp.tv_sec);\
COPY(trigger_tstamp.tv_nsec);\ COPY(trigger_tstamp.tv_usec);\
COPY(tstamp.tv_sec);\ COPY(tstamp.tv_sec);\
COPY(tstamp.tv_nsec);\ COPY(tstamp.tv_usec);\
COPY(appl_ptr);\ COPY(appl_ptr);\
COPY(hw_ptr);\ COPY(hw_ptr);\
COPY(delay);\ COPY(delay);\
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/compat.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/rawmidi.h> #include <sound/rawmidi.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -43,9 +42,14 @@ struct sndrv_rawmidi_params32 { ...@@ -43,9 +42,14 @@ struct sndrv_rawmidi_params32 {
COPY(no_active_sensing);\ COPY(no_active_sensing);\
} }
struct timeval32 {
s32 tv_sec;
s32 tv_usec;
} __attribute__((packed));
struct sndrv_rawmidi_status32 { struct sndrv_rawmidi_status32 {
s32 stream; s32 stream;
struct compat_timespec tstamp; struct timeval32 tstamp;
u32 avail; u32 avail;
u32 xruns; u32 xruns;
unsigned char reserved[16]; unsigned char reserved[16];
...@@ -55,7 +59,7 @@ struct sndrv_rawmidi_status32 { ...@@ -55,7 +59,7 @@ struct sndrv_rawmidi_status32 {
{\ {\
COPY(stream);\ COPY(stream);\
COPY(tstamp.tv_sec);\ COPY(tstamp.tv_sec);\
COPY(tstamp.tv_nsec);\ COPY(tstamp.tv_usec);\
COPY(avail);\ COPY(avail);\
COPY(xruns);\ COPY(xruns);\
} }
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/compat.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/timer.h> #include <sound/timer.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -32,7 +31,7 @@ struct sndrv_timer_info32 { ...@@ -32,7 +31,7 @@ struct sndrv_timer_info32 {
s32 card; s32 card;
unsigned char id[64]; unsigned char id[64];
unsigned char name[80]; unsigned char name[80];
u32 reserved0; u32 ticks;
u32 resolution; u32 resolution;
unsigned char reserved[64]; unsigned char reserved[64];
}; };
...@@ -43,11 +42,17 @@ struct sndrv_timer_info32 { ...@@ -43,11 +42,17 @@ struct sndrv_timer_info32 {
COPY(card);\ COPY(card);\
memcpy(dst->id, src->id, sizeof(src->id));\ memcpy(dst->id, src->id, sizeof(src->id));\
memcpy(dst->name, src->name, sizeof(src->name));\ memcpy(dst->name, src->name, sizeof(src->name));\
COPY(ticks);\
COPY(resolution);\ COPY(resolution);\
} }
struct timeval32 {
s32 tv_sec;
s32 tv_usec;
};
struct sndrv_timer_status32 { struct sndrv_timer_status32 {
struct compat_timespec tstamp; struct timeval32 tstamp;
u32 resolution; u32 resolution;
u32 lost; u32 lost;
u32 overrun; u32 overrun;
...@@ -58,7 +63,7 @@ struct sndrv_timer_status32 { ...@@ -58,7 +63,7 @@ struct sndrv_timer_status32 {
#define CVT_sndrv_timer_status()\ #define CVT_sndrv_timer_status()\
{\ {\
COPY(tstamp.tv_sec);\ COPY(tstamp.tv_sec);\
COPY(tstamp.tv_nsec);\ COPY(tstamp.tv_usec);\
COPY(resolution);\ COPY(resolution);\
COPY(lost);\ COPY(lost);\
COPY(overrun);\ COPY(overrun);\
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mm.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <sound/memalloc.h> #include <sound/memalloc.h>
...@@ -97,7 +98,7 @@ struct snd_mem_list { ...@@ -97,7 +98,7 @@ struct snd_mem_list {
* again. * again.
*/ */
void *snd_pci_hack_alloc_consistent(struct pci_dev *hwdev, size_t size, static void *snd_pci_hack_alloc_consistent(struct pci_dev *hwdev, size_t size,
dma_addr_t *dma_handle) dma_addr_t *dma_handle)
{ {
void *ret; void *ret;
......
...@@ -1477,10 +1477,10 @@ static int snd_pcm_oss_release_file(snd_pcm_oss_file_t *pcm_oss_file) ...@@ -1477,10 +1477,10 @@ static int snd_pcm_oss_release_file(snd_pcm_oss_file_t *pcm_oss_file)
continue; continue;
runtime = substream->runtime; runtime = substream->runtime;
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irq(substream);
if (snd_pcm_running(substream)) if (snd_pcm_running(substream))
snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irq(substream);
if (substream->open_flag) { if (substream->open_flag) {
if (substream->ops->hw_free != NULL) if (substream->ops->hw_free != NULL)
substream->ops->hw_free(substream); substream->ops->hw_free(substream);
...@@ -1918,21 +1918,21 @@ static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait) ...@@ -1918,21 +1918,21 @@ static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
if (psubstream != NULL) { if (psubstream != NULL) {
snd_pcm_runtime_t *runtime = psubstream->runtime; snd_pcm_runtime_t *runtime = psubstream->runtime;
poll_wait(file, &runtime->sleep, wait); poll_wait(file, &runtime->sleep, wait);
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irq(psubstream);
if (runtime->status->state != SNDRV_PCM_STATE_DRAINING && if (runtime->status->state != SNDRV_PCM_STATE_DRAINING &&
(runtime->status->state != SNDRV_PCM_STATE_RUNNING || (runtime->status->state != SNDRV_PCM_STATE_RUNNING ||
snd_pcm_oss_playback_ready(psubstream))) snd_pcm_oss_playback_ready(psubstream)))
mask |= POLLOUT | POLLWRNORM; mask |= POLLOUT | POLLWRNORM;
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irq(psubstream);
} }
if (csubstream != NULL) { if (csubstream != NULL) {
snd_pcm_runtime_t *runtime = csubstream->runtime; snd_pcm_runtime_t *runtime = csubstream->runtime;
poll_wait(file, &runtime->sleep, wait); poll_wait(file, &runtime->sleep, wait);
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irq(csubstream);
if (runtime->status->state != SNDRV_PCM_STATE_RUNNING || if (runtime->status->state != SNDRV_PCM_STATE_RUNNING ||
snd_pcm_oss_capture_ready(csubstream)) snd_pcm_oss_capture_ready(csubstream))
mask |= POLLIN | POLLRDNORM; mask |= POLLIN | POLLRDNORM;
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irq(csubstream);
} }
return mask; return mask;
......
...@@ -317,10 +317,10 @@ static void snd_pcm_substream_proc_hw_params_read(snd_info_entry_t *entry, snd_i ...@@ -317,10 +317,10 @@ static void snd_pcm_substream_proc_hw_params_read(snd_info_entry_t *entry, snd_i
snd_iprintf(buffer, "closed\n"); snd_iprintf(buffer, "closed\n");
return; return;
} }
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irq(substream);
if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
snd_iprintf(buffer, "no setup\n"); snd_iprintf(buffer, "no setup\n");
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irq(substream);
return; return;
} }
snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access)); snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access));
...@@ -340,7 +340,7 @@ static void snd_pcm_substream_proc_hw_params_read(snd_info_entry_t *entry, snd_i ...@@ -340,7 +340,7 @@ static void snd_pcm_substream_proc_hw_params_read(snd_info_entry_t *entry, snd_i
snd_iprintf(buffer, "OSS periods: %u\n", runtime->oss.periods); snd_iprintf(buffer, "OSS periods: %u\n", runtime->oss.periods);
} }
#endif #endif
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irq(substream);
} }
static void snd_pcm_substream_proc_sw_params_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) static void snd_pcm_substream_proc_sw_params_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
...@@ -351,10 +351,10 @@ static void snd_pcm_substream_proc_sw_params_read(snd_info_entry_t *entry, snd_i ...@@ -351,10 +351,10 @@ static void snd_pcm_substream_proc_sw_params_read(snd_info_entry_t *entry, snd_i
snd_iprintf(buffer, "closed\n"); snd_iprintf(buffer, "closed\n");
return; return;
} }
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irq(substream);
if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
snd_iprintf(buffer, "no setup\n"); snd_iprintf(buffer, "no setup\n");
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irq(substream);
return; return;
} }
snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode)); snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode));
...@@ -367,7 +367,7 @@ static void snd_pcm_substream_proc_sw_params_read(snd_info_entry_t *entry, snd_i ...@@ -367,7 +367,7 @@ static void snd_pcm_substream_proc_sw_params_read(snd_info_entry_t *entry, snd_i
snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold); snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold);
snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size); snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size);
snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary); snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary);
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irq(substream);
} }
static void snd_pcm_substream_proc_status_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) static void snd_pcm_substream_proc_status_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
...@@ -588,13 +588,15 @@ int snd_pcm_new_stream(snd_pcm_t *pcm, int stream, int substream_count) ...@@ -588,13 +588,15 @@ int snd_pcm_new_stream(snd_pcm_t *pcm, int stream, int substream_count)
pstr->substream = substream; pstr->substream = substream;
else else
prev->next = substream; prev->next = substream;
substream->link_next = substream;
substream->link_prev = substream;
err = snd_pcm_substream_proc_init(substream); err = snd_pcm_substream_proc_init(substream);
if (err < 0) { if (err < 0) {
snd_magic_kfree(substream); snd_magic_kfree(substream);
return err; return err;
} }
substream->group = &substream->self_group;
spin_lock_init(&substream->self_group.lock);
INIT_LIST_HEAD(&substream->self_group.substreams);
list_add_tail(&substream->link_list, &substream->self_group.substreams);
spin_lock_init(&substream->timer_lock); spin_lock_init(&substream->timer_lock);
prev = substream; prev = substream;
} }
...@@ -793,7 +795,6 @@ int snd_pcm_open_substream(snd_pcm_t *pcm, int stream, ...@@ -793,7 +795,6 @@ int snd_pcm_open_substream(snd_pcm_t *pcm, int stream,
memset((void*)runtime->control, 0, size); memset((void*)runtime->control, 0, size);
init_waitqueue_head(&runtime->sleep); init_waitqueue_head(&runtime->sleep);
spin_lock_init(&runtime->lock);
atomic_set(&runtime->mmap_count, 0); atomic_set(&runtime->mmap_count, 0);
init_timer(&runtime->tick_timer); init_timer(&runtime->tick_timer);
runtime->tick_timer.function = snd_pcm_tick_timer_func; runtime->tick_timer.function = snd_pcm_tick_timer_func;
...@@ -1022,6 +1023,7 @@ EXPORT_SYMBOL(snd_pcm_release_substream); ...@@ -1022,6 +1023,7 @@ EXPORT_SYMBOL(snd_pcm_release_substream);
EXPORT_SYMBOL(snd_pcm_format_name); EXPORT_SYMBOL(snd_pcm_format_name);
EXPORT_SYMBOL(snd_pcm_subformat_name); EXPORT_SYMBOL(snd_pcm_subformat_name);
/* pcm_native.c */ /* pcm_native.c */
EXPORT_SYMBOL(snd_pcm_link_rwlock);
EXPORT_SYMBOL(snd_pcm_start); EXPORT_SYMBOL(snd_pcm_start);
#ifdef CONFIG_PM #ifdef CONFIG_PM
EXPORT_SYMBOL(snd_pcm_suspend); EXPORT_SYMBOL(snd_pcm_suspend);
......
...@@ -126,7 +126,7 @@ void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t ...@@ -126,7 +126,7 @@ void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t
} }
} }
int snd_pcm_update_hw_ptr_interrupt(snd_pcm_substream_t *substream) static inline int snd_pcm_update_hw_ptr_interrupt(snd_pcm_substream_t *substream)
{ {
snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_uframes_t pos; snd_pcm_uframes_t pos;
...@@ -1976,18 +1976,20 @@ void snd_pcm_tick_prepare(snd_pcm_substream_t *substream) ...@@ -1976,18 +1976,20 @@ void snd_pcm_tick_prepare(snd_pcm_substream_t *substream)
void snd_pcm_tick_elapsed(snd_pcm_substream_t *substream) void snd_pcm_tick_elapsed(snd_pcm_substream_t *substream)
{ {
snd_pcm_runtime_t *runtime; snd_pcm_runtime_t *runtime;
unsigned long flags;
snd_assert(substream != NULL, return); snd_assert(substream != NULL, return);
runtime = substream->runtime; runtime = substream->runtime;
snd_assert(runtime != NULL, return); snd_assert(runtime != NULL, return);
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irqsave(substream, flags);
if (!snd_pcm_running(substream) || if (!snd_pcm_running(substream) ||
snd_pcm_update_hw_ptr(substream) < 0) snd_pcm_update_hw_ptr(substream) < 0)
goto _end; goto _end;
if (runtime->sleep_min) if (runtime->sleep_min)
snd_pcm_tick_prepare(substream); snd_pcm_tick_prepare(substream);
_end: _end:
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irqrestore(substream, flags);
} }
/** /**
...@@ -2004,6 +2006,8 @@ void snd_pcm_tick_elapsed(snd_pcm_substream_t *substream) ...@@ -2004,6 +2006,8 @@ void snd_pcm_tick_elapsed(snd_pcm_substream_t *substream)
void snd_pcm_period_elapsed(snd_pcm_substream_t *substream) void snd_pcm_period_elapsed(snd_pcm_substream_t *substream)
{ {
snd_pcm_runtime_t *runtime; snd_pcm_runtime_t *runtime;
unsigned long flags;
snd_assert(substream != NULL, return); snd_assert(substream != NULL, return);
runtime = substream->runtime; runtime = substream->runtime;
snd_assert(runtime != NULL, return); snd_assert(runtime != NULL, return);
...@@ -2011,7 +2015,7 @@ void snd_pcm_period_elapsed(snd_pcm_substream_t *substream) ...@@ -2011,7 +2015,7 @@ void snd_pcm_period_elapsed(snd_pcm_substream_t *substream)
if (runtime->transfer_ack_begin) if (runtime->transfer_ack_begin)
runtime->transfer_ack_begin(substream); runtime->transfer_ack_begin(substream);
spin_lock(&runtime->lock); snd_pcm_stream_lock_irqsave(substream, flags);
if (!snd_pcm_running(substream) || if (!snd_pcm_running(substream) ||
snd_pcm_update_hw_ptr_interrupt(substream) < 0) snd_pcm_update_hw_ptr_interrupt(substream) < 0)
goto _end; goto _end;
...@@ -2021,7 +2025,7 @@ void snd_pcm_period_elapsed(snd_pcm_substream_t *substream) ...@@ -2021,7 +2025,7 @@ void snd_pcm_period_elapsed(snd_pcm_substream_t *substream)
if (runtime->sleep_min) if (runtime->sleep_min)
snd_pcm_tick_prepare(substream); snd_pcm_tick_prepare(substream);
_end: _end:
spin_unlock(&runtime->lock); snd_pcm_stream_unlock_irqrestore(substream, flags);
if (runtime->transfer_ack_end) if (runtime->transfer_ack_end)
runtime->transfer_ack_end(substream); runtime->transfer_ack_end(substream);
kill_fasync(&runtime->fasync, SIGIO, POLL_IN); kill_fasync(&runtime->fasync, SIGIO, POLL_IN);
...@@ -2065,7 +2069,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream, ...@@ -2065,7 +2069,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
if (size > runtime->xfer_align) if (size > runtime->xfer_align)
size -= size % runtime->xfer_align; size -= size % runtime->xfer_align;
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) { switch (runtime->status->state) {
case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_RUNNING: case SNDRV_PCM_STATE_RUNNING:
...@@ -2107,16 +2111,16 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream, ...@@ -2107,16 +2111,16 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
state = SIGNALED; state = SIGNALED;
break; break;
} }
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irq(substream);
if (schedule_timeout(10 * HZ) == 0) { if (schedule_timeout(10 * HZ) == 0) {
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irq(substream);
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED && if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
runtime->status->state != SNDRV_PCM_STATE_PAUSED) { runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED; state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
break; break;
} }
} }
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) { switch (runtime->status->state) {
case SNDRV_PCM_STATE_XRUN: case SNDRV_PCM_STATE_XRUN:
case SNDRV_PCM_STATE_DRAINING: case SNDRV_PCM_STATE_DRAINING:
...@@ -2162,15 +2166,13 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream, ...@@ -2162,15 +2166,13 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
if (frames > cont) if (frames > cont)
frames = cont; frames = cont;
snd_assert(frames != 0, snd_assert(frames != 0, snd_pcm_stream_unlock_irq(substream); return -EINVAL);
spin_unlock_irq(&runtime->lock);
return -EINVAL);
appl_ptr = runtime->control->appl_ptr; appl_ptr = runtime->control->appl_ptr;
appl_ofs = appl_ptr % runtime->buffer_size; appl_ofs = appl_ptr % runtime->buffer_size;
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irq(substream);
if ((err = transfer(substream, appl_ofs, (void *)data, offset, frames)) < 0) if ((err = transfer(substream, appl_ofs, (void *)data, offset, frames)) < 0)
goto _end; goto _end;
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) { switch (runtime->status->state) {
case SNDRV_PCM_STATE_XRUN: case SNDRV_PCM_STATE_XRUN:
err = -EPIPE; err = -EPIPE;
...@@ -2204,7 +2206,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream, ...@@ -2204,7 +2206,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
snd_pcm_tick_prepare(substream); snd_pcm_tick_prepare(substream);
} }
_end_unlock: _end_unlock:
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irq(substream);
_end: _end:
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
} }
...@@ -2348,7 +2350,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void ...@@ -2348,7 +2350,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void
if (size > runtime->xfer_align) if (size > runtime->xfer_align)
size -= size % runtime->xfer_align; size -= size % runtime->xfer_align;
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) { switch (runtime->status->state) {
case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_PREPARED:
if (size >= runtime->start_threshold) { if (size >= runtime->start_threshold) {
...@@ -2403,16 +2405,16 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void ...@@ -2403,16 +2405,16 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void
state = SIGNALED; state = SIGNALED;
break; break;
} }
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irq(substream);
if (schedule_timeout(10 * HZ) == 0) { if (schedule_timeout(10 * HZ) == 0) {
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irq(substream);
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED && if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
runtime->status->state != SNDRV_PCM_STATE_PAUSED) { runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED; state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
break; break;
} }
} }
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) { switch (runtime->status->state) {
case SNDRV_PCM_STATE_XRUN: case SNDRV_PCM_STATE_XRUN:
state = ERROR; state = ERROR;
...@@ -2459,15 +2461,13 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void ...@@ -2459,15 +2461,13 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void
cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
if (frames > cont) if (frames > cont)
frames = cont; frames = cont;
snd_assert(frames != 0, snd_assert(frames != 0, snd_pcm_stream_unlock_irq(substream); return -EINVAL);
spin_unlock_irq(&runtime->lock);
return -EINVAL);
appl_ptr = runtime->control->appl_ptr; appl_ptr = runtime->control->appl_ptr;
appl_ofs = appl_ptr % runtime->buffer_size; appl_ofs = appl_ptr % runtime->buffer_size;
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irq(substream);
if ((err = transfer(substream, appl_ofs, (void *)data, offset, frames)) < 0) if ((err = transfer(substream, appl_ofs, (void *)data, offset, frames)) < 0)
goto _end; goto _end;
spin_lock_irq(&runtime->lock); snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) { switch (runtime->status->state) {
case SNDRV_PCM_STATE_XRUN: case SNDRV_PCM_STATE_XRUN:
err = -EPIPE; err = -EPIPE;
...@@ -2495,7 +2495,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void ...@@ -2495,7 +2495,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void
snd_pcm_tick_prepare(substream); snd_pcm_tick_prepare(substream);
} }
_end_unlock: _end_unlock:
spin_unlock_irq(&runtime->lock); snd_pcm_stream_unlock_irq(substream);
_end: _end:
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
} }
......
This diff is collapsed.
...@@ -74,6 +74,7 @@ obj-$(call sequencer,$(CONFIG_SND_ES1938)) += $(RAWMIDI_OBJS) $(OPL3_OBJS) ...@@ -74,6 +74,7 @@ obj-$(call sequencer,$(CONFIG_SND_ES1938)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
obj-$(call sequencer,$(CONFIG_SND_ES1968)) += $(RAWMIDI_OBJS) obj-$(call sequencer,$(CONFIG_SND_ES1968)) += $(RAWMIDI_OBJS)
obj-$(call sequencer,$(CONFIG_SND_FM801)) += $(RAWMIDI_OBJS) $(OPL3_OBJS) obj-$(call sequencer,$(CONFIG_SND_FM801)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
obj-$(call sequencer,$(CONFIG_SND_ICE1712)) += $(RAWMIDI_OBJS) obj-$(call sequencer,$(CONFIG_SND_ICE1712)) += $(RAWMIDI_OBJS)
obj-$(call sequencer,$(CONFIG_SND_ICE1724)) += $(RAWMIDI_OBJS)
obj-$(call sequencer,$(CONFIG_SND_INTEL8X0)) += $(RAWMIDI_OBJS) obj-$(call sequencer,$(CONFIG_SND_INTEL8X0)) += $(RAWMIDI_OBJS)
obj-$(call sequencer,$(CONFIG_SND_SONICVIBES)) += $(RAWMIDI_OBJS) $(OPL3_OBJS) obj-$(call sequencer,$(CONFIG_SND_SONICVIBES)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
obj-$(call sequencer,$(CONFIG_SND_VIA82XX)) += $(RAWMIDI_OBJS) obj-$(call sequencer,$(CONFIG_SND_VIA82XX)) += $(RAWMIDI_OBJS)
......
...@@ -20,9 +20,9 @@ ...@@ -20,9 +20,9 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/version.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mm.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <sound/memalloc.h> #include <sound/memalloc.h>
......
...@@ -335,6 +335,7 @@ static int __init alsa_sound_init(void) ...@@ -335,6 +335,7 @@ static int __init alsa_sound_init(void)
devfs_mk_dir("snd"); devfs_mk_dir("snd");
if (register_chrdev(major, "alsa", &snd_fops)) { if (register_chrdev(major, "alsa", &snd_fops)) {
snd_printk(KERN_ERR "unable to register native major device number %d\n", major); snd_printk(KERN_ERR "unable to register native major device number %d\n", major);
devfs_remove("snd");
return -EIO; return -EIO;
} }
#ifdef CONFIG_SND_DEBUG_MEMORY #ifdef CONFIG_SND_DEBUG_MEMORY
...@@ -344,6 +345,8 @@ static int __init alsa_sound_init(void) ...@@ -344,6 +345,8 @@ static int __init alsa_sound_init(void)
#ifdef CONFIG_SND_DEBUG_MEMORY #ifdef CONFIG_SND_DEBUG_MEMORY
snd_memory_done(); snd_memory_done();
#endif #endif
unregister_chrdev(major, "alsa");
devfs_remove("snd");
return -ENOMEM; return -ENOMEM;
} }
#ifdef CONFIG_SND_OSSEMUL #ifdef CONFIG_SND_OSSEMUL
......
...@@ -31,6 +31,7 @@ obj-$(CONFIG_SND_ES1938) += snd-mpu401-uart.o ...@@ -31,6 +31,7 @@ obj-$(CONFIG_SND_ES1938) += snd-mpu401-uart.o
obj-$(CONFIG_SND_ES1968) += snd-mpu401-uart.o obj-$(CONFIG_SND_ES1968) += snd-mpu401-uart.o
obj-$(CONFIG_SND_FM801) += snd-mpu401-uart.o obj-$(CONFIG_SND_FM801) += snd-mpu401-uart.o
obj-$(CONFIG_SND_ICE1712) += snd-mpu401-uart.o obj-$(CONFIG_SND_ICE1712) += snd-mpu401-uart.o
obj-$(CONFIG_SND_ICE1724) += snd-mpu401-uart.o
obj-$(CONFIG_SND_INTEL8X0) += snd-mpu401-uart.o obj-$(CONFIG_SND_INTEL8X0) += snd-mpu401-uart.o
obj-$(CONFIG_SND_SONICVIBES) += snd-mpu401-uart.o obj-$(CONFIG_SND_SONICVIBES) += snd-mpu401-uart.o
obj-$(CONFIG_SND_VIA82XX) += snd-mpu401-uart.o obj-$(CONFIG_SND_VIA82XX) += snd-mpu401-uart.o
......
...@@ -90,27 +90,27 @@ static void snd_mpu401_uart_clear_rx(mpu401_t *mpu) ...@@ -90,27 +90,27 @@ static void snd_mpu401_uart_clear_rx(mpu401_t *mpu)
#endif #endif
} }
static irqreturn_t _snd_mpu401_uart_interrupt(mpu401_t *mpu) static void _snd_mpu401_uart_interrupt(mpu401_t *mpu)
{ {
if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
if (! test_and_set_bit(MPU401_MODE_BIT_RX_LOOP, &mpu->mode)) {
spin_lock(&mpu->input_lock); spin_lock(&mpu->input_lock);
if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
atomic_dec(&mpu->rx_loop);
snd_mpu401_uart_input_read(mpu); snd_mpu401_uart_input_read(mpu);
spin_unlock(&mpu->input_lock); atomic_inc(&mpu->rx_loop);
clear_bit(MPU401_MODE_BIT_RX_LOOP, &mpu->mode); } else {
}
} else
snd_mpu401_uart_clear_rx(mpu); snd_mpu401_uart_clear_rx(mpu);
}
spin_unlock(&mpu->input_lock);
/* ok. for better Tx performance try do some output when input is done */ /* ok. for better Tx performance try do some output when input is done */
if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
spin_lock(&mpu->output_lock); if (spin_trylock(&mpu->output_lock)) {
atomic_dec(&mpu->tx_loop);
snd_mpu401_uart_output_write(mpu); snd_mpu401_uart_output_write(mpu);
atomic_inc(&mpu->tx_loop);
spin_unlock(&mpu->output_lock); spin_unlock(&mpu->output_lock);
} }
}
/* FIXME! This should really check whether the irq was for us */
return IRQ_HANDLED;
} }
/** /**
...@@ -127,7 +127,8 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *reg ...@@ -127,7 +127,8 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *reg
if (mpu == NULL) if (mpu == NULL)
return IRQ_NONE; return IRQ_NONE;
return _snd_mpu401_uart_interrupt(mpu); _snd_mpu401_uart_interrupt(mpu);
return IRQ_HANDLED;
} }
/* /*
...@@ -242,6 +243,7 @@ static int snd_mpu401_uart_input_open(snd_rawmidi_substream_t * substream) ...@@ -242,6 +243,7 @@ static int snd_mpu401_uart_input_open(snd_rawmidi_substream_t * substream)
snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1); snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
} }
mpu->substream_input = substream; mpu->substream_input = substream;
atomic_set(&mpu->rx_loop, 1);
set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
return 0; return 0;
} }
...@@ -259,6 +261,7 @@ static int snd_mpu401_uart_output_open(snd_rawmidi_substream_t * substream) ...@@ -259,6 +261,7 @@ static int snd_mpu401_uart_output_open(snd_rawmidi_substream_t * substream)
snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1); snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
} }
mpu->substream_output = substream; mpu->substream_output = substream;
atomic_set(&mpu->tx_loop, 1);
set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode); set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
return 0; return 0;
} }
...@@ -312,12 +315,15 @@ static void snd_mpu401_uart_input_trigger(snd_rawmidi_substream_t * substream, i ...@@ -312,12 +315,15 @@ static void snd_mpu401_uart_input_trigger(snd_rawmidi_substream_t * substream, i
/* read data in advance */ /* read data in advance */
/* prevent double enter via rawmidi->event callback */ /* prevent double enter via rawmidi->event callback */
if (! test_and_set_bit(MPU401_MODE_BIT_RX_LOOP, &mpu->mode)) { if (atomic_dec_and_test(&mpu->rx_loop)) {
spin_lock_irqsave(&mpu->input_lock, flags); local_irq_save(flags);
if (spin_trylock(&mpu->input_lock)) {
snd_mpu401_uart_input_read(mpu); snd_mpu401_uart_input_read(mpu);
spin_unlock_irqrestore(&mpu->input_lock, flags); spin_unlock(&mpu->input_lock);
clear_bit(MPU401_MODE_BIT_RX_LOOP, &mpu->mode);
} }
local_irq_restore(flags);
}
atomic_inc(&mpu->rx_loop);
} else { } else {
if (mpu->irq < 0) if (mpu->irq < 0)
snd_mpu401_uart_remove_timer(mpu, 1); snd_mpu401_uart_remove_timer(mpu, 1);
...@@ -371,9 +377,11 @@ static void snd_mpu401_uart_output_write(mpu401_t * mpu) ...@@ -371,9 +377,11 @@ static void snd_mpu401_uart_output_write(mpu401_t * mpu)
break; break;
} }
} }
if (timeout == 0)
break; /* Tx FIFO full - try again later */
} else { } else {
snd_mpu401_uart_remove_timer (mpu, 0); snd_mpu401_uart_remove_timer (mpu, 0);
max = 1; /* no other data - leave the tx loop */ break; /* no other data - leave the tx loop */
} }
} while (--max > 0); } while (--max > 0);
} }
...@@ -389,6 +397,7 @@ static void snd_mpu401_uart_output_trigger(snd_rawmidi_substream_t * substream, ...@@ -389,6 +397,7 @@ static void snd_mpu401_uart_output_trigger(snd_rawmidi_substream_t * substream,
mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return); mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return);
if (up) { if (up) {
set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
/* try to add the timer at each output trigger, /* try to add the timer at each output trigger,
* since the output timer might have been removed in * since the output timer might have been removed in
* snd_mpu401_uart_output_write(). * snd_mpu401_uart_output_write().
...@@ -397,12 +406,15 @@ static void snd_mpu401_uart_output_trigger(snd_rawmidi_substream_t * substream, ...@@ -397,12 +406,15 @@ static void snd_mpu401_uart_output_trigger(snd_rawmidi_substream_t * substream,
/* output pending data */ /* output pending data */
/* prevent double enter via rawmidi->event callback */ /* prevent double enter via rawmidi->event callback */
if (! test_and_set_bit(MPU401_MODE_BIT_TX_LOOP, &mpu->mode)) { if (atomic_dec_and_test(&mpu->tx_loop)) {
spin_lock_irqsave(&mpu->output_lock, flags); local_irq_save(flags);
if (spin_trylock(&mpu->output_lock)) {
snd_mpu401_uart_output_write(mpu); snd_mpu401_uart_output_write(mpu);
spin_unlock_irqrestore(&mpu->output_lock, flags); spin_unlock(&mpu->output_lock);
clear_bit(MPU401_MODE_BIT_TX_LOOP, &mpu->mode); }
local_irq_restore(flags);
} }
atomic_inc(&mpu->tx_loop);
} else { } else {
snd_mpu401_uart_remove_timer(mpu, 0); snd_mpu401_uart_remove_timer(mpu, 0);
clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
......
...@@ -160,18 +160,12 @@ static int snd_opl3_detect(opl3_t * opl3) ...@@ -160,18 +160,12 @@ static int snd_opl3_detect(opl3_t * opl3)
opl3->hardware = OPL3_HW_OPL2; opl3->hardware = OPL3_HW_OPL2;
} else { } else {
/* /*
* Detect availability of OPL4. Unfortunately, the OPL4 * If we had an OPL4 chip, opl3->hardware would have been set
* port of the chip may not be connected to the PC bus. * by the OPL4 driver; so we can assume OPL3 here.
*/ */
snd_assert(opl3->r_port != 0, return -ENODEV); snd_assert(opl3->r_port != 0, return -ENODEV);
opl3->command(opl3, OPL3_RIGHT | OPL3_REG_MODE, OPL3_OPL3_ENABLE | OPL3_OPL4_ENABLE);
/* All OPL4 registers are readable. */
if (inb(opl3->r_port + 1) == (OPL3_OPL3_ENABLE | OPL3_OPL4_ENABLE)) {
opl3->hardware = OPL3_HW_OPL4;
} else {
opl3->hardware = OPL3_HW_OPL3; opl3->hardware = OPL3_HW_OPL3;
} }
}
return 0; return 0;
} }
......
...@@ -11,6 +11,8 @@ ifeq ($(subst m,y,$(CONFIG_L3)),y) ...@@ -11,6 +11,8 @@ ifeq ($(subst m,y,$(CONFIG_L3)),y)
obj-$(CONFIG_L3) += l3/ obj-$(CONFIG_L3) += l3/
endif endif
obj-$(CONFIG_SND) += other/
# Toplevel Module Dependency # Toplevel Module Dependency
obj-$(CONFIG_SND_INTERWAVE_STB) += snd-tea6330t.o snd-i2c.o obj-$(CONFIG_SND_INTERWAVE_STB) += snd-tea6330t.o snd-i2c.o
obj-$(CONFIG_SND_ICE1712) += snd-cs8427.o snd-i2c.o obj-$(CONFIG_SND_ICE1712) += snd-cs8427.o snd-i2c.o
This diff is collapsed.
This diff is collapsed.
#
# Makefile for ALSA
# Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
#
snd-ak4xxx-adda-objs := ak4xxx-adda.o
# Module Dependency
obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o
obj-$(CONFIG_SND_ICE1724) += snd-ak4xxx-adda.o
This diff is collapsed.
...@@ -41,7 +41,7 @@ config SND_CS4236 ...@@ -41,7 +41,7 @@ config SND_CS4236
config SND_PC98_CS4232 config SND_PC98_CS4232
tristate "NEC PC9800 CS4232 driver" tristate "NEC PC9800 CS4232 driver"
depends on SND && PC9800 depends on SND && X86_PC9800
help help
Say 'Y' or 'M' to include support for NEC PC-9801/PC-9821 on-board Say 'Y' or 'M' to include support for NEC PC-9801/PC-9821 on-board
soundchip based on CS4232. soundchip based on CS4232.
......
...@@ -307,8 +307,10 @@ static int __init alsa_card_ad1816a_init(void) ...@@ -307,8 +307,10 @@ static int __init alsa_card_ad1816a_init(void)
cards += pnp_register_card_driver(&ad1816a_pnpc_driver); cards += pnp_register_card_driver(&ad1816a_pnpc_driver);
#ifdef MODULE #ifdef MODULE
if (!cards) if (!cards) {
pnp_unregister_card_driver(&ad1816a_pnpc_driver);
printk(KERN_ERR "no AD1816A based soundcards found.\n"); printk(KERN_ERR "no AD1816A based soundcards found.\n");
}
#endif /* MODULE */ #endif /* MODULE */
return cards ? 0 : -ENODEV; return cards ? 0 : -ENODEV;
} }
......
...@@ -328,8 +328,10 @@ static int __init alsa_card_als100_init(void) ...@@ -328,8 +328,10 @@ static int __init alsa_card_als100_init(void)
cards += pnp_register_card_driver(&als100_pnpc_driver); cards += pnp_register_card_driver(&als100_pnpc_driver);
#ifdef MODULE #ifdef MODULE
if (!cards) if (!cards) {
pnp_unregister_card_driver(&als100_pnpc_driver);
snd_printk(KERN_ERR "no ALS100 based soundcards found\n"); snd_printk(KERN_ERR "no ALS100 based soundcards found\n");
}
#endif #endif
return cards ? 0 : -ENODEV; return cards ? 0 : -ENODEV;
} }
......
...@@ -365,8 +365,10 @@ static int __init alsa_card_azt2320_init(void) ...@@ -365,8 +365,10 @@ static int __init alsa_card_azt2320_init(void)
cards += pnp_register_card_driver(&azt2320_pnpc_driver); cards += pnp_register_card_driver(&azt2320_pnpc_driver);
#ifdef MODULE #ifdef MODULE
if (!cards) if (!cards) {
pnp_unregister_card_driver(&azt2320_pnpc_driver);
snd_printk(KERN_ERR "no AZT2320 based soundcards found\n"); snd_printk(KERN_ERR "no AZT2320 based soundcards found\n");
}
#endif #endif
return cards ? 0 : -ENODEV; return cards ? 0 : -ENODEV;
} }
......
...@@ -613,6 +613,9 @@ static int __init alsa_card_cmi8330_init(void) ...@@ -613,6 +613,9 @@ static int __init alsa_card_cmi8330_init(void)
#endif #endif
if (!cards) { if (!cards) {
#ifdef CONFIG_PNP
pnp_unregister_card_driver(&cmi8330_pnpc_driver);
#endif
#ifdef MODULE #ifdef MODULE
snd_printk(KERN_ERR "CMI8330 not found or device busy\n"); snd_printk(KERN_ERR "CMI8330 not found or device busy\n");
#endif #endif
......
...@@ -448,6 +448,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, ...@@ -448,6 +448,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream,
cs4231_t *chip = snd_pcm_substream_chip(substream); cs4231_t *chip = snd_pcm_substream_chip(substream);
int result = 0; int result = 0;
unsigned int what; unsigned int what;
struct list_head *pos;
snd_pcm_substream_t *s; snd_pcm_substream_t *s;
int do_start; int do_start;
...@@ -467,8 +468,8 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, ...@@ -467,8 +468,8 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream,
} }
what = 0; what = 0;
s = substream; snd_pcm_group_for_each(pos, substream) {
do { s = snd_pcm_group_substream_entry(pos);
if (s == chip->playback_substream) { if (s == chip->playback_substream) {
what |= CS4231_PLAYBACK_ENABLE; what |= CS4231_PLAYBACK_ENABLE;
snd_pcm_trigger_done(s, substream); snd_pcm_trigger_done(s, substream);
...@@ -476,8 +477,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, ...@@ -476,8 +477,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream,
what |= CS4231_RECORD_ENABLE; what |= CS4231_RECORD_ENABLE;
snd_pcm_trigger_done(s, substream); snd_pcm_trigger_done(s, substream);
} }
s = s->link_next; }
} while (s != substream);
spin_lock(&chip->reg_lock); spin_lock(&chip->reg_lock);
if (do_start) { if (do_start) {
chip->image[CS4231_IFACE_CTRL] |= what; chip->image[CS4231_IFACE_CTRL] |= what;
......
...@@ -590,6 +590,9 @@ static int __init alsa_card_cs423x_init(void) ...@@ -590,6 +590,9 @@ static int __init alsa_card_cs423x_init(void)
cards += pnp_register_card_driver(&cs423x_pnpc_driver); cards += pnp_register_card_driver(&cs423x_pnpc_driver);
#endif #endif
if (!cards) { if (!cards) {
#ifdef CONFIG_PNP
pnp_unregister_card_driver(&cs423x_pnpc_driver);
#endif
#ifdef MODULE #ifdef MODULE
printk(KERN_ERR IDENT " soundcard not found or device busy\n"); printk(KERN_ERR IDENT " soundcard not found or device busy\n");
#endif #endif
......
...@@ -2242,6 +2242,9 @@ static int __init alsa_card_es18xx_init(void) ...@@ -2242,6 +2242,9 @@ static int __init alsa_card_es18xx_init(void)
cards += pnp_register_card_driver(&es18xx_pnpc_driver); cards += pnp_register_card_driver(&es18xx_pnpc_driver);
#endif #endif
if(!cards) { if(!cards) {
#ifdef CONFIG_PNP
pnp_unregister_card_driver(&es18xx_pnpc_driver);
#endif
#ifdef MODULE #ifdef MODULE
snd_printk(KERN_ERR "ESS AudioDrive ES18xx soundcard not found or device busy\n"); snd_printk(KERN_ERR "ESS AudioDrive ES18xx soundcard not found or device busy\n");
#endif #endif
......
...@@ -32,8 +32,7 @@ ...@@ -32,8 +32,7 @@
irqreturn_t snd_gus_interrupt(int irq, void *dev_id, struct pt_regs *regs) irqreturn_t snd_gus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
snd_gus_card_t * gus = snd_magic_cast(snd_gus_card_t, snd_gus_card_t * gus = snd_magic_cast(snd_gus_card_t, dev_id, return IRQ_NONE);
dev_id, return IRQ_NONE);
unsigned char status; unsigned char status;
int loop = 100; int loop = 100;
int handled = 0; int handled = 0;
......
...@@ -949,6 +949,9 @@ static int __init alsa_card_interwave_init(void) ...@@ -949,6 +949,9 @@ static int __init alsa_card_interwave_init(void)
#endif #endif
if (!cards) { if (!cards) {
#ifdef CONFIG_PNP
pnp_unregister_card_driver(&interwave_pnpc_driver);
#endif
#ifdef MODULE #ifdef MODULE
printk(KERN_ERR "InterWave soundcard not found or device busy\n"); printk(KERN_ERR "InterWave soundcard not found or device busy\n");
#endif #endif
......
...@@ -902,6 +902,9 @@ static int __init alsa_card_opl3sa2_init(void) ...@@ -902,6 +902,9 @@ static int __init alsa_card_opl3sa2_init(void)
if (!cards) { if (!cards) {
#ifdef MODULE #ifdef MODULE
snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n"); snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n");
#endif
#ifdef CONFIG_PNP
pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
#endif #endif
return -ENODEV; return -ENODEV;
} }
......
...@@ -969,8 +969,10 @@ static int snd_opti93x_trigger(snd_pcm_substream_t *substream, ...@@ -969,8 +969,10 @@ static int snd_opti93x_trigger(snd_pcm_substream_t *substream,
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
{ {
unsigned int what = 0; unsigned int what = 0;
snd_pcm_substream_t *s = substream; struct list_head *pos;
do { snd_pcm_substream_t *s;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == chip->playback_substream) { if (s == chip->playback_substream) {
what |= OPTi93X_PLAYBACK_ENABLE; what |= OPTi93X_PLAYBACK_ENABLE;
snd_pcm_trigger_done(s, substream); snd_pcm_trigger_done(s, substream);
...@@ -978,8 +980,7 @@ static int snd_opti93x_trigger(snd_pcm_substream_t *substream, ...@@ -978,8 +980,7 @@ static int snd_opti93x_trigger(snd_pcm_substream_t *substream,
what |= OPTi93X_CAPTURE_ENABLE; what |= OPTi93X_CAPTURE_ENABLE;
snd_pcm_trigger_done(s, substream); snd_pcm_trigger_done(s, substream);
} }
s = s->link_next; }
} while (s != substream);
spin_lock(&chip->lock); spin_lock(&chip->lock);
if (cmd == SNDRV_PCM_TRIGGER_START) { if (cmd == SNDRV_PCM_TRIGGER_START) {
snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF, what, what); snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF, what, what);
...@@ -1946,7 +1947,7 @@ static int __devinit snd_card_opti9xx_probe(struct pnp_card_link *pcard, ...@@ -1946,7 +1947,7 @@ static int __devinit snd_card_opti9xx_probe(struct pnp_card_link *pcard,
chip = (opti9xx_t *)card->private_data; chip = (opti9xx_t *)card->private_data;
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
if (isapnp && (hw = snd_card_opti9xx_pnp(chip, pcard, pid)) > 0) { if (isapnp && pcard && (hw = snd_card_opti9xx_pnp(chip, pcard, pid)) > 0) {
switch (hw) { switch (hw) {
case 0x0924: case 0x0924:
hw = OPTi9XX_HW_82C924; hw = OPTi9XX_HW_82C924;
...@@ -2203,6 +2204,9 @@ static int __init alsa_card_opti9xx_init(void) ...@@ -2203,6 +2204,9 @@ static int __init alsa_card_opti9xx_init(void)
cards = pnp_register_card_driver(&opti9xx_pnpc_driver); cards = pnp_register_card_driver(&opti9xx_pnpc_driver);
if (cards == 0 && (error = snd_card_opti9xx_probe(NULL, NULL)) < 0) { if (cards == 0 && (error = snd_card_opti9xx_probe(NULL, NULL)) < 0) {
#ifdef CONFIG_PNP
pnp_unregister_card_driver(&opti9xx_pnpc_driver);
#endif
#ifdef MODULE #ifdef MODULE
#ifdef OPTi93X #ifdef OPTi93X
printk(KERN_ERR "no OPTi 82C93x soundcard found\n"); printk(KERN_ERR "no OPTi 82C93x soundcard found\n");
......
...@@ -84,11 +84,10 @@ static irqreturn_t snd_card_es968_interrupt(int irq, void *dev_id, ...@@ -84,11 +84,10 @@ static irqreturn_t snd_card_es968_interrupt(int irq, void *dev_id,
sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE); sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE);
if (chip->open & SB_OPEN_PCM) { if (chip->open & SB_OPEN_PCM) {
snd_sb8dsp_interrupt(chip); return snd_sb8dsp_interrupt(chip);
} else { } else {
snd_sb8dsp_midi_interrupt(chip); return snd_sb8dsp_midi_interrupt(chip);
} }
return IRQ_HANDLED;
} }
static int __devinit snd_card_es968_pnp(int dev, struct snd_card_es968 *acard, static int __devinit snd_card_es968_pnp(int dev, struct snd_card_es968 *acard,
...@@ -225,10 +224,13 @@ static struct pnp_card_driver es968_pnpc_driver = { ...@@ -225,10 +224,13 @@ static struct pnp_card_driver es968_pnpc_driver = {
static int __init alsa_card_es968_init(void) static int __init alsa_card_es968_init(void)
{ {
int res = pnp_register_card_driver(&es968_pnpc_driver); int res = pnp_register_card_driver(&es968_pnpc_driver);
#ifdef MODULE
if (res == 0) if (res == 0)
{
pnp_unregister_card_driver(&es968_pnpc_driver);
#ifdef MODULE
snd_printk(KERN_ERR "no ES968 based soundcards found\n"); snd_printk(KERN_ERR "no ES968 based soundcards found\n");
#endif #endif
}
return res < 0 ? res : 0; return res < 0 ? res : 0;
} }
......
...@@ -625,6 +625,9 @@ static int __init alsa_card_sb16_init(void) ...@@ -625,6 +625,9 @@ static int __init alsa_card_sb16_init(void)
#endif #endif
if (!cards) { if (!cards) {
#ifdef CONFIG_PNP
pnp_unregister_card_driver(&sb16_pnpc_driver);
#endif
#ifdef MODULE #ifdef MODULE
snd_printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n"); snd_printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n");
#ifdef SNDRV_SBAWE_EMU8000 #ifdef SNDRV_SBAWE_EMU8000
......
...@@ -75,11 +75,10 @@ static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id, struct pt_regs *regs ...@@ -75,11 +75,10 @@ static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id, struct pt_regs *regs
sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE); sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE);
if (chip->open & SB_OPEN_PCM) { if (chip->open & SB_OPEN_PCM) {
snd_sb8dsp_interrupt(chip); return snd_sb8dsp_interrupt(chip);
} else { } else {
snd_sb8dsp_midi_interrupt(chip); return snd_sb8dsp_midi_interrupt(chip);
} }
return IRQ_HANDLED;
} }
static void snd_sb8_free(snd_card_t *card) static void snd_sb8_free(snd_card_t *card)
......
...@@ -331,7 +331,7 @@ static int snd_sb8_capture_trigger(snd_pcm_substream_t * substream, ...@@ -331,7 +331,7 @@ static int snd_sb8_capture_trigger(snd_pcm_substream_t * substream,
return 0; return 0;
} }
void snd_sb8dsp_interrupt(sb_t *chip) irqreturn_t snd_sb8dsp_interrupt(sb_t *chip)
{ {
snd_pcm_substream_t *substream; snd_pcm_substream_t *substream;
snd_pcm_runtime_t *runtime; snd_pcm_runtime_t *runtime;
...@@ -356,6 +356,7 @@ void snd_sb8dsp_interrupt(sb_t *chip) ...@@ -356,6 +356,7 @@ void snd_sb8dsp_interrupt(sb_t *chip)
snd_pcm_period_elapsed(substream); snd_pcm_period_elapsed(substream);
break; break;
} }
return IRQ_HANDLED;
} }
static snd_pcm_uframes_t snd_sb8_playback_pointer(snd_pcm_substream_t * substream) static snd_pcm_uframes_t snd_sb8_playback_pointer(snd_pcm_substream_t * substream)
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
*/ */
void snd_sb8dsp_midi_interrupt(sb_t * chip) irqreturn_t snd_sb8dsp_midi_interrupt(sb_t * chip)
{ {
snd_rawmidi_t *rmidi; snd_rawmidi_t *rmidi;
int max = 64; int max = 64;
...@@ -41,7 +41,7 @@ void snd_sb8dsp_midi_interrupt(sb_t * chip) ...@@ -41,7 +41,7 @@ void snd_sb8dsp_midi_interrupt(sb_t * chip)
if (chip == NULL || (rmidi = chip->rmidi) == NULL) { if (chip == NULL || (rmidi = chip->rmidi) == NULL) {
inb(SBP(chip, READ)); /* ack interrupt */ inb(SBP(chip, READ)); /* ack interrupt */
return; return IRQ_NONE;
} }
while (max-- > 0) { while (max-- > 0) {
spin_lock(&chip->midi_input_lock); spin_lock(&chip->midi_input_lock);
...@@ -53,6 +53,7 @@ void snd_sb8dsp_midi_interrupt(sb_t * chip) ...@@ -53,6 +53,7 @@ void snd_sb8dsp_midi_interrupt(sb_t * chip)
spin_unlock(&chip->midi_input_lock); spin_unlock(&chip->midi_input_lock);
} }
} }
return IRQ_HANDLED;
} }
/* /*
......
...@@ -710,6 +710,9 @@ static int __init alsa_card_wavefront_init(void) ...@@ -710,6 +710,9 @@ static int __init alsa_card_wavefront_init(void)
cards += pnp_register_card_driver(&wavefront_pnpc_driver); cards += pnp_register_card_driver(&wavefront_pnpc_driver);
#endif #endif
if (!cards) { if (!cards) {
#ifdef CONFIG_PNP
pnp_unregister_card_driver(&wavefront_pnpc_driver);
#endif
#ifdef MODULE #ifdef MODULE
printk (KERN_ERR "No WaveFront cards found or devices busy\n"); printk (KERN_ERR "No WaveFront cards found or devices busy\n");
#endif #endif
...@@ -722,7 +725,9 @@ static void __exit alsa_card_wavefront_exit(void) ...@@ -722,7 +725,9 @@ static void __exit alsa_card_wavefront_exit(void)
{ {
int idx; int idx;
#ifdef CONFIG_PNP
pnp_unregister_card_driver(&wavefront_pnpc_driver); pnp_unregister_card_driver(&wavefront_pnpc_driver);
#endif
for (idx = 0; idx < SNDRV_CARDS; idx++) for (idx = 0; idx < SNDRV_CARDS; idx++)
snd_card_free(snd_wavefront_legacy[idx]); snd_card_free(snd_wavefront_legacy[idx]);
} }
......
...@@ -13,6 +13,7 @@ obj-$(CONFIG_SND_ENS1371) += snd-ac97-codec.o ...@@ -13,6 +13,7 @@ obj-$(CONFIG_SND_ENS1371) += snd-ac97-codec.o
obj-$(CONFIG_SND_ES1968) += snd-ac97-codec.o obj-$(CONFIG_SND_ES1968) += snd-ac97-codec.o
obj-$(CONFIG_SND_FM801) += snd-ac97-codec.o obj-$(CONFIG_SND_FM801) += snd-ac97-codec.o
obj-$(CONFIG_SND_ICE1712) += snd-ac97-codec.o obj-$(CONFIG_SND_ICE1712) += snd-ac97-codec.o
obj-$(CONFIG_SND_ICE1724) += snd-ac97-codec.o
obj-$(CONFIG_SND_INTEL8X0) += snd-ac97-codec.o obj-$(CONFIG_SND_INTEL8X0) += snd-ac97-codec.o
obj-$(CONFIG_SND_MAESTRO3) += snd-ac97-codec.o obj-$(CONFIG_SND_MAESTRO3) += snd-ac97-codec.o
obj-$(CONFIG_SND_VIA82XX) += snd-ac97-codec.o obj-$(CONFIG_SND_VIA82XX) += snd-ac97-codec.o
......
...@@ -143,10 +143,12 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = { ...@@ -143,10 +143,12 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x54584e20, 0xffffffff, "TLC320AD9xC", NULL, NULL }, { 0x54584e20, 0xffffffff, "TLC320AD9xC", NULL, NULL },
{ 0x56494161, 0xffffffff, "VIA1612A", NULL, NULL }, // modified ICE1232 with S/PDIF { 0x56494161, 0xffffffff, "VIA1612A", NULL, NULL }, // modified ICE1232 with S/PDIF
{ 0x57454301, 0xffffffff, "W83971D", NULL, NULL }, { 0x57454301, 0xffffffff, "W83971D", NULL, NULL },
{ 0x574d4c00, 0xffffffff, "WM9701A", patch_wolfson00,NULL }, { 0x574d4c00, 0xffffffff, "WM9701A", NULL, NULL },
{ 0x574d4c03, 0xffffffff, "WM9703/9707", patch_wolfson03,NULL }, { 0x574d4C03, 0xffffffff, "WM9703/WM9707/WM9708/WM9717", patch_wolfson03, NULL},
{ 0x574d4c04, 0xffffffff, "WM9704/quad", patch_wolfson04,NULL }, { 0x574d4C04, 0xffffffff, "WM9704M/WM9704Q", patch_wolfson04, NULL},
{ 0x574d4c05, 0xffffffff, "WM9705", NULL, NULL }, // patch? { 0x574d4C05, 0xffffffff, "WM9705/WM9710", patch_wolfson05, NULL},
{ 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL},
{ 0x574d4C12, 0xffffffff, "WM9711/WM9712", patch_wolfson11, NULL},
{ 0x594d4800, 0xffffffff, "YMF743", NULL, NULL }, { 0x594d4800, 0xffffffff, "YMF743", NULL, NULL },
{ 0x594d4802, 0xffffffff, "YMF752", NULL, NULL }, { 0x594d4802, 0xffffffff, "YMF752", NULL, NULL },
{ 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL }, { 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL },
......
...@@ -51,55 +51,63 @@ int patch_yamaha_ymf753(ac97_t * ac97) ...@@ -51,55 +51,63 @@ int patch_yamaha_ymf753(ac97_t * ac97)
return 0; return 0;
} }
int patch_wolfson00(ac97_t * ac97) /*
{ * May 2, 2003 Liam Girdwood <liam.girdwood@wolfsonmicro.com>
/* This sequence is suspect because it was designed for * removed broken wolfson00 patch.
the WM9704, and is known to fail when applied to the * added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
WM9707. If you're having trouble initializing a */
WM9700, this is the place to start looking.
Randolph Bentson <bentson@holmsjoen.com> */
// WM9701A
snd_ac97_write_cache(ac97, 0x72, 0x0808);
snd_ac97_write_cache(ac97, 0x74, 0x0808);
// patch for DVD noise
snd_ac97_write_cache(ac97, 0x5a, 0x0200);
// init vol
snd_ac97_write_cache(ac97, 0x70, 0x0808);
snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000); #define AC97_WM97XX_FMIXER_VOL 0x72
return 0; #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) int patch_wolfson03(ac97_t * ac97)
{ {
/* This is known to work for the ViewSonic ViewPad 1000 /* This is known to work for the ViewSonic ViewPad 1000
Randolph Bentson <bentson@holmsjoen.com> */ Randolph Bentson <bentson@holmsjoen.com> */
// WM9703/9707 // WM9703/9707/9708/9717
snd_ac97_write_cache(ac97, 0x72, 0x0808); snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
snd_ac97_write_cache(ac97, 0x20, 0x8000); snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0x8000);
return 0; return 0;
} }
int patch_wolfson04(ac97_t * ac97) int patch_wolfson04(ac97_t * ac97)
{ {
// WM9704 // WM9704M/9704Q
snd_ac97_write_cache(ac97, 0x72, 0x0808); // set front and rear mixer volume
snd_ac97_write_cache(ac97, 0x74, 0x0808); snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
snd_ac97_write_cache(ac97, AC97_WM9704_RMIXER_VOL, 0x0808);
// patch for DVD noise // patch for DVD noise
snd_ac97_write_cache(ac97, 0x5a, 0x0200); snd_ac97_write_cache(ac97, AC97_WM9704_TEST, 0x0200);
// init vol // init vol
snd_ac97_write_cache(ac97, 0x70, 0x0808); snd_ac97_write_cache(ac97, AC97_WM9704_RPCM_VOL, 0x0808);
// set rear surround volume
snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000); snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000);
return 0; return 0;
} }
int patch_wolfson05(ac97_t * ac97)
{
// WM9705, WM9710
// set front mixer volume
snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
return 0;
}
int patch_wolfson11(ac97_t * ac97)
{
// WM9711, WM9712
// set out3 volume
snd_ac97_write_cache(ac97, AC97_WM9711_OUT3VOL, 0x0808);
return 0;
}
int patch_tritech_tr28028(ac97_t * ac97) int patch_tritech_tr28028(ac97_t * ac97)
{ {
snd_ac97_write_cache(ac97, 0x26, 0x0300); snd_ac97_write_cache(ac97, 0x26, 0x0300);
......
...@@ -26,6 +26,8 @@ int patch_yamaha_ymf753(ac97_t * ac97); ...@@ -26,6 +26,8 @@ int patch_yamaha_ymf753(ac97_t * ac97);
int patch_wolfson00(ac97_t * ac97); int patch_wolfson00(ac97_t * ac97);
int patch_wolfson03(ac97_t * ac97); int patch_wolfson03(ac97_t * ac97);
int patch_wolfson04(ac97_t * ac97); 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_tritech_tr28028(ac97_t * ac97);
int patch_sigmatel_stac9708(ac97_t * ac97); int patch_sigmatel_stac9708(ac97_t * ac97);
int patch_sigmatel_stac9721(ac97_t * ac97); int patch_sigmatel_stac9721(ac97_t * ac97);
......
...@@ -1211,6 +1211,7 @@ static int snd_ali_trigger(snd_pcm_substream_t *substream, ...@@ -1211,6 +1211,7 @@ static int snd_ali_trigger(snd_pcm_substream_t *substream,
{ {
ali_t *codec = snd_pcm_substream_chip(substream); ali_t *codec = snd_pcm_substream_chip(substream);
struct list_head *pos;
snd_pcm_substream_t *s; snd_pcm_substream_t *s;
unsigned int what, whati, capture_flag; unsigned int what, whati, capture_flag;
snd_ali_voice_t *pvoice = NULL, *evoice = NULL; snd_ali_voice_t *pvoice = NULL, *evoice = NULL;
...@@ -1229,8 +1230,8 @@ static int snd_ali_trigger(snd_pcm_substream_t *substream, ...@@ -1229,8 +1230,8 @@ static int snd_ali_trigger(snd_pcm_substream_t *substream,
} }
what = whati = capture_flag = 0; what = whati = capture_flag = 0;
s = substream; snd_pcm_group_for_each(pos, substream) {
do { s = snd_pcm_group_substream_entry(pos);
if ((ali_t *) _snd_pcm_chip(s->pcm) == codec) { if ((ali_t *) _snd_pcm_chip(s->pcm) == codec) {
pvoice = (snd_ali_voice_t *) s->runtime->private_data; pvoice = (snd_ali_voice_t *) s->runtime->private_data;
evoice = pvoice->extra; evoice = pvoice->extra;
...@@ -1254,8 +1255,7 @@ static int snd_ali_trigger(snd_pcm_substream_t *substream, ...@@ -1254,8 +1255,7 @@ static int snd_ali_trigger(snd_pcm_substream_t *substream,
if (pvoice->mode) if (pvoice->mode)
capture_flag = 1; capture_flag = 1;
} }
s = s->link_next; }
} while (s != substream);
spin_lock(&codec->reg_lock); spin_lock(&codec->reg_lock);
if (! do_start) { if (! do_start) {
outl(what, ALI_REG(codec, ALI_STOP)); outl(what, ALI_REG(codec, ALI_STOP));
......
...@@ -1496,6 +1496,7 @@ static void setup_ac3(cmipci_t *cm, snd_pcm_substream_t *subs, int do_ac3, int r ...@@ -1496,6 +1496,7 @@ static void setup_ac3(cmipci_t *cm, snd_pcm_substream_t *subs, int do_ac3, int r
/* SPD24SEL for 037, 0x02 */ /* SPD24SEL for 037, 0x02 */
/* SPD24SEL for 039, 0x20, but cannot be set */ /* SPD24SEL for 039, 0x20, but cannot be set */
snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_SPD24SEL); snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_SPD24SEL);
snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL);
} else { /* can_ac3_sw */ } else { /* can_ac3_sw */
#ifdef DO_SOFT_AC3 #ifdef DO_SOFT_AC3
/* FIXME: ugly hack! */ /* FIXME: ugly hack! */
...@@ -1519,7 +1520,14 @@ static void setup_ac3(cmipci_t *cm, snd_pcm_substream_t *subs, int do_ac3, int r ...@@ -1519,7 +1520,14 @@ static void setup_ac3(cmipci_t *cm, snd_pcm_substream_t *subs, int do_ac3, int r
snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_AC3EN2); snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_AC3EN2);
if (cm->can_ac3_hw) { if (cm->can_ac3_hw) {
/* chip model >= 37 */
if (snd_pcm_format_width(subs->runtime->format) > 16) {
snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL);
snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_SPD24SEL);
} else {
snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL);
snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_SPD24SEL); snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_SPD24SEL);
}
} else { } else {
#ifdef DO_SOFT_AC3 #ifdef DO_SOFT_AC3
snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL);
...@@ -1669,7 +1677,6 @@ static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id, struct pt_regs *r ...@@ -1669,7 +1677,6 @@ static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id, struct pt_regs *r
if ((status & CM_CHINT1) && cm->channel[1].running) if ((status & CM_CHINT1) && cm->channel[1].running)
snd_pcm_period_elapsed(cm->channel[1].substream); snd_pcm_period_elapsed(cm->channel[1].substream);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1742,7 +1749,7 @@ static snd_pcm_hardware_t snd_cmipci_playback_spdif = ...@@ -1742,7 +1749,7 @@ static snd_pcm_hardware_t snd_cmipci_playback_spdif =
{ {
.info = (SNDRV_PCM_INFO_INTERLEAVED | .info = (SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE), SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE),
.formats = SNDRV_PCM_FMTBIT_S16_LE /*| SNDRV_PCM_FMTBIT_S32_LE*/, .formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
.rate_min = 44100, .rate_min = 44100,
.rate_max = 48000, .rate_max = 48000,
...@@ -1897,6 +1904,8 @@ static int snd_cmipci_playback_spdif_open(snd_pcm_substream_t *substream) ...@@ -1897,6 +1904,8 @@ static int snd_cmipci_playback_spdif_open(snd_pcm_substream_t *substream)
if (cm->can_ac3_hw) if (cm->can_ac3_hw)
#endif #endif
runtime->hw.info |= SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID; runtime->hw.info |= SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID;
if (cm->chip_version >= 37)
runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE;
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x40000); snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x40000);
cm->dig_pcm_status = cm->dig_status; cm->dig_pcm_status = cm->dig_status;
return 0; return 0;
......
This diff is collapsed.
...@@ -111,8 +111,11 @@ MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC); ...@@ -111,8 +111,11 @@ MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
#define ES_REG_CONTROL 0x00 /* R/W: Interrupt/Chip select control register */ #define ES_REG_CONTROL 0x00 /* R/W: Interrupt/Chip select control register */
#define ES_1370_ADC_STOP (1<<31) /* disable capture buffer transfers */ #define ES_1370_ADC_STOP (1<<31) /* disable capture buffer transfers */
#define ES_1370_XCTL1 (1<<30) /* general purpose output bit */ #define ES_1370_XCTL1 (1<<30) /* general purpose output bit */
#define ES_1373_TEST_BIT (1<<29) /* should be set to 0 for normal operation */ #define ES_1373_BYPASS_P1 (1<<31) /* bypass SRC for PB1 */
#define ES_1373_RECEN_B (1<<28) /* mix record with playback for I2S/SPDIF out */ #define ES_1373_BYPASS_P2 (1<<30) /* bypass SRC for PB2 */
#define ES_1373_BYPASS_R (1<<29) /* bypass SRC for REC */
#define ES_1373_TEST_BIT (1<<28) /* should be set to 0 for normal operation */
#define ES_1373_RECEN_B (1<<27) /* mix record with playback for I2S/SPDIF out */
#define ES_1373_SPDIF_THRU (1<<26) /* 0 = SPDIF thru mode, 1 = SPDIF == dig out */ #define ES_1373_SPDIF_THRU (1<<26) /* 0 = SPDIF thru mode, 1 = SPDIF == dig out */
#define ES_1371_JOY_ASEL(o) (((o)&0x03)<<24)/* joystick port mapping */ #define ES_1371_JOY_ASEL(o) (((o)&0x03)<<24)/* joystick port mapping */
#define ES_1371_JOY_ASELM (0x03<<24) /* mask for above */ #define ES_1371_JOY_ASELM (0x03<<24) /* mask for above */
...@@ -739,8 +742,10 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd) ...@@ -739,8 +742,10 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
{ {
unsigned int what = 0; unsigned int what = 0;
snd_pcm_substream_t *s = substream; struct list_head *pos;
do { snd_pcm_substream_t *s;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == ensoniq->playback1_substream) { if (s == ensoniq->playback1_substream) {
what |= ES_P1_PAUSE; what |= ES_P1_PAUSE;
snd_pcm_trigger_done(s, substream); snd_pcm_trigger_done(s, substream);
...@@ -749,8 +754,7 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd) ...@@ -749,8 +754,7 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
snd_pcm_trigger_done(s, substream); snd_pcm_trigger_done(s, substream);
} else if (s == ensoniq->capture_substream) } else if (s == ensoniq->capture_substream)
return -EINVAL; return -EINVAL;
s = s->link_next; }
} while (s != substream);
spin_lock(&ensoniq->reg_lock); spin_lock(&ensoniq->reg_lock);
if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)
ensoniq->sctrl |= what; ensoniq->sctrl |= what;
...@@ -764,8 +768,10 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd) ...@@ -764,8 +768,10 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
{ {
unsigned int what = 0; unsigned int what = 0;
snd_pcm_substream_t *s = substream; struct list_head *pos;
do { snd_pcm_substream_t *s;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == ensoniq->playback1_substream) { if (s == ensoniq->playback1_substream) {
what |= ES_DAC1_EN; what |= ES_DAC1_EN;
snd_pcm_trigger_done(s, substream); snd_pcm_trigger_done(s, substream);
...@@ -776,8 +782,7 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd) ...@@ -776,8 +782,7 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
what |= ES_ADC_EN; what |= ES_ADC_EN;
snd_pcm_trigger_done(s, substream); snd_pcm_trigger_done(s, substream);
} }
s = s->link_next; }
} while (s != substream);
spin_lock(&ensoniq->reg_lock); spin_lock(&ensoniq->reg_lock);
if (cmd == SNDRV_PCM_TRIGGER_START) if (cmd == SNDRV_PCM_TRIGGER_START)
ensoniq->ctrl |= what; ensoniq->ctrl |= what;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment