Commit 9c0df338 authored by Jaroslav Kysela's avatar Jaroslav Kysela

[ALSA] Remove spinlock in callbacks

AC97 Codec Core,AK4531 codec
Removed spinlocks in callback, use sempahore instead since all ac97
callbacks are supposed to be non-atomic.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 394bc516
...@@ -480,8 +480,8 @@ struct _snd_ac97 { ...@@ -480,8 +480,8 @@ struct _snd_ac97 {
snd_info_entry_t *proc_regs; snd_info_entry_t *proc_regs;
unsigned short subsystem_vendor; unsigned short subsystem_vendor;
unsigned short subsystem_device; unsigned short subsystem_device;
spinlock_t reg_lock; struct semaphore reg_mutex;
struct semaphore mutex; /* mutex for AD18xx multi-codecs and paging (2.3) */ struct semaphore page_mutex; /* mutex for AD18xx multi-codecs and paging (2.3) */
unsigned short num; /* number of codec: 0 = primary, 1 = secondary */ unsigned short num; /* number of codec: 0 = primary, 1 = secondary */
unsigned short addr; /* physical address of codec [0-3] */ unsigned short addr; /* physical address of codec [0-3] */
unsigned int id; /* identification of codec */ unsigned int id; /* identification of codec */
......
...@@ -72,7 +72,7 @@ struct _snd_ak4531 { ...@@ -72,7 +72,7 @@ struct _snd_ak4531 {
void (*private_free) (ak4531_t *ak4531); void (*private_free) (ak4531_t *ak4531);
/* --- */ /* --- */
unsigned char regs[0x20]; unsigned char regs[0x20];
spinlock_t reg_lock; struct semaphore reg_mutex;
}; };
int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531); int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531);
......
...@@ -333,11 +333,11 @@ void snd_ac97_write_cache(ac97_t *ac97, unsigned short reg, unsigned short value ...@@ -333,11 +333,11 @@ void snd_ac97_write_cache(ac97_t *ac97, unsigned short reg, unsigned short value
{ {
if (!snd_ac97_valid_reg(ac97, reg)) if (!snd_ac97_valid_reg(ac97, reg))
return; return;
spin_lock(&ac97->reg_lock); down(&ac97->reg_mutex);
ac97->regs[reg] = value; ac97->regs[reg] = value;
spin_unlock(&ac97->reg_lock);
ac97->bus->ops->write(ac97, reg, value); ac97->bus->ops->write(ac97, reg, value);
set_bit(reg, ac97->reg_accessed); set_bit(reg, ac97->reg_accessed);
up(&ac97->reg_mutex);
} }
/** /**
...@@ -358,14 +358,13 @@ int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value) ...@@ -358,14 +358,13 @@ int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value)
if (!snd_ac97_valid_reg(ac97, reg)) if (!snd_ac97_valid_reg(ac97, reg))
return -EINVAL; return -EINVAL;
spin_lock(&ac97->reg_lock); down(&ac97->reg_mutex);
change = ac97->regs[reg] != value; change = ac97->regs[reg] != value;
if (change) { if (change) {
ac97->regs[reg] = value; ac97->regs[reg] = value;
spin_unlock(&ac97->reg_lock);
ac97->bus->ops->write(ac97, reg, value); ac97->bus->ops->write(ac97, reg, value);
} else }
spin_unlock(&ac97->reg_lock); up(&ac97->reg_mutex);
return change; return change;
} }
...@@ -385,20 +384,29 @@ int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value) ...@@ -385,20 +384,29 @@ int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value)
int snd_ac97_update_bits(ac97_t *ac97, unsigned short reg, unsigned short mask, unsigned short value) int snd_ac97_update_bits(ac97_t *ac97, unsigned short reg, unsigned short mask, unsigned short value)
{ {
int change; int change;
unsigned short old, new;
if (!snd_ac97_valid_reg(ac97, reg)) if (!snd_ac97_valid_reg(ac97, reg))
return -EINVAL; return -EINVAL;
spin_lock(&ac97->reg_lock); down(&ac97->reg_mutex);
change = snd_ac97_update_bits_nolock(ac97, reg, mask, value);
up(&ac97->reg_mutex);
return change;
}
/* no lock version - see snd_ac97_updat_bits() */
int snd_ac97_update_bits_nolock(ac97_t *ac97, unsigned short reg,
unsigned short mask, unsigned short value)
{
int change;
unsigned short old, new;
old = snd_ac97_read_cache(ac97, reg); old = snd_ac97_read_cache(ac97, reg);
new = (old & ~mask) | value; new = (old & ~mask) | value;
change = old != new; change = old != new;
if (change) { if (change) {
ac97->regs[reg] = new; ac97->regs[reg] = new;
spin_unlock(&ac97->reg_lock);
ac97->bus->ops->write(ac97, reg, new); ac97->bus->ops->write(ac97, reg, new);
} else }
spin_unlock(&ac97->reg_lock);
return change; return change;
} }
...@@ -407,15 +415,14 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho ...@@ -407,15 +415,14 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho
int change; int change;
unsigned short old, new, cfg; unsigned short old, new, cfg;
down(&ac97->mutex); down(&ac97->page_mutex);
spin_lock(&ac97->reg_lock);
old = ac97->spec.ad18xx.pcmreg[codec]; old = ac97->spec.ad18xx.pcmreg[codec];
new = (old & ~mask) | value; new = (old & ~mask) | value;
cfg = snd_ac97_read_cache(ac97, AC97_AD_SERIAL_CFG);
change = old != new; change = old != new;
if (change) { if (change) {
down(&ac97->reg_mutex);
cfg = snd_ac97_read_cache(ac97, AC97_AD_SERIAL_CFG);
ac97->spec.ad18xx.pcmreg[codec] = new; ac97->spec.ad18xx.pcmreg[codec] = new;
spin_unlock(&ac97->reg_lock);
/* select single codec */ /* select single codec */
ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG, ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG,
(cfg & ~0x7000) | (cfg & ~0x7000) |
...@@ -425,9 +432,9 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho ...@@ -425,9 +432,9 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho
/* select all codecs */ /* select all codecs */
ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG, ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG,
cfg | 0x7000); cfg | 0x7000);
} else up(&ac97->reg_mutex);
spin_unlock(&ac97->reg_lock); }
up(&ac97->mutex); up(&ac97->page_mutex);
return change; return change;
} }
...@@ -611,12 +618,12 @@ static int snd_ac97_getput_page(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ...@@ -611,12 +618,12 @@ static int snd_ac97_getput_page(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
(reg >= 0x60 && reg < 0x70)) { (reg >= 0x60 && reg < 0x70)) {
unsigned short page_save; unsigned short page_save;
unsigned short page = (kcontrol->private_value >> 25) & 0x0f; unsigned short page = (kcontrol->private_value >> 25) & 0x0f;
down(&ac97->mutex); /* lock paging */ down(&ac97->page_mutex); /* lock paging */
page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
err = func(kcontrol, ucontrol); err = func(kcontrol, ucontrol);
snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
up(&ac97->mutex); /* unlock paging */ up(&ac97->page_mutex); /* unlock paging */
} else } else
err = func(kcontrol, ucontrol); err = func(kcontrol, ucontrol);
return err; return err;
...@@ -760,12 +767,12 @@ static int snd_ac97_spdif_default_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_val ...@@ -760,12 +767,12 @@ static int snd_ac97_spdif_default_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
{ {
ac97_t *ac97 = snd_kcontrol_chip(kcontrol); ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
spin_lock(&ac97->reg_lock); down(&ac97->reg_mutex);
ucontrol->value.iec958.status[0] = ac97->spdif_status & 0xff; ucontrol->value.iec958.status[0] = ac97->spdif_status & 0xff;
ucontrol->value.iec958.status[1] = (ac97->spdif_status >> 8) & 0xff; ucontrol->value.iec958.status[1] = (ac97->spdif_status >> 8) & 0xff;
ucontrol->value.iec958.status[2] = (ac97->spdif_status >> 16) & 0xff; ucontrol->value.iec958.status[2] = (ac97->spdif_status >> 16) & 0xff;
ucontrol->value.iec958.status[3] = (ac97->spdif_status >> 24) & 0xff; ucontrol->value.iec958.status[3] = (ac97->spdif_status >> 24) & 0xff;
spin_unlock(&ac97->reg_lock); up(&ac97->reg_mutex);
return 0; return 0;
} }
...@@ -776,7 +783,6 @@ static int snd_ac97_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val ...@@ -776,7 +783,6 @@ static int snd_ac97_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
unsigned short val = 0; unsigned short val = 0;
int change; int change;
spin_lock(&ac97->reg_lock);
new = val = ucontrol->value.iec958.status[0] & (IEC958_AES0_PROFESSIONAL|IEC958_AES0_NONAUDIO); new = val = ucontrol->value.iec958.status[0] & (IEC958_AES0_PROFESSIONAL|IEC958_AES0_NONAUDIO);
if (ucontrol->value.iec958.status[0] & IEC958_AES0_PROFESSIONAL) { if (ucontrol->value.iec958.status[0] & IEC958_AES0_PROFESSIONAL) {
new |= ucontrol->value.iec958.status[0] & (IEC958_AES0_PRO_FS|IEC958_AES0_PRO_EMPHASIS_5015); new |= ucontrol->value.iec958.status[0] & (IEC958_AES0_PRO_FS|IEC958_AES0_PRO_EMPHASIS_5015);
...@@ -805,9 +811,9 @@ static int snd_ac97_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val ...@@ -805,9 +811,9 @@ static int snd_ac97_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
} }
} }
down(&ac97->reg_mutex);
change = ac97->spdif_status != new; change = ac97->spdif_status != new;
ac97->spdif_status = new; ac97->spdif_status = new;
spin_unlock(&ac97->reg_lock);
if (ac97->flags & AC97_CS_SPDIF) { if (ac97->flags & AC97_CS_SPDIF) {
int x = (val >> 12) & 0x03; int x = (val >> 12) & 0x03;
...@@ -816,23 +822,24 @@ static int snd_ac97_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val ...@@ -816,23 +822,24 @@ static int snd_ac97_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
case 2: x = 0; break; // 48.0 case 2: x = 0; break; // 48.0
default: x = 0; break; // illegal. default: x = 0; break; // illegal.
} }
change |= snd_ac97_update_bits(ac97, AC97_CSR_SPDIF, 0x3fff, ((val & 0xcfff) | (x << 12))); change |= snd_ac97_update_bits_nolock(ac97, AC97_CSR_SPDIF, 0x3fff, ((val & 0xcfff) | (x << 12)));
} else if (ac97->flags & AC97_CX_SPDIF) { } else if (ac97->flags & AC97_CX_SPDIF) {
int v; int v;
v = new & (IEC958_AES0_CON_EMPHASIS_5015|IEC958_AES0_CON_NOT_COPYRIGHT) ? 0 : AC97_CXR_COPYRGT; v = new & (IEC958_AES0_CON_EMPHASIS_5015|IEC958_AES0_CON_NOT_COPYRIGHT) ? 0 : AC97_CXR_COPYRGT;
v |= new & IEC958_AES0_NONAUDIO ? AC97_CXR_SPDIF_AC3 : AC97_CXR_SPDIF_PCM; v |= new & IEC958_AES0_NONAUDIO ? AC97_CXR_SPDIF_AC3 : AC97_CXR_SPDIF_PCM;
change |= snd_ac97_update_bits(ac97, AC97_CXR_AUDIO_MISC, change |= snd_ac97_update_bits_nolock(ac97, AC97_CXR_AUDIO_MISC,
AC97_CXR_SPDIF_MASK | AC97_CXR_COPYRGT, AC97_CXR_SPDIF_MASK | AC97_CXR_COPYRGT,
v); v);
} else { } else {
unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS); unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS);
snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */
change |= snd_ac97_update_bits(ac97, AC97_SPDIF, 0x3fff, val); change |= snd_ac97_update_bits_nolock(ac97, AC97_SPDIF, 0x3fff, val);
if (extst & AC97_EA_SPDIF) { if (extst & AC97_EA_SPDIF) {
snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */
} }
} }
up(&ac97->reg_mutex);
return change; return change;
} }
...@@ -841,30 +848,30 @@ static int snd_ac97_put_spsa(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco ...@@ -841,30 +848,30 @@ static int snd_ac97_put_spsa(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
{ {
ac97_t *ac97 = snd_kcontrol_chip(kcontrol); ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff; int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0x0f; /* single only */ int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff;
// int invert = (kcontrol->private_value >> 24) & 0xff; // int invert = (kcontrol->private_value >> 24) & 0xff;
unsigned short value, old, new; unsigned short value, old, new;
int change;
value = (ucontrol->value.integer.value[0] & mask); value = (ucontrol->value.integer.value[0] & mask);
down(&ac97->reg_mutex);
mask <<= shift; mask <<= shift;
value <<= shift; value <<= shift;
spin_lock(&ac97->reg_lock);
old = snd_ac97_read_cache(ac97, reg); old = snd_ac97_read_cache(ac97, reg);
new = (old & ~mask) | value; new = (old & ~mask) | value;
spin_unlock(&ac97->reg_lock); change = old != new;
if (old != new) { if (change) {
int change;
unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS); unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS);
snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */
change = snd_ac97_update_bits(ac97, reg, mask, value); change = snd_ac97_update_bits_nolock(ac97, reg, mask, value);
if (extst & AC97_EA_SPDIF) if (extst & AC97_EA_SPDIF)
snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */
return change;
} }
return 0; up(&ac97->reg_mutex);
return change;
} }
const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = { const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = {
...@@ -974,10 +981,10 @@ static int snd_ac97_ad18xx_pcm_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_ele ...@@ -974,10 +981,10 @@ static int snd_ac97_ad18xx_pcm_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_ele
ac97_t *ac97 = snd_kcontrol_chip(kcontrol); ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
int codec = kcontrol->private_value & 3; int codec = kcontrol->private_value & 3;
spin_lock(&ac97->reg_lock); down(&ac97->page_mutex);
ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31); ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31);
ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31); ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31);
spin_unlock(&ac97->reg_lock); up(&ac97->page_mutex);
return 0; return 0;
} }
...@@ -1902,8 +1909,8 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) ...@@ -1902,8 +1909,8 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
ac97->limited_regs = template->limited_regs; ac97->limited_regs = template->limited_regs;
memcpy(ac97->reg_accessed, template->reg_accessed, sizeof(ac97->reg_accessed)); memcpy(ac97->reg_accessed, template->reg_accessed, sizeof(ac97->reg_accessed));
bus->codec[ac97->num] = ac97; bus->codec[ac97->num] = ac97;
spin_lock_init(&ac97->reg_lock); init_MUTEX(&ac97->reg_mutex);
init_MUTEX(&ac97->mutex); init_MUTEX(&ac97->page_mutex);
if (ac97->pci) { if (ac97->pci) {
pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_VENDOR_ID, &ac97->subsystem_vendor); pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_VENDOR_ID, &ac97->subsystem_vendor);
......
...@@ -52,6 +52,9 @@ void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst); ...@@ -52,6 +52,9 @@ void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst);
void snd_ac97_restore_status(ac97_t *ac97); void snd_ac97_restore_status(ac97_t *ac97);
void snd_ac97_restore_iec958(ac97_t *ac97); void snd_ac97_restore_iec958(ac97_t *ac97);
int snd_ac97_update_bits_nolock(ac97_t *ac97, unsigned short reg,
unsigned short mask, unsigned short value);
/* ac97_proc.c */ /* ac97_proc.c */
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
void snd_ac97_bus_proc_init(ac97_bus_t * ac97); void snd_ac97_bus_proc_init(ac97_bus_t * ac97);
......
...@@ -55,12 +55,12 @@ static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned shor ...@@ -55,12 +55,12 @@ static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned shor
unsigned short page_save; unsigned short page_save;
int ret; int ret;
down(&ac97->mutex); down(&ac97->page_mutex);
page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
ret = snd_ac97_update_bits(ac97, reg, mask, value); ret = snd_ac97_update_bits(ac97, reg, mask, value);
snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
up(&ac97->mutex); /* unlock paging */ up(&ac97->page_mutex); /* unlock paging */
return ret; return ret;
} }
......
...@@ -206,14 +206,12 @@ static int set_spdif_rate(ac97_t *ac97, unsigned short rate) ...@@ -206,14 +206,12 @@ static int set_spdif_rate(ac97_t *ac97, unsigned short rate)
mask = AC97_SC_SPSR_MASK; mask = AC97_SC_SPSR_MASK;
} }
spin_lock(&ac97->reg_lock); down(&ac97->reg_mutex);
old = snd_ac97_read(ac97, reg) & mask; old = snd_ac97_read(ac97, reg) & mask;
spin_unlock(&ac97->reg_lock);
if (old != bits) { if (old != bits) {
snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0);
snd_ac97_update_bits(ac97, reg, mask, bits); snd_ac97_update_bits_nolock(ac97, reg, mask, bits);
/* update the internal spdif bits */ /* update the internal spdif bits */
spin_lock(&ac97->reg_lock);
sbits = ac97->spdif_status; sbits = ac97->spdif_status;
if (sbits & IEC958_AES0_PROFESSIONAL) { if (sbits & IEC958_AES0_PROFESSIONAL) {
sbits &= ~IEC958_AES0_PRO_FS; sbits &= ~IEC958_AES0_PRO_FS;
...@@ -231,9 +229,9 @@ static int set_spdif_rate(ac97_t *ac97, unsigned short rate) ...@@ -231,9 +229,9 @@ static int set_spdif_rate(ac97_t *ac97, unsigned short rate)
} }
} }
ac97->spdif_status = sbits; ac97->spdif_status = sbits;
spin_unlock(&ac97->reg_lock);
} }
snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF);
up(&ac97->reg_mutex);
return 0; return 0;
} }
......
...@@ -296,7 +296,7 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff ...@@ -296,7 +296,7 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff
{ {
ac97_t *ac97 = entry->private_data; ac97_t *ac97 = entry->private_data;
down(&ac97->mutex); down(&ac97->page_mutex);
if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86
int idx; int idx;
for (idx = 0; idx < 3; idx++) for (idx = 0; idx < 3; idx++)
...@@ -322,7 +322,7 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff ...@@ -322,7 +322,7 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff
} else { } else {
snd_ac97_proc_read_main(ac97, buffer, 0); snd_ac97_proc_read_main(ac97, buffer, 0);
} }
up(&ac97->mutex); up(&ac97->page_mutex);
} }
#ifdef CONFIG_SND_DEBUG #ifdef CONFIG_SND_DEBUG
...@@ -332,7 +332,7 @@ static void snd_ac97_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t ...@@ -332,7 +332,7 @@ static void snd_ac97_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t
ac97_t *ac97 = entry->private_data; ac97_t *ac97 = entry->private_data;
char line[64]; char line[64];
unsigned int reg, val; unsigned int reg, val;
down(&ac97->mutex); down(&ac97->page_mutex);
while (!snd_info_get_line(buffer, line, sizeof(line))) { while (!snd_info_get_line(buffer, line, sizeof(line))) {
if (sscanf(line, "%x %x", &reg, &val) != 2) if (sscanf(line, "%x %x", &reg, &val) != 2)
continue; continue;
...@@ -340,7 +340,7 @@ static void snd_ac97_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t ...@@ -340,7 +340,7 @@ static void snd_ac97_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t
if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff) if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff)
snd_ac97_write_cache(ac97, reg, val); snd_ac97_write_cache(ac97, reg, val);
} }
up(&ac97->mutex); up(&ac97->page_mutex);
} }
#endif #endif
...@@ -359,7 +359,7 @@ static void snd_ac97_proc_regs_read(snd_info_entry_t *entry, ...@@ -359,7 +359,7 @@ static void snd_ac97_proc_regs_read(snd_info_entry_t *entry,
{ {
ac97_t *ac97 = entry->private_data; ac97_t *ac97 = entry->private_data;
down(&ac97->mutex); down(&ac97->page_mutex);
if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86
int idx; int idx;
...@@ -375,7 +375,7 @@ static void snd_ac97_proc_regs_read(snd_info_entry_t *entry, ...@@ -375,7 +375,7 @@ static void snd_ac97_proc_regs_read(snd_info_entry_t *entry,
} else { } else {
snd_ac97_proc_regs_read_main(ac97, buffer, 0); snd_ac97_proc_regs_read_main(ac97, buffer, 0);
} }
up(&ac97->mutex); up(&ac97->page_mutex);
} }
void snd_ac97_proc_init(ac97_t * ac97) void snd_ac97_proc_init(ac97_t * ac97)
......
...@@ -72,16 +72,15 @@ static int snd_ak4531_info_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t ...@@ -72,16 +72,15 @@ static int snd_ak4531_info_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
static int snd_ak4531_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) static int snd_ak4531_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{ {
ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol); ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff; int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 16) & 0x07; int shift = (kcontrol->private_value >> 16) & 0x07;
int mask = (kcontrol->private_value >> 24) & 0xff; int mask = (kcontrol->private_value >> 24) & 0xff;
int invert = (kcontrol->private_value >> 22) & 1; int invert = (kcontrol->private_value >> 22) & 1;
int val; int val;
spin_lock_irqsave(&ak4531->reg_lock, flags); down(&ak4531->reg_mutex);
val = (ak4531->regs[reg] >> shift) & mask; val = (ak4531->regs[reg] >> shift) & mask;
spin_unlock_irqrestore(&ak4531->reg_lock, flags); up(&ak4531->reg_mutex);
if (invert) { if (invert) {
val = mask - val; val = mask - val;
} }
...@@ -92,7 +91,6 @@ static int snd_ak4531_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t ...@@ -92,7 +91,6 @@ static int snd_ak4531_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
static int snd_ak4531_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) static int snd_ak4531_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{ {
ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol); ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff; int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 16) & 0x07; int shift = (kcontrol->private_value >> 16) & 0x07;
int mask = (kcontrol->private_value >> 24) & 0xff; int mask = (kcontrol->private_value >> 24) & 0xff;
...@@ -105,11 +103,11 @@ static int snd_ak4531_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t ...@@ -105,11 +103,11 @@ static int snd_ak4531_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
val = mask - val; val = mask - val;
} }
val <<= shift; val <<= shift;
spin_lock_irqsave(&ak4531->reg_lock, flags); down(&ak4531->reg_mutex);
val = (ak4531->regs[reg] & ~(mask << shift)) | val; val = (ak4531->regs[reg] & ~(mask << shift)) | val;
change = val != ak4531->regs[reg]; change = val != ak4531->regs[reg];
ak4531->write(ak4531, reg, ak4531->regs[reg] = val); ak4531->write(ak4531, reg, ak4531->regs[reg] = val);
spin_unlock_irqrestore(&ak4531->reg_lock, flags); up(&ak4531->reg_mutex);
return change; return change;
} }
...@@ -133,7 +131,6 @@ static int snd_ak4531_info_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t ...@@ -133,7 +131,6 @@ static int snd_ak4531_info_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
static int snd_ak4531_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) static int snd_ak4531_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{ {
ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol); ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff; int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff;
int left_shift = (kcontrol->private_value >> 16) & 0x07; int left_shift = (kcontrol->private_value >> 16) & 0x07;
...@@ -142,10 +139,10 @@ static int snd_ak4531_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t ...@@ -142,10 +139,10 @@ static int snd_ak4531_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
int invert = (kcontrol->private_value >> 22) & 1; int invert = (kcontrol->private_value >> 22) & 1;
int left, right; int left, right;
spin_lock_irqsave(&ak4531->reg_lock, flags); down(&ak4531->reg_mutex);
left = (ak4531->regs[left_reg] >> left_shift) & mask; left = (ak4531->regs[left_reg] >> left_shift) & mask;
right = (ak4531->regs[right_reg] >> right_shift) & mask; right = (ak4531->regs[right_reg] >> right_shift) & mask;
spin_unlock_irqrestore(&ak4531->reg_lock, flags); up(&ak4531->reg_mutex);
if (invert) { if (invert) {
left = mask - left; left = mask - left;
right = mask - right; right = mask - right;
...@@ -158,7 +155,6 @@ static int snd_ak4531_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t ...@@ -158,7 +155,6 @@ static int snd_ak4531_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
static int snd_ak4531_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) static int snd_ak4531_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{ {
ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol); ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff; int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff;
int left_shift = (kcontrol->private_value >> 16) & 0x07; int left_shift = (kcontrol->private_value >> 16) & 0x07;
...@@ -176,7 +172,7 @@ static int snd_ak4531_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t ...@@ -176,7 +172,7 @@ static int snd_ak4531_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
} }
left <<= left_shift; left <<= left_shift;
right <<= right_shift; right <<= right_shift;
spin_lock_irqsave(&ak4531->reg_lock, flags); down(&ak4531->reg_mutex);
if (left_reg == right_reg) { if (left_reg == right_reg) {
left = (ak4531->regs[left_reg] & ~((mask << left_shift) | (mask << right_shift))) | left | right; left = (ak4531->regs[left_reg] & ~((mask << left_shift) | (mask << right_shift))) | left | right;
change = left != ak4531->regs[left_reg]; change = left != ak4531->regs[left_reg];
...@@ -188,7 +184,7 @@ static int snd_ak4531_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t ...@@ -188,7 +184,7 @@ static int snd_ak4531_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left); ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left);
ak4531->write(ak4531, right_reg, ak4531->regs[right_reg] = right); ak4531->write(ak4531, right_reg, ak4531->regs[right_reg] = right);
} }
spin_unlock_irqrestore(&ak4531->reg_lock, flags); up(&ak4531->reg_mutex);
return change; return change;
} }
...@@ -210,25 +206,23 @@ static int snd_ak4531_info_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_info ...@@ -210,25 +206,23 @@ static int snd_ak4531_info_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_info
static int snd_ak4531_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) static int snd_ak4531_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{ {
ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol); ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg1 = kcontrol->private_value & 0xff; int reg1 = kcontrol->private_value & 0xff;
int reg2 = (kcontrol->private_value >> 8) & 0xff; int reg2 = (kcontrol->private_value >> 8) & 0xff;
int left_shift = (kcontrol->private_value >> 16) & 0x0f; int left_shift = (kcontrol->private_value >> 16) & 0x0f;
int right_shift = (kcontrol->private_value >> 24) & 0x0f; int right_shift = (kcontrol->private_value >> 24) & 0x0f;
spin_lock_irqsave(&ak4531->reg_lock, flags); down(&ak4531->reg_mutex);
ucontrol->value.integer.value[0] = (ak4531->regs[reg1] >> left_shift) & 1; ucontrol->value.integer.value[0] = (ak4531->regs[reg1] >> left_shift) & 1;
ucontrol->value.integer.value[1] = (ak4531->regs[reg2] >> left_shift) & 1; ucontrol->value.integer.value[1] = (ak4531->regs[reg2] >> left_shift) & 1;
ucontrol->value.integer.value[2] = (ak4531->regs[reg1] >> right_shift) & 1; ucontrol->value.integer.value[2] = (ak4531->regs[reg1] >> right_shift) & 1;
ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1; ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1;
spin_unlock_irqrestore(&ak4531->reg_lock, flags); up(&ak4531->reg_mutex);
return 0; return 0;
} }
static int snd_ak4531_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) static int snd_ak4531_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{ {
ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol); ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg1 = kcontrol->private_value & 0xff; int reg1 = kcontrol->private_value & 0xff;
int reg2 = (kcontrol->private_value >> 8) & 0xff; int reg2 = (kcontrol->private_value >> 8) & 0xff;
int left_shift = (kcontrol->private_value >> 16) & 0x0f; int left_shift = (kcontrol->private_value >> 16) & 0x0f;
...@@ -236,7 +230,7 @@ static int snd_ak4531_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value ...@@ -236,7 +230,7 @@ static int snd_ak4531_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
int change; int change;
int val1, val2; int val1, val2;
spin_lock_irqsave(&ak4531->reg_lock, flags); down(&ak4531->reg_mutex);
val1 = ak4531->regs[reg1] & ~((1 << left_shift) | (1 << right_shift)); val1 = ak4531->regs[reg1] & ~((1 << left_shift) | (1 << right_shift));
val2 = ak4531->regs[reg2] & ~((1 << left_shift) | (1 << right_shift)); val2 = ak4531->regs[reg2] & ~((1 << left_shift) | (1 << right_shift));
val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift; val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift;
...@@ -246,7 +240,7 @@ static int snd_ak4531_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value ...@@ -246,7 +240,7 @@ static int snd_ak4531_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
change = val1 != ak4531->regs[reg1] || val2 != ak4531->regs[reg2]; change = val1 != ak4531->regs[reg1] || val2 != ak4531->regs[reg2];
ak4531->write(ak4531, reg1, ak4531->regs[reg1] = val1); ak4531->write(ak4531, reg1, ak4531->regs[reg1] = val1);
ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2); ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2);
spin_unlock_irqrestore(&ak4531->reg_lock, flags); up(&ak4531->reg_mutex);
return change; return change;
} }
...@@ -367,7 +361,7 @@ int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531) ...@@ -367,7 +361,7 @@ int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531)
if (ak4531 == NULL) if (ak4531 == NULL)
return -ENOMEM; return -ENOMEM;
*ak4531 = *_ak4531; *ak4531 = *_ak4531;
spin_lock_init(&ak4531->reg_lock); init_MUTEX(&ak4531->reg_mutex);
if ((err = snd_component_add(card, "AK4531")) < 0) { if ((err = snd_component_add(card, "AK4531")) < 0) {
snd_ak4531_free(ak4531); snd_ak4531_free(ak4531);
return err; return err;
......
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