diff options
Diffstat (limited to 'sound')
537 files changed, 22518 insertions, 15689 deletions
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c index 47c6787158a7..f4254703d29f 100644 --- a/sound/ac97/bus.c +++ b/sound/ac97/bus.c @@ -241,10 +241,9 @@ static ssize_t cold_reset_store(struct device *dev, { struct ac97_controller *ac97_ctrl; - mutex_lock(&ac97_controllers_mutex); + guard(mutex)(&ac97_controllers_mutex); ac97_ctrl = to_ac97_controller(dev); ac97_ctrl->ops->reset(ac97_ctrl); - mutex_unlock(&ac97_controllers_mutex); return len; } static DEVICE_ATTR_WO(cold_reset); @@ -258,10 +257,9 @@ static ssize_t warm_reset_store(struct device *dev, if (!dev) return -ENODEV; - mutex_lock(&ac97_controllers_mutex); + guard(mutex)(&ac97_controllers_mutex); ac97_ctrl = to_ac97_controller(dev); ac97_ctrl->ops->warm_reset(ac97_ctrl); - mutex_unlock(&ac97_controllers_mutex); return len; } static DEVICE_ATTR_WO(warm_reset); @@ -284,10 +282,10 @@ static const struct attribute_group *ac97_adapter_groups[] = { static void ac97_del_adapter(struct ac97_controller *ac97_ctrl) { - mutex_lock(&ac97_controllers_mutex); - ac97_ctrl_codecs_unregister(ac97_ctrl); - list_del(&ac97_ctrl->controllers); - mutex_unlock(&ac97_controllers_mutex); + scoped_guard(mutex, &ac97_controllers_mutex) { + ac97_ctrl_codecs_unregister(ac97_ctrl); + list_del(&ac97_ctrl->controllers); + } device_unregister(&ac97_ctrl->adap); } @@ -311,7 +309,7 @@ static int ac97_add_adapter(struct ac97_controller *ac97_ctrl) { int ret; - mutex_lock(&ac97_controllers_mutex); + guard(mutex)(&ac97_controllers_mutex); ret = idr_alloc(&ac97_adapter_idr, ac97_ctrl, 0, 0, GFP_KERNEL); ac97_ctrl->nr = ret; if (ret >= 0) { @@ -322,13 +320,11 @@ static int ac97_add_adapter(struct ac97_controller *ac97_ctrl) if (ret) put_device(&ac97_ctrl->adap); } - if (!ret) + if (!ret) { list_add(&ac97_ctrl->controllers, &ac97_controllers); - mutex_unlock(&ac97_controllers_mutex); - - if (!ret) dev_dbg(&ac97_ctrl->adap, "adapter registered by %s\n", dev_name(ac97_ctrl->parent)); + } return ret; } diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index ac347a14f282..4cf959017c9d 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c @@ -122,10 +122,9 @@ static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); s8 l, r; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); - mutex_unlock(&onyx->mutex); ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT; ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT; @@ -146,15 +145,13 @@ static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[1] > -1 + VOLUME_RANGE_SHIFT) return -EINVAL; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] && - r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) { - mutex_unlock(&onyx->mutex); + r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) return 0; - } onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, ucontrol->value.integer.value[0] @@ -162,7 +159,6 @@ static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol, onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, ucontrol->value.integer.value[1] - VOLUME_RANGE_SHIFT); - mutex_unlock(&onyx->mutex); return 1; } @@ -198,9 +194,8 @@ static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); u8 ig; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig); - mutex_unlock(&onyx->mutex); ucontrol->value.integer.value[0] = (ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT; @@ -217,14 +212,13 @@ static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0] < 3 + INPUTGAIN_RANGE_SHIFT || ucontrol->value.integer.value[0] > 28 + INPUTGAIN_RANGE_SHIFT) return -EINVAL; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); n = v; n &= ~ONYX_ADC_PGA_GAIN_MASK; n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT) & ONYX_ADC_PGA_GAIN_MASK; onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n); - mutex_unlock(&onyx->mutex); return n != v; } @@ -252,9 +246,8 @@ static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); s8 v; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); - mutex_unlock(&onyx->mutex); ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC); @@ -265,13 +258,12 @@ static void onyx_set_capture_source(struct onyx *onyx, int mic) { s8 v; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); v &= ~ONYX_ADC_INPUT_MIC; if (mic) v |= ONYX_ADC_INPUT_MIC; onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v); - mutex_unlock(&onyx->mutex); } static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol, @@ -312,9 +304,8 @@ static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); u8 c; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c); - mutex_unlock(&onyx->mutex); ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT); ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT); @@ -329,9 +320,9 @@ static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol, u8 v = 0, c = 0; int err = -EBUSY; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); if (onyx->analog_locked) - goto out_unlock; + return -EBUSY; onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); c = v; @@ -342,9 +333,6 @@ static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol, c |= ONYX_MUTE_RIGHT; err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c); - out_unlock: - mutex_unlock(&onyx->mutex); - return !err ? (v != c) : err; } @@ -373,9 +361,8 @@ static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol, u8 address = (pv >> 8) & 0xff; u8 mask = pv & 0xff; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, address, &c); - mutex_unlock(&onyx->mutex); ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity; @@ -394,11 +381,10 @@ static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol, u8 address = (pv >> 8) & 0xff; u8 mask = pv & 0xff; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); if (spdiflock && onyx->spdif_locked) { /* even if alsamixer doesn't care.. */ - err = -EBUSY; - goto out_unlock; + return -EBUSY; } onyx_read_register(onyx, address, &v); c = v; @@ -407,9 +393,6 @@ static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol, c |= mask; err = onyx_write_register(onyx, address, c); - out_unlock: - mutex_unlock(&onyx->mutex); - return !err ? (v != c) : err; } @@ -490,7 +473,7 @@ static int onyx_spdif_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); u8 v; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); ucontrol->value.iec958.status[0] = v & 0x3e; @@ -502,7 +485,6 @@ static int onyx_spdif_get(struct snd_kcontrol *kcontrol, onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); ucontrol->value.iec958.status[4] = v & 0x0f; - mutex_unlock(&onyx->mutex); return 0; } @@ -513,7 +495,7 @@ static int onyx_spdif_put(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); u8 v; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e); onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v); @@ -528,7 +510,6 @@ static int onyx_spdif_put(struct snd_kcontrol *kcontrol, onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f); onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v); - mutex_unlock(&onyx->mutex); return 1; } @@ -673,14 +654,13 @@ static int onyx_usable(struct codec_info_item *cii, struct onyx *onyx = cii->codec_data; int spdif_enabled, analog_enabled; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); spdif_enabled = !!(v & ONYX_SPDIF_ENABLE); onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); analog_enabled = (v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT)) != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT); - mutex_unlock(&onyx->mutex); switch (ti->tag) { case 0: return 1; @@ -696,9 +676,8 @@ static int onyx_prepare(struct codec_info_item *cii, { u8 v; struct onyx *onyx = cii->codec_data; - int err = -EBUSY; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) { @@ -707,10 +686,9 @@ static int onyx_prepare(struct codec_info_item *cii, if (onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT)) - goto out_unlock; + return -EBUSY; onyx->analog_locked = 1; - err = 0; - goto out_unlock; + return 0; } #endif switch (substream->runtime->rate) { @@ -720,8 +698,7 @@ static int onyx_prepare(struct codec_info_item *cii, /* these rates are ok for all outputs */ /* FIXME: program spdif channel control bits here so that * userspace doesn't have to if it only plays pcm! */ - err = 0; - goto out_unlock; + return 0; default: /* got some rate that the digital output can't do, * so disable and lock it */ @@ -729,16 +706,12 @@ static int onyx_prepare(struct codec_info_item *cii, if (onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v & ~ONYX_SPDIF_ENABLE)) - goto out_unlock; + return -EBUSY; onyx->spdif_locked = 1; - err = 0; - goto out_unlock; + return 0; } - out_unlock: - mutex_unlock(&onyx->mutex); - - return err; + return -EBUSY; } static int onyx_open(struct codec_info_item *cii, @@ -746,9 +719,8 @@ static int onyx_open(struct codec_info_item *cii, { struct onyx *onyx = cii->codec_data; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx->open_count++; - mutex_unlock(&onyx->mutex); return 0; } @@ -758,11 +730,10 @@ static int onyx_close(struct codec_info_item *cii, { struct onyx *onyx = cii->codec_data; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx->open_count--; if (!onyx->open_count) onyx->spdif_locked = onyx->analog_locked = 0; - mutex_unlock(&onyx->mutex); return 0; } @@ -772,7 +743,7 @@ static int onyx_switch_clock(struct codec_info_item *cii, { struct onyx *onyx = cii->codec_data; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); /* this *MUST* be more elaborate later... */ switch (what) { case CLOCK_SWITCH_PREPARE_SLAVE: @@ -784,7 +755,6 @@ static int onyx_switch_clock(struct codec_info_item *cii, default: /* silence warning */ break; } - mutex_unlock(&onyx->mutex); return 0; } @@ -795,27 +765,21 @@ static int onyx_suspend(struct codec_info_item *cii, pm_message_t state) { struct onyx *onyx = cii->codec_data; u8 v; - int err = -ENXIO; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) - goto out_unlock; + return -ENXIO; onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV); /* Apple does a sleep here but the datasheet says to do it on resume */ - err = 0; - out_unlock: - mutex_unlock(&onyx->mutex); - - return err; + return 0; } static int onyx_resume(struct codec_info_item *cii) { struct onyx *onyx = cii->codec_data; u8 v; - int err = -ENXIO; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); /* reset codec */ onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); @@ -827,17 +791,13 @@ static int onyx_resume(struct codec_info_item *cii) /* take codec out of suspend (if it still is after reset) */ if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) - goto out_unlock; + return -ENXIO; onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV)); /* FIXME: should divide by sample rate, but 8k is the lowest we go */ msleep(2205000/8000); /* reset all values */ onyx_register_init(onyx); - err = 0; - out_unlock: - mutex_unlock(&onyx->mutex); - - return err; + return 0; } #endif /* CONFIG_PM */ @@ -1013,7 +973,7 @@ static int onyx_i2c_probe(struct i2c_client *client) goto fail; } - strscpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN); + strscpy(onyx->codec.name, "onyx"); onyx->codec.owner = THIS_MODULE; onyx->codec.init = onyx_init_codec; onyx->codec.exit = onyx_exit_codec; diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index 804b2ebbe28f..7085e0b93e29 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c @@ -235,10 +235,9 @@ static int tas_snd_vol_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->cached_volume_l; ucontrol->value.integer.value[1] = tas->cached_volume_r; - mutex_unlock(&tas->mtx); return 0; } @@ -254,18 +253,15 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[1] > 177) return -EINVAL; - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); if (tas->cached_volume_l == ucontrol->value.integer.value[0] - && tas->cached_volume_r == ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); + && tas->cached_volume_r == ucontrol->value.integer.value[1]) return 0; - } tas->cached_volume_l = ucontrol->value.integer.value[0]; tas->cached_volume_r = ucontrol->value.integer.value[1]; if (tas->hw_enabled) tas_set_volume(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -285,10 +281,9 @@ static int tas_snd_mute_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = !tas->mute_l; ucontrol->value.integer.value[1] = !tas->mute_r; - mutex_unlock(&tas->mtx); return 0; } @@ -297,18 +292,15 @@ static int tas_snd_mute_put(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); if (tas->mute_l == !ucontrol->value.integer.value[0] - && tas->mute_r == !ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); + && tas->mute_r == !ucontrol->value.integer.value[1]) return 0; - } tas->mute_l = !ucontrol->value.integer.value[0]; tas->mute_r = !ucontrol->value.integer.value[1]; if (tas->hw_enabled) tas_set_volume(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -337,10 +329,9 @@ static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol, struct tas *tas = snd_kcontrol_chip(kcontrol); int idx = kcontrol->private_value; - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->mixer_l[idx]; ucontrol->value.integer.value[1] = tas->mixer_r[idx]; - mutex_unlock(&tas->mtx); return 0; } @@ -351,19 +342,16 @@ static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol, struct tas *tas = snd_kcontrol_chip(kcontrol); int idx = kcontrol->private_value; - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); if (tas->mixer_l[idx] == ucontrol->value.integer.value[0] - && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); + && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) return 0; - } tas->mixer_l[idx] = ucontrol->value.integer.value[0]; tas->mixer_r[idx] = ucontrol->value.integer.value[1]; if (tas->hw_enabled) tas_set_mixer(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -396,9 +384,8 @@ static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->drc_range; - mutex_unlock(&tas->mtx); return 0; } @@ -411,16 +398,13 @@ static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] > TAS3004_DRC_MAX) return -EINVAL; - mutex_lock(&tas->mtx); - if (tas->drc_range == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + guard(mutex)(&tas->mtx); + if (tas->drc_range == ucontrol->value.integer.value[0]) return 0; - } tas->drc_range = ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas3004_set_drc(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -440,9 +424,8 @@ static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->drc_enabled; - mutex_unlock(&tas->mtx); return 0; } @@ -451,16 +434,13 @@ static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); - if (tas->drc_enabled == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + guard(mutex)(&tas->mtx); + if (tas->drc_enabled == ucontrol->value.integer.value[0]) return 0; - } tas->drc_enabled = !!ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas3004_set_drc(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -486,9 +466,8 @@ static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B); - mutex_unlock(&tas->mtx); return 0; } @@ -500,7 +479,7 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.enumerated.item[0] > 1) return -EINVAL; - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); oldacr = tas->acr; /* @@ -512,13 +491,10 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.enumerated.item[0]) tas->acr |= TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL | TAS_ACR_B_MON_SEL_RIGHT; - if (oldacr == tas->acr) { - mutex_unlock(&tas->mtx); + if (oldacr == tas->acr) return 0; - } if (tas->hw_enabled) tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); - mutex_unlock(&tas->mtx); return 1; } @@ -557,9 +533,8 @@ static int tas_snd_treble_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->treble; - mutex_unlock(&tas->mtx); return 0; } @@ -571,16 +546,13 @@ static int tas_snd_treble_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0] < TAS3004_TREBLE_MIN || ucontrol->value.integer.value[0] > TAS3004_TREBLE_MAX) return -EINVAL; - mutex_lock(&tas->mtx); - if (tas->treble == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + guard(mutex)(&tas->mtx); + if (tas->treble == ucontrol->value.integer.value[0]) return 0; - } tas->treble = ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas_set_treble(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -608,9 +580,8 @@ static int tas_snd_bass_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->bass; - mutex_unlock(&tas->mtx); return 0; } @@ -622,16 +593,13 @@ static int tas_snd_bass_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0] < TAS3004_BASS_MIN || ucontrol->value.integer.value[0] > TAS3004_BASS_MAX) return -EINVAL; - mutex_lock(&tas->mtx); - if (tas->bass == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + guard(mutex)(&tas->mtx); + if (tas->bass == ucontrol->value.integer.value[0]) return 0; - } tas->bass = ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas_set_bass(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -722,13 +690,13 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock break; case CLOCK_SWITCH_SLAVE: /* Clocks are back, re-init the codec */ - mutex_lock(&tas->mtx); - tas_reset_init(tas); - tas_set_volume(tas); - tas_set_mixer(tas); - tas->hw_enabled = 1; - tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); - mutex_unlock(&tas->mtx); + scoped_guard(mutex, &tas->mtx) { + tas_reset_init(tas); + tas_set_volume(tas); + tas_set_mixer(tas); + tas->hw_enabled = 1; + tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); + } break; default: /* doesn't happen as of now */ @@ -743,23 +711,21 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock * our i2c device is suspended, and then take note of that! */ static int tas_suspend(struct tas *tas) { - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); tas->hw_enabled = 0; tas->acr |= TAS_ACR_ANALOG_PDOWN; tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); - mutex_unlock(&tas->mtx); return 0; } static int tas_resume(struct tas *tas) { /* reset codec */ - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); tas_reset_init(tas); tas_set_volume(tas); tas_set_mixer(tas); tas->hw_enabled = 1; - mutex_unlock(&tas->mtx); return 0; } @@ -802,14 +768,13 @@ static int tas_init_codec(struct aoa_codec *codec) return -EINVAL; } - mutex_lock(&tas->mtx); - if (tas_reset_init(tas)) { - printk(KERN_ERR PFX "tas failed to initialise\n"); - mutex_unlock(&tas->mtx); - return -ENXIO; + scoped_guard(mutex, &tas->mtx) { + if (tas_reset_init(tas)) { + printk(KERN_ERR PFX "tas failed to initialise\n"); + return -ENXIO; + } + tas->hw_enabled = 1; } - tas->hw_enabled = 1; - mutex_unlock(&tas->mtx); if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, aoa_get_card(), @@ -892,7 +857,7 @@ static int tas_i2c_probe(struct i2c_client *client) /* seems that half is a saner default */ tas->drc_range = TAS3004_DRC_MAX / 2; - strscpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN); + strscpy(tas->codec.name, "tas"); tas->codec.owner = THIS_MODULE; tas->codec.init = tas_init_codec; tas->codec.exit = tas_exit_codec; diff --git a/sound/aoa/codecs/toonie.c b/sound/aoa/codecs/toonie.c index 0da5af129492..b59967c49e0a 100644 --- a/sound/aoa/codecs/toonie.c +++ b/sound/aoa/codecs/toonie.c @@ -126,7 +126,7 @@ static int __init toonie_init(void) if (!toonie) return -ENOMEM; - strscpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name)); + strscpy(toonie->codec.name, "toonie"); toonie->codec.owner = THIS_MODULE; toonie->codec.init = toonie_init_codec; toonie->codec.exit = toonie_exit_codec; diff --git a/sound/aoa/core/alsa.c b/sound/aoa/core/alsa.c index 7fce8581ddbd..aad7dfe089c7 100644 --- a/sound/aoa/core/alsa.c +++ b/sound/aoa/core/alsa.c @@ -28,10 +28,10 @@ int aoa_alsa_init(char *name, struct module *mod, struct device *dev) return err; aoa_card = alsa_card->private_data; aoa_card->alsa_card = alsa_card; - strscpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver)); - strscpy(alsa_card->shortname, name, sizeof(alsa_card->shortname)); - strscpy(alsa_card->longname, name, sizeof(alsa_card->longname)); - strscpy(alsa_card->mixername, name, sizeof(alsa_card->mixername)); + strscpy(alsa_card->driver, "AppleOnbdAudio"); + strscpy(alsa_card->shortname, name); + strscpy(alsa_card->longname, name); + strscpy(alsa_card->mixername, name); err = snd_card_register(aoa_card->alsa_card); if (err < 0) { printk(KERN_ERR "snd-aoa: couldn't register alsa card\n"); diff --git a/sound/aoa/core/gpio-feature.c b/sound/aoa/core/gpio-feature.c index 39bb409b27f6..19ed0e6907da 100644 --- a/sound/aoa/core/gpio-feature.c +++ b/sound/aoa/core/gpio-feature.c @@ -212,10 +212,9 @@ static void ftr_handle_notify(struct work_struct *work) struct gpio_notification *notif = container_of(work, struct gpio_notification, work.work); - mutex_lock(¬if->mutex); + guard(mutex)(¬if->mutex); if (notif->notify) notif->notify(notif->data); - mutex_unlock(¬if->mutex); } static void gpio_enable_dual_edge(int gpio) @@ -341,19 +340,17 @@ static int ftr_set_notify(struct gpio_runtime *rt, if (!irq) return -ENODEV; - mutex_lock(¬if->mutex); + guard(mutex)(¬if->mutex); old = notif->notify; - if (!old && !notify) { - err = 0; - goto out_unlock; - } + if (!old && !notify) + return 0; if (old && notify) { if (old == notify && notif->data == data) err = 0; - goto out_unlock; + return err; } if (old && !notify) @@ -362,16 +359,13 @@ static int ftr_set_notify(struct gpio_runtime *rt, if (!old && notify) { err = request_irq(irq, ftr_handle_notify_irq, 0, name, notif); if (err) - goto out_unlock; + return err; } notif->notify = notify; notif->data = data; - err = 0; - out_unlock: - mutex_unlock(¬if->mutex); - return err; + return 0; } static int ftr_get_detect(struct gpio_runtime *rt, diff --git a/sound/aoa/core/gpio-pmf.c b/sound/aoa/core/gpio-pmf.c index 37866039d1ea..e76bde25e41a 100644 --- a/sound/aoa/core/gpio-pmf.c +++ b/sound/aoa/core/gpio-pmf.c @@ -74,10 +74,9 @@ static void pmf_handle_notify(struct work_struct *work) struct gpio_notification *notif = container_of(work, struct gpio_notification, work.work); - mutex_lock(¬if->mutex); + guard(mutex)(¬if->mutex); if (notif->notify) notif->notify(notif->data); - mutex_unlock(¬if->mutex); } static void pmf_gpio_init(struct gpio_runtime *rt) @@ -154,19 +153,17 @@ static int pmf_set_notify(struct gpio_runtime *rt, return -EINVAL; } - mutex_lock(¬if->mutex); + guard(mutex)(¬if->mutex); old = notif->notify; - if (!old && !notify) { - err = 0; - goto out_unlock; - } + if (!old && !notify) + return 0; if (old && notify) { if (old == notify && notif->data == data) err = 0; - goto out_unlock; + return err; } if (old && !notify) { @@ -178,10 +175,8 @@ static int pmf_set_notify(struct gpio_runtime *rt, if (!old && notify) { irq_client = kzalloc(sizeof(struct pmf_irq_client), GFP_KERNEL); - if (!irq_client) { - err = -ENOMEM; - goto out_unlock; - } + if (!irq_client) + return -ENOMEM; irq_client->data = notif; irq_client->handler = pmf_handle_notify_irq; irq_client->owner = THIS_MODULE; @@ -192,17 +187,14 @@ static int pmf_set_notify(struct gpio_runtime *rt, printk(KERN_ERR "snd-aoa: gpio layer failed to" " register %s irq (%d)\n", name, err); kfree(irq_client); - goto out_unlock; + return err; } notif->gpio_private = irq_client; } notif->notify = notify; notif->data = data; - err = 0; - out_unlock: - mutex_unlock(¬if->mutex); - return err; + return 0; } static int pmf_get_detect(struct gpio_runtime *rt, diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index e68b4cb4df29..bb2a0ef3004b 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c @@ -949,8 +949,7 @@ static void layout_attached_codec(struct aoa_codec *codec) ldev->gpio.methods->set_lineout(codec->gpio, 1); ctl = snd_ctl_new1(&lineout_ctl, codec->gpio); if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) - strscpy(ctl->id.name, - "Headphone Switch", sizeof(ctl->id.name)); + strscpy(ctl->id.name, "Headphone Switch"); ldev->lineout_ctrl = ctl; aoa_snd_ctl_add(ctl); ldev->have_lineout_detect = @@ -964,15 +963,13 @@ static void layout_attached_codec(struct aoa_codec *codec) ldev); if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) strscpy(ctl->id.name, - "Headphone Detect Autoswitch", - sizeof(ctl->id.name)); + "Headphone Detect Autoswitch"); aoa_snd_ctl_add(ctl); ctl = snd_ctl_new1(&lineout_detected, ldev); if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) strscpy(ctl->id.name, - "Headphone Detected", - sizeof(ctl->id.name)); + "Headphone Detected"); ldev->lineout_detected_ctrl = ctl; aoa_snd_ctl_add(ctl); } diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index ce84288168e4..f4d43c854bbd 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c @@ -93,14 +93,12 @@ static irqreturn_t i2sbus_bus_intr(int irq, void *devid) struct i2sbus_dev *dev = devid; u32 intreg; - spin_lock(&dev->low_lock); + guard(spinlock)(&dev->low_lock); intreg = in_le32(&dev->intfregs->intr_ctl); /* acknowledge interrupt reasons */ out_le32(&dev->intfregs->intr_ctl, intreg); - spin_unlock(&dev->low_lock); - return IRQ_HANDLED; } diff --git a/sound/aoa/soundbus/i2sbus/pcm.c b/sound/aoa/soundbus/i2sbus/pcm.c index 98b812ffbde6..4c480ad2c05d 100644 --- a/sound/aoa/soundbus/i2sbus/pcm.c +++ b/sound/aoa/soundbus/i2sbus/pcm.c @@ -79,11 +79,10 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) u64 formats = 0; unsigned int rates = 0; struct transfer_info v; - int result = 0; int bus_factor = 0, sysclock_factor = 0; int found_this; - mutex_lock(&i2sdev->lock); + guard(mutex)(&i2sdev->lock); get_pcm_info(i2sdev, in, &pi, &other); @@ -92,8 +91,7 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) if (pi->active) { /* alsa messed up */ - result = -EBUSY; - goto out_unlock; + return -EBUSY; } /* we now need to assign the hw */ @@ -117,10 +115,8 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) ti++; } } - if (!masks_inited || !bus_factor || !sysclock_factor) { - result = -ENODEV; - goto out_unlock; - } + if (!masks_inited || !bus_factor || !sysclock_factor) + return -ENODEV; /* bus dependent stuff */ hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME | @@ -194,15 +190,12 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) hw->periods_max = MAX_DBDMA_COMMANDS; err = snd_pcm_hw_constraint_integer(pi->substream->runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) { - result = err; - goto out_unlock; - } + if (err < 0) + return err; list_for_each_entry(cii, &sdev->codec_list, list) { if (cii->codec->open) { err = cii->codec->open(cii, pi->substream); if (err) { - result = err; /* unwind */ found_this = 0; list_for_each_entry_reverse(rev, @@ -214,14 +207,12 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) if (rev == cii) found_this = 1; } - goto out_unlock; + return err; } } } - out_unlock: - mutex_unlock(&i2sdev->lock); - return result; + return 0; } #undef CHECK_RATE @@ -232,7 +223,7 @@ static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in) struct pcm_info *pi; int err = 0, tmp; - mutex_lock(&i2sdev->lock); + guard(mutex)(&i2sdev->lock); get_pcm_info(i2sdev, in, &pi, NULL); @@ -246,7 +237,6 @@ static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in) pi->substream = NULL; pi->active = 0; - mutex_unlock(&i2sdev->lock); return err; } @@ -330,33 +320,26 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) int input_16bit; struct pcm_info *pi, *other; int cnt; - int result = 0; unsigned int cmd, stopaddr; - mutex_lock(&i2sdev->lock); + guard(mutex)(&i2sdev->lock); get_pcm_info(i2sdev, in, &pi, &other); - if (pi->dbdma_ring.running) { - result = -EBUSY; - goto out_unlock; - } + if (pi->dbdma_ring.running) + return -EBUSY; if (pi->dbdma_ring.stopping) i2sbus_wait_for_stop(i2sdev, pi); - if (!pi->substream || !pi->substream->runtime) { - result = -EINVAL; - goto out_unlock; - } + if (!pi->substream || !pi->substream->runtime) + return -EINVAL; runtime = pi->substream->runtime; pi->active = 1; if (other->active && ((i2sdev->format != runtime->format) - || (i2sdev->rate != runtime->rate))) { - result = -EINVAL; - goto out_unlock; - } + || (i2sdev->rate != runtime->rate))) + return -EINVAL; i2sdev->format = runtime->format; i2sdev->rate = runtime->rate; @@ -412,10 +395,8 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) bi.bus_factor = cii->codec->bus_factor; break; } - if (!bi.bus_factor) { - result = -ENODEV; - goto out_unlock; - } + if (!bi.bus_factor) + return -ENODEV; input_16bit = 1; break; case SNDRV_PCM_FORMAT_S32_BE: @@ -426,8 +407,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) input_16bit = 0; break; default: - result = -EINVAL; - goto out_unlock; + return -EINVAL; } /* we assume all sysclocks are the same! */ list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { @@ -438,10 +418,8 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) if (clock_and_divisors(bi.sysclock_factor, bi.bus_factor, runtime->rate, - &sfr) < 0) { - result = -EINVAL; - goto out_unlock; - } + &sfr) < 0) + return -EINVAL; switch (bi.bus_factor) { case 32: sfr |= I2S_SF_SERIAL_FORMAT_I2S_32X; @@ -457,10 +435,8 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) int err = 0; if (cii->codec->prepare) err = cii->codec->prepare(cii, &bi, pi->substream); - if (err) { - result = err; - goto out_unlock; - } + if (err) + return err; } /* codecs are fine with it, so set our clocks */ if (input_16bit) @@ -476,7 +452,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) /* not locking these is fine since we touch them only in this function */ if (in_le32(&i2sdev->intfregs->serial_format) == sfr && in_le32(&i2sdev->intfregs->data_word_sizes) == dws) - goto out_unlock; + return 0; /* let's notify the codecs about clocks going away. * For now we only do mastering on the i2s cell... */ @@ -514,9 +490,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) if (cii->codec->switch_clock) cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE); - out_unlock: - mutex_unlock(&i2sdev->lock); - return result; + return 0; } #ifdef CONFIG_PM @@ -531,20 +505,16 @@ static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd) { struct codec_info_item *cii; struct pcm_info *pi; - int result = 0; - unsigned long flags; - spin_lock_irqsave(&i2sdev->low_lock, flags); + guard(spinlock_irqsave)(&i2sdev->low_lock); get_pcm_info(i2sdev, in, &pi, NULL); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: - if (pi->dbdma_ring.running) { - result = -EALREADY; - goto out_unlock; - } + if (pi->dbdma_ring.running) + return -EALREADY; list_for_each_entry(cii, &i2sdev->sound.codec_list, list) if (cii->codec->start) cii->codec->start(cii, pi->substream); @@ -558,7 +528,7 @@ static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd) udelay(10); if (in_le32(&pi->dbdma->status) & ACTIVE) { pi->dbdma_ring.stopping = 0; - goto out_unlock; /* keep running */ + return 0; /* keep running */ } } } @@ -584,10 +554,8 @@ static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd) case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: - if (!pi->dbdma_ring.running) { - result = -EALREADY; - goto out_unlock; - } + if (!pi->dbdma_ring.running) + return -EALREADY; pi->dbdma_ring.running = 0; /* Set the S0 bit to make the DMA branch to the stop cmd */ @@ -599,13 +567,10 @@ static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd) cii->codec->stop(cii, pi->substream); break; default: - result = -EINVAL; - goto out_unlock; + return -EINVAL; } - out_unlock: - spin_unlock_irqrestore(&i2sdev->low_lock, flags); - return result; + return 0; } static snd_pcm_uframes_t i2sbus_pcm_pointer(struct i2sbus_dev *i2sdev, int in) @@ -632,70 +597,67 @@ static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in) int dma_stopped = 0; struct snd_pcm_runtime *runtime; - spin_lock(&i2sdev->low_lock); - get_pcm_info(i2sdev, in, &pi, NULL); - if (!pi->dbdma_ring.running && !pi->dbdma_ring.stopping) - goto out_unlock; + scoped_guard(spinlock, &i2sdev->low_lock) { + get_pcm_info(i2sdev, in, &pi, NULL); + if (!pi->dbdma_ring.running && !pi->dbdma_ring.stopping) + return; + + i = pi->current_period; + runtime = pi->substream->runtime; + while (pi->dbdma_ring.cmds[i].xfer_status) { + if (le16_to_cpu(pi->dbdma_ring.cmds[i].xfer_status) & BT) + /* + * BT is the branch taken bit. If it took a branch + * it is because we set the S0 bit to make it + * branch to the stop command. + */ + dma_stopped = 1; + pi->dbdma_ring.cmds[i].xfer_status = 0; + + if (++i >= runtime->periods) { + i = 0; + pi->frame_count += runtime->buffer_size; + } + pi->current_period = i; - i = pi->current_period; - runtime = pi->substream->runtime; - while (pi->dbdma_ring.cmds[i].xfer_status) { - if (le16_to_cpu(pi->dbdma_ring.cmds[i].xfer_status) & BT) /* - * BT is the branch taken bit. If it took a branch - * it is because we set the S0 bit to make it - * branch to the stop command. + * Check the frame count. The DMA tends to get a bit + * ahead of the frame counter, which confuses the core. */ - dma_stopped = 1; - pi->dbdma_ring.cmds[i].xfer_status = 0; - - if (++i >= runtime->periods) { - i = 0; - pi->frame_count += runtime->buffer_size; + fc = in_le32(&i2sdev->intfregs->frame_count); + nframes = i * runtime->period_size; + if (fc < pi->frame_count + nframes) + pi->frame_count = fc - nframes; } - pi->current_period = i; - - /* - * Check the frame count. The DMA tends to get a bit - * ahead of the frame counter, which confuses the core. - */ - fc = in_le32(&i2sdev->intfregs->frame_count); - nframes = i * runtime->period_size; - if (fc < pi->frame_count + nframes) - pi->frame_count = fc - nframes; - } - if (dma_stopped) { - timeout = 1000; - for (;;) { - status = in_le32(&pi->dbdma->status); - if (!(status & ACTIVE) && (!in || (status & 0x80))) - break; - if (--timeout <= 0) { - printk(KERN_ERR "i2sbus: timed out " - "waiting for DMA to stop!\n"); - break; + if (dma_stopped) { + timeout = 1000; + for (;;) { + status = in_le32(&pi->dbdma->status); + if (!(status & ACTIVE) && (!in || (status & 0x80))) + break; + if (--timeout <= 0) { + printk(KERN_ERR + "i2sbus: timed out waiting for DMA to stop!\n"); + break; + } + udelay(1); } - udelay(1); - } - /* Turn off DMA controller, clear S0 bit */ - out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16); + /* Turn off DMA controller, clear S0 bit */ + out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16); - pi->dbdma_ring.stopping = 0; - if (pi->stop_completion) - complete(pi->stop_completion); + pi->dbdma_ring.stopping = 0; + if (pi->stop_completion) + complete(pi->stop_completion); + } + + if (!pi->dbdma_ring.running) + return; } - if (!pi->dbdma_ring.running) - goto out_unlock; - spin_unlock(&i2sdev->low_lock); /* may call _trigger again, hence needs to be unlocked */ snd_pcm_period_elapsed(pi->substream); - return; - - out_unlock: - spin_unlock(&i2sdev->low_lock); } irqreturn_t i2sbus_tx_intr(int irq, void *devid) diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 243965615ef2..5548ed8e6b1c 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -73,7 +73,7 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, if (ac97->num >= 4) return; - mutex_lock(&aaci->ac97_sem); + guard(mutex)(&aaci->ac97_sem); aaci_ac97_select_codec(aaci, ac97); @@ -97,8 +97,6 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, if (v & (SLFR_1TXB|SLFR_2TXB)) dev_err(&aaci->dev->dev, "timeout waiting for write to complete\n"); - - mutex_unlock(&aaci->ac97_sem); } /* @@ -113,7 +111,7 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) if (ac97->num >= 4) return ~0; - mutex_lock(&aaci->ac97_sem); + guard(mutex)(&aaci->ac97_sem); aaci_ac97_select_codec(aaci, ac97); @@ -134,8 +132,7 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) if (v & SLFR_1TXB) { dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n"); - v = ~0; - goto out; + return ~0; } /* Now wait for the response frame */ @@ -151,8 +148,7 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) if (v != (SLFR_1RXV|SLFR_2RXV)) { dev_err(&aaci->dev->dev, "timeout on RX valid\n"); - v = ~0; - goto out; + return ~0; } do { @@ -171,8 +167,6 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) v = ~0; } } while (retries); - out: - mutex_unlock(&aaci->ac97_sem); return v; } @@ -216,45 +210,43 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) return; } - spin_lock(&aacirun->lock); - - ptr = aacirun->ptr; - do { - unsigned int len = aacirun->fifo_bytes; - u32 val; - - if (aacirun->bytes <= 0) { - aacirun->bytes += aacirun->period; - period_elapsed = true; - } - if (!(aacirun->cr & CR_EN)) - break; - - val = readl(aacirun->base + AACI_SR); - if (!(val & SR_RXHF)) - break; - if (!(val & SR_RXFF)) - len >>= 1; - - aacirun->bytes -= len; - - /* reading 16 bytes at a time */ - for( ; len > 0; len -= 16) { - asm( - "ldmia %1, {r0, r1, r2, r3}\n\t" - "stmia %0!, {r0, r1, r2, r3}" - : "+r" (ptr) - : "r" (aacirun->fifo) - : "r0", "r1", "r2", "r3", "cc"); - - if (ptr >= aacirun->end) - ptr = aacirun->start; - } - } while(1); - - aacirun->ptr = ptr; - - spin_unlock(&aacirun->lock); + scoped_guard(spinlock, &aacirun->lock) { + ptr = aacirun->ptr; + do { + unsigned int len = aacirun->fifo_bytes; + u32 val; + + if (aacirun->bytes <= 0) { + aacirun->bytes += aacirun->period; + period_elapsed = true; + } + if (!(aacirun->cr & CR_EN)) + break; + + val = readl(aacirun->base + AACI_SR); + if (!(val & SR_RXHF)) + break; + if (!(val & SR_RXFF)) + len >>= 1; + + aacirun->bytes -= len; + + /* reading 16 bytes at a time */ + for( ; len > 0; len -= 16) { + asm( + "ldmia %1, {r0, r1, r2, r3}\n\t" + "stmia %0!, {r0, r1, r2, r3}" + : "+r" (ptr) + : "r" (aacirun->fifo) + : "r0", "r1", "r2", "r3", "cc"); + + if (ptr >= aacirun->end) + ptr = aacirun->start; + } + } while(1); + + aacirun->ptr = ptr; + } if (period_elapsed) snd_pcm_period_elapsed(aacirun->substream); @@ -276,45 +268,43 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) return; } - spin_lock(&aacirun->lock); - - ptr = aacirun->ptr; - do { - unsigned int len = aacirun->fifo_bytes; - u32 val; - - if (aacirun->bytes <= 0) { - aacirun->bytes += aacirun->period; - period_elapsed = true; - } - if (!(aacirun->cr & CR_EN)) - break; - - val = readl(aacirun->base + AACI_SR); - if (!(val & SR_TXHE)) - break; - if (!(val & SR_TXFE)) - len >>= 1; - - aacirun->bytes -= len; - - /* writing 16 bytes at a time */ - for ( ; len > 0; len -= 16) { - asm( - "ldmia %0!, {r0, r1, r2, r3}\n\t" - "stmia %1, {r0, r1, r2, r3}" - : "+r" (ptr) - : "r" (aacirun->fifo) - : "r0", "r1", "r2", "r3", "cc"); - - if (ptr >= aacirun->end) - ptr = aacirun->start; - } - } while (1); - - aacirun->ptr = ptr; - - spin_unlock(&aacirun->lock); + scoped_guard(spinlock, &aacirun->lock) { + ptr = aacirun->ptr; + do { + unsigned int len = aacirun->fifo_bytes; + u32 val; + + if (aacirun->bytes <= 0) { + aacirun->bytes += aacirun->period; + period_elapsed = true; + } + if (!(aacirun->cr & CR_EN)) + break; + + val = readl(aacirun->base + AACI_SR); + if (!(val & SR_TXHE)) + break; + if (!(val & SR_TXFE)) + len >>= 1; + + aacirun->bytes -= len; + + /* writing 16 bytes at a time */ + for ( ; len > 0; len -= 16) { + asm( + "ldmia %0!, {r0, r1, r2, r3}\n\t" + "stmia %1, {r0, r1, r2, r3}" + : "+r" (ptr) + : "r" (aacirun->fifo) + : "r0", "r1", "r2", "r3", "cc"); + + if (ptr >= aacirun->end) + ptr = aacirun->start; + } + } while (1); + + aacirun->ptr = ptr; + } if (period_elapsed) snd_pcm_period_elapsed(aacirun->substream); @@ -437,14 +427,13 @@ static int aaci_pcm_open(struct snd_pcm_substream *substream) */ runtime->hw.fifo_size = aaci->fifo_depth * 2; - mutex_lock(&aaci->irq_lock); + guard(mutex)(&aaci->irq_lock); if (!aaci->users++) { ret = request_irq(aaci->dev->irq[0], aaci_irq, IRQF_SHARED, DRIVER_NAME, aaci); if (ret != 0) aaci->users--; } - mutex_unlock(&aaci->irq_lock); return ret; } @@ -462,10 +451,9 @@ static int aaci_pcm_close(struct snd_pcm_substream *substream) aacirun->substream = NULL; - mutex_lock(&aaci->irq_lock); + guard(mutex)(&aaci->irq_lock); if (!--aaci->users) free_irq(aaci->dev->irq[0], aaci); - mutex_unlock(&aaci->irq_lock); return 0; } @@ -585,10 +573,8 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun) static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) { struct aaci_runtime *aacirun = substream->runtime->private_data; - unsigned long flags; - int ret = 0; - spin_lock_irqsave(&aacirun->lock, flags); + guard(spinlock_irqsave)(&aacirun->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -614,12 +600,10 @@ static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cm break; default: - ret = -EINVAL; + return -EINVAL; } - spin_unlock_irqrestore(&aacirun->lock, flags); - - return ret; + return 0; } static const struct snd_pcm_ops aaci_playback_ops = { @@ -669,10 +653,8 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun) static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) { struct aaci_runtime *aacirun = substream->runtime->private_data; - unsigned long flags; - int ret = 0; - spin_lock_irqsave(&aacirun->lock, flags); + guard(spinlock_irqsave)(&aacirun->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -698,12 +680,10 @@ static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd break; default: - ret = -EINVAL; + return -EINVAL; } - spin_unlock_irqrestore(&aacirun->lock, flags); - - return ret; + return 0; } static int aaci_pcm_capture_prepare(struct snd_pcm_substream *substream) diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index a03a3291de84..64510318091f 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -51,7 +51,7 @@ int pxa2xx_ac97_read(int slot, unsigned short reg) if (slot > 0) return -ENODEV; - mutex_lock(&car_mutex); + guard(mutex)(&car_mutex); /* set up primary or secondary codec space */ if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS) @@ -67,13 +67,12 @@ int pxa2xx_ac97_read(int slot, unsigned short reg) gsr_bits = 0; val = (readl(reg_addr) & 0xffff); if (reg == AC97_GPIO_STATUS) - goto out; + return val; if (wait_event_timeout(gsr_wq, (readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE, 1) <= 0 && !((readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE)) { printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n", __func__, reg, readl(ac97_reg_base + GSR) | gsr_bits); - val = -ETIMEDOUT; - goto out; + return -ETIMEDOUT; } /* valid data now */ @@ -82,8 +81,6 @@ int pxa2xx_ac97_read(int slot, unsigned short reg) val = (readl(reg_addr) & 0xffff); /* but we've just started another cycle... */ wait_event_timeout(gsr_wq, (readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE, 1); - -out: mutex_unlock(&car_mutex); return val; } EXPORT_SYMBOL_GPL(pxa2xx_ac97_read); @@ -93,7 +90,7 @@ int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val) u32 __iomem *reg_addr; int ret = 0; - mutex_lock(&car_mutex); + guard(mutex)(&car_mutex); /* set up primary or secondary codec space */ if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS) @@ -114,7 +111,6 @@ int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val) ret = -EIO; } - mutex_unlock(&car_mutex); return ret; } EXPORT_SYMBOL_GPL(pxa2xx_ac97_write); diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 693d48f08b88..df0a049192de 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -88,7 +88,7 @@ static int atmel_ac97c_playback_open(struct snd_pcm_substream *substream) struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - mutex_lock(&opened_mutex); + guard(mutex)(&opened_mutex); chip->opened++; runtime->hw = atmel_ac97c_hw; if (chip->cur_rate) { @@ -97,7 +97,6 @@ static int atmel_ac97c_playback_open(struct snd_pcm_substream *substream) } if (chip->cur_format) runtime->hw.formats = pcm_format_to_bits(chip->cur_format); - mutex_unlock(&opened_mutex); chip->playback_substream = substream; return 0; } @@ -107,7 +106,7 @@ static int atmel_ac97c_capture_open(struct snd_pcm_substream *substream) struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - mutex_lock(&opened_mutex); + guard(mutex)(&opened_mutex); chip->opened++; runtime->hw = atmel_ac97c_hw; if (chip->cur_rate) { @@ -116,7 +115,6 @@ static int atmel_ac97c_capture_open(struct snd_pcm_substream *substream) } if (chip->cur_format) runtime->hw.formats = pcm_format_to_bits(chip->cur_format); - mutex_unlock(&opened_mutex); chip->capture_substream = substream; return 0; } @@ -125,13 +123,12 @@ static int atmel_ac97c_playback_close(struct snd_pcm_substream *substream) { struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - mutex_lock(&opened_mutex); + guard(mutex)(&opened_mutex); chip->opened--; if (!chip->opened) { chip->cur_rate = 0; chip->cur_format = 0; } - mutex_unlock(&opened_mutex); chip->playback_substream = NULL; @@ -142,13 +139,12 @@ static int atmel_ac97c_capture_close(struct snd_pcm_substream *substream) { struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - mutex_lock(&opened_mutex); + guard(mutex)(&opened_mutex); chip->opened--; if (!chip->opened) { chip->cur_rate = 0; chip->cur_format = 0; } - mutex_unlock(&opened_mutex); chip->capture_substream = NULL; @@ -161,10 +157,9 @@ static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream, struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); /* Set restrictions to params. */ - mutex_lock(&opened_mutex); + guard(mutex)(&opened_mutex); chip->cur_rate = params_rate(hw_params); chip->cur_format = params_format(hw_params); - mutex_unlock(&opened_mutex); return 0; } @@ -175,10 +170,9 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream, struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); /* Set restrictions to params. */ - mutex_lock(&opened_mutex); + guard(mutex)(&opened_mutex); chip->cur_rate = params_rate(hw_params); chip->cur_format = params_format(hw_params); - mutex_unlock(&opened_mutex); return 0; } diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index a66f258cafaa..da514fef45bc 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -176,14 +176,25 @@ static int snd_compr_free(struct inode *inode, struct file *f) return 0; } +static void +snd_compr_tstamp32_from_64(struct snd_compr_tstamp *tstamp32, + const struct snd_compr_tstamp64 *tstamp64) +{ + tstamp32->byte_offset = tstamp64->byte_offset; + tstamp32->copied_total = (u32)tstamp64->copied_total; + tstamp32->pcm_frames = (u32)tstamp64->pcm_frames; + tstamp32->pcm_io_frames = (u32)tstamp64->pcm_io_frames; + tstamp32->sampling_rate = tstamp64->sampling_rate; +} + static int snd_compr_update_tstamp(struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { if (!stream->ops->pointer) return -ENOTSUPP; stream->ops->pointer(stream, tstamp); - pr_debug("dsp consumed till %d total %d bytes\n", - tstamp->byte_offset, tstamp->copied_total); + pr_debug("dsp consumed till %u total %llu bytes\n", tstamp->byte_offset, + tstamp->copied_total); if (stream->direction == SND_COMPRESS_PLAYBACK) stream->runtime->total_bytes_transferred = tstamp->copied_total; else @@ -192,7 +203,7 @@ static int snd_compr_update_tstamp(struct snd_compr_stream *stream, } static size_t snd_compr_calc_avail(struct snd_compr_stream *stream, - struct snd_compr_avail *avail) + struct snd_compr_avail64 *avail) { memset(avail, 0, sizeof(*avail)); snd_compr_update_tstamp(stream, &avail->tstamp); @@ -204,9 +215,9 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream, pr_debug("detected init and someone forgot to do a write\n"); return stream->runtime->buffer_size; } - pr_debug("app wrote %lld, DSP consumed %lld\n", - stream->runtime->total_bytes_available, - stream->runtime->total_bytes_transferred); + pr_debug("app wrote %llu, DSP consumed %llu\n", + stream->runtime->total_bytes_available, + stream->runtime->total_bytes_transferred); if (stream->runtime->total_bytes_available == stream->runtime->total_bytes_transferred) { if (stream->direction == SND_COMPRESS_PLAYBACK) { @@ -223,28 +234,43 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream, if (stream->direction == SND_COMPRESS_PLAYBACK) avail->avail = stream->runtime->buffer_size - avail->avail; - pr_debug("ret avail as %lld\n", avail->avail); + pr_debug("ret avail as %zu\n", (size_t)avail->avail); return avail->avail; } static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream) { - struct snd_compr_avail avail; + struct snd_compr_avail64 avail; return snd_compr_calc_avail(stream, &avail); } -static int -snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg) +static void snd_compr_avail32_from_64(struct snd_compr_avail *avail32, + const struct snd_compr_avail64 *avail64) { - struct snd_compr_avail ioctl_avail; + avail32->avail = avail64->avail; + snd_compr_tstamp32_from_64(&avail32->tstamp, &avail64->tstamp); +} + +static int snd_compr_ioctl_avail(struct snd_compr_stream *stream, + unsigned long arg, bool is_32bit) +{ + struct snd_compr_avail64 ioctl_avail64; + struct snd_compr_avail ioctl_avail32; size_t avail; + const void *copy_from = &ioctl_avail64; + size_t copy_size = sizeof(ioctl_avail64); if (stream->direction == SND_COMPRESS_ACCEL) return -EBADFD; - avail = snd_compr_calc_avail(stream, &ioctl_avail); - ioctl_avail.avail = avail; + avail = snd_compr_calc_avail(stream, &ioctl_avail64); + ioctl_avail64.avail = avail; + if (is_32bit) { + snd_compr_avail32_from_64(&ioctl_avail32, &ioctl_avail64); + copy_from = &ioctl_avail32; + copy_size = sizeof(ioctl_avail32); + } switch (stream->runtime->state) { case SNDRV_PCM_STATE_OPEN: @@ -255,8 +281,7 @@ snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg) break; } - if (copy_to_user((__u64 __user *)arg, - &ioctl_avail, sizeof(ioctl_avail))) + if (copy_to_user((__u64 __user *)arg, copy_from, copy_size)) return -EFAULT; return 0; } @@ -274,8 +299,7 @@ static int snd_compr_write_data(struct snd_compr_stream *stream, (app_pointer * runtime->buffer_size); dstn = runtime->buffer + app_pointer; - pr_debug("copying %ld at %lld\n", - (unsigned long)count, app_pointer); + pr_debug("copying %lu at %llu\n", (unsigned long)count, app_pointer); if (count < runtime->buffer_size - app_pointer) { if (copy_from_user(dstn, buf, count)) return -EFAULT; @@ -318,7 +342,7 @@ static ssize_t snd_compr_write(struct file *f, const char __user *buf, } avail = snd_compr_get_avail(stream); - pr_debug("avail returned %ld\n", (unsigned long)avail); + pr_debug("avail returned %lu\n", (unsigned long)avail); /* calculate how much we can write to buffer */ if (avail > count) avail = count; @@ -374,7 +398,7 @@ static ssize_t snd_compr_read(struct file *f, char __user *buf, } avail = snd_compr_get_avail(stream); - pr_debug("avail returned %ld\n", (unsigned long)avail); + pr_debug("avail returned %lu\n", (unsigned long)avail); /* calculate how much we can read from buffer */ if (avail > count) avail = count; @@ -443,7 +467,7 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait) #endif avail = snd_compr_get_avail(stream); - pr_debug("avail is %ld\n", (unsigned long)avail); + pr_debug("avail is %lu\n", (unsigned long)avail); /* check if we have at least one fragment to fill */ switch (runtime->state) { case SNDRV_PCM_STATE_DRAINING: @@ -723,16 +747,26 @@ snd_compr_set_metadata(struct snd_compr_stream *stream, unsigned long arg) return retval; } -static inline int -snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg) +static inline int snd_compr_tstamp(struct snd_compr_stream *stream, + unsigned long arg, bool is_32bit) { - struct snd_compr_tstamp tstamp = {0}; + struct snd_compr_tstamp64 tstamp64 = { 0 }; + struct snd_compr_tstamp tstamp32 = { 0 }; + const void *copy_from = &tstamp64; + size_t copy_size = sizeof(tstamp64); int ret; - ret = snd_compr_update_tstamp(stream, &tstamp); - if (ret == 0) - ret = copy_to_user((struct snd_compr_tstamp __user *)arg, - &tstamp, sizeof(tstamp)) ? -EFAULT : 0; + ret = snd_compr_update_tstamp(stream, &tstamp64); + if (ret == 0) { + if (is_32bit) { + snd_compr_tstamp32_from_64(&tstamp32, &tstamp64); + copy_from = &tstamp32; + copy_size = sizeof(tstamp32); + } + ret = copy_to_user((void __user *)arg, copy_from, copy_size) ? + -EFAULT : + 0; + } return ret; } @@ -1309,9 +1343,13 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) switch (cmd) { case SNDRV_COMPRESS_TSTAMP: - return snd_compr_tstamp(stream, arg); + return snd_compr_tstamp(stream, arg, true); + case SNDRV_COMPRESS_TSTAMP64: + return snd_compr_tstamp(stream, arg, false); case SNDRV_COMPRESS_AVAIL: - return snd_compr_ioctl_avail(stream, arg); + return snd_compr_ioctl_avail(stream, arg, true); + case SNDRV_COMPRESS_AVAIL64: + return snd_compr_ioctl_avail(stream, arg, false); case SNDRV_COMPRESS_PAUSE: return snd_compr_pause(stream); case SNDRV_COMPRESS_RESUME: diff --git a/sound/core/misc.c b/sound/core/misc.c index c2fda3bd90a0..88d9e1f9a6e9 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -127,35 +127,30 @@ int snd_fasync_helper(int fd, struct file *file, int on, INIT_LIST_HEAD(&fasync->list); } - spin_lock_irq(&snd_fasync_lock); - if (*fasyncp) { - kfree(fasync); - fasync = *fasyncp; - } else { - if (!fasync) { - spin_unlock_irq(&snd_fasync_lock); - return 0; + scoped_guard(spinlock_irq, &snd_fasync_lock) { + if (*fasyncp) { + kfree(fasync); + fasync = *fasyncp; + } else { + if (!fasync) + return 0; + *fasyncp = fasync; } - *fasyncp = fasync; + fasync->on = on; } - fasync->on = on; - spin_unlock_irq(&snd_fasync_lock); return fasync_helper(fd, file, on, &fasync->fasync); } EXPORT_SYMBOL_GPL(snd_fasync_helper); void snd_kill_fasync(struct snd_fasync *fasync, int signal, int poll) { - unsigned long flags; - if (!fasync || !fasync->on) return; - spin_lock_irqsave(&snd_fasync_lock, flags); + guard(spinlock_irqsave)(&snd_fasync_lock); fasync->signal = signal; fasync->poll = poll; list_move(&fasync->list, &snd_fasync_list); schedule_work(&snd_fasync_work); - spin_unlock_irqrestore(&snd_fasync_lock, flags); } EXPORT_SYMBOL_GPL(snd_kill_fasync); diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 4ecb17bd5436..a82dd155e1d3 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2002,9 +2002,8 @@ static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsig static int snd_pcm_oss_nonblock(struct file * file) { - spin_lock(&file->f_lock); + guard(spinlock)(&file->f_lock); file->f_flags |= O_NONBLOCK; - spin_unlock(&file->f_lock); return 0; } diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 72040964b6fd..f0c17503df42 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -111,6 +111,7 @@ void snd_dmaengine_pcm_set_config_from_dai_data( if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { slave_config->dst_addr = dma_data->addr; slave_config->dst_maxburst = dma_data->maxburst; + slave_config->dst_port_window_size = dma_data->port_window_size; if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; @@ -119,6 +120,7 @@ void snd_dmaengine_pcm_set_config_from_dai_data( } else { slave_config->src_addr = dma_data->addr; slave_config->src_maxburst = dma_data->maxburst; + slave_config->src_port_window_size = dma_data->port_window_size; if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 1eab940fa2e5..68bee40c9ada 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -84,19 +84,24 @@ void snd_pcm_group_init(struct snd_pcm_group *group) } /* define group lock helpers */ -#define DEFINE_PCM_GROUP_LOCK(action, mutex_action) \ +#define DEFINE_PCM_GROUP_LOCK(action, bh_lock, bh_unlock, mutex_action) \ static void snd_pcm_group_ ## action(struct snd_pcm_group *group, bool nonatomic) \ { \ - if (nonatomic) \ + if (nonatomic) { \ mutex_ ## mutex_action(&group->mutex); \ - else \ - spin_ ## action(&group->lock); \ -} - -DEFINE_PCM_GROUP_LOCK(lock, lock); -DEFINE_PCM_GROUP_LOCK(unlock, unlock); -DEFINE_PCM_GROUP_LOCK(lock_irq, lock); -DEFINE_PCM_GROUP_LOCK(unlock_irq, unlock); + } else { \ + if (IS_ENABLED(CONFIG_PREEMPT_RT) && bh_lock) \ + local_bh_disable(); \ + spin_ ## action(&group->lock); \ + if (IS_ENABLED(CONFIG_PREEMPT_RT) && bh_unlock) \ + local_bh_enable(); \ + } \ +} + +DEFINE_PCM_GROUP_LOCK(lock, false, false, lock); +DEFINE_PCM_GROUP_LOCK(unlock, false, false, unlock); +DEFINE_PCM_GROUP_LOCK(lock_irq, true, false, lock); +DEFINE_PCM_GROUP_LOCK(unlock_irq, false, true, unlock); /** * snd_pcm_stream_lock - Lock the PCM stream diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index 77c1214acd90..02d30d8b6c3a 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c @@ -117,18 +117,15 @@ static DEFINE_MUTEX(register_mutex); static int odev_open(struct inode *inode, struct file *file) { - int level, rc; + int level; if (iminor(inode) == SNDRV_MINOR_OSS_MUSIC) level = SNDRV_SEQ_OSS_MODE_MUSIC; else level = SNDRV_SEQ_OSS_MODE_SYNTH; - mutex_lock(®ister_mutex); - rc = snd_seq_oss_open(file, level); - mutex_unlock(®ister_mutex); - - return rc; + guard(mutex)(®ister_mutex); + return snd_seq_oss_open(file, level); } static int @@ -140,10 +137,8 @@ odev_release(struct inode *inode, struct file *file) if (!dp) return 0; - mutex_lock(®ister_mutex); + guard(mutex)(®ister_mutex); snd_seq_oss_release(dp); - mutex_unlock(®ister_mutex); - return 0; } @@ -229,13 +224,12 @@ register_device(void) { int rc; - mutex_lock(®ister_mutex); + guard(mutex)(®ister_mutex); rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0, &seq_oss_f_ops, NULL); if (rc < 0) { pr_err("ALSA: seq_oss: can't register device seq\n"); - mutex_unlock(®ister_mutex); return rc; } rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, @@ -244,22 +238,19 @@ register_device(void) if (rc < 0) { pr_err("ALSA: seq_oss: can't register device music\n"); snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0); - mutex_unlock(®ister_mutex); return rc; } - mutex_unlock(®ister_mutex); return 0; } static void unregister_device(void) { - mutex_lock(®ister_mutex); + guard(mutex)(®ister_mutex); if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0) pr_err("ALSA: seq_oss: error unregister device music\n"); if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0) < 0) pr_err("ALSA: seq_oss: error unregister device seq\n"); - mutex_unlock(®ister_mutex); } /* @@ -273,12 +264,11 @@ static struct snd_info_entry *info_entry; static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buf) { - mutex_lock(®ister_mutex); + guard(mutex)(®ister_mutex); snd_iprintf(buf, "OSS sequencer emulation version %s\n", SNDRV_SEQ_OSS_VERSION_STR); snd_seq_oss_system_info_read(buf); snd_seq_oss_synth_info_read(buf); snd_seq_oss_midi_info_read(buf); - mutex_unlock(®ister_mutex); } diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h index 6163a00bc8de..935cf3df0b30 100644 --- a/sound/core/seq/oss/seq_oss_device.h +++ b/sound/core/seq/oss/seq_oss_device.h @@ -137,12 +137,7 @@ snd_seq_oss_dispatch(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int a static inline int snd_seq_oss_control(struct seq_oss_devinfo *dp, unsigned int type, void *arg) { - int err; - - snd_seq_client_ioctl_lock(dp->cseq); - err = snd_seq_kernel_client_ctl(dp->cseq, type, arg); - snd_seq_client_ioctl_unlock(dp->cseq); - return err; + return snd_seq_kernel_client_ioctl(dp->cseq, type, arg); } /* fill the addresses in header */ diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c index f8e247d9e5c9..023e5d0a4351 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c @@ -40,6 +40,7 @@ struct seq_oss_midi { struct mutex open_mutex; }; +DEFINE_FREE(seq_oss_midi, struct seq_oss_midi *, if (!IS_ERR_OR_NULL(_T)) snd_use_lock_free(&(_T)->use_lock)) /* * midi device table @@ -90,13 +91,11 @@ static struct seq_oss_midi * get_mdev(int dev) { struct seq_oss_midi *mdev; - unsigned long flags; - spin_lock_irqsave(®ister_lock, flags); + guard(spinlock_irqsave)(®ister_lock); mdev = midi_devs[dev]; if (mdev) snd_use_lock_use(&mdev->use_lock); - spin_unlock_irqrestore(®ister_lock, flags); return mdev; } @@ -108,19 +107,16 @@ find_slot(int client, int port) { int i; struct seq_oss_midi *mdev; - unsigned long flags; - spin_lock_irqsave(®ister_lock, flags); + guard(spinlock_irqsave)(®ister_lock); for (i = 0; i < max_midi_devs; i++) { mdev = midi_devs[i]; if (mdev && mdev->client == client && mdev->port == port) { /* found! */ snd_use_lock_use(&mdev->use_lock); - spin_unlock_irqrestore(®ister_lock, flags); return mdev; } } - spin_unlock_irqrestore(®ister_lock, flags); return NULL; } @@ -135,7 +131,6 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo) { int i; struct seq_oss_midi *mdev; - unsigned long flags; /* the port must include generic midi */ if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC)) @@ -185,14 +180,13 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo) /* * look for en empty slot */ - spin_lock_irqsave(®ister_lock, flags); + guard(spinlock_irqsave)(®ister_lock); for (i = 0; i < max_midi_devs; i++) { if (midi_devs[i] == NULL) break; } if (i >= max_midi_devs) { if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) { - spin_unlock_irqrestore(®ister_lock, flags); snd_midi_event_free(mdev->coder); kfree(mdev); return -ENOMEM; @@ -201,7 +195,6 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo) } mdev->seq_device = i; midi_devs[mdev->seq_device] = mdev; - spin_unlock_irqrestore(®ister_lock, flags); return 0; } @@ -213,26 +206,24 @@ int snd_seq_oss_midi_check_exit_port(int client, int port) { struct seq_oss_midi *mdev; - unsigned long flags; int index; mdev = find_slot(client, port); if (mdev) { - spin_lock_irqsave(®ister_lock, flags); - midi_devs[mdev->seq_device] = NULL; - spin_unlock_irqrestore(®ister_lock, flags); + scoped_guard(spinlock_irqsave, ®ister_lock) { + midi_devs[mdev->seq_device] = NULL; + } snd_use_lock_free(&mdev->use_lock); snd_use_lock_sync(&mdev->use_lock); snd_midi_event_free(mdev->coder); kfree(mdev); } - spin_lock_irqsave(®ister_lock, flags); + guard(spinlock_irqsave)(®ister_lock); for (index = max_midi_devs - 1; index >= 0; index--) { if (midi_devs[index]) break; } max_midi_devs = index + 1; - spin_unlock_irqrestore(®ister_lock, flags); return 0; } @@ -245,9 +236,8 @@ snd_seq_oss_midi_clear_all(void) { int i; struct seq_oss_midi *mdev; - unsigned long flags; - spin_lock_irqsave(®ister_lock, flags); + guard(spinlock_irqsave)(®ister_lock); for (i = 0; i < max_midi_devs; i++) { mdev = midi_devs[i]; if (mdev) { @@ -257,7 +247,6 @@ snd_seq_oss_midi_clear_all(void) } } max_midi_devs = 0; - spin_unlock_irqrestore(®ister_lock, flags); } @@ -267,9 +256,8 @@ snd_seq_oss_midi_clear_all(void) void snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp) { - spin_lock_irq(®ister_lock); + guard(spinlock_irq)(®ister_lock); dp->max_mididev = max_midi_devs; - spin_unlock_irq(®ister_lock); } /* @@ -317,20 +305,17 @@ int snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode) { int perm; - struct seq_oss_midi *mdev; + struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL; struct snd_seq_port_subscribe subs; - int err; mdev = get_mididev(dp, dev); if (!mdev) return -ENODEV; - mutex_lock(&mdev->open_mutex); + guard(mutex)(&mdev->open_mutex); /* already used? */ - if (mdev->opened && mdev->devinfo != dp) { - err = -EBUSY; - goto unlock; - } + if (mdev->opened && mdev->devinfo != dp) + return -EBUSY; perm = 0; if (is_write_mode(fmode)) @@ -338,16 +323,12 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode) if (is_read_mode(fmode)) perm |= PERM_READ; perm &= mdev->flags; - if (perm == 0) { - err = -ENXIO; - goto unlock; - } + if (perm == 0) + return -ENXIO; /* already opened? */ - if ((mdev->opened & perm) == perm) { - err = 0; - goto unlock; - } + if ((mdev->opened & perm) == perm) + return 0; perm &= ~mdev->opened; @@ -370,18 +351,11 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode) mdev->opened |= PERM_READ; } - if (! mdev->opened) { - err = -ENXIO; - goto unlock; - } + if (!mdev->opened) + return -ENXIO; mdev->devinfo = dp; - err = 0; - - unlock: - mutex_unlock(&mdev->open_mutex); - snd_use_lock_free(&mdev->use_lock); - return err; + return 0; } /* @@ -390,15 +364,15 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode) int snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev) { - struct seq_oss_midi *mdev; + struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL; struct snd_seq_port_subscribe subs; mdev = get_mididev(dp, dev); if (!mdev) return -ENODEV; - mutex_lock(&mdev->open_mutex); + guard(mutex)(&mdev->open_mutex); if (!mdev->opened || mdev->devinfo != dp) - goto unlock; + return 0; memset(&subs, 0, sizeof(subs)); if (mdev->opened & PERM_WRITE) { @@ -416,10 +390,6 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev) mdev->opened = 0; mdev->devinfo = NULL; - - unlock: - mutex_unlock(&mdev->open_mutex); - snd_use_lock_free(&mdev->use_lock); return 0; } @@ -429,7 +399,7 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev) int snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev) { - struct seq_oss_midi *mdev; + struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL; int mode; mdev = get_mididev(dp, dev); @@ -442,7 +412,6 @@ snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev) if (mdev->opened & PERM_READ) mode |= SNDRV_SEQ_OSS_FILE_READ; - snd_use_lock_free(&mdev->use_lock); return mode; } @@ -453,15 +422,13 @@ snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev) void snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev) { - struct seq_oss_midi *mdev; + struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL; mdev = get_mididev(dp, dev); if (!mdev) return; - if (! mdev->opened) { - snd_use_lock_free(&mdev->use_lock); + if (!mdev->opened) return; - } if (mdev->opened & PERM_WRITE) { struct snd_seq_event ev; @@ -492,7 +459,6 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev) } } // snd_seq_oss_midi_close(dp, dev); - snd_use_lock_free(&mdev->use_lock); } @@ -502,14 +468,13 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev) void snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_addr *addr) { - struct seq_oss_midi *mdev; + struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL; mdev = get_mididev(dp, dev); if (!mdev) return; addr->client = mdev->client; addr->port = mdev->port; - snd_use_lock_free(&mdev->use_lock); } @@ -520,26 +485,20 @@ int snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data) { struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data; - struct seq_oss_midi *mdev; - int rc; + struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL; if (dp->readq == NULL) return 0; mdev = find_slot(ev->source.client, ev->source.port); if (!mdev) return 0; - if (! (mdev->opened & PERM_READ)) { - snd_use_lock_free(&mdev->use_lock); + if (!(mdev->opened & PERM_READ)) return 0; - } if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) - rc = send_synth_event(dp, ev, mdev->seq_device); + return send_synth_event(dp, ev, mdev->seq_device); else - rc = send_midi_event(dp, ev, mdev); - - snd_use_lock_free(&mdev->use_lock); - return rc; + return send_midi_event(dp, ev, mdev); } /* @@ -636,17 +595,15 @@ send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq int snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev) { - struct seq_oss_midi *mdev; + struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL; mdev = get_mididev(dp, dev); if (!mdev) return -ENODEV; if (snd_midi_event_encode_byte(mdev->coder, c, ev)) { snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port); - snd_use_lock_free(&mdev->use_lock); return 0; } - snd_use_lock_free(&mdev->use_lock); return -EINVAL; } @@ -656,7 +613,7 @@ snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, stru int snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf) { - struct seq_oss_midi *mdev; + struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL; mdev = get_mididev(dp, dev); if (!mdev) @@ -665,7 +622,6 @@ snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info inf->dev_type = 0; /* FIXME: ?? */ inf->capabilities = 0; /* FIXME: ?? */ strscpy(inf->name, mdev->name, sizeof(inf->name)); - snd_use_lock_free(&mdev->use_lock); return 0; } @@ -692,10 +648,11 @@ void snd_seq_oss_midi_info_read(struct snd_info_buffer *buf) { int i; - struct seq_oss_midi *mdev; snd_iprintf(buf, "\nNumber of MIDI devices: %d\n", max_midi_devs); for (i = 0; i < max_midi_devs; i++) { + struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL; + snd_iprintf(buf, "\nmidi %d: ", i); mdev = get_mdev(i); if (mdev == NULL) { @@ -707,7 +664,6 @@ snd_seq_oss_midi_info_read(struct snd_info_buffer *buf) snd_iprintf(buf, " capability %s / opened %s\n", capmode_str(mdev->flags), capmode_str(mdev->opened)); - snd_use_lock_free(&mdev->use_lock); } } #endif /* CONFIG_SND_PROC_FS */ diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c index f0db5d3dcba4..bbaf72e70b35 100644 --- a/sound/core/seq/oss/seq_oss_readq.c +++ b/sound/core/seq/oss/seq_oss_readq.c @@ -140,13 +140,9 @@ int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev, int snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev) { - unsigned long flags; - - spin_lock_irqsave(&q->lock, flags); - if (q->qlen >= q->maxlen - 1) { - spin_unlock_irqrestore(&q->lock, flags); + guard(spinlock_irqsave)(&q->lock); + if (q->qlen >= q->maxlen - 1) return -ENOMEM; - } memcpy(&q->q[q->tail], ev, sizeof(*ev)); q->tail = (q->tail + 1) % q->maxlen; @@ -155,8 +151,6 @@ snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev) /* wake up sleeper */ wake_up(&q->midi_sleep); - spin_unlock_irqrestore(&q->lock, flags); - return 0; } diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c index 9de47e098b29..8c4e5913c7e6 100644 --- a/sound/core/seq/oss/seq_oss_synth.c +++ b/sound/core/seq/oss/seq_oss_synth.c @@ -44,6 +44,7 @@ struct seq_oss_synth { snd_use_lock_t use_lock; }; +DEFINE_FREE(seq_oss_synth, struct seq_oss_synth *, if (!IS_ERR_OR_NULL(_T)) snd_use_lock_free(&(_T)->use_lock)) /* * device table @@ -85,7 +86,6 @@ snd_seq_oss_synth_probe(struct device *_dev) int i; struct seq_oss_synth *rec; struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev); - unsigned long flags; rec = kzalloc(sizeof(*rec), GFP_KERNEL); if (!rec) @@ -103,23 +103,22 @@ snd_seq_oss_synth_probe(struct device *_dev) strscpy(rec->name, dev->name, sizeof(rec->name)); /* registration */ - spin_lock_irqsave(®ister_lock, flags); - for (i = 0; i < max_synth_devs; i++) { - if (synth_devs[i] == NULL) - break; - } - if (i >= max_synth_devs) { - if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) { - spin_unlock_irqrestore(®ister_lock, flags); - pr_err("ALSA: seq_oss: no more synth slot\n"); - kfree(rec); - return -ENOMEM; + scoped_guard(spinlock_irqsave, ®ister_lock) { + for (i = 0; i < max_synth_devs; i++) { + if (synth_devs[i] == NULL) + break; } - max_synth_devs++; + if (i >= max_synth_devs) { + if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) { + pr_err("ALSA: seq_oss: no more synth slot\n"); + kfree(rec); + return -ENOMEM; + } + max_synth_devs++; + } + rec->seq_device = i; + synth_devs[i] = rec; } - rec->seq_device = i; - synth_devs[i] = rec; - spin_unlock_irqrestore(®ister_lock, flags); dev->driver_data = rec; #ifdef SNDRV_OSS_INFO_DEV_SYNTH if (i < SNDRV_CARDS) @@ -135,27 +134,25 @@ snd_seq_oss_synth_remove(struct device *_dev) struct snd_seq_device *dev = to_seq_dev(_dev); int index; struct seq_oss_synth *rec = dev->driver_data; - unsigned long flags; - spin_lock_irqsave(®ister_lock, flags); - for (index = 0; index < max_synth_devs; index++) { - if (synth_devs[index] == rec) - break; - } - if (index >= max_synth_devs) { - spin_unlock_irqrestore(®ister_lock, flags); - pr_err("ALSA: seq_oss: can't unregister synth\n"); - return -EINVAL; - } - synth_devs[index] = NULL; - if (index == max_synth_devs - 1) { - for (index--; index >= 0; index--) { - if (synth_devs[index]) + scoped_guard(spinlock_irqsave, ®ister_lock) { + for (index = 0; index < max_synth_devs; index++) { + if (synth_devs[index] == rec) break; } - max_synth_devs = index + 1; + if (index >= max_synth_devs) { + pr_err("ALSA: seq_oss: can't unregister synth\n"); + return -EINVAL; + } + synth_devs[index] = NULL; + if (index == max_synth_devs - 1) { + for (index--; index >= 0; index--) { + if (synth_devs[index]) + break; + } + max_synth_devs = index + 1; + } } - spin_unlock_irqrestore(®ister_lock, flags); #ifdef SNDRV_OSS_INFO_DEV_SYNTH if (rec->seq_device < SNDRV_CARDS) snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_SYNTH, rec->seq_device); @@ -174,13 +171,11 @@ static struct seq_oss_synth * get_sdev(int dev) { struct seq_oss_synth *rec; - unsigned long flags; - spin_lock_irqsave(®ister_lock, flags); + guard(spinlock_irqsave)(®ister_lock); rec = synth_devs[dev]; if (rec) snd_use_lock_use(&rec->use_lock); - spin_unlock_irqrestore(®ister_lock, flags); return rec; } @@ -193,20 +188,18 @@ void snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp) { int i; - struct seq_oss_synth *rec; struct seq_oss_synthinfo *info; dp->max_synthdev = max_synth_devs; dp->synth_opened = 0; memset(dp->synths, 0, sizeof(dp->synths)); for (i = 0; i < dp->max_synthdev; i++) { - rec = get_sdev(i); + struct seq_oss_synth *rec __free(seq_oss_synth) = get_sdev(i); + if (rec == NULL) continue; - if (rec->oper.open == NULL || rec->oper.close == NULL) { - snd_use_lock_free(&rec->use_lock); + if (rec->oper.open == NULL || rec->oper.close == NULL) continue; - } info = &dp->synths[i]; info->arg.app_index = dp->port; info->arg.file_mode = dp->file_mode; @@ -216,13 +209,10 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp) else info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS; info->opened = 0; - if (!try_module_get(rec->oper.owner)) { - snd_use_lock_free(&rec->use_lock); + if (!try_module_get(rec->oper.owner)) continue; - } if (rec->oper.open(&info->arg, rec->private_data) < 0) { module_put(rec->oper.owner); - snd_use_lock_free(&rec->use_lock); continue; } info->nr_voices = rec->nr_voices; @@ -231,7 +221,6 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp) if (!info->ch) { rec->oper.close(&info->arg); module_put(rec->oper.owner); - snd_use_lock_free(&rec->use_lock); continue; } reset_channels(info); @@ -239,7 +228,6 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp) info->opened++; rec->opened++; dp->synth_opened++; - snd_use_lock_free(&rec->use_lock); } } @@ -286,7 +274,6 @@ void snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp) { int i; - struct seq_oss_synth *rec; struct seq_oss_synthinfo *info; if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)) @@ -301,7 +288,9 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp) midi_synth_dev.opened--; } } else { - rec = get_sdev(i); + struct seq_oss_synth *rec __free(seq_oss_synth) = + get_sdev(i); + if (rec == NULL) continue; if (rec->opened > 0) { @@ -309,7 +298,6 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp) module_put(rec->oper.owner); rec->opened = 0; } - snd_use_lock_free(&rec->use_lock); } kfree(info->ch); info->ch = NULL; @@ -380,7 +368,7 @@ reset_channels(struct seq_oss_synthinfo *info) void snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev) { - struct seq_oss_synth *rec; + struct seq_oss_synth *rec __free(seq_oss_synth) = NULL; struct seq_oss_synthinfo *info; info = get_synthinfo_nospec(dp, dev); @@ -416,7 +404,6 @@ snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev) ev.type = SNDRV_SEQ_EVENT_RESET; snd_seq_oss_dispatch(dp, &ev, 0, 0); } - snd_use_lock_free(&rec->use_lock); } @@ -428,9 +415,8 @@ int snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt, const char __user *buf, int p, int c) { - struct seq_oss_synth *rec; + struct seq_oss_synth *rec __free(seq_oss_synth) = NULL; struct seq_oss_synthinfo *info; - int rc; info = get_synthinfo_nospec(dp, dev); if (!info) @@ -443,11 +429,9 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt, return -ENXIO; if (rec->oper.load_patch == NULL) - rc = -ENXIO; + return -ENXIO; else - rc = rec->oper.load_patch(&info->arg, fmt, buf, p, c); - snd_use_lock_free(&rec->use_lock); - return rc; + return rec->oper.load_patch(&info->arg, fmt, buf, p, c); } /* @@ -456,13 +440,11 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt, struct seq_oss_synthinfo * snd_seq_oss_synth_info(struct seq_oss_devinfo *dp, int dev) { - struct seq_oss_synth *rec; + struct seq_oss_synth *rec __free(seq_oss_synth) = NULL; rec = get_synthdev(dp, dev); - if (rec) { - snd_use_lock_free(&rec->use_lock); + if (rec) return get_synthinfo_nospec(dp, dev); - } return NULL; } @@ -513,9 +495,8 @@ snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event int snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr) { - struct seq_oss_synth *rec; + struct seq_oss_synth *rec __free(seq_oss_synth) = NULL; struct seq_oss_synthinfo *info; - int rc; info = get_synthinfo_nospec(dp, dev); if (!info || info->is_midi) @@ -524,11 +505,9 @@ snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, u if (!rec) return -ENXIO; if (rec->oper.ioctl == NULL) - rc = -ENXIO; + return -ENXIO; else - rc = rec->oper.ioctl(&info->arg, cmd, addr); - snd_use_lock_free(&rec->use_lock); - return rc; + return rec->oper.ioctl(&info->arg, cmd, addr); } @@ -555,7 +534,6 @@ snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char * int snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf) { - struct seq_oss_synth *rec; struct seq_oss_synthinfo *info = get_synthinfo_nospec(dp, dev); if (!info) @@ -571,7 +549,9 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in inf->device = dev; strscpy(inf->name, minf.name, sizeof(inf->name)); } else { - rec = get_synthdev(dp, dev); + struct seq_oss_synth *rec __free(seq_oss_synth) = + get_synthdev(dp, dev); + if (!rec) return -ENXIO; inf->synth_type = rec->synth_type; @@ -579,7 +559,6 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in inf->nr_voices = rec->nr_voices; inf->device = dev; strscpy(inf->name, rec->name, sizeof(inf->name)); - snd_use_lock_free(&rec->use_lock); } return 0; } @@ -593,10 +572,11 @@ void snd_seq_oss_synth_info_read(struct snd_info_buffer *buf) { int i; - struct seq_oss_synth *rec; snd_iprintf(buf, "\nNumber of synth devices: %d\n", max_synth_devs); for (i = 0; i < max_synth_devs; i++) { + struct seq_oss_synth *rec __free(seq_oss_synth) = NULL; + snd_iprintf(buf, "\nsynth %d: ", i); rec = get_sdev(i); if (rec == NULL) { @@ -610,7 +590,6 @@ snd_seq_oss_synth_info_read(struct snd_info_buffer *buf) snd_iprintf(buf, " capabilities : ioctl %s / load_patch %s\n", str_enabled_disabled((long)rec->oper.ioctl), str_enabled_disabled((long)rec->oper.load_patch)); - snd_use_lock_free(&rec->use_lock); } } #endif /* CONFIG_SND_PROC_FS */ diff --git a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c index 3e3209ce53b1..a93ff8315b8e 100644 --- a/sound/core/seq/oss/seq_oss_writeq.c +++ b/sound/core/seq/oss/seq_oss_writeq.c @@ -122,13 +122,10 @@ snd_seq_oss_writeq_sync(struct seq_oss_writeq *q) void snd_seq_oss_writeq_wakeup(struct seq_oss_writeq *q, abstime_t time) { - unsigned long flags; - - spin_lock_irqsave(&q->sync_lock, flags); + guard(spinlock_irqsave)(&q->sync_lock); q->sync_time = time; q->sync_event_put = 0; wake_up(&q->sync_sleep); - spin_unlock_irqrestore(&q->sync_lock, flags); } diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index aa9c956d2581..f9a6e497f997 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -108,7 +108,6 @@ static struct snd_seq_client *clientptr(int clientid) static struct snd_seq_client *client_use_ptr(int clientid, bool load_module) { - unsigned long flags; struct snd_seq_client *client; if (clientid < 0 || clientid >= SNDRV_SEQ_MAX_CLIENTS) { @@ -116,15 +115,13 @@ static struct snd_seq_client *client_use_ptr(int clientid, bool load_module) clientid); return NULL; } - spin_lock_irqsave(&clients_lock, flags); - client = clientptr(clientid); - if (client) - goto __lock; - if (clienttablock[clientid]) { - spin_unlock_irqrestore(&clients_lock, flags); - return NULL; + scoped_guard(spinlock_irqsave, &clients_lock) { + client = clientptr(clientid); + if (client) + return snd_seq_client_ref(client); + if (clienttablock[clientid]) + return NULL; } - spin_unlock_irqrestore(&clients_lock, flags); #ifdef CONFIG_MODULES if (load_module) { static DECLARE_BITMAP(client_requested, SNDRV_SEQ_GLOBAL_CLIENTS); @@ -153,19 +150,14 @@ static struct snd_seq_client *client_use_ptr(int clientid, bool load_module) snd_seq_device_load_drivers(); } } - spin_lock_irqsave(&clients_lock, flags); - client = clientptr(clientid); - if (client) - goto __lock; - spin_unlock_irqrestore(&clients_lock, flags); + scoped_guard(spinlock_irqsave, &clients_lock) { + client = clientptr(clientid); + if (client) + return snd_seq_client_ref(client); + } } #endif return NULL; - - __lock: - snd_use_lock_use(&client->use_lock); - spin_unlock_irqrestore(&clients_lock, flags); - return client; } /* get snd_seq_client object for the given id quickly */ @@ -182,41 +174,6 @@ static struct snd_seq_client *client_load_and_use_ptr(int clientid) return client_use_ptr(clientid, IS_ENABLED(CONFIG_MODULES)); } -/* Take refcount and perform ioctl_mutex lock on the given client; - * used only for OSS sequencer - * Unlock via snd_seq_client_ioctl_unlock() below - */ -bool snd_seq_client_ioctl_lock(int clientid) -{ - struct snd_seq_client *client; - - client = client_load_and_use_ptr(clientid); - if (!client) - return false; - mutex_lock(&client->ioctl_mutex); - /* The client isn't unrefed here; see snd_seq_client_ioctl_unlock() */ - return true; -} -EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_lock); - -/* Unlock and unref the given client; for OSS sequencer use only */ -void snd_seq_client_ioctl_unlock(int clientid) -{ - struct snd_seq_client *client; - - client = snd_seq_client_use_ptr(clientid); - if (WARN_ON(!client)) - return; - mutex_unlock(&client->ioctl_mutex); - /* The doubly unrefs below are intentional; the first one releases the - * leftover from snd_seq_client_ioctl_lock() above, and the second one - * is for releasing snd_seq_client_use_ptr() in this function - */ - snd_seq_client_unlock(client); - snd_seq_client_unlock(client); -} -EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_unlock); - static void usage_alloc(struct snd_seq_usage *res, int num) { res->cur += num; @@ -262,25 +219,24 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize) client->ump_endpoint_port = -1; /* find free slot in the client table */ - spin_lock_irq(&clients_lock); - if (client_index < 0) { - for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN; - c < SNDRV_SEQ_MAX_CLIENTS; - c++) { - if (clienttab[c] || clienttablock[c]) - continue; - clienttab[client->number = c] = client; - spin_unlock_irq(&clients_lock); - return client; - } - } else { - if (clienttab[client_index] == NULL && !clienttablock[client_index]) { - clienttab[client->number = client_index] = client; - spin_unlock_irq(&clients_lock); - return client; + scoped_guard(spinlock_irq, &clients_lock) { + if (client_index < 0) { + for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN; + c < SNDRV_SEQ_MAX_CLIENTS; + c++) { + if (clienttab[c] || clienttablock[c]) + continue; + clienttab[client->number = c] = client; + return client; + } + } else { + if (clienttab[client_index] == NULL && !clienttablock[client_index]) { + clienttab[client->number = client_index] = client; + return client; + } } } - spin_unlock_irq(&clients_lock); + snd_seq_pool_delete(&client->pool); kfree(client); return NULL; /* no free slot found or busy, return failure code */ @@ -291,41 +247,41 @@ static int seq_free_client1(struct snd_seq_client *client) { if (!client) return 0; - spin_lock_irq(&clients_lock); - clienttablock[client->number] = 1; - clienttab[client->number] = NULL; - spin_unlock_irq(&clients_lock); + scoped_guard(spinlock_irq, &clients_lock) { + clienttablock[client->number] = 1; + clienttab[client->number] = NULL; + } snd_seq_delete_all_ports(client); snd_seq_queue_client_leave(client->number); snd_use_lock_sync(&client->use_lock); if (client->pool) snd_seq_pool_delete(&client->pool); - spin_lock_irq(&clients_lock); - clienttablock[client->number] = 0; - spin_unlock_irq(&clients_lock); + scoped_guard(spinlock_irq, &clients_lock) { + clienttablock[client->number] = 0; + } return 0; } static void seq_free_client(struct snd_seq_client * client) { - mutex_lock(®ister_mutex); - switch (client->type) { - case NO_CLIENT: - pr_warn("ALSA: seq: Trying to free unused client %d\n", - client->number); - break; - case USER_CLIENT: - case KERNEL_CLIENT: - seq_free_client1(client); - usage_free(&client_usage, 1); - break; + scoped_guard(mutex, ®ister_mutex) { + switch (client->type) { + case NO_CLIENT: + pr_warn("ALSA: seq: Trying to free unused client %d\n", + client->number); + break; + case USER_CLIENT: + case KERNEL_CLIENT: + seq_free_client1(client); + usage_free(&client_usage, 1); + break; - default: - pr_err("ALSA: seq: Trying to free client %d with undefined type = %d\n", - client->number, client->type); + default: + pr_err("ALSA: seq: Trying to free client %d with undefined type = %d\n", + client->number, client->type); + } } - mutex_unlock(®ister_mutex); snd_seq_system_client_ev_client_exit(client->number); } @@ -346,37 +302,34 @@ static int snd_seq_open(struct inode *inode, struct file *file) if (err < 0) return err; - mutex_lock(®ister_mutex); - client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS); - if (!client) { - mutex_unlock(®ister_mutex); - return -ENOMEM; /* failure code */ - } - - mode = snd_seq_file_flags(file); - if (mode & SNDRV_SEQ_LFLG_INPUT) - client->accept_input = 1; - if (mode & SNDRV_SEQ_LFLG_OUTPUT) - client->accept_output = 1; - - user = &client->data.user; - user->fifo = NULL; - user->fifo_pool_size = 0; - - if (mode & SNDRV_SEQ_LFLG_INPUT) { - user->fifo_pool_size = SNDRV_SEQ_DEFAULT_CLIENT_EVENTS; - user->fifo = snd_seq_fifo_new(user->fifo_pool_size); - if (user->fifo == NULL) { - seq_free_client1(client); - kfree(client); - mutex_unlock(®ister_mutex); - return -ENOMEM; + scoped_guard(mutex, ®ister_mutex) { + client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS); + if (!client) + return -ENOMEM; /* failure code */ + + mode = snd_seq_file_flags(file); + if (mode & SNDRV_SEQ_LFLG_INPUT) + client->accept_input = 1; + if (mode & SNDRV_SEQ_LFLG_OUTPUT) + client->accept_output = 1; + + user = &client->data.user; + user->fifo = NULL; + user->fifo_pool_size = 0; + + if (mode & SNDRV_SEQ_LFLG_INPUT) { + user->fifo_pool_size = SNDRV_SEQ_DEFAULT_CLIENT_EVENTS; + user->fifo = snd_seq_fifo_new(user->fifo_pool_size); + if (user->fifo == NULL) { + seq_free_client1(client); + kfree(client); + return -ENOMEM; + } } - } - usage_alloc(&client_usage, 1); - client->type = USER_CLIENT; - mutex_unlock(®ister_mutex); + usage_alloc(&client_usage, 1); + client->type = USER_CLIENT; + } c = client->number; file->private_data = client; @@ -463,7 +416,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, cell = NULL; err = 0; - snd_seq_fifo_lock(fifo); + guard(snd_seq_fifo)(fifo); if (IS_ENABLED(CONFIG_SND_SEQ_UMP) && client->midi_version > 0) aligned_size = sizeof(struct snd_seq_ump_event); @@ -521,7 +474,6 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, if (err == -EAGAIN && result > 0) err = 0; } - snd_seq_fifo_unlock(fifo); return (err < 0) ? err : result; } @@ -542,24 +494,21 @@ static int check_port_perm(struct snd_seq_client_port *port, unsigned int flags) */ static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event) { - struct snd_seq_client *dest; + struct snd_seq_client *dest __free(snd_seq_client) = NULL; dest = snd_seq_client_use_ptr(event->dest.client); if (dest == NULL) return NULL; if (! dest->accept_input) - goto __not_avail; + return NULL; if (snd_seq_ev_is_ump(event)) - return dest; /* ok - no filter checks */ + return no_free_ptr(dest); /* ok - no filter checks */ if ((dest->filter & SNDRV_SEQ_FILTER_USE_EVENT) && ! test_bit(event->type, dest->event_filter)) - goto __not_avail; + return NULL; - return dest; /* ok - accessible */ -__not_avail: - snd_seq_client_unlock(dest); - return NULL; + return no_free_ptr(dest); /* ok - accessible */ } @@ -616,7 +565,7 @@ static int bounce_error_event(struct snd_seq_client *client, static int update_timestamp_of_queue(struct snd_seq_event *event, int queue, int real_time) { - struct snd_seq_queue *q; + struct snd_seq_queue *q __free(snd_seq_queue) = NULL; q = queueptr(queue); if (! q) @@ -630,7 +579,6 @@ static int update_timestamp_of_queue(struct snd_seq_event *event, event->time.tick = snd_seq_timer_get_cur_tick(q->timer); event->flags |= SNDRV_SEQ_TIME_STAMP_TICK; } - queuefree(q); return 1; } @@ -656,73 +604,63 @@ int __snd_seq_deliver_single_event(struct snd_seq_client *dest, return 0; } -/* - * deliver an event to the specified destination. - * if filter is non-zero, client filter bitmap is tested. - * - * RETURN VALUE: 0 : if succeeded - * <0 : error - */ -static int snd_seq_deliver_single_event(struct snd_seq_client *client, - struct snd_seq_event *event, - int atomic, int hop) +/* deliver a single event; called from snd_seq_deliver_single_event() */ +static int _snd_seq_deliver_single_event(struct snd_seq_client *client, + struct snd_seq_event *event, + int atomic, int hop) { - struct snd_seq_client *dest = NULL; - struct snd_seq_client_port *dest_port = NULL; - int result = -ENOENT; - int direct; - - direct = snd_seq_ev_is_direct(event); + struct snd_seq_client *dest __free(snd_seq_client) = NULL; + struct snd_seq_client_port *dest_port __free(snd_seq_port) = NULL; dest = get_event_dest_client(event); if (dest == NULL) - goto __skip; + return -ENOENT; dest_port = snd_seq_port_use_ptr(dest, event->dest.port); if (dest_port == NULL) - goto __skip; + return -ENOENT; /* check permission */ - if (! check_port_perm(dest_port, SNDRV_SEQ_PORT_CAP_WRITE)) { - result = -EPERM; - goto __skip; - } - + if (!check_port_perm(dest_port, SNDRV_SEQ_PORT_CAP_WRITE)) + return -EPERM; + if (dest_port->timestamping) update_timestamp_of_queue(event, dest_port->time_queue, dest_port->time_real); #if IS_ENABLED(CONFIG_SND_SEQ_UMP) if (snd_seq_ev_is_ump(event)) { - if (!(dest->filter & SNDRV_SEQ_FILTER_NO_CONVERT)) { - result = snd_seq_deliver_from_ump(client, dest, dest_port, - event, atomic, hop); - goto __skip; - } else if (dest->type == USER_CLIENT && - !snd_seq_client_is_ump(dest)) { - result = 0; // drop the event - goto __skip; - } - } else if (snd_seq_client_is_ump(dest)) { - if (!(dest->filter & SNDRV_SEQ_FILTER_NO_CONVERT)) { - result = snd_seq_deliver_to_ump(client, dest, dest_port, + if (!(dest->filter & SNDRV_SEQ_FILTER_NO_CONVERT)) + return snd_seq_deliver_from_ump(client, dest, dest_port, event, atomic, hop); - goto __skip; - } + else if (dest->type == USER_CLIENT && + !snd_seq_client_is_ump(dest)) + return 0; // drop the event + } else if (snd_seq_client_is_ump(dest)) { + if (!(dest->filter & SNDRV_SEQ_FILTER_NO_CONVERT)) + return snd_seq_deliver_to_ump(client, dest, dest_port, + event, atomic, hop); } #endif /* CONFIG_SND_SEQ_UMP */ - result = __snd_seq_deliver_single_event(dest, dest_port, event, - atomic, hop); + return __snd_seq_deliver_single_event(dest, dest_port, event, + atomic, hop); +} - __skip: - if (dest_port) - snd_seq_port_unlock(dest_port); - if (dest) - snd_seq_client_unlock(dest); +/* + * deliver an event to the specified destination. + * if filter is non-zero, client filter bitmap is tested. + * + * RETURN VALUE: 0 : if succeeded + * <0 : error + */ +static int snd_seq_deliver_single_event(struct snd_seq_client *client, + struct snd_seq_event *event, + int atomic, int hop) +{ + int result = _snd_seq_deliver_single_event(client, event, atomic, hop); - if (result < 0 && !direct) { - result = bounce_error_event(client, event, result, atomic, hop); - } + if (result < 0 && !snd_seq_ev_is_direct(event)) + return bounce_error_event(client, event, result, atomic, hop); return result; } @@ -734,7 +672,7 @@ static int __deliver_to_subscribers(struct snd_seq_client *client, struct snd_seq_event *event, int port, int atomic, int hop) { - struct snd_seq_client_port *src_port; + struct snd_seq_client_port *src_port __free(snd_seq_port) = NULL; struct snd_seq_subscribers *subs; int err, result = 0, num_ev = 0; union __snd_seq_event event_saved; @@ -781,7 +719,6 @@ static int __deliver_to_subscribers(struct snd_seq_client *client, read_unlock(&grp->list_lock); else up_read(&grp->list_mutex); - snd_seq_port_unlock(src_port); memcpy(event, &event_saved, saved_size); return (result < 0) ? result : num_ev; } @@ -864,7 +801,7 @@ static int snd_seq_deliver_event(struct snd_seq_client *client, struct snd_seq_e */ int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop) { - struct snd_seq_client *client; + struct snd_seq_client *client __free(snd_seq_client) = NULL; int result; if (snd_BUG_ON(!cell)) @@ -926,7 +863,6 @@ int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop) snd_seq_cell_free(cell); } - snd_seq_client_unlock(client); return result; } @@ -950,10 +886,10 @@ static int snd_seq_client_enqueue_event(struct snd_seq_client *client, event->queue = SNDRV_SEQ_QUEUE_DIRECT; } else if (event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS) { /* check presence of source port */ - struct snd_seq_client_port *src_port = snd_seq_port_use_ptr(client, event->source.port); - if (src_port == NULL) + struct snd_seq_client_port *src_port __free(snd_seq_port) = + snd_seq_port_use_ptr(client, event->source.port); + if (!src_port) return -EINVAL; - snd_seq_port_unlock(src_port); } /* direct event processing without enqueued */ @@ -1218,8 +1154,7 @@ static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void *arg) static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void *arg) { struct snd_seq_running_info *info = arg; - struct snd_seq_client *cptr; - int err = 0; + struct snd_seq_client *cptr __free(snd_seq_client) = NULL; /* requested client number */ cptr = client_load_and_use_ptr(info->client); @@ -1227,25 +1162,16 @@ static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void *arg) return -ENOENT; /* don't change !!! */ #ifdef SNDRV_BIG_ENDIAN - if (!info->big_endian) { - err = -EINVAL; - goto __err; - } + if (!info->big_endian) + return -EINVAL; #else - if (info->big_endian) { - err = -EINVAL; - goto __err; - } - + if (info->big_endian) + return -EINVAL; #endif - if (info->cpu_mode > sizeof(long)) { - err = -EINVAL; - goto __err; - } + if (info->cpu_mode > sizeof(long)) + return -EINVAL; cptr->convert32 = (info->cpu_mode < sizeof(long)); - __err: - snd_seq_client_unlock(cptr); - return err; + return 0; } /* CLIENT_INFO ioctl() */ @@ -1281,7 +1207,7 @@ static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client, void *arg) { struct snd_seq_client_info *client_info = arg; - struct snd_seq_client *cptr; + struct snd_seq_client *cptr __free(snd_seq_client) = NULL; /* requested client number */ cptr = client_load_and_use_ptr(client_info->client); @@ -1289,8 +1215,6 @@ static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client, return -ENOENT; /* don't change !!! */ get_client_info(cptr, client_info); - snd_seq_client_unlock(cptr); - return 0; } @@ -1420,24 +1344,19 @@ static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, void *arg) static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg) { struct snd_seq_port_info *info = arg; - struct snd_seq_client *cptr; - struct snd_seq_client_port *port; + struct snd_seq_client *cptr __free(snd_seq_client) = NULL; + struct snd_seq_client_port *port __free(snd_seq_port) = NULL; cptr = client_load_and_use_ptr(info->addr.client); if (cptr == NULL) return -ENXIO; port = snd_seq_port_use_ptr(cptr, info->addr.port); - if (port == NULL) { - snd_seq_client_unlock(cptr); + if (port == NULL) return -ENOENT; /* don't change */ - } /* get port info */ snd_seq_get_port_info(port, info); - snd_seq_port_unlock(port); - snd_seq_client_unlock(cptr); - return 0; } @@ -1448,14 +1367,13 @@ static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg) static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, void *arg) { struct snd_seq_port_info *info = arg; - struct snd_seq_client_port *port; + struct snd_seq_client_port *port __free(snd_seq_port) = NULL; if (info->addr.client != client->number) /* only set our own ports ! */ return -EPERM; port = snd_seq_port_use_ptr(client, info->addr.port); if (port) { snd_seq_set_port_info(port, info); - snd_seq_port_unlock(port); /* notify the change */ snd_seq_system_client_ev_port_change(info->addr.client, info->addr.port); @@ -1526,41 +1444,34 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client, void *arg) { struct snd_seq_port_subscribe *subs = arg; - int result = -EINVAL; - struct snd_seq_client *receiver = NULL, *sender = NULL; - struct snd_seq_client_port *sport = NULL, *dport = NULL; + struct snd_seq_client *receiver __free(snd_seq_client) = NULL; + struct snd_seq_client *sender __free(snd_seq_client) = NULL; + struct snd_seq_client_port *sport __free(snd_seq_port) = NULL; + struct snd_seq_client_port *dport __free(snd_seq_port) = NULL; + int result; receiver = client_load_and_use_ptr(subs->dest.client); if (!receiver) - goto __end; + return -EINVAL; sender = client_load_and_use_ptr(subs->sender.client); if (!sender) - goto __end; + return -EINVAL; sport = snd_seq_port_use_ptr(sender, subs->sender.port); if (!sport) - goto __end; + return -EINVAL; dport = snd_seq_port_use_ptr(receiver, subs->dest.port); if (!dport) - goto __end; + return -EINVAL; result = check_subscription_permission(client, sport, dport, subs); if (result < 0) - goto __end; + return result; /* connect them */ result = snd_seq_port_connect(client, sender, sport, receiver, dport, subs); if (! result) /* broadcast announce */ snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED); - __end: - if (sport) - snd_seq_port_unlock(sport); - if (dport) - snd_seq_port_unlock(dport); - if (sender) - snd_seq_client_unlock(sender); - if (receiver) - snd_seq_client_unlock(receiver); return result; } @@ -1572,40 +1483,33 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client, void *arg) { struct snd_seq_port_subscribe *subs = arg; - int result = -ENXIO; - struct snd_seq_client *receiver = NULL, *sender = NULL; - struct snd_seq_client_port *sport = NULL, *dport = NULL; + struct snd_seq_client *receiver __free(snd_seq_client) = NULL; + struct snd_seq_client *sender __free(snd_seq_client) = NULL; + struct snd_seq_client_port *sport __free(snd_seq_port) = NULL; + struct snd_seq_client_port *dport __free(snd_seq_port) = NULL; + int result; receiver = snd_seq_client_use_ptr(subs->dest.client); if (!receiver) - goto __end; + return -ENXIO; sender = snd_seq_client_use_ptr(subs->sender.client); if (!sender) - goto __end; + return -ENXIO; sport = snd_seq_port_use_ptr(sender, subs->sender.port); if (!sport) - goto __end; + return -ENXIO; dport = snd_seq_port_use_ptr(receiver, subs->dest.port); if (!dport) - goto __end; + return -ENXIO; result = check_subscription_permission(client, sport, dport, subs); if (result < 0) - goto __end; + return result; result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, subs); if (! result) /* broadcast announce */ snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED); - __end: - if (sport) - snd_seq_port_unlock(sport); - if (dport) - snd_seq_port_unlock(dport); - if (sender) - snd_seq_client_unlock(sender); - if (receiver) - snd_seq_client_unlock(receiver); return result; } @@ -1614,7 +1518,7 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client, static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg) { struct snd_seq_queue_info *info = arg; - struct snd_seq_queue *q; + struct snd_seq_queue *q __free(snd_seq_queue) = NULL; q = snd_seq_queue_alloc(client->number, info->locked, info->flags); if (IS_ERR(q)) @@ -1628,7 +1532,6 @@ static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg) if (!info->name[0]) snprintf(info->name, sizeof(info->name), "Queue-%d", q->queue); strscpy(q->name, info->name, sizeof(q->name)); - snd_use_lock_free(&q->use_lock); return 0; } @@ -1646,7 +1549,7 @@ static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client, void *arg) { struct snd_seq_queue_info *info = arg; - struct snd_seq_queue *q; + struct snd_seq_queue *q __free(snd_seq_queue) = NULL; q = queueptr(info->queue); if (q == NULL) @@ -1657,7 +1560,6 @@ static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client, info->owner = q->owner; info->locked = q->locked; strscpy(info->name, q->name, sizeof(info->name)); - queuefree(q); return 0; } @@ -1667,7 +1569,7 @@ static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client, void *arg) { struct snd_seq_queue_info *info = arg; - struct snd_seq_queue *q; + struct snd_seq_queue *q __free(snd_seq_queue) = NULL; if (info->owner != client->number) return -EINVAL; @@ -1685,12 +1587,9 @@ static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client, q = queueptr(info->queue); if (! q) return -EINVAL; - if (q->owner != client->number) { - queuefree(q); + if (q->owner != client->number) return -EPERM; - } strscpy(q->name, info->name, sizeof(q->name)); - queuefree(q); return 0; } @@ -1700,7 +1599,7 @@ static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client, void *arg) { struct snd_seq_queue_info *info = arg; - struct snd_seq_queue *q; + struct snd_seq_queue *q __free(snd_seq_queue) = NULL; q = snd_seq_queue_find_name(info->name); if (q == NULL) @@ -1708,7 +1607,6 @@ static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client, info->queue = q->queue; info->owner = q->owner; info->locked = q->locked; - queuefree(q); return 0; } @@ -1718,7 +1616,7 @@ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client, void *arg) { struct snd_seq_queue_status *status = arg; - struct snd_seq_queue *queue; + struct snd_seq_queue *queue __free(snd_seq_queue) = NULL; struct snd_seq_timer *tmr; queue = queueptr(status->queue); @@ -1736,7 +1634,6 @@ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client, status->running = tmr->running; status->flags = queue->flags; - queuefree(queue); return 0; } @@ -1747,7 +1644,7 @@ static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client, void *arg) { struct snd_seq_queue_tempo *tempo = arg; - struct snd_seq_queue *queue; + struct snd_seq_queue *queue __free(snd_seq_queue) = NULL; struct snd_seq_timer *tmr; queue = queueptr(tempo->queue); @@ -1764,7 +1661,6 @@ static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client, tempo->skew_base = tmr->skew_base; if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 4)) tempo->tempo_base = tmr->tempo_base; - queuefree(queue); return 0; } @@ -1797,14 +1693,14 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, void *arg) { struct snd_seq_queue_timer *timer = arg; - struct snd_seq_queue *queue; + struct snd_seq_queue *queue __free(snd_seq_queue) = NULL; struct snd_seq_timer *tmr; queue = queueptr(timer->queue); if (queue == NULL) return -EINVAL; - mutex_lock(&queue->timer_mutex); + guard(mutex)(&queue->timer_mutex); tmr = queue->timer; memset(timer, 0, sizeof(*timer)); timer->queue = queue->queue; @@ -1814,8 +1710,6 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, timer->u.alsa.id = tmr->alsa_id; timer->u.alsa.resolution = tmr->preferred_resolution; } - mutex_unlock(&queue->timer_mutex); - queuefree(queue); return 0; } @@ -1832,13 +1726,13 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, return -EINVAL; if (snd_seq_queue_check_access(timer->queue, client->number)) { - struct snd_seq_queue *q; + struct snd_seq_queue *q __free(snd_seq_queue) = NULL; struct snd_seq_timer *tmr; q = queueptr(timer->queue); if (q == NULL) return -ENXIO; - mutex_lock(&q->timer_mutex); + guard(mutex)(&q->timer_mutex); tmr = q->timer; snd_seq_queue_timer_close(timer->queue); tmr->type = timer->type; @@ -1847,8 +1741,6 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, tmr->preferred_resolution = timer->u.alsa.resolution; } result = snd_seq_queue_timer_open(timer->queue); - mutex_unlock(&q->timer_mutex); - queuefree(q); } else { return -EPERM; } @@ -1896,7 +1788,7 @@ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client, void *arg) { struct snd_seq_client_pool *info = arg; - struct snd_seq_client *cptr; + struct snd_seq_client *cptr __free(snd_seq_client) = NULL; cptr = client_load_and_use_ptr(info->client); if (cptr == NULL) @@ -1915,7 +1807,6 @@ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client, info->input_pool = 0; info->input_free = 0; } - snd_seq_client_unlock(cptr); return 0; } @@ -1997,26 +1888,16 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, void *arg) { struct snd_seq_port_subscribe *subs = arg; - int result; - struct snd_seq_client *sender = NULL; - struct snd_seq_client_port *sport = NULL; + struct snd_seq_client *sender __free(snd_seq_client) = NULL; + struct snd_seq_client_port *sport __free(snd_seq_port) = NULL; - result = -EINVAL; sender = client_load_and_use_ptr(subs->sender.client); if (!sender) - goto __end; + return -EINVAL; sport = snd_seq_port_use_ptr(sender, subs->sender.port); if (!sport) - goto __end; - result = snd_seq_port_get_subscription(&sport->c_src, &subs->dest, - subs); - __end: - if (sport) - snd_seq_port_unlock(sport); - if (sender) - snd_seq_client_unlock(sender); - - return result; + return -EINVAL; + return snd_seq_port_get_subscription(&sport->c_src, &subs->dest, subs); } @@ -2026,19 +1907,18 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg) { struct snd_seq_query_subs *subs = arg; - int result = -ENXIO; - struct snd_seq_client *cptr = NULL; - struct snd_seq_client_port *port = NULL; + struct snd_seq_client *cptr __free(snd_seq_client) = NULL; + struct snd_seq_client_port *port __free(snd_seq_port) = NULL; struct snd_seq_port_subs_info *group; struct list_head *p; int i; cptr = client_load_and_use_ptr(subs->root.client); if (!cptr) - goto __end; + return -ENXIO; port = snd_seq_port_use_ptr(cptr, subs->root.port); if (!port) - goto __end; + return -ENXIO; switch (subs->type) { case SNDRV_SEQ_QUERY_SUBS_READ: @@ -2048,14 +1928,13 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg) group = &port->c_dest; break; default: - goto __end; + return -ENXIO; } - down_read(&group->list_mutex); + guard(rwsem_read)(&group->list_mutex); /* search for the subscriber */ subs->num_subs = group->count; i = 0; - result = -ENOENT; list_for_each(p, &group->list_head) { if (i++ == subs->index) { /* found! */ @@ -2069,19 +1948,11 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg) } subs->flags = s->info.flags; subs->queue = s->info.queue; - result = 0; - break; + return 0; } } - up_read(&group->list_mutex); - - __end: - if (port) - snd_seq_port_unlock(port); - if (cptr) - snd_seq_client_unlock(cptr); - return result; + return -ENOENT; } @@ -2092,7 +1963,7 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client, void *arg) { struct snd_seq_client_info *info = arg; - struct snd_seq_client *cptr = NULL; + struct snd_seq_client *cptr __free(snd_seq_client) = NULL; /* search for next client */ if (info->client < INT_MAX) @@ -2101,16 +1972,12 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client, info->client = 0; for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) { cptr = client_load_and_use_ptr(info->client); - if (cptr) - break; /* found */ + if (cptr) { + get_client_info(cptr, info); + return 0; /* found */ + } } - if (cptr == NULL) - return -ENOENT; - - get_client_info(cptr, info); - snd_seq_client_unlock(cptr); - - return 0; + return -ENOENT; } /* @@ -2120,8 +1987,8 @@ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client, void *arg) { struct snd_seq_port_info *info = arg; - struct snd_seq_client *cptr; - struct snd_seq_client_port *port = NULL; + struct snd_seq_client *cptr __free(snd_seq_client) = NULL; + struct snd_seq_client_port *port __free(snd_seq_port) = NULL; cptr = client_load_and_use_ptr(info->addr.client); if (cptr == NULL) @@ -2130,16 +1997,12 @@ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client, /* search for next port */ info->addr.port++; port = snd_seq_port_query_nearest(cptr, info); - if (port == NULL) { - snd_seq_client_unlock(cptr); + if (port == NULL) return -ENOENT; - } /* get port info */ info->addr = port->addr; snd_seq_get_port_info(port, info); - snd_seq_port_unlock(port); - snd_seq_client_unlock(cptr); return 0; } @@ -2204,7 +2067,7 @@ static int snd_seq_ioctl_client_ump_info(struct snd_seq_client *caller, { struct snd_seq_client_ump_info __user *argp = (struct snd_seq_client_ump_info __user *)arg; - struct snd_seq_client *cptr; + struct snd_seq_client *cptr __free(snd_seq_client) = NULL; int client, type, err = 0; size_t size; void *p; @@ -2224,51 +2087,49 @@ static int snd_seq_ioctl_client_ump_info(struct snd_seq_client *caller, if (!cptr) return -ENOENT; - mutex_lock(&cptr->ioctl_mutex); - if (!cptr->midi_version) { - err = -EBADFD; - goto error; - } - - if (cmd == SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO) { - if (!cptr->ump_info) - p = NULL; - else - p = cptr->ump_info[type]; - if (!p) { - err = -ENODEV; - goto error; - } - if (copy_to_user(argp->info, p, size)) { - err = -EFAULT; - goto error; - } - } else { - if (cptr->type != USER_CLIENT) { + scoped_guard(mutex, &cptr->ioctl_mutex) { + if (!cptr->midi_version) { err = -EBADFD; - goto error; + break; } - if (!cptr->ump_info) { - cptr->ump_info = kcalloc(NUM_UMP_INFOS, - sizeof(void *), GFP_KERNEL); + + if (cmd == SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO) { + if (!cptr->ump_info) + p = NULL; + else + p = cptr->ump_info[type]; + if (!p) { + err = -ENODEV; + break; + } + if (copy_to_user(argp->info, p, size)) { + err = -EFAULT; + break; + } + } else { + if (cptr->type != USER_CLIENT) { + err = -EBADFD; + break; + } if (!cptr->ump_info) { - err = -ENOMEM; - goto error; + cptr->ump_info = kcalloc(NUM_UMP_INFOS, + sizeof(void *), GFP_KERNEL); + if (!cptr->ump_info) { + err = -ENOMEM; + break; + } } + p = memdup_user(argp->info, size); + if (IS_ERR(p)) { + err = PTR_ERR(p); + break; + } + kfree(cptr->ump_info[type]); + terminate_ump_info_strings(p, type); + cptr->ump_info[type] = p; } - p = memdup_user(argp->info, size); - if (IS_ERR(p)) { - err = PTR_ERR(p); - goto error; - } - kfree(cptr->ump_info[type]); - terminate_ump_info_strings(p, type); - cptr->ump_info[type] = p; - } - error: - mutex_unlock(&cptr->ioctl_mutex); - snd_seq_client_unlock(cptr); + } if (!err && cmd == SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO) { if (type == SNDRV_SEQ_CLIENT_UMP_INFO_ENDPOINT) snd_seq_system_ump_notify(client, 0, @@ -2381,9 +2242,9 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd, return -EFAULT; } - mutex_lock(&client->ioctl_mutex); - err = handler->func(client, &buf); - mutex_unlock(&client->ioctl_mutex); + scoped_guard(mutex, &client->ioctl_mutex) { + err = handler->func(client, &buf); + } if (err >= 0) { /* Some commands includes a bug in 'dir' field. */ if (handler->cmd == SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT || @@ -2420,34 +2281,32 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, if (card == NULL && client_index >= SNDRV_SEQ_GLOBAL_CLIENTS) return -EINVAL; - mutex_lock(®ister_mutex); + scoped_guard(mutex, ®ister_mutex) { - if (card) { - client_index += SNDRV_SEQ_GLOBAL_CLIENTS - + card->number * SNDRV_SEQ_CLIENTS_PER_CARD; - if (client_index >= SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN) - client_index = -1; - } + if (card) { + client_index += SNDRV_SEQ_GLOBAL_CLIENTS + + card->number * SNDRV_SEQ_CLIENTS_PER_CARD; + if (client_index >= SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN) + client_index = -1; + } - /* empty write queue as default */ - client = seq_create_client1(client_index, 0); - if (client == NULL) { - mutex_unlock(®ister_mutex); - return -EBUSY; /* failure code */ - } - usage_alloc(&client_usage, 1); + /* empty write queue as default */ + client = seq_create_client1(client_index, 0); + if (client == NULL) + return -EBUSY; /* failure code */ + usage_alloc(&client_usage, 1); - client->accept_input = 1; - client->accept_output = 1; - client->data.kernel.card = card; - client->user_pversion = SNDRV_SEQ_VERSION; + client->accept_input = 1; + client->accept_output = 1; + client->data.kernel.card = card; + client->user_pversion = SNDRV_SEQ_VERSION; - va_start(args, name_fmt); - vsnprintf(client->name, sizeof(client->name), name_fmt, args); - va_end(args); + va_start(args, name_fmt); + vsnprintf(client->name, sizeof(client->name), name_fmt, args); + va_end(args); - client->type = KERNEL_CLIENT; - mutex_unlock(®ister_mutex); + client->type = KERNEL_CLIENT; + } /* make others aware this new client */ snd_seq_system_client_ev_client_start(client->number); @@ -2483,8 +2342,7 @@ EXPORT_SYMBOL(snd_seq_delete_kernel_client); int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev, struct file *file, bool blocking) { - struct snd_seq_client *cptr; - int result; + struct snd_seq_client *cptr __free(snd_seq_client) = NULL; if (snd_BUG_ON(!ev)) return -EINVAL; @@ -2507,17 +2365,13 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev, return -EINVAL; if (!cptr->accept_output) { - result = -EPERM; + return -EPERM; } else { /* send it */ - mutex_lock(&cptr->ioctl_mutex); - result = snd_seq_client_enqueue_event(cptr, ev, file, blocking, - false, 0, - &cptr->ioctl_mutex); - mutex_unlock(&cptr->ioctl_mutex); + guard(mutex)(&cptr->ioctl_mutex); + return snd_seq_client_enqueue_event(cptr, ev, file, blocking, + false, 0, + &cptr->ioctl_mutex); } - - snd_seq_client_unlock(cptr); - return result; } EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); @@ -2531,8 +2385,7 @@ EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev, int atomic, int hop) { - struct snd_seq_client *cptr; - int result; + struct snd_seq_client *cptr __free(snd_seq_client) = NULL; if (snd_BUG_ON(!ev)) return -EINVAL; @@ -2549,15 +2402,27 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev, return -EINVAL; if (!cptr->accept_output) - result = -EPERM; + return -EPERM; else - result = snd_seq_deliver_event(cptr, ev, atomic, hop); - - snd_seq_client_unlock(cptr); - return result; + return snd_seq_deliver_event(cptr, ev, atomic, hop); } EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); +static int call_seq_client_ctl(struct snd_seq_client *client, + unsigned int cmd, void *arg) +{ + const struct ioctl_handler *handler; + + for (handler = ioctl_handlers; handler->cmd > 0; ++handler) { + if (handler->cmd == cmd) + return handler->func(client, arg); + } + + pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n", + cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); + return -ENOTTY; +} + /** * snd_seq_kernel_client_ctl - operate a command for a client with data in * kernel space. @@ -2572,24 +2437,29 @@ EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); */ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) { - const struct ioctl_handler *handler; struct snd_seq_client *client; client = clientptr(clientid); if (client == NULL) return -ENXIO; - for (handler = ioctl_handlers; handler->cmd > 0; ++handler) { - if (handler->cmd == cmd) - return handler->func(client, arg); - } - - pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n", - cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); - return -ENOTTY; + return call_seq_client_ctl(client, cmd, arg); } EXPORT_SYMBOL(snd_seq_kernel_client_ctl); +/* a similar like above but taking locks; used only from OSS sequencer layer */ +int snd_seq_kernel_client_ioctl(int clientid, unsigned int cmd, void *arg) +{ + struct snd_seq_client *client __free(snd_seq_client) = NULL; + + client = client_load_and_use_ptr(clientid); + if (!client) + return -ENXIO; + guard(mutex)(&client->ioctl_mutex); + return call_seq_client_ctl(client, cmd, arg); +} +EXPORT_SYMBOL_GPL(snd_seq_kernel_client_ioctl); + /* exported (for OSS emulator) */ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait) { @@ -2616,7 +2486,7 @@ EXPORT_SYMBOL_GPL(snd_seq_kernel_client_get); void snd_seq_kernel_client_put(struct snd_seq_client *cptr) { if (cptr) - snd_seq_client_unlock(cptr); + snd_seq_client_unref(cptr); } EXPORT_SYMBOL_GPL(snd_seq_kernel_client_put); @@ -2634,11 +2504,9 @@ static void snd_seq_info_dump_subscribers(struct snd_info_buffer *buffer, struct snd_seq_subscribers *s; int count = 0; - down_read(&group->list_mutex); - if (list_empty(&group->list_head)) { - up_read(&group->list_mutex); + guard(rwsem_read)(&group->list_mutex); + if (list_empty(&group->list_head)) return; - } snd_iprintf(buffer, msg); list_for_each(p, &group->list_head) { if (is_src) @@ -2655,7 +2523,6 @@ static void snd_seq_info_dump_subscribers(struct snd_info_buffer *buffer, if (group->exclusive) snd_iprintf(buffer, "[ex]"); } - up_read(&group->list_mutex); snd_iprintf(buffer, "\n"); } @@ -2681,7 +2548,7 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer, { struct snd_seq_client_port *p; - mutex_lock(&client->ports_mutex); + guard(mutex)(&client->ports_mutex); list_for_each_entry(p, &client->ports_list_head, list) { if (p->capability & SNDRV_SEQ_PORT_CAP_INACTIVE) continue; @@ -2700,7 +2567,6 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer, snd_seq_info_dump_subscribers(buffer, &p->c_src, 1, " Connecting To: "); snd_seq_info_dump_subscribers(buffer, &p->c_dest, 0, " Connected From: "); } - mutex_unlock(&client->ports_mutex); } static const char *midi_version_string(unsigned int version) @@ -2722,7 +2588,6 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { int c; - struct snd_seq_client *client; snd_iprintf(buffer, "Client info\n"); snd_iprintf(buffer, " cur clients : %d\n", client_usage.cur); @@ -2732,15 +2597,15 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry, /* list the client table */ for (c = 0; c < SNDRV_SEQ_MAX_CLIENTS; c++) { + struct snd_seq_client *client __free(snd_seq_client) = NULL; + client = client_load_and_use_ptr(c); if (client == NULL) continue; - if (client->type == NO_CLIENT) { - snd_seq_client_unlock(client); + if (client->type == NO_CLIENT) continue; - } - mutex_lock(&client->ioctl_mutex); + guard(mutex)(&client->ioctl_mutex); snd_iprintf(buffer, "Client %3d : \"%s\" [%s %s]\n", c, client->name, client->type == USER_CLIENT ? "User" : "Kernel", @@ -2758,8 +2623,6 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry, snd_iprintf(buffer, " Input pool :\n"); snd_seq_info_pool(buffer, client->data.user.fifo->pool, " "); } - mutex_unlock(&client->ioctl_mutex); - snd_seq_client_unlock(client); } } #endif /* CONFIG_SND_PROC_FS */ @@ -2797,10 +2660,10 @@ int __init snd_sequencer_device_init(void) return err; dev_set_name(seq_dev, "seq"); - mutex_lock(®ister_mutex); - err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, - &snd_seq_f_ops, NULL, seq_dev); - mutex_unlock(®ister_mutex); + scoped_guard(mutex, ®ister_mutex) { + err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, + &snd_seq_f_ops, NULL, seq_dev); + } if (err < 0) { put_device(seq_dev); return err; diff --git a/sound/core/seq/seq_clientmgr.h b/sound/core/seq/seq_clientmgr.h index 915b1017286e..ece02c58db70 100644 --- a/sound/core/seq/seq_clientmgr.h +++ b/sound/core/seq/seq_clientmgr.h @@ -78,8 +78,20 @@ void snd_sequencer_device_done(void); /* get locked pointer to client */ struct snd_seq_client *snd_seq_client_use_ptr(int clientid); +static inline struct snd_seq_client * +snd_seq_client_ref(struct snd_seq_client *client) +{ + snd_use_lock_use(&client->use_lock); + return client; +} + /* unlock pointer to client */ -#define snd_seq_client_unlock(client) snd_use_lock_free(&(client)->use_lock) +static inline void snd_seq_client_unref(struct snd_seq_client *client) +{ + snd_use_lock_free(&client->use_lock); +} + +DEFINE_FREE(snd_seq_client, struct snd_seq_client *, if (!IS_ERR_OR_NULL(_T)) snd_seq_client_unref(_T)) /* dispatch event to client(s) */ int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop); @@ -94,8 +106,7 @@ int __snd_seq_deliver_single_event(struct snd_seq_client *dest, int atomic, int hop); /* only for OSS sequencer */ -bool snd_seq_client_ioctl_lock(int clientid); -void snd_seq_client_ioctl_unlock(int clientid); +int snd_seq_kernel_client_ioctl(int clientid, unsigned int cmd, void *arg); extern int seq_client_load[15]; diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c index 3a10b081f129..91cce1890111 100644 --- a/sound/core/seq/seq_fifo.c +++ b/sound/core/seq/seq_fifo.c @@ -106,12 +106,11 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f, if (snd_BUG_ON(!f)) return -EINVAL; - snd_use_lock_use(&f->use_lock); + guard(snd_seq_fifo)(f); err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL, NULL); /* always non-blocking */ if (err < 0) { if ((err == -ENOMEM) || (err == -EAGAIN)) atomic_inc(&f->overflow); - snd_use_lock_free(&f->use_lock); return err; } @@ -130,8 +129,6 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f, if (waitqueue_active(&f->input_sleep)) wake_up(&f->input_sleep); - snd_use_lock_free(&f->use_lock); - return 0; /* success */ } @@ -213,6 +210,7 @@ int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file, poll_table *wait) { poll_wait(file, &f->input_sleep, wait); + guard(spinlock_irq)(&f->lock); return (f->cells > 0); } @@ -263,14 +261,10 @@ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize) /* get the number of unused cells safely */ int snd_seq_fifo_unused_cells(struct snd_seq_fifo *f) { - int cells; - if (!f) return 0; - snd_use_lock_use(&f->use_lock); - scoped_guard(spinlock_irqsave, &f->lock) - cells = snd_seq_unused_cells(f->pool); - snd_use_lock_free(&f->use_lock); - return cells; + guard(snd_seq_fifo)(f); + guard(spinlock_irqsave)(&f->lock); + return snd_seq_unused_cells(f->pool); } diff --git a/sound/core/seq/seq_fifo.h b/sound/core/seq/seq_fifo.h index b56a7b897c9c..4c9c49127746 100644 --- a/sound/core/seq/seq_fifo.h +++ b/sound/core/seq/seq_fifo.h @@ -37,6 +37,7 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f, struct snd_seq_event *event); /* lock fifo from release */ #define snd_seq_fifo_lock(fifo) snd_use_lock_use(&(fifo)->use_lock) #define snd_seq_fifo_unlock(fifo) snd_use_lock_free(&(fifo)->use_lock) +DEFINE_GUARD(snd_seq_fifo, struct snd_seq_fifo *, snd_seq_fifo_lock(_T), snd_seq_fifo_unlock(_T)) /* get a cell from fifo - fifo should be locked */ int snd_seq_fifo_cell_out(struct snd_seq_fifo *f, struct snd_seq_event_cell **cellp, int nonblock); diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index cc2f8e846584..40fa379847e5 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -178,17 +178,10 @@ static int unsubscribe_port(struct snd_seq_client *client, static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr, struct snd_seq_client **cp) { - struct snd_seq_client_port *p; *cp = snd_seq_client_use_ptr(addr->client); - if (*cp) { - p = snd_seq_port_use_ptr(*cp, addr->port); - if (! p) { - snd_seq_client_unlock(*cp); - *cp = NULL; - } - return p; - } - return NULL; + if (!*cp) + return NULL; + return snd_seq_port_use_ptr(*cp, addr->port); } static void delete_and_unsubscribe_port(struct snd_seq_client *client, @@ -218,8 +211,8 @@ static void clear_subscriber_list(struct snd_seq_client *client, list_for_each_safe(p, n, &grp->list_head) { struct snd_seq_subscribers *subs; - struct snd_seq_client *c; - struct snd_seq_client_port *aport; + struct snd_seq_client *c __free(snd_seq_client) = NULL; + struct snd_seq_client_port *aport __free(snd_seq_port) = NULL; subs = get_subscriber(p, is_src); if (is_src) @@ -241,8 +234,6 @@ static void clear_subscriber_list(struct snd_seq_client *client, /* ok we got the connected port */ delete_and_unsubscribe_port(c, aport, subs, !is_src, true); kfree(subs); - snd_seq_port_unlock(aport); - snd_seq_client_unlock(c); } } diff --git a/sound/core/seq/seq_ports.h b/sound/core/seq/seq_ports.h index b3b35018cb82..40ed6cf7cb90 100644 --- a/sound/core/seq/seq_ports.h +++ b/sound/core/seq/seq_ports.h @@ -96,6 +96,8 @@ struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *cl /* unlock the port */ #define snd_seq_port_unlock(port) snd_use_lock_free(&(port)->use_lock) +DEFINE_FREE(snd_seq_port, struct snd_seq_client_port *, if (!IS_ERR_OR_NULL(_T)) snd_seq_port_unlock(_T)) + /* create a port, port number or a negative error code is returned */ int snd_seq_create_port(struct snd_seq_client *client, int port_index, struct snd_seq_client_port **port_ret); diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index 10add922323d..f5c0e401c8ae 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c @@ -209,14 +209,13 @@ struct snd_seq_queue *queueptr(int queueid) struct snd_seq_queue *snd_seq_queue_find_name(char *name) { int i; - struct snd_seq_queue *q; for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { + struct snd_seq_queue *q __free(snd_seq_queue) = NULL; q = queueptr(i); if (q) { if (strncmp(q->name, name, sizeof(q->name)) == 0) - return q; - queuefree(q); + return no_free_ptr(q); } } return NULL; @@ -286,7 +285,7 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop) int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop) { int dest, err; - struct snd_seq_queue *q; + struct snd_seq_queue *q __free(snd_seq_queue) = NULL; if (snd_BUG_ON(!cell)) return -EINVAL; @@ -321,16 +320,12 @@ int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop) break; } - if (err < 0) { - queuefree(q); /* unlock */ + if (err < 0) return err; - } /* trigger dispatching */ snd_seq_check_queue(q, atomic, hop); - queuefree(q); /* unlock */ - return 0; } @@ -366,15 +361,12 @@ static inline void queue_access_unlock(struct snd_seq_queue *q) /* exported - only checking permission */ int snd_seq_queue_check_access(int queueid, int client) { - struct snd_seq_queue *q = queueptr(queueid); - int access_ok; + struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(queueid); if (! q) return 0; - scoped_guard(spinlock_irqsave, &q->owner_lock) - access_ok = check_access(q, client); - queuefree(q); - return access_ok; + guard(spinlock_irqsave)(&q->owner_lock); + return check_access(q, client); } /*----------------------------------------------------------------*/ @@ -384,22 +376,19 @@ int snd_seq_queue_check_access(int queueid, int client) */ int snd_seq_queue_set_owner(int queueid, int client, int locked) { - struct snd_seq_queue *q = queueptr(queueid); + struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(queueid); if (q == NULL) return -EINVAL; - if (! queue_access_lock(q, client)) { - queuefree(q); + if (!queue_access_lock(q, client)) return -EPERM; - } scoped_guard(spinlock_irqsave, &q->owner_lock) { q->locked = locked ? 1 : 0; q->owner = client; } queue_access_unlock(q); - queuefree(q); return 0; } @@ -414,7 +403,7 @@ int snd_seq_queue_set_owner(int queueid, int client, int locked) int snd_seq_queue_timer_open(int queueid) { int result = 0; - struct snd_seq_queue *queue; + struct snd_seq_queue *queue __free(snd_seq_queue) = NULL; struct snd_seq_timer *tmr; queue = queueptr(queueid); @@ -426,7 +415,6 @@ int snd_seq_queue_timer_open(int queueid) snd_seq_timer_defaults(tmr); result = snd_seq_timer_open(queue); } - queuefree(queue); return result; } @@ -435,14 +423,13 @@ int snd_seq_queue_timer_open(int queueid) */ int snd_seq_queue_timer_close(int queueid) { - struct snd_seq_queue *queue; + struct snd_seq_queue *queue __free(snd_seq_queue) = NULL; int result = 0; queue = queueptr(queueid); if (queue == NULL) return -EINVAL; snd_seq_timer_close(queue); - queuefree(queue); return result; } @@ -450,15 +437,13 @@ int snd_seq_queue_timer_close(int queueid) int snd_seq_queue_timer_set_tempo(int queueid, int client, struct snd_seq_queue_tempo *info) { - struct snd_seq_queue *q = queueptr(queueid); + struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(queueid); int result; if (q == NULL) return -EINVAL; - if (! queue_access_lock(q, client)) { - queuefree(q); + if (!queue_access_lock(q, client)) return -EPERM; - } result = snd_seq_timer_set_tempo_ppq(q->timer, info->tempo, info->ppq, info->tempo_base); @@ -466,7 +451,6 @@ int snd_seq_queue_timer_set_tempo(int queueid, int client, result = snd_seq_timer_set_skew(q->timer, info->skew_value, info->skew_base); queue_access_unlock(q); - queuefree(q); return result; } @@ -495,15 +479,13 @@ static void queue_use(struct snd_seq_queue *queue, int client, int use) */ int snd_seq_queue_use(int queueid, int client, int use) { - struct snd_seq_queue *queue; + struct snd_seq_queue *queue __free(snd_seq_queue) = NULL; queue = queueptr(queueid); if (queue == NULL) return -EINVAL; - mutex_lock(&queue->timer_mutex); + guard(mutex)(&queue->timer_mutex); queue_use(queue, client, use); - mutex_unlock(&queue->timer_mutex); - queuefree(queue); return 0; } @@ -514,15 +496,12 @@ int snd_seq_queue_use(int queueid, int client, int use) */ int snd_seq_queue_is_used(int queueid, int client) { - struct snd_seq_queue *q; - int result; + struct snd_seq_queue *q __free(snd_seq_queue) = NULL; q = queueptr(queueid); if (q == NULL) return -EINVAL; /* invalid queue */ - result = test_bit(client, q->clients_bitmap) ? 1 : 0; - queuefree(q); - return result; + return test_bit(client, q->clients_bitmap) ? 1 : 0; } @@ -535,11 +514,10 @@ int snd_seq_queue_is_used(int queueid, int client) void snd_seq_queue_client_leave(int client) { int i; - struct snd_seq_queue *q; /* delete own queues from queue list */ for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - q = queue_list_remove(i, client); + struct snd_seq_queue *q = queue_list_remove(i, client); if (q) queue_delete(q); } @@ -548,7 +526,7 @@ void snd_seq_queue_client_leave(int client) * they are not owned by this client */ for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - q = queueptr(i); + struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(i); if (!q) continue; if (test_bit(client, q->clients_bitmap)) { @@ -556,7 +534,6 @@ void snd_seq_queue_client_leave(int client) snd_seq_prioq_leave(q->timeq, client, 0); snd_seq_queue_use(q->queue, client, 0); } - queuefree(q); } } @@ -568,10 +545,9 @@ void snd_seq_queue_client_leave(int client) void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info) { int i; - struct snd_seq_queue *q; for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - q = queueptr(i); + struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(i); if (!q) continue; if (test_bit(client, q->clients_bitmap) && @@ -580,7 +556,6 @@ void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info) snd_seq_prioq_remove_events(q->tickq, client, info); snd_seq_prioq_remove_events(q->timeq, client, info); } - queuefree(q); } } @@ -667,7 +642,7 @@ static void snd_seq_queue_process_event(struct snd_seq_queue *q, */ int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop) { - struct snd_seq_queue *q; + struct snd_seq_queue *q __free(snd_seq_queue) = NULL; if (snd_BUG_ON(!ev)) return -EINVAL; @@ -676,15 +651,12 @@ int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop) if (q == NULL) return -EINVAL; - if (! queue_access_lock(q, ev->source.client)) { - queuefree(q); + if (!queue_access_lock(q, ev->source.client)) return -EPERM; - } snd_seq_queue_process_event(q, ev, atomic, hop); queue_access_unlock(q); - queuefree(q); return 0; } @@ -697,13 +669,12 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { int i, bpm; - struct snd_seq_queue *q; struct snd_seq_timer *tmr; bool locked; int owner; for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - q = queueptr(i); + struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(i); if (!q) continue; @@ -731,7 +702,6 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry, snd_iprintf(buffer, "current time : %d.%09d s\n", tmr->cur_time.tv_sec, tmr->cur_time.tv_nsec); snd_iprintf(buffer, "current tick : %d\n", tmr->tick.cur_tick); snd_iprintf(buffer, "\n"); - queuefree(q); } } #endif /* CONFIG_SND_PROC_FS */ diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h index b81379c9af43..afcd3c5484a6 100644 --- a/sound/core/seq/seq_queue.h +++ b/sound/core/seq/seq_queue.h @@ -73,6 +73,8 @@ struct snd_seq_queue *queueptr(int queueid); /* unlock */ #define queuefree(q) snd_use_lock_free(&(q)->use_lock) +DEFINE_FREE(snd_seq_queue, struct snd_seq_queue *, if (!IS_ERR_OR_NULL(_T)) queuefree(_T)) + /* return the (first) queue matching with the specified name */ struct snd_seq_queue *snd_seq_queue_find_name(char *name); diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index c9f0392ac7f1..29b018a212fc 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c @@ -440,13 +440,13 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { int idx; - struct snd_seq_queue *q; struct snd_seq_timer *tmr; struct snd_timer_instance *ti; unsigned long resolution; for (idx = 0; idx < SNDRV_SEQ_MAX_QUEUES; idx++) { - q = queueptr(idx); + struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(idx); + if (q == NULL) continue; scoped_guard(mutex, &q->timer_mutex) { @@ -461,7 +461,6 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry, snd_iprintf(buffer, " Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000); snd_iprintf(buffer, " Skew : %u / %u\n", tmr->skew, tmr->skew_base); } - queuefree(q); } } #endif /* CONFIG_SND_PROC_FS */ diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index a8902dc45dc1..64ef03b2d579 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -414,39 +414,39 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) dpcm->last_jiffies = jiffies; dpcm->pcm_rate_shift = 0; dpcm->last_drift = 0; - spin_lock(&cable->lock); - cable->running |= stream; - cable->pause &= ~stream; - err = cable->ops->start(dpcm); - spin_unlock(&cable->lock); + scoped_guard(spinlock, &cable->lock) { + cable->running |= stream; + cable->pause &= ~stream; + err = cable->ops->start(dpcm); + } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); break; case SNDRV_PCM_TRIGGER_STOP: - spin_lock(&cable->lock); - cable->running &= ~stream; - cable->pause &= ~stream; - err = cable->ops->stop(dpcm); - spin_unlock(&cable->lock); + scoped_guard(spinlock, &cable->lock) { + cable->running &= ~stream; + cable->pause &= ~stream; + err = cable->ops->stop(dpcm); + } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_SUSPEND: - spin_lock(&cable->lock); - cable->pause |= stream; - err = cable->ops->stop(dpcm); - spin_unlock(&cable->lock); + scoped_guard(spinlock, &cable->lock) { + cable->pause |= stream; + err = cable->ops->stop(dpcm); + } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: - spin_lock(&cable->lock); - dpcm->last_jiffies = jiffies; - cable->pause &= ~stream; - err = cable->ops->start(dpcm); - spin_unlock(&cable->lock); + scoped_guard(spinlock, &cable->lock) { + dpcm->last_jiffies = jiffies; + cable->pause &= ~stream; + err = cable->ops->start(dpcm); + } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); break; @@ -511,13 +511,12 @@ static int loopback_prepare(struct snd_pcm_substream *substream) dpcm->pcm_salign = salign; dpcm->pcm_period_size = frames_to_bytes(runtime, runtime->period_size); - mutex_lock(&dpcm->loopback->cable_lock); + guard(mutex)(&dpcm->loopback->cable_lock); if (!(cable->valid & ~(1 << substream->stream)) || (get_setup(dpcm)->notify && substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) params_change(substream); cable->valid |= 1 << substream->stream; - mutex_unlock(&dpcm->loopback->cable_lock); return 0; } @@ -701,21 +700,22 @@ static unsigned int loopback_jiffies_timer_pos_update static void loopback_jiffies_timer_function(struct timer_list *t) { struct loopback_pcm *dpcm = timer_container_of(dpcm, t, timer); - unsigned long flags; - - spin_lock_irqsave(&dpcm->cable->lock, flags); - if (loopback_jiffies_timer_pos_update(dpcm->cable) & - (1 << dpcm->substream->stream)) { - loopback_jiffies_timer_start(dpcm); - if (dpcm->period_update_pending) { - dpcm->period_update_pending = 0; - spin_unlock_irqrestore(&dpcm->cable->lock, flags); - /* need to unlock before calling below */ - snd_pcm_period_elapsed(dpcm->substream); - return; + bool period_elapsed = false; + + scoped_guard(spinlock_irqsave, &dpcm->cable->lock) { + if (loopback_jiffies_timer_pos_update(dpcm->cable) & + (1 << dpcm->substream->stream)) { + loopback_jiffies_timer_start(dpcm); + if (dpcm->period_update_pending) { + dpcm->period_update_pending = 0; + period_elapsed = true; + break; + } } } - spin_unlock_irqrestore(&dpcm->cable->lock, flags); + + if (period_elapsed) + snd_pcm_period_elapsed(dpcm->substream); } /* call in cable->lock */ @@ -760,68 +760,68 @@ static void loopback_snd_timer_period_elapsed(struct loopback_cable *cable, struct snd_pcm_substream *substream_play, *substream_capt; struct snd_pcm_runtime *valid_runtime; unsigned int running, elapsed_bytes; - unsigned long flags; + bool xrun = false; - spin_lock_irqsave(&cable->lock, flags); - running = cable->running ^ cable->pause; - /* no need to do anything if no stream is running */ - if (!running) { - spin_unlock_irqrestore(&cable->lock, flags); - return; - } + scoped_guard(spinlock_irqsave, &cable->lock) { + running = cable->running ^ cable->pause; + /* no need to do anything if no stream is running */ + if (!running) + return; - dpcm_play = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; - dpcm_capt = cable->streams[SNDRV_PCM_STREAM_CAPTURE]; + dpcm_play = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; + dpcm_capt = cable->streams[SNDRV_PCM_STREAM_CAPTURE]; - if (event == SNDRV_TIMER_EVENT_MSTOP) { - if (!dpcm_play || - dpcm_play->substream->runtime->state != - SNDRV_PCM_STATE_DRAINING) { - spin_unlock_irqrestore(&cable->lock, flags); - return; + if (event == SNDRV_TIMER_EVENT_MSTOP) { + if (!dpcm_play || + dpcm_play->substream->runtime->state != + SNDRV_PCM_STATE_DRAINING) + return; } - } - substream_play = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? + substream_play = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? dpcm_play->substream : NULL; - substream_capt = (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) ? + substream_capt = (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) ? dpcm_capt->substream : NULL; - valid_runtime = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? - dpcm_play->substream->runtime : - dpcm_capt->substream->runtime; - - /* resolution is only valid for SNDRV_TIMER_EVENT_TICK events */ - if (event == SNDRV_TIMER_EVENT_TICK) { - /* The hardware rules guarantee that playback and capture period - * are the same. Therefore only one device has to be checked - * here. - */ - if (loopback_snd_timer_check_resolution(valid_runtime, - resolution) < 0) { - spin_unlock_irqrestore(&cable->lock, flags); - if (substream_play) - snd_pcm_stop_xrun(substream_play); - if (substream_capt) - snd_pcm_stop_xrun(substream_capt); - return; + valid_runtime = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? + dpcm_play->substream->runtime : + dpcm_capt->substream->runtime; + + /* resolution is only valid for SNDRV_TIMER_EVENT_TICK events */ + if (event == SNDRV_TIMER_EVENT_TICK) { + /* The hardware rules guarantee that playback and capture period + * are the same. Therefore only one device has to be checked + * here. + */ + if (loopback_snd_timer_check_resolution(valid_runtime, + resolution) < 0) { + xrun = true; + break; + } + } + + elapsed_bytes = frames_to_bytes(valid_runtime, + valid_runtime->period_size); + /* The same timer interrupt is used for playback and capture device */ + if ((running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) && + (running & (1 << SNDRV_PCM_STREAM_CAPTURE))) { + copy_play_buf(dpcm_play, dpcm_capt, elapsed_bytes); + bytepos_finish(dpcm_play, elapsed_bytes); + bytepos_finish(dpcm_capt, elapsed_bytes); + } else if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { + bytepos_finish(dpcm_play, elapsed_bytes); + } else if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) { + clear_capture_buf(dpcm_capt, elapsed_bytes); + bytepos_finish(dpcm_capt, elapsed_bytes); } } - elapsed_bytes = frames_to_bytes(valid_runtime, - valid_runtime->period_size); - /* The same timer interrupt is used for playback and capture device */ - if ((running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) && - (running & (1 << SNDRV_PCM_STREAM_CAPTURE))) { - copy_play_buf(dpcm_play, dpcm_capt, elapsed_bytes); - bytepos_finish(dpcm_play, elapsed_bytes); - bytepos_finish(dpcm_capt, elapsed_bytes); - } else if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { - bytepos_finish(dpcm_play, elapsed_bytes); - } else if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) { - clear_capture_buf(dpcm_capt, elapsed_bytes); - bytepos_finish(dpcm_capt, elapsed_bytes); + if (xrun) { + if (substream_play) + snd_pcm_stop_xrun(substream_play); + if (substream_capt) + snd_pcm_stop_xrun(substream_capt); + return; } - spin_unlock_irqrestore(&cable->lock, flags); if (substream_play) snd_pcm_period_elapsed(substream_play); @@ -910,11 +910,10 @@ static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream) struct loopback_pcm *dpcm = runtime->private_data; snd_pcm_uframes_t pos; - spin_lock(&dpcm->cable->lock); + guard(spinlock)(&dpcm->cable->lock); if (dpcm->cable->ops->pos_update) dpcm->cable->ops->pos_update(dpcm->cable); pos = dpcm->buf_pos; - spin_unlock(&dpcm->cable->lock); return bytes_to_frames(runtime, pos); } @@ -958,9 +957,8 @@ static int loopback_hw_free(struct snd_pcm_substream *substream) struct loopback_pcm *dpcm = runtime->private_data; struct loopback_cable *cable = dpcm->cable; - mutex_lock(&dpcm->loopback->cable_lock); + guard(mutex)(&dpcm->loopback->cable_lock); cable->valid &= ~(1 << substream->stream); - mutex_unlock(&dpcm->loopback->cable_lock); return 0; } @@ -980,10 +978,10 @@ static int rule_format(struct snd_pcm_hw_params *params, struct snd_mask m; snd_mask_none(&m); - mutex_lock(&dpcm->loopback->cable_lock); - m.bits[0] = (u_int32_t)cable->hw.formats; - m.bits[1] = (u_int32_t)(cable->hw.formats >> 32); - mutex_unlock(&dpcm->loopback->cable_lock); + scoped_guard(mutex, &dpcm->loopback->cable_lock) { + m.bits[0] = (u_int32_t)cable->hw.formats; + m.bits[1] = (u_int32_t)(cable->hw.formats >> 32); + } return snd_mask_refine(hw_param_mask(params, rule->var), &m); } @@ -994,10 +992,10 @@ static int rule_rate(struct snd_pcm_hw_params *params, struct loopback_cable *cable = dpcm->cable; struct snd_interval t; - mutex_lock(&dpcm->loopback->cable_lock); - t.min = cable->hw.rate_min; - t.max = cable->hw.rate_max; - mutex_unlock(&dpcm->loopback->cable_lock); + scoped_guard(mutex, &dpcm->loopback->cable_lock) { + t.min = cable->hw.rate_min; + t.max = cable->hw.rate_max; + } t.openmin = t.openmax = 0; t.integer = 0; return snd_interval_refine(hw_param_interval(params, rule->var), &t); @@ -1010,10 +1008,10 @@ static int rule_channels(struct snd_pcm_hw_params *params, struct loopback_cable *cable = dpcm->cable; struct snd_interval t; - mutex_lock(&dpcm->loopback->cable_lock); - t.min = cable->hw.channels_min; - t.max = cable->hw.channels_max; - mutex_unlock(&dpcm->loopback->cable_lock); + scoped_guard(mutex, &dpcm->loopback->cable_lock) { + t.min = cable->hw.channels_min; + t.max = cable->hw.channels_max; + } t.openmin = t.openmax = 0; t.integer = 0; return snd_interval_refine(hw_param_interval(params, rule->var), &t); @@ -1026,10 +1024,10 @@ static int rule_period_bytes(struct snd_pcm_hw_params *params, struct loopback_cable *cable = dpcm->cable; struct snd_interval t; - mutex_lock(&dpcm->loopback->cable_lock); - t.min = cable->hw.period_bytes_min; - t.max = cable->hw.period_bytes_max; - mutex_unlock(&dpcm->loopback->cable_lock); + scoped_guard(mutex, &dpcm->loopback->cable_lock) { + t.min = cable->hw.period_bytes_min; + t.max = cable->hw.period_bytes_max; + } t.openmin = 0; t.openmax = 0; t.integer = 0; @@ -1047,9 +1045,8 @@ static void free_cable(struct snd_pcm_substream *substream) return; if (cable->streams[!substream->stream]) { /* other stream is still alive */ - spin_lock_irq(&cable->lock); + guard(spinlock_irq)(&cable->lock); cable->streams[substream->stream] = NULL; - spin_unlock_irq(&cable->lock); } else { struct loopback_pcm *dpcm = substream->runtime->private_data; @@ -1238,12 +1235,10 @@ static int loopback_open(struct snd_pcm_substream *substream) int err = 0; int dev = get_cable_index(substream); - mutex_lock(&loopback->cable_lock); + guard(mutex)(&loopback->cable_lock); dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); - if (!dpcm) { - err = -ENOMEM; - goto unlock; - } + if (!dpcm) + return -ENOMEM; dpcm->loopback = loopback; dpcm->substream = substream; @@ -1317,16 +1312,15 @@ static int loopback_open(struct snd_pcm_substream *substream) else runtime->hw = cable->hw; - spin_lock_irq(&cable->lock); - cable->streams[substream->stream] = dpcm; - spin_unlock_irq(&cable->lock); + scoped_guard(spinlock_irq, &cable->lock) { + cable->streams[substream->stream] = dpcm; + } unlock: if (err < 0) { free_cable(substream); kfree(dpcm); } - mutex_unlock(&loopback->cable_lock); return err; } @@ -1338,9 +1332,8 @@ static int loopback_close(struct snd_pcm_substream *substream) if (dpcm->cable->ops->close_substream) err = dpcm->cable->ops->close_substream(dpcm); - mutex_lock(&loopback->cable_lock); + guard(mutex)(&loopback->cable_lock); free_cable(substream); - mutex_unlock(&loopback->cable_lock); return err; } @@ -1391,11 +1384,10 @@ static int loopback_rate_shift_get(struct snd_kcontrol *kcontrol, { struct loopback *loopback = snd_kcontrol_chip(kcontrol); - mutex_lock(&loopback->cable_lock); + guard(mutex)(&loopback->cable_lock); ucontrol->value.integer.value[0] = loopback->setup[kcontrol->id.subdevice] [kcontrol->id.device].rate_shift; - mutex_unlock(&loopback->cable_lock); return 0; } @@ -1411,14 +1403,13 @@ static int loopback_rate_shift_put(struct snd_kcontrol *kcontrol, val = 80000; if (val > 120000) val = 120000; - mutex_lock(&loopback->cable_lock); + guard(mutex)(&loopback->cable_lock); if (val != loopback->setup[kcontrol->id.subdevice] [kcontrol->id.device].rate_shift) { loopback->setup[kcontrol->id.subdevice] [kcontrol->id.device].rate_shift = val; change = 1; } - mutex_unlock(&loopback->cable_lock); return change; } @@ -1427,11 +1418,10 @@ static int loopback_notify_get(struct snd_kcontrol *kcontrol, { struct loopback *loopback = snd_kcontrol_chip(kcontrol); - mutex_lock(&loopback->cable_lock); + guard(mutex)(&loopback->cable_lock); ucontrol->value.integer.value[0] = loopback->setup[kcontrol->id.subdevice] [kcontrol->id.device].notify; - mutex_unlock(&loopback->cable_lock); return 0; } @@ -1443,14 +1433,13 @@ static int loopback_notify_put(struct snd_kcontrol *kcontrol, int change = 0; val = ucontrol->value.integer.value[0] ? 1 : 0; - mutex_lock(&loopback->cable_lock); + guard(mutex)(&loopback->cable_lock); if (val != loopback->setup[kcontrol->id.subdevice] [kcontrol->id.device].notify) { loopback->setup[kcontrol->id.subdevice] [kcontrol->id.device].notify = val; change = 1; } - mutex_unlock(&loopback->cable_lock); return change; } @@ -1462,14 +1451,13 @@ static int loopback_active_get(struct snd_kcontrol *kcontrol, unsigned int val = 0; - mutex_lock(&loopback->cable_lock); + guard(mutex)(&loopback->cable_lock); cable = loopback->cables[kcontrol->id.subdevice][kcontrol->id.device ^ 1]; if (cable != NULL) { unsigned int running = cable->running ^ cable->pause; val = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? 1 : 0; } - mutex_unlock(&loopback->cable_lock); ucontrol->value.integer.value[0] = val; return 0; } @@ -1512,11 +1500,10 @@ static int loopback_rate_get(struct snd_kcontrol *kcontrol, { struct loopback *loopback = snd_kcontrol_chip(kcontrol); - mutex_lock(&loopback->cable_lock); + guard(mutex)(&loopback->cable_lock); ucontrol->value.integer.value[0] = loopback->setup[kcontrol->id.subdevice] [kcontrol->id.device].rate; - mutex_unlock(&loopback->cable_lock); return 0; } @@ -1536,11 +1523,10 @@ static int loopback_channels_get(struct snd_kcontrol *kcontrol, { struct loopback *loopback = snd_kcontrol_chip(kcontrol); - mutex_lock(&loopback->cable_lock); + guard(mutex)(&loopback->cable_lock); ucontrol->value.integer.value[0] = loopback->setup[kcontrol->id.subdevice] [kcontrol->id.device].channels; - mutex_unlock(&loopback->cable_lock); return 0; } @@ -1558,12 +1544,11 @@ static int loopback_access_get(struct snd_kcontrol *kcontrol, struct loopback *loopback = snd_kcontrol_chip(kcontrol); snd_pcm_access_t access; - mutex_lock(&loopback->cable_lock); + guard(mutex)(&loopback->cable_lock); access = loopback->setup[kcontrol->id.subdevice][kcontrol->id.device].access; ucontrol->value.enumerated.item[0] = !is_access_interleaved(access); - mutex_unlock(&loopback->cable_lock); return 0; } @@ -1731,12 +1716,11 @@ static void print_cable_info(struct snd_info_entry *entry, struct loopback *loopback = entry->private_data; int sub, num; - mutex_lock(&loopback->cable_lock); + guard(mutex)(&loopback->cable_lock); num = entry->name[strlen(entry->name)-1]; num = num == '0' ? 0 : 1; for (sub = 0; sub < MAX_PCM_SUBSTREAMS; sub++) print_substream_info(buffer, loopback, sub, num); - mutex_unlock(&loopback->cable_lock); } static int loopback_cable_proc_new(struct loopback *loopback, int cidx) @@ -1765,10 +1749,9 @@ static void print_timer_source_info(struct snd_info_entry *entry, { struct loopback *loopback = entry->private_data; - mutex_lock(&loopback->cable_lock); + guard(mutex)(&loopback->cable_lock); snd_iprintf(buffer, "%s\n", loopback->timer_source ? loopback->timer_source : ""); - mutex_unlock(&loopback->cable_lock); } static void change_timer_source_info(struct snd_info_entry *entry, @@ -1777,10 +1760,9 @@ static void change_timer_source_info(struct snd_info_entry *entry, struct loopback *loopback = entry->private_data; char line[64]; - mutex_lock(&loopback->cable_lock); + guard(mutex)(&loopback->cable_lock); if (!snd_info_get_line(buffer, line, sizeof(line))) loopback_set_timer_source(loopback, strim(line)); - mutex_unlock(&loopback->cable_lock); } static int loopback_timer_source_proc_new(struct loopback *loopback) diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 6dac0b2523c1..1860ff75fe15 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -269,19 +269,19 @@ static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm) static int dummy_systimer_start(struct snd_pcm_substream *substream) { struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; - spin_lock(&dpcm->lock); + + guard(spinlock)(&dpcm->lock); dpcm->base_time = jiffies; dummy_systimer_rearm(dpcm); - spin_unlock(&dpcm->lock); return 0; } static int dummy_systimer_stop(struct snd_pcm_substream *substream) { struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; - spin_lock(&dpcm->lock); + + guard(spinlock)(&dpcm->lock); timer_delete(&dpcm->timer); - spin_unlock(&dpcm->lock); return 0; } @@ -303,15 +303,14 @@ static int dummy_systimer_prepare(struct snd_pcm_substream *substream) static void dummy_systimer_callback(struct timer_list *t) { struct dummy_systimer_pcm *dpcm = timer_container_of(dpcm, t, timer); - unsigned long flags; int elapsed = 0; - spin_lock_irqsave(&dpcm->lock, flags); - dummy_systimer_update(dpcm); - dummy_systimer_rearm(dpcm); - elapsed = dpcm->elapsed; - dpcm->elapsed = 0; - spin_unlock_irqrestore(&dpcm->lock, flags); + scoped_guard(spinlock_irqsave, &dpcm->lock) { + dummy_systimer_update(dpcm); + dummy_systimer_rearm(dpcm); + elapsed = dpcm->elapsed; + dpcm->elapsed = 0; + } if (elapsed) snd_pcm_period_elapsed(dpcm->substream); } @@ -320,13 +319,10 @@ static snd_pcm_uframes_t dummy_systimer_pointer(struct snd_pcm_substream *substream) { struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; - snd_pcm_uframes_t pos; - spin_lock(&dpcm->lock); + guard(spinlock)(&dpcm->lock); dummy_systimer_update(dpcm); - pos = dpcm->frac_pos / HZ; - spin_unlock(&dpcm->lock); - return pos; + return dpcm->frac_pos / HZ; } static int dummy_systimer_create(struct snd_pcm_substream *substream) @@ -724,10 +720,9 @@ static int snd_dummy_volume_get(struct snd_kcontrol *kcontrol, struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); int addr = kcontrol->private_value; - spin_lock_irq(&dummy->mixer_lock); + guard(spinlock_irq)(&dummy->mixer_lock); ucontrol->value.integer.value[0] = dummy->mixer_volume[addr][0]; ucontrol->value.integer.value[1] = dummy->mixer_volume[addr][1]; - spin_unlock_irq(&dummy->mixer_lock); return 0; } @@ -748,12 +743,11 @@ static int snd_dummy_volume_put(struct snd_kcontrol *kcontrol, right = mixer_volume_level_min; if (right > mixer_volume_level_max) right = mixer_volume_level_max; - spin_lock_irq(&dummy->mixer_lock); + guard(spinlock_irq)(&dummy->mixer_lock); change = dummy->mixer_volume[addr][0] != left || dummy->mixer_volume[addr][1] != right; dummy->mixer_volume[addr][0] = left; dummy->mixer_volume[addr][1] = right; - spin_unlock_irq(&dummy->mixer_lock); return change; } @@ -773,10 +767,9 @@ static int snd_dummy_capsrc_get(struct snd_kcontrol *kcontrol, struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); int addr = kcontrol->private_value; - spin_lock_irq(&dummy->mixer_lock); + guard(spinlock_irq)(&dummy->mixer_lock); ucontrol->value.integer.value[0] = dummy->capture_source[addr][0]; ucontrol->value.integer.value[1] = dummy->capture_source[addr][1]; - spin_unlock_irq(&dummy->mixer_lock); return 0; } @@ -788,12 +781,11 @@ static int snd_dummy_capsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el left = ucontrol->value.integer.value[0] & 1; right = ucontrol->value.integer.value[1] & 1; - spin_lock_irq(&dummy->mixer_lock); + guard(spinlock_irq)(&dummy->mixer_lock); change = dummy->capture_source[addr][0] != left && dummy->capture_source[addr][1] != right; dummy->capture_source[addr][0] = left; dummy->capture_source[addr][1] = right; - spin_unlock_irq(&dummy->mixer_lock); return change; } diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index 670f8ba92c08..4af89822bf32 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -81,27 +81,21 @@ static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu) static void uart_interrupt_tx(struct snd_mpu401 *mpu) { - unsigned long flags; - if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { - spin_lock_irqsave(&mpu->output_lock, flags); + guard(spinlock_irqsave)(&mpu->output_lock); snd_mpu401_uart_output_write(mpu); - spin_unlock_irqrestore(&mpu->output_lock, flags); } } static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) { - unsigned long flags; - if (mpu->info_flags & MPU401_INFO_INPUT) { - spin_lock_irqsave(&mpu->input_lock, flags); + guard(spinlock_irqsave)(&mpu->input_lock); if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) snd_mpu401_uart_input_read(mpu); else snd_mpu401_uart_clear_rx(mpu); - spin_unlock_irqrestore(&mpu->input_lock, flags); } if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) /* ok. for better Tx performance try do some output @@ -158,12 +152,11 @@ EXPORT_SYMBOL(snd_mpu401_uart_interrupt_tx); static void snd_mpu401_uart_timer(struct timer_list *t) { struct snd_mpu401 *mpu = timer_container_of(mpu, t, timer); - unsigned long flags; - spin_lock_irqsave(&mpu->timer_lock, flags); - /*mpu->mode |= MPU401_MODE_TIMER;*/ - mod_timer(&mpu->timer, 1 + jiffies); - spin_unlock_irqrestore(&mpu->timer_lock, flags); + scoped_guard(spinlock_irqsave, &mpu->timer_lock) { + /*mpu->mode |= MPU401_MODE_TIMER;*/ + mod_timer(&mpu->timer, 1 + jiffies); + } if (mpu->rmidi) _snd_mpu401_uart_interrupt(mpu); } @@ -173,16 +166,13 @@ static void snd_mpu401_uart_timer(struct timer_list *t) */ static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input) { - unsigned long flags; - - spin_lock_irqsave (&mpu->timer_lock, flags); + guard(spinlock_irqsave)(&mpu->timer_lock); if (mpu->timer_invoked == 0) { timer_setup(&mpu->timer, snd_mpu401_uart_timer, 0); mod_timer(&mpu->timer, 1 + jiffies); } mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : MPU401_MODE_OUTPUT_TIMER; - spin_unlock_irqrestore (&mpu->timer_lock, flags); } /* @@ -190,16 +180,13 @@ static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input) */ static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input) { - unsigned long flags; - - spin_lock_irqsave (&mpu->timer_lock, flags); + guard(spinlock_irqsave)(&mpu->timer_lock); if (mpu->timer_invoked) { mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : ~MPU401_MODE_OUTPUT_TIMER; if (! mpu->timer_invoked) timer_delete(&mpu->timer); } - spin_unlock_irqrestore (&mpu->timer_lock, flags); } /* @@ -210,10 +197,9 @@ static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input) static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, int ack) { - unsigned long flags; int timeout, ok; - spin_lock_irqsave(&mpu->input_lock, flags); + guard(spinlock_irqsave)(&mpu->input_lock); if (mpu->hardware != MPU401_HW_TRID4DWAVE) { mpu->write(mpu, 0x00, MPU401D(mpu)); /*snd_mpu401_uart_clear_rx(mpu);*/ @@ -244,7 +230,6 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, ok = 1; } else ok = 1; - spin_unlock_irqrestore(&mpu->input_lock, flags); if (!ok) { dev_err(mpu->rmidi->dev, "cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", @@ -358,7 +343,6 @@ static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream) static void snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct snd_mpu401 *mpu; int max = 64; @@ -374,9 +358,8 @@ snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) } /* read data in advance */ - spin_lock_irqsave(&mpu->input_lock, flags); + guard(spinlock_irqsave)(&mpu->input_lock); snd_mpu401_uart_input_read(mpu); - spin_unlock_irqrestore(&mpu->input_lock, flags); } else { if (mpu->info_flags & MPU401_INFO_USE_TIMER) snd_mpu401_uart_remove_timer(mpu, 1); @@ -445,7 +428,6 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu) static void snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct snd_mpu401 *mpu; mpu = substream->rmidi->private_data; @@ -460,9 +442,8 @@ snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) snd_mpu401_uart_add_timer(mpu, 0); /* output pending data */ - spin_lock_irqsave(&mpu->output_lock, flags); + guard(spinlock_irqsave)(&mpu->output_lock); snd_mpu401_uart_output_write(mpu); - spin_unlock_irqrestore(&mpu->output_lock, flags); } else { if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) snd_mpu401_uart_remove_timer(mpu, 0); diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 91828f496738..d31eadf4be5f 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -304,11 +304,9 @@ static void snd_mtpav_output_write(struct snd_rawmidi_substream *substream) { struct mtpav *mtp_card = substream->rmidi->private_data; struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - spin_lock_irqsave(&mtp_card->spinlock, flags); + guard(spinlock_irqsave)(&mtp_card->spinlock); snd_mtpav_output_port_write(mtp_card, portp, substream); - spin_unlock_irqrestore(&mtp_card->spinlock, flags); } @@ -334,14 +332,12 @@ static int snd_mtpav_input_open(struct snd_rawmidi_substream *substream) { struct mtpav *mtp_card = substream->rmidi->private_data; struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - spin_lock_irqsave(&mtp_card->spinlock, flags); + guard(spinlock_irqsave)(&mtp_card->spinlock); portp->mode |= MTPAV_MODE_INPUT_OPENED; portp->input = substream; if (mtp_card->share_irq++ == 0) snd_mtpav_mputreg(mtp_card, CREG, (SIGC_INTEN | SIGC_WRITE)); // enable pport interrupts - spin_unlock_irqrestore(&mtp_card->spinlock, flags); return 0; } @@ -352,14 +348,12 @@ static int snd_mtpav_input_close(struct snd_rawmidi_substream *substream) { struct mtpav *mtp_card = substream->rmidi->private_data; struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - spin_lock_irqsave(&mtp_card->spinlock, flags); + guard(spinlock_irqsave)(&mtp_card->spinlock); portp->mode &= ~MTPAV_MODE_INPUT_OPENED; portp->input = NULL; if (--mtp_card->share_irq == 0) snd_mtpav_mputreg(mtp_card, CREG, 0); // disable pport interrupts - spin_unlock_irqrestore(&mtp_card->spinlock, flags); return 0; } @@ -370,15 +364,12 @@ static void snd_mtpav_input_trigger(struct snd_rawmidi_substream *substream, int { struct mtpav *mtp_card = substream->rmidi->private_data; struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - spin_lock_irqsave(&mtp_card->spinlock, flags); + guard(spinlock_irqsave)(&mtp_card->spinlock); if (up) portp->mode |= MTPAV_MODE_INPUT_TRIGGERED; else portp->mode &= ~MTPAV_MODE_INPUT_TRIGGERED; - spin_unlock_irqrestore(&mtp_card->spinlock, flags); - } @@ -388,11 +379,10 @@ static void snd_mtpav_input_trigger(struct snd_rawmidi_substream *substream, int static void snd_mtpav_output_timer(struct timer_list *t) { - unsigned long flags; struct mtpav *chip = timer_container_of(chip, t, timer); int p; - spin_lock_irqsave(&chip->spinlock, flags); + guard(spinlock_irqsave)(&chip->spinlock); /* reprogram timer */ mod_timer(&chip->timer, 1 + jiffies); /* process each port */ @@ -401,7 +391,6 @@ static void snd_mtpav_output_timer(struct timer_list *t) if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output) snd_mtpav_output_port_write(chip, portp, portp->output); } - spin_unlock_irqrestore(&chip->spinlock, flags); } /* spinlock held! */ @@ -423,12 +412,10 @@ static int snd_mtpav_output_open(struct snd_rawmidi_substream *substream) { struct mtpav *mtp_card = substream->rmidi->private_data; struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - spin_lock_irqsave(&mtp_card->spinlock, flags); + guard(spinlock_irqsave)(&mtp_card->spinlock); portp->mode |= MTPAV_MODE_OUTPUT_OPENED; portp->output = substream; - spin_unlock_irqrestore(&mtp_card->spinlock, flags); return 0; }; @@ -439,12 +426,10 @@ static int snd_mtpav_output_close(struct snd_rawmidi_substream *substream) { struct mtpav *mtp_card = substream->rmidi->private_data; struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - spin_lock_irqsave(&mtp_card->spinlock, flags); + guard(spinlock_irqsave)(&mtp_card->spinlock); portp->mode &= ~MTPAV_MODE_OUTPUT_OPENED; portp->output = NULL; - spin_unlock_irqrestore(&mtp_card->spinlock, flags); return 0; }; @@ -455,21 +440,20 @@ static void snd_mtpav_output_trigger(struct snd_rawmidi_substream *substream, in { struct mtpav *mtp_card = substream->rmidi->private_data; struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - if (up) { - if (! (portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED)) { - if (mtp_card->istimer++ == 0) - snd_mtpav_add_output_timer(mtp_card); - portp->mode |= MTPAV_MODE_OUTPUT_TRIGGERED; + + scoped_guard(spinlock_irqsave, &mtp_card->spinlock) { + if (up) { + if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED)) { + if (mtp_card->istimer++ == 0) + snd_mtpav_add_output_timer(mtp_card); + portp->mode |= MTPAV_MODE_OUTPUT_TRIGGERED; + } + } else { + portp->mode &= ~MTPAV_MODE_OUTPUT_TRIGGERED; + if (--mtp_card->istimer == 0) + snd_mtpav_remove_output_timer(mtp_card); } - } else { - portp->mode &= ~MTPAV_MODE_OUTPUT_TRIGGERED; - if (--mtp_card->istimer == 0) - snd_mtpav_remove_output_timer(mtp_card); } - spin_unlock_irqrestore(&mtp_card->spinlock, flags); if (up) snd_mtpav_output_write(substream); @@ -550,9 +534,8 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id) { struct mtpav *mcard = dev_id; - spin_lock(&mcard->spinlock); + guard(spinlock)(&mcard->spinlock); snd_mtpav_read_bytes(mcard); - spin_unlock(&mcard->spinlock); return IRQ_HANDLED; } @@ -658,12 +641,10 @@ static int snd_mtpav_get_RAWMIDI(struct mtpav *mcard) static void snd_mtpav_free(struct snd_card *card) { struct mtpav *crd = card->private_data; - unsigned long flags; - spin_lock_irqsave(&crd->spinlock, flags); + guard(spinlock_irqsave)(&crd->spinlock); if (crd->istimer > 0) snd_mtpav_remove_output_timer(crd); - spin_unlock_irqrestore(&crd->spinlock, flags); } /* diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index bbeebbe467ea..fe50b48c10e7 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c @@ -432,9 +432,8 @@ static int snd_mts64_ctl_smpte_switch_get(struct snd_kcontrol* kctl, { struct mts64 *mts = snd_kcontrol_chip(kctl); - spin_lock_irq(&mts->lock); + guard(spinlock_irq)(&mts->lock); uctl->value.integer.value[0] = mts->smpte_switch; - spin_unlock_irq(&mts->lock); return 0; } @@ -445,14 +444,12 @@ static int snd_mts64_ctl_smpte_switch_put(struct snd_kcontrol* kctl, struct snd_ctl_elem_value *uctl) { struct mts64 *mts = snd_kcontrol_chip(kctl); - int changed = 0; int val = !!uctl->value.integer.value[0]; - spin_lock_irq(&mts->lock); + guard(spinlock_irq)(&mts->lock); if (mts->smpte_switch == val) - goto __out; + return 0; - changed = 1; mts->smpte_switch = val; if (mts->smpte_switch) { mts64_smpte_start(mts->pardev->port, @@ -462,9 +459,7 @@ static int snd_mts64_ctl_smpte_switch_put(struct snd_kcontrol* kctl, } else { mts64_smpte_stop(mts->pardev->port); } -__out: - spin_unlock_irq(&mts->lock); - return changed; + return 1; } static const struct snd_kcontrol_new mts64_ctl_smpte_switch = { @@ -515,9 +510,8 @@ static int snd_mts64_ctl_smpte_time_get(struct snd_kcontrol *kctl, struct mts64 *mts = snd_kcontrol_chip(kctl); int idx = kctl->private_value; - spin_lock_irq(&mts->lock); + guard(spinlock_irq)(&mts->lock); uctl->value.integer.value[0] = mts->time[idx]; - spin_unlock_irq(&mts->lock); return 0; } @@ -528,16 +522,14 @@ static int snd_mts64_ctl_smpte_time_put(struct snd_kcontrol *kctl, struct mts64 *mts = snd_kcontrol_chip(kctl); int idx = kctl->private_value; unsigned int time = uctl->value.integer.value[0] % 60; - int changed = 0; - spin_lock_irq(&mts->lock); + guard(spinlock_irq)(&mts->lock); if (mts->time[idx] != time) { - changed = 1; mts->time[idx] = time; + return 1; } - spin_unlock_irq(&mts->lock); - return changed; + return 0; } static const struct snd_kcontrol_new mts64_ctl_smpte_time_hours = { @@ -600,9 +592,8 @@ static int snd_mts64_ctl_smpte_fps_get(struct snd_kcontrol *kctl, { struct mts64 *mts = snd_kcontrol_chip(kctl); - spin_lock_irq(&mts->lock); + guard(spinlock_irq)(&mts->lock); uctl->value.enumerated.item[0] = mts->fps; - spin_unlock_irq(&mts->lock); return 0; } @@ -611,18 +602,16 @@ static int snd_mts64_ctl_smpte_fps_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) { struct mts64 *mts = snd_kcontrol_chip(kctl); - int changed = 0; if (uctl->value.enumerated.item[0] >= 5) return -EINVAL; - spin_lock_irq(&mts->lock); + guard(spinlock_irq)(&mts->lock); if (mts->fps != uctl->value.enumerated.item[0]) { - changed = 1; mts->fps = uctl->value.enumerated.item[0]; + return 1; } - spin_unlock_irq(&mts->lock); - return changed; + return 0; } static const struct snd_kcontrol_new mts64_ctl_smpte_fps = { @@ -687,15 +676,14 @@ static int snd_mts64_rawmidi_open(struct snd_rawmidi_substream *substream) static int snd_mts64_rawmidi_close(struct snd_rawmidi_substream *substream) { struct mts64 *mts = substream->rmidi->private_data; - unsigned long flags; --(mts->open_count); if (mts->open_count == 0) { /* We need the spinlock_irqsave here because we can still have IRQs at this point */ - spin_lock_irqsave(&mts->lock, flags); - mts64_device_close(mts); - spin_unlock_irqrestore(&mts->lock, flags); + scoped_guard(spinlock_irqsave, &mts->lock) { + mts64_device_close(mts); + } msleep(500); @@ -710,29 +698,24 @@ static void snd_mts64_rawmidi_output_trigger(struct snd_rawmidi_substream *subst { struct mts64 *mts = substream->rmidi->private_data; u8 data; - unsigned long flags; - spin_lock_irqsave(&mts->lock, flags); + guard(spinlock_irqsave)(&mts->lock); while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) { mts64_write_midi(mts, data, substream->number+1); snd_rawmidi_transmit_ack(substream, 1); } - spin_unlock_irqrestore(&mts->lock, flags); } static void snd_mts64_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) { struct mts64 *mts = substream->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&mts->lock, flags); + guard(spinlock_irqsave)(&mts->lock); if (up) mts->mode[substream->number] |= MTS64_MODE_INPUT_TRIGGERED; else mts->mode[substream->number] &= ~MTS64_MODE_INPUT_TRIGGERED; - - spin_unlock_irqrestore(&mts->lock, flags); } static const struct snd_rawmidi_ops snd_mts64_rawmidi_output_ops = { @@ -819,7 +802,7 @@ static void snd_mts64_interrupt(void *private) if (!mts) return; - spin_lock(&mts->lock); + guard(spinlock)(&mts->lock); ret = mts64_read(mts->pardev->port); data = ret & 0x00ff; status = ret >> 8; @@ -828,13 +811,11 @@ static void snd_mts64_interrupt(void *private) mts->current_midi_input_port = mts64_map_midi_input(data); } else { if (mts->current_midi_input_port == -1) - goto __out; + return; substream = mts->midi_input_substream[mts->current_midi_input_port]; if (mts->mode[substream->number] & MTS64_MODE_INPUT_TRIGGERED) snd_rawmidi_receive(substream, &data, 1); } -__out: - spin_unlock(&mts->lock); } static void snd_mts64_attach(struct parport *p) diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index cd9642a6689b..fa8a2ccbbd51 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -25,7 +25,6 @@ MODULE_LICENSE("GPL"); static void snd_opl2_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val) { - unsigned long flags; unsigned long port; /* @@ -35,20 +34,17 @@ static void snd_opl2_command(struct snd_opl3 * opl3, unsigned short cmd, unsigne port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port; - spin_lock_irqsave(&opl3->reg_lock, flags); + guard(spinlock_irqsave)(&opl3->reg_lock); outb((unsigned char) cmd, port); udelay(10); outb((unsigned char) val, port + 1); udelay(30); - - spin_unlock_irqrestore(&opl3->reg_lock, flags); } static void snd_opl3_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val) { - unsigned long flags; unsigned long port; /* @@ -58,7 +54,7 @@ static void snd_opl3_command(struct snd_opl3 * opl3, unsigned short cmd, unsigne port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port; - spin_lock_irqsave(&opl3->reg_lock, flags); + guard(spinlock_irqsave)(&opl3->reg_lock); outb((unsigned char) cmd, port); inb(opl3->l_port); @@ -67,8 +63,6 @@ static void snd_opl3_command(struct snd_opl3 * opl3, unsigned short cmd, unsigne outb((unsigned char) val, port + 1); inb(opl3->l_port); inb(opl3->l_port); - - spin_unlock_irqrestore(&opl3->reg_lock, flags); } static int snd_opl3_detect(struct snd_opl3 * opl3) @@ -142,34 +136,30 @@ static int snd_opl3_detect(struct snd_opl3 * opl3) static int snd_opl3_timer1_start(struct snd_timer * timer) { - unsigned long flags; unsigned char tmp; unsigned int ticks; struct snd_opl3 *opl3; opl3 = snd_timer_chip(timer); - spin_lock_irqsave(&opl3->timer_lock, flags); + guard(spinlock_irqsave)(&opl3->timer_lock); ticks = timer->sticks; tmp = (opl3->timer_enable | OPL3_TIMER1_START) & ~OPL3_TIMER1_MASK; opl3->timer_enable = tmp; opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER1, 256 - ticks); /* timer 1 count */ opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* enable timer 1 IRQ */ - spin_unlock_irqrestore(&opl3->timer_lock, flags); return 0; } static int snd_opl3_timer1_stop(struct snd_timer * timer) { - unsigned long flags; unsigned char tmp; struct snd_opl3 *opl3; opl3 = snd_timer_chip(timer); - spin_lock_irqsave(&opl3->timer_lock, flags); + guard(spinlock_irqsave)(&opl3->timer_lock); tmp = (opl3->timer_enable | OPL3_TIMER1_MASK) & ~OPL3_TIMER1_START; opl3->timer_enable = tmp; opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* disable timer #1 */ - spin_unlock_irqrestore(&opl3->timer_lock, flags); return 0; } @@ -179,34 +169,30 @@ static int snd_opl3_timer1_stop(struct snd_timer * timer) static int snd_opl3_timer2_start(struct snd_timer * timer) { - unsigned long flags; unsigned char tmp; unsigned int ticks; struct snd_opl3 *opl3; opl3 = snd_timer_chip(timer); - spin_lock_irqsave(&opl3->timer_lock, flags); + guard(spinlock_irqsave)(&opl3->timer_lock); ticks = timer->sticks; tmp = (opl3->timer_enable | OPL3_TIMER2_START) & ~OPL3_TIMER2_MASK; opl3->timer_enable = tmp; opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER2, 256 - ticks); /* timer 1 count */ opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* enable timer 1 IRQ */ - spin_unlock_irqrestore(&opl3->timer_lock, flags); return 0; } static int snd_opl3_timer2_stop(struct snd_timer * timer) { - unsigned long flags; unsigned char tmp; struct snd_opl3 *opl3; opl3 = snd_timer_chip(timer); - spin_lock_irqsave(&opl3->timer_lock, flags); + guard(spinlock_irqsave)(&opl3->timer_lock); tmp = (opl3->timer_enable | OPL3_TIMER2_MASK) & ~OPL3_TIMER2_START; opl3->timer_enable = tmp; opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* disable timer #1 */ - spin_unlock_irqrestore(&opl3->timer_lock, flags); return 0; } diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index de7449cb6515..6d3c5b5a35ff 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c @@ -234,29 +234,27 @@ void snd_opl3_timer_func(struct timer_list *t) { struct snd_opl3 *opl3 = timer_container_of(opl3, t, tlist); - unsigned long flags; int again = 0; int i; - spin_lock_irqsave(&opl3->voice_lock, flags); - for (i = 0; i < opl3->max_voices; i++) { - struct snd_opl3_voice *vp = &opl3->voices[i]; - if (vp->state > 0 && vp->note_off_check) { - if (vp->note_off == jiffies) - snd_opl3_note_off_unsafe(opl3, vp->note, 0, - vp->chan); - else - again++; + scoped_guard(spinlock_irqsave, &opl3->voice_lock) { + for (i = 0; i < opl3->max_voices; i++) { + struct snd_opl3_voice *vp = &opl3->voices[i]; + if (vp->state > 0 && vp->note_off_check) { + if (vp->note_off == jiffies) + snd_opl3_note_off_unsafe(opl3, vp->note, 0, + vp->chan); + else + again++; + } } } - spin_unlock_irqrestore(&opl3->voice_lock, flags); - spin_lock_irqsave(&opl3->sys_timer_lock, flags); + guard(spinlock_irqsave)(&opl3->sys_timer_lock); if (again) mod_timer(&opl3->tlist, jiffies + 1); /* invoke again */ else opl3->sys_timer_status = 0; - spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); } /* @@ -264,13 +262,11 @@ void snd_opl3_timer_func(struct timer_list *t) */ static void snd_opl3_start_timer(struct snd_opl3 *opl3) { - unsigned long flags; - spin_lock_irqsave(&opl3->sys_timer_lock, flags); + guard(spinlock_irqsave)(&opl3->sys_timer_lock); if (! opl3->sys_timer_status) { mod_timer(&opl3->tlist, jiffies + 1); opl3->sys_timer_status = 1; } - spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); } /* ------------------------------ */ @@ -309,7 +305,6 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) struct fm_patch *patch; struct fm_instrument *fm; - unsigned long flags; opl3 = p; @@ -337,20 +332,17 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) prg = chan->midi_program; } - spin_lock_irqsave(&opl3->voice_lock, flags); + guard(spinlock_irqsave)(&opl3->voice_lock); if (use_internal_drums) { snd_opl3_drum_switch(opl3, note, vel, 1, chan); - spin_unlock_irqrestore(&opl3->voice_lock, flags); return; } __extra_prg: patch = snd_opl3_find_patch(opl3, prg, bank, 0); - if (!patch) { - spin_unlock_irqrestore(&opl3->voice_lock, flags); + if (!patch) return; - } fm = &patch->inst; switch (patch->type) { @@ -364,7 +356,6 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) } fallthrough; default: - spin_unlock_irqrestore(&opl3->voice_lock, flags); return; } opl3_dbg(opl3, " --> OPL%i instrument: %s\n", @@ -378,10 +369,8 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) voice = snd_opl3_oss_map[chan->number]; } - if (voice < 0) { - spin_unlock_irqrestore(&opl3->voice_lock, flags); + if (voice < 0) return; - } if (voice < MAX_OPL2_VOICES) { /* Left register block for voices 0 .. 8 */ @@ -597,7 +586,6 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) opl3_dbg(opl3, " *** allocating extra program\n"); goto __extra_prg; } - spin_unlock_irqrestore(&opl3->voice_lock, flags); } static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice) @@ -686,11 +674,9 @@ void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan) { struct snd_opl3 *opl3 = p; - unsigned long flags; - spin_lock_irqsave(&opl3->voice_lock, flags); + guard(spinlock_irqsave)(&opl3->voice_lock); snd_opl3_note_off_unsafe(p, note, vel, chan); - spin_unlock_irqrestore(&opl3->voice_lock, flags); } /* @@ -764,9 +750,7 @@ static void snd_opl3_pitch_ctrl(struct snd_opl3 *opl3, struct snd_midi_channel * int voice; struct snd_opl3_voice *vp; - unsigned long flags; - - spin_lock_irqsave(&opl3->voice_lock, flags); + guard(spinlock_irqsave)(&opl3->voice_lock); if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { for (voice = 0; voice < opl3->max_voices; voice++) { @@ -782,7 +766,6 @@ static void snd_opl3_pitch_ctrl(struct snd_opl3 *opl3, struct snd_midi_channel * snd_opl3_update_pitch(opl3, voice); } } - spin_unlock_irqrestore(&opl3->voice_lock, flags); } /* diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c index 9fc78b7fb780..d3278428d360 100644 --- a/sound/drivers/opl3/opl3_seq.c +++ b/sound/drivers/opl3/opl3_seq.c @@ -40,13 +40,11 @@ int snd_opl3_synth_setup(struct snd_opl3 * opl3) int idx; struct snd_hwdep *hwdep = opl3->hwdep; - mutex_lock(&hwdep->open_mutex); - if (hwdep->used) { - mutex_unlock(&hwdep->open_mutex); - return -EBUSY; + scoped_guard(mutex, &hwdep->open_mutex) { + if (hwdep->used) + return -EBUSY; + hwdep->used++; } - hwdep->used++; - mutex_unlock(&hwdep->open_mutex); snd_opl3_reset(opl3); @@ -68,22 +66,21 @@ int snd_opl3_synth_setup(struct snd_opl3 * opl3) void snd_opl3_synth_cleanup(struct snd_opl3 * opl3) { - unsigned long flags; struct snd_hwdep *hwdep; /* Stop system timer */ - spin_lock_irqsave(&opl3->sys_timer_lock, flags); - if (opl3->sys_timer_status) { - timer_delete(&opl3->tlist); - opl3->sys_timer_status = 0; + scoped_guard(spinlock_irq, &opl3->sys_timer_lock) { + if (opl3->sys_timer_status) { + timer_delete(&opl3->tlist); + opl3->sys_timer_status = 0; + } } - spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); snd_opl3_reset(opl3); hwdep = opl3->hwdep; - mutex_lock(&hwdep->open_mutex); - hwdep->used--; - mutex_unlock(&hwdep->open_mutex); + scoped_guard(mutex, &hwdep->open_mutex) { + hwdep->used--; + } wake_up(&hwdep->open_wait); } diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c index ef6b2d533958..44fbc6bf0654 100644 --- a/sound/drivers/opl4/opl4_lib.c +++ b/sound/drivers/opl4/opl4_lib.c @@ -47,10 +47,9 @@ EXPORT_SYMBOL(snd_opl4_read); void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size) { - unsigned long flags; u8 memcfg; - spin_lock_irqsave(&opl4->reg_lock, flags); + guard(spinlock_irqsave)(&opl4->reg_lock); memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT); @@ -65,18 +64,15 @@ void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size insb(opl4->pcm_port + 1, buf, size); snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg); - - spin_unlock_irqrestore(&opl4->reg_lock, flags); } EXPORT_SYMBOL(snd_opl4_read_memory); void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size) { - unsigned long flags; u8 memcfg; - spin_lock_irqsave(&opl4->reg_lock, flags); + guard(spinlock_irqsave)(&opl4->reg_lock); memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT); @@ -91,8 +87,6 @@ void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, i outsb(opl4->pcm_port + 1, buf, size); snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg); - - spin_unlock_irqrestore(&opl4->reg_lock, flags); } EXPORT_SYMBOL(snd_opl4_write_memory); diff --git a/sound/drivers/opl4/opl4_mixer.c b/sound/drivers/opl4/opl4_mixer.c index fa1e6eff43ab..deebb8636437 100644 --- a/sound/drivers/opl4/opl4_mixer.c +++ b/sound/drivers/opl4/opl4_mixer.c @@ -19,13 +19,11 @@ static int snd_opl4_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ static int snd_opl4_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); - unsigned long flags; u8 reg = kcontrol->private_value; u8 value; - spin_lock_irqsave(&opl4->reg_lock, flags); + guard(spinlock_irqsave)(&opl4->reg_lock); value = snd_opl4_read(opl4, reg); - spin_unlock_irqrestore(&opl4->reg_lock, flags); ucontrol->value.integer.value[0] = 7 - (value & 7); ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7); return 0; @@ -34,16 +32,14 @@ static int snd_opl4_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v static int snd_opl4_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); - unsigned long flags; u8 reg = kcontrol->private_value; u8 value, old_value; value = (7 - (ucontrol->value.integer.value[0] & 7)) | ((7 - (ucontrol->value.integer.value[1] & 7)) << 3); - spin_lock_irqsave(&opl4->reg_lock, flags); + guard(spinlock_irqsave)(&opl4->reg_lock); old_value = snd_opl4_read(opl4, reg); snd_opl4_write(opl4, reg, value); - spin_unlock_irqrestore(&opl4->reg_lock, flags); return value != old_value; } diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c index f2149091e10a..fd0ba4704d9f 100644 --- a/sound/drivers/opl4/opl4_proc.c +++ b/sound/drivers/opl4/opl4_proc.c @@ -14,13 +14,10 @@ static int snd_opl4_mem_proc_open(struct snd_info_entry *entry, { struct snd_opl4 *opl4 = entry->private_data; - mutex_lock(&opl4->access_mutex); - if (opl4->memory_access) { - mutex_unlock(&opl4->access_mutex); + guard(mutex)(&opl4->access_mutex); + if (opl4->memory_access) return -EBUSY; - } opl4->memory_access++; - mutex_unlock(&opl4->access_mutex); return 0; } @@ -29,9 +26,8 @@ static int snd_opl4_mem_proc_release(struct snd_info_entry *entry, { struct snd_opl4 *opl4 = entry->private_data; - mutex_lock(&opl4->access_mutex); + guard(mutex)(&opl4->access_mutex); opl4->memory_access--; - mutex_unlock(&opl4->access_mutex); return 0; } diff --git a/sound/drivers/opl4/opl4_seq.c b/sound/drivers/opl4/opl4_seq.c index f59ca660c616..7bb22089a093 100644 --- a/sound/drivers/opl4/opl4_seq.c +++ b/sound/drivers/opl4/opl4_seq.c @@ -63,24 +63,18 @@ static int snd_opl4_seq_use(void *private_data, struct snd_seq_port_subscribe *i struct snd_opl4 *opl4 = private_data; int err; - mutex_lock(&opl4->access_mutex); - - if (opl4->used) { - mutex_unlock(&opl4->access_mutex); - return -EBUSY; - } - opl4->used++; - - if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) { - err = snd_opl4_seq_use_inc(opl4); - if (err < 0) { - mutex_unlock(&opl4->access_mutex); - return err; + scoped_guard(mutex, &opl4->access_mutex) { + if (opl4->used) + return -EBUSY; + opl4->used++; + + if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) { + err = snd_opl4_seq_use_inc(opl4); + if (err < 0) + return err; } } - mutex_unlock(&opl4->access_mutex); - snd_opl4_synth_reset(opl4); return 0; } @@ -91,9 +85,9 @@ static int snd_opl4_seq_unuse(void *private_data, struct snd_seq_port_subscribe snd_opl4_synth_shutdown(opl4); - mutex_lock(&opl4->access_mutex); - opl4->used--; - mutex_unlock(&opl4->access_mutex); + scoped_guard(mutex, &opl4->access_mutex) { + opl4->used--; + } if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) snd_opl4_seq_use_dec(opl4); diff --git a/sound/drivers/opl4/opl4_synth.c b/sound/drivers/opl4/opl4_synth.c index 34e2bd52bba1..82dbb8519ab1 100644 --- a/sound/drivers/opl4/opl4_synth.c +++ b/sound/drivers/opl4/opl4_synth.c @@ -272,13 +272,12 @@ static const unsigned char snd_opl4_volume_table[128] = { */ void snd_opl4_synth_reset(struct snd_opl4 *opl4) { - unsigned long flags; int i; - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < OPL4_MAX_VOICES; i++) - snd_opl4_write(opl4, OPL4_REG_MISC + i, OPL4_DAMP_BIT); - spin_unlock_irqrestore(&opl4->reg_lock, flags); + scoped_guard(spinlock_irqsave, &opl4->reg_lock) { + for (i = 0; i < OPL4_MAX_VOICES; i++) + snd_opl4_write(opl4, OPL4_REG_MISC + i, OPL4_DAMP_BIT); + } INIT_LIST_HEAD(&opl4->off_voices); INIT_LIST_HEAD(&opl4->on_voices); @@ -296,14 +295,12 @@ void snd_opl4_synth_reset(struct snd_opl4 *opl4) */ void snd_opl4_synth_shutdown(struct snd_opl4 *opl4) { - unsigned long flags; int i; - spin_lock_irqsave(&opl4->reg_lock, flags); + guard(spinlock_irqsave)(&opl4->reg_lock); for (i = 0; i < OPL4_MAX_VOICES; i++) snd_opl4_write(opl4, OPL4_REG_MISC + i, opl4->voices[i].reg_misc & ~OPL4_KEY_ON_BIT); - spin_unlock_irqrestore(&opl4->reg_lock, flags); } /* @@ -313,17 +310,15 @@ static void snd_opl4_do_for_note(struct snd_opl4 *opl4, int note, struct snd_mid void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice)) { int i; - unsigned long flags; struct opl4_voice *voice; - spin_lock_irqsave(&opl4->reg_lock, flags); + guard(spinlock_irqsave)(&opl4->reg_lock); for (i = 0; i < OPL4_MAX_VOICES; i++) { voice = &opl4->voices[i]; if (voice->chan == chan && voice->note == note) { func(opl4, voice); } } - spin_unlock_irqrestore(&opl4->reg_lock, flags); } /* @@ -334,17 +329,15 @@ static void snd_opl4_do_for_channel(struct snd_opl4 *opl4, void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice)) { int i; - unsigned long flags; struct opl4_voice *voice; - spin_lock_irqsave(&opl4->reg_lock, flags); + guard(spinlock_irqsave)(&opl4->reg_lock); for (i = 0; i < OPL4_MAX_VOICES; i++) { voice = &opl4->voices[i]; if (voice->chan == chan) { func(opl4, voice); } } - spin_unlock_irqrestore(&opl4->reg_lock, flags); } /* @@ -354,16 +347,14 @@ static void snd_opl4_do_for_all(struct snd_opl4 *opl4, void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice)) { int i; - unsigned long flags; struct opl4_voice *voice; - spin_lock_irqsave(&opl4->reg_lock, flags); + guard(spinlock_irqsave)(&opl4->reg_lock); for (i = 0; i < OPL4_MAX_VOICES; i++) { voice = &opl4->voices[i]; if (voice->chan) func(opl4, voice); } - spin_unlock_irqrestore(&opl4->reg_lock, flags); } static void snd_opl4_update_volume(struct snd_opl4 *opl4, struct opl4_voice *voice) @@ -486,7 +477,6 @@ void snd_opl4_note_on(void *private_data, int note, int vel, struct snd_midi_cha struct opl4_voice *voice[2]; const struct opl4_sound *sound[2]; int voices = 0, i; - unsigned long flags; /* determine the number of voices and voice parameters */ i = chan->drum_channel ? 0x80 : (chan->midi_program & 0x7f); @@ -501,41 +491,41 @@ void snd_opl4_note_on(void *private_data, int note, int vel, struct snd_midi_cha } /* allocate and initialize the needed voices */ - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < voices; i++) { - voice[i] = snd_opl4_get_voice(opl4); - list_move_tail(&voice[i]->list, &opl4->on_voices); - voice[i]->chan = chan; - voice[i]->note = note; - voice[i]->velocity = vel & 0x7f; - voice[i]->sound = sound[i]; - } + scoped_guard(spinlock_irqsave, &opl4->reg_lock) { + for (i = 0; i < voices; i++) { + voice[i] = snd_opl4_get_voice(opl4); + list_move_tail(&voice[i]->list, &opl4->on_voices); + voice[i]->chan = chan; + voice[i]->note = note; + voice[i]->velocity = vel & 0x7f; + voice[i]->sound = sound[i]; + } - /* set tone number (triggers header loading) */ - for (i = 0; i < voices; i++) { - voice[i]->reg_f_number = - (sound[i]->tone >> 8) & OPL4_TONE_NUMBER_BIT8; - snd_opl4_write(opl4, OPL4_REG_F_NUMBER + voice[i]->number, - voice[i]->reg_f_number); - snd_opl4_write(opl4, OPL4_REG_TONE_NUMBER + voice[i]->number, - sound[i]->tone & 0xff); - } + /* set tone number (triggers header loading) */ + for (i = 0; i < voices; i++) { + voice[i]->reg_f_number = + (sound[i]->tone >> 8) & OPL4_TONE_NUMBER_BIT8; + snd_opl4_write(opl4, OPL4_REG_F_NUMBER + voice[i]->number, + voice[i]->reg_f_number); + snd_opl4_write(opl4, OPL4_REG_TONE_NUMBER + voice[i]->number, + sound[i]->tone & 0xff); + } - /* set parameters which can be set while loading */ - for (i = 0; i < voices; i++) { - voice[i]->reg_misc = OPL4_LFO_RESET_BIT; - snd_opl4_update_pan(opl4, voice[i]); - snd_opl4_update_pitch(opl4, voice[i]); - voice[i]->level_direct = OPL4_LEVEL_DIRECT_BIT; - snd_opl4_update_volume(opl4, voice[i]); + /* set parameters which can be set while loading */ + for (i = 0; i < voices; i++) { + voice[i]->reg_misc = OPL4_LFO_RESET_BIT; + snd_opl4_update_pan(opl4, voice[i]); + snd_opl4_update_pitch(opl4, voice[i]); + voice[i]->level_direct = OPL4_LEVEL_DIRECT_BIT; + snd_opl4_update_volume(opl4, voice[i]); + } } - spin_unlock_irqrestore(&opl4->reg_lock, flags); /* wait for completion of loading */ snd_opl4_wait_for_wave_headers(opl4); /* set remaining parameters */ - spin_lock_irqsave(&opl4->reg_lock, flags); + guard(spinlock_irqsave)(&opl4->reg_lock); for (i = 0; i < voices; i++) { snd_opl4_update_tone_parameters(opl4, voice[i]); voice[i]->reg_lfo_vibrato = voice[i]->sound->reg_lfo_vibrato; @@ -549,7 +539,6 @@ void snd_opl4_note_on(void *private_data, int note, int vel, struct snd_midi_cha snd_opl4_write(opl4, OPL4_REG_MISC + voice[i]->number, voice[i]->reg_misc); } - spin_unlock_irqrestore(&opl4->reg_lock, flags); } static void snd_opl4_voice_off(struct snd_opl4 *opl4, struct opl4_voice *voice) diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index b4fa6625a3d6..b903a138fc2a 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c @@ -496,29 +496,25 @@ static void snd_portman_midi_input_trigger(struct snd_rawmidi_substream *substre int up) { struct portman *pm = substream->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&pm->reg_lock, flags); + guard(spinlock_irqsave)(&pm->reg_lock); if (up) pm->mode[substream->number] |= PORTMAN2X4_MODE_INPUT_TRIGGERED; else pm->mode[substream->number] &= ~PORTMAN2X4_MODE_INPUT_TRIGGERED; - spin_unlock_irqrestore(&pm->reg_lock, flags); } static void snd_portman_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { struct portman *pm = substream->rmidi->private_data; - unsigned long flags; unsigned char byte; - spin_lock_irqsave(&pm->reg_lock, flags); + guard(spinlock_irqsave)(&pm->reg_lock); if (up) { while ((snd_rawmidi_transmit(substream, &byte, 1) == 1)) portman_write_midi(pm, substream->number, byte); } - spin_unlock_irqrestore(&pm->reg_lock, flags); } static const struct snd_rawmidi_ops snd_portman_midi_output = { @@ -590,7 +586,7 @@ static void snd_portman_interrupt(void *userdata) unsigned char midivalue = 0; struct portman *pm = ((struct snd_card*)userdata)->private_data; - spin_lock(&pm->reg_lock); + guard(spinlock)(&pm->reg_lock); /* While any input data is waiting */ while ((portman_read_status(pm) & INT_REQ) == INT_REQ) { @@ -617,8 +613,6 @@ static void snd_portman_interrupt(void *userdata) } } - - spin_unlock(&pm->reg_lock); } static void snd_portman_attach(struct parport *p) diff --git a/sound/drivers/serial-generic.c b/sound/drivers/serial-generic.c index 21ae053c0576..766206c6ca75 100644 --- a/sound/drivers/serial-generic.c +++ b/sound/drivers/serial-generic.c @@ -37,6 +37,8 @@ MODULE_LICENSE("GPL"); #define SERIAL_TX_STATE_ACTIVE 1 #define SERIAL_TX_STATE_WAKEUP 2 +#define INTERNAL_BUF_SIZE 256 + struct snd_serial_generic { struct serdev_device *serdev; @@ -51,6 +53,7 @@ struct snd_serial_generic { struct work_struct tx_work; unsigned long tx_state; + char tx_buf[INTERNAL_BUF_SIZE]; }; static void snd_serial_generic_tx_wakeup(struct snd_serial_generic *drvdata) @@ -61,11 +64,8 @@ static void snd_serial_generic_tx_wakeup(struct snd_serial_generic *drvdata) schedule_work(&drvdata->tx_work); } -#define INTERNAL_BUF_SIZE 256 - static void snd_serial_generic_tx_work(struct work_struct *work) { - static char buf[INTERNAL_BUF_SIZE]; int num_bytes; struct snd_serial_generic *drvdata = container_of(work, struct snd_serial_generic, tx_work); @@ -78,8 +78,10 @@ static void snd_serial_generic_tx_work(struct work_struct *work) if (!test_bit(SERIAL_MODE_OUTPUT_OPEN, &drvdata->filemode)) break; - num_bytes = snd_rawmidi_transmit_peek(substream, buf, INTERNAL_BUF_SIZE); - num_bytes = serdev_device_write_buf(drvdata->serdev, buf, num_bytes); + num_bytes = snd_rawmidi_transmit_peek(substream, drvdata->tx_buf, + INTERNAL_BUF_SIZE); + num_bytes = serdev_device_write_buf(drvdata->serdev, drvdata->tx_buf, + num_bytes); if (!num_bytes) break; diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 52772ccfc377..3c28961091b1 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -281,29 +281,24 @@ static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id) struct snd_uart16550 *uart; uart = dev_id; - spin_lock(&uart->open_lock); - if (uart->filemode == SERIAL_MODE_NOT_OPENED) { - spin_unlock(&uart->open_lock); + guard(spinlock)(&uart->open_lock); + if (uart->filemode == SERIAL_MODE_NOT_OPENED) return IRQ_NONE; - } /* indicate to the UART that the interrupt has been serviced */ inb(uart->base + UART_IIR); snd_uart16550_io_loop(uart); - spin_unlock(&uart->open_lock); return IRQ_HANDLED; } /* When the polling mode, this function calls snd_uart16550_io_loop. */ static void snd_uart16550_buffer_timer(struct timer_list *t) { - unsigned long flags; struct snd_uart16550 *uart; uart = timer_container_of(uart, t, buffer_timer); - spin_lock_irqsave(&uart->open_lock, flags); + guard(spinlock_irqsave)(&uart->open_lock); snd_uart16550_del_timer(uart); snd_uart16550_io_loop(uart); - spin_unlock_irqrestore(&uart->open_lock, flags); } /* @@ -499,71 +494,61 @@ static void snd_uart16550_do_close(struct snd_uart16550 * uart) static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream) { - unsigned long flags; struct snd_uart16550 *uart = substream->rmidi->private_data; - spin_lock_irqsave(&uart->open_lock, flags); + guard(spinlock_irqsave)(&uart->open_lock); if (uart->filemode == SERIAL_MODE_NOT_OPENED) snd_uart16550_do_open(uart); uart->filemode |= SERIAL_MODE_INPUT_OPEN; uart->midi_input[substream->number] = substream; - spin_unlock_irqrestore(&uart->open_lock, flags); return 0; } static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream) { - unsigned long flags; struct snd_uart16550 *uart = substream->rmidi->private_data; - spin_lock_irqsave(&uart->open_lock, flags); + guard(spinlock_irqsave)(&uart->open_lock); uart->filemode &= ~SERIAL_MODE_INPUT_OPEN; uart->midi_input[substream->number] = NULL; if (uart->filemode == SERIAL_MODE_NOT_OPENED) snd_uart16550_do_close(uart); - spin_unlock_irqrestore(&uart->open_lock, flags); return 0; } static void snd_uart16550_input_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct snd_uart16550 *uart = substream->rmidi->private_data; - spin_lock_irqsave(&uart->open_lock, flags); + guard(spinlock_irqsave)(&uart->open_lock); if (up) uart->filemode |= SERIAL_MODE_INPUT_TRIGGERED; else uart->filemode &= ~SERIAL_MODE_INPUT_TRIGGERED; - spin_unlock_irqrestore(&uart->open_lock, flags); } static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream) { - unsigned long flags; struct snd_uart16550 *uart = substream->rmidi->private_data; - spin_lock_irqsave(&uart->open_lock, flags); + guard(spinlock_irqsave)(&uart->open_lock); if (uart->filemode == SERIAL_MODE_NOT_OPENED) snd_uart16550_do_open(uart); uart->filemode |= SERIAL_MODE_OUTPUT_OPEN; uart->midi_output[substream->number] = substream; - spin_unlock_irqrestore(&uart->open_lock, flags); return 0; }; static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream) { - unsigned long flags; struct snd_uart16550 *uart = substream->rmidi->private_data; - spin_lock_irqsave(&uart->open_lock, flags); + guard(spinlock_irqsave)(&uart->open_lock); uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN; uart->midi_output[substream->number] = NULL; if (uart->filemode == SERIAL_MODE_NOT_OPENED) snd_uart16550_do_close(uart); - spin_unlock_irqrestore(&uart->open_lock, flags); return 0; }; @@ -632,7 +617,6 @@ static int snd_uart16550_output_byte(struct snd_uart16550 *uart, static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) { - unsigned long flags; unsigned char midi_byte, addr_byte; struct snd_uart16550 *uart = substream->rmidi->private_data; char first; @@ -643,7 +627,7 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) * variables (ie buff_in & buff_out) */ - spin_lock_irqsave(&uart->open_lock, flags); + guard(spinlock_irqsave)(&uart->open_lock); if (uart->irq < 0) /* polling */ snd_uart16550_io_loop(uart); @@ -718,21 +702,19 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) } lasttime = jiffies; } - spin_unlock_irqrestore(&uart->open_lock, flags); } static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct snd_uart16550 *uart = substream->rmidi->private_data; - spin_lock_irqsave(&uart->open_lock, flags); - if (up) - uart->filemode |= SERIAL_MODE_OUTPUT_TRIGGERED; - else - uart->filemode &= ~SERIAL_MODE_OUTPUT_TRIGGERED; - spin_unlock_irqrestore(&uart->open_lock, flags); + scoped_guard(spinlock_irqsave, &uart->open_lock) { + if (up) + uart->filemode |= SERIAL_MODE_OUTPUT_TRIGGERED; + else + uart->filemode &= ~SERIAL_MODE_OUTPUT_TRIGGERED; + } if (up) snd_uart16550_output_write(substream); } diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index 7f25fa7c0404..52b93407bfe3 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c @@ -344,12 +344,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) */ int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh) { - int err; - - mutex_lock(&chip->lock); - err = vx_send_msg_nolock(chip, rmh); - mutex_unlock(&chip->lock); - return err; + guard(mutex)(&chip->lock); + return vx_send_msg_nolock(chip, rmh); } @@ -404,12 +400,8 @@ int vx_send_rih_nolock(struct vx_core *chip, int cmd) */ int vx_send_rih(struct vx_core *chip, int cmd) { - int err; - - mutex_lock(&chip->lock); - err = vx_send_rih_nolock(chip, cmd); - mutex_unlock(&chip->lock); - return err; + guard(mutex)(&chip->lock); + return vx_send_rih_nolock(chip, cmd); } #define END_OF_RESET_WAIT_TIME 500 /* us */ @@ -481,13 +473,12 @@ static int vx_test_irq_src(struct vx_core *chip, unsigned int *ret) int err; vx_init_rmh(&chip->irq_rmh, CMD_TEST_IT); - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); err = vx_send_msg_nolock(chip, &chip->irq_rmh); if (err < 0) *ret = 0; else *ret = chip->irq_rmh.Stat[0]; - mutex_unlock(&chip->lock); return err; } diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c index 0a51ecdc084a..9dc5cecaa86a 100644 --- a/sound/drivers/vx/vx_mixer.c +++ b/sound/drivers/vx/vx_mixer.c @@ -25,9 +25,8 @@ static void vx_write_codec_reg(struct vx_core *chip, int codec, unsigned int dat if (chip->chip_status & VX_STAT_IS_STALE) return; - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); chip->ops->write_codec(chip, codec, data); - mutex_unlock(&chip->lock); } /* @@ -166,9 +165,8 @@ static void vx_change_audio_source(struct vx_core *chip, int src) if (chip->chip_status & VX_STAT_IS_STALE) return; - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); chip->ops->change_audio_source(chip, src); - mutex_unlock(&chip->lock); } @@ -411,10 +409,10 @@ static int vx_output_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ele { struct vx_core *chip = snd_kcontrol_chip(kcontrol); int codec = kcontrol->id.index; - mutex_lock(&chip->mixer_mutex); + + guard(mutex)(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->output_level[codec][0]; ucontrol->value.integer.value[1] = chip->output_level[codec][1]; - mutex_unlock(&chip->mixer_mutex); return 0; } @@ -429,16 +427,14 @@ static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele val[1] = ucontrol->value.integer.value[1]; if (val[0] > vmax || val[1] > vmax) return -EINVAL; - mutex_lock(&chip->mixer_mutex); + guard(mutex)(&chip->mixer_mutex); if (val[0] != chip->output_level[codec][0] || val[1] != chip->output_level[codec][1]) { vx_set_analog_output_level(chip, codec, val[0], val[1]); chip->output_level[codec][0] = val[0]; chip->output_level[codec][1] = val[1]; - mutex_unlock(&chip->mixer_mutex); return 1; } - mutex_unlock(&chip->mixer_mutex); return 0; } @@ -490,14 +486,12 @@ static int vx_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v if (ucontrol->value.enumerated.item[0] > 1) return -EINVAL; } - mutex_lock(&chip->mixer_mutex); + guard(mutex)(&chip->mixer_mutex); if (chip->audio_source_target != ucontrol->value.enumerated.item[0]) { chip->audio_source_target = ucontrol->value.enumerated.item[0]; vx_sync_audio_source(chip); - mutex_unlock(&chip->mixer_mutex); return 1; } - mutex_unlock(&chip->mixer_mutex); return 0; } @@ -534,14 +528,12 @@ static int vx_clock_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ if (ucontrol->value.enumerated.item[0] > 2) return -EINVAL; - mutex_lock(&chip->mixer_mutex); + guard(mutex)(&chip->mixer_mutex); if (chip->clock_mode != ucontrol->value.enumerated.item[0]) { chip->clock_mode = ucontrol->value.enumerated.item[0]; vx_set_clock(chip, chip->freq); - mutex_unlock(&chip->mixer_mutex); return 1; } - mutex_unlock(&chip->mixer_mutex); return 0; } @@ -571,10 +563,9 @@ static int vx_audio_gain_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ int audio = kcontrol->private_value & 0xff; int capture = (kcontrol->private_value >> 8) & 1; - mutex_lock(&chip->mixer_mutex); + guard(mutex)(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->audio_gain[capture][audio]; ucontrol->value.integer.value[1] = chip->audio_gain[capture][audio+1]; - mutex_unlock(&chip->mixer_mutex); return 0; } @@ -589,15 +580,13 @@ static int vx_audio_gain_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ val[1] = ucontrol->value.integer.value[1]; if (val[0] > CVAL_MAX || val[1] > CVAL_MAX) return -EINVAL; - mutex_lock(&chip->mixer_mutex); + guard(mutex)(&chip->mixer_mutex); if (val[0] != chip->audio_gain[capture][audio] || val[1] != chip->audio_gain[capture][audio+1]) { vx_set_audio_gain(chip, audio, capture, val[0]); vx_set_audio_gain(chip, audio+1, capture, val[1]); - mutex_unlock(&chip->mixer_mutex); return 1; } - mutex_unlock(&chip->mixer_mutex); return 0; } @@ -606,10 +595,9 @@ static int vx_audio_monitor_get(struct snd_kcontrol *kcontrol, struct snd_ctl_el struct vx_core *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; - mutex_lock(&chip->mixer_mutex); + guard(mutex)(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->audio_monitor[audio]; ucontrol->value.integer.value[1] = chip->audio_monitor[audio+1]; - mutex_unlock(&chip->mixer_mutex); return 0; } @@ -624,17 +612,15 @@ static int vx_audio_monitor_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el if (val[0] > CVAL_MAX || val[1] > CVAL_MAX) return -EINVAL; - mutex_lock(&chip->mixer_mutex); + guard(mutex)(&chip->mixer_mutex); if (val[0] != chip->audio_monitor[audio] || val[1] != chip->audio_monitor[audio+1]) { vx_set_monitor_level(chip, audio, val[0], chip->audio_monitor_active[audio]); vx_set_monitor_level(chip, audio+1, val[1], chip->audio_monitor_active[audio+1]); - mutex_unlock(&chip->mixer_mutex); return 1; } - mutex_unlock(&chip->mixer_mutex); return 0; } @@ -645,10 +631,9 @@ static int vx_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va struct vx_core *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; - mutex_lock(&chip->mixer_mutex); + guard(mutex)(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->audio_active[audio]; ucontrol->value.integer.value[1] = chip->audio_active[audio+1]; - mutex_unlock(&chip->mixer_mutex); return 0; } @@ -657,17 +642,15 @@ static int vx_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va struct vx_core *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; - mutex_lock(&chip->mixer_mutex); + guard(mutex)(&chip->mixer_mutex); if (ucontrol->value.integer.value[0] != chip->audio_active[audio] || ucontrol->value.integer.value[1] != chip->audio_active[audio+1]) { vx_set_audio_switch(chip, audio, !!ucontrol->value.integer.value[0]); vx_set_audio_switch(chip, audio+1, !!ucontrol->value.integer.value[1]); - mutex_unlock(&chip->mixer_mutex); return 1; } - mutex_unlock(&chip->mixer_mutex); return 0; } @@ -676,10 +659,9 @@ static int vx_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ struct vx_core *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; - mutex_lock(&chip->mixer_mutex); + guard(mutex)(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->audio_monitor_active[audio]; ucontrol->value.integer.value[1] = chip->audio_monitor_active[audio+1]; - mutex_unlock(&chip->mixer_mutex); return 0; } @@ -688,17 +670,15 @@ static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ struct vx_core *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; - mutex_lock(&chip->mixer_mutex); + guard(mutex)(&chip->mixer_mutex); if (ucontrol->value.integer.value[0] != chip->audio_monitor_active[audio] || ucontrol->value.integer.value[1] != chip->audio_monitor_active[audio+1]) { vx_set_monitor_level(chip, audio, chip->audio_monitor[audio], !!ucontrol->value.integer.value[0]); vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1], !!ucontrol->value.integer.value[1]); - mutex_unlock(&chip->mixer_mutex); return 1; } - mutex_unlock(&chip->mixer_mutex); return 0; } @@ -754,12 +734,11 @@ static int vx_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu { struct vx_core *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mixer_mutex); + guard(mutex)(&chip->mixer_mutex); ucontrol->value.iec958.status[0] = (chip->uer_bits >> 0) & 0xff; ucontrol->value.iec958.status[1] = (chip->uer_bits >> 8) & 0xff; ucontrol->value.iec958.status[2] = (chip->uer_bits >> 16) & 0xff; ucontrol->value.iec958.status[3] = (chip->uer_bits >> 24) & 0xff; - mutex_unlock(&chip->mixer_mutex); return 0; } @@ -781,14 +760,12 @@ static int vx_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu (ucontrol->value.iec958.status[1] << 8) | (ucontrol->value.iec958.status[2] << 16) | (ucontrol->value.iec958.status[3] << 24); - mutex_lock(&chip->mixer_mutex); + guard(mutex)(&chip->mixer_mutex); if (chip->uer_bits != val) { chip->uer_bits = val; vx_set_iec958_status(chip, val); - mutex_unlock(&chip->mixer_mutex); return 1; } - mutex_unlock(&chip->mixer_mutex); return 0; } diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index defc489494af..7fd8f413d6cf 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -630,12 +630,11 @@ static int vx_pcm_playback_transfer_chunk(struct vx_core *chip, /* we don't need irqsave here, because this function * is called from either trigger callback or irq handler */ - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); vx_pseudo_dma_write(chip, runtime, pipe, size); err = vx_notify_end_of_buffer(chip, pipe); /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); - mutex_unlock(&chip->lock); return err; } diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c index 3eca22151225..1d90db3b0abd 100644 --- a/sound/drivers/vx/vx_uer.c +++ b/sound/drivers/vx/vx_uer.c @@ -49,7 +49,7 @@ static int vx_read_one_cbit(struct vx_core *chip, int index) { int val; - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); if (chip->type >= VX_TYPE_VXPOCKET) { vx_outb(chip, CSUER, 1); /* read */ vx_outb(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK); @@ -59,7 +59,6 @@ static int vx_read_one_cbit(struct vx_core *chip, int index) vx_outl(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK); val = (vx_inl(chip, RUER) >> 7) & 0x01; } - mutex_unlock(&chip->lock); return val; } @@ -71,7 +70,7 @@ static int vx_read_one_cbit(struct vx_core *chip, int index) static void vx_write_one_cbit(struct vx_core *chip, int index, int val) { val = !!val; /* 0 or 1 */ - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); if (vx_is_pcmcia(chip)) { vx_outb(chip, CSUER, 0); /* write */ vx_outb(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK)); @@ -79,7 +78,6 @@ static void vx_write_one_cbit(struct vx_core *chip, int index, int val) vx_outl(chip, CSUER, 0); /* write */ vx_outl(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK)); } - mutex_unlock(&chip->lock); } /* @@ -178,10 +176,10 @@ static void vx_change_clock_source(struct vx_core *chip, int source) { /* we mute DAC to prevent clicks */ vx_toggle_dac_mute(chip, 1); - mutex_lock(&chip->lock); - chip->ops->set_clock_source(chip, source); - chip->clock_source = source; - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) { + chip->ops->set_clock_source(chip, source); + chip->clock_source = source; + } /* unmute */ vx_toggle_dac_mute(chip, 0); } @@ -198,7 +196,7 @@ void vx_set_internal_clock(struct vx_core *chip, unsigned int freq) clock = vx_calc_clock_from_freq(chip, freq); dev_dbg(chip->card->dev, "set internal clock to 0x%x from freq %d\n", clock, freq); - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); if (vx_is_pcmcia(chip)) { vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f); vx_outb(chip, LOFREQ, clock & 0xff); @@ -206,7 +204,6 @@ void vx_set_internal_clock(struct vx_core *chip, unsigned int freq) vx_outl(chip, HIFREQ, (clock >> 8) & 0x0f); vx_outl(chip, LOFREQ, clock & 0xff); } - mutex_unlock(&chip->lock); } diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 7fc51f829ecc..5cdc34877fc1 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -1688,20 +1688,16 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, struct pkt_desc *descs; int i, type, tag, err; - mutex_lock(&s->mutex); + guard(mutex)(&s->mutex); if (WARN_ON(amdtp_stream_running(s) || - (s->data_block_quadlets < 1))) { - err = -EBADFD; - goto err_unlock; - } + (s->data_block_quadlets < 1))) + return -EBADFD; if (s->direction == AMDTP_IN_STREAM) { // NOTE: IT context should be used for constant IRQ. - if (is_irq_target) { - err = -EINVAL; - goto err_unlock; - } + if (is_irq_target) + return -EINVAL; s->data_block_counter = UINT_MAX; } else { @@ -1725,7 +1721,7 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, err = iso_packets_buffer_init(&s->buffer, s->unit, queue_size, max_ctx_payload_size, dir); if (err < 0) - goto err_unlock; + return err; s->queue_size = queue_size; s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, @@ -1846,8 +1842,6 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, if (err < 0) goto err_pkt_descs; - mutex_unlock(&s->mutex); - return 0; err_pkt_descs: kfree(s->packet_descs); @@ -1863,8 +1857,6 @@ err_context: s->context = ERR_PTR(-1); err_buffer: iso_packets_buffer_destroy(&s->buffer, s->unit); -err_unlock: - mutex_unlock(&s->mutex); return err; } @@ -1934,12 +1926,10 @@ EXPORT_SYMBOL(amdtp_stream_update); */ static void amdtp_stream_stop(struct amdtp_stream *s) { - mutex_lock(&s->mutex); + guard(mutex)(&s->mutex); - if (!amdtp_stream_running(s)) { - mutex_unlock(&s->mutex); + if (!amdtp_stream_running(s)) return; - } cancel_work_sync(&s->period_work); fw_iso_context_stop(s->context); @@ -1955,8 +1945,6 @@ static void amdtp_stream_stop(struct amdtp_stream *s) if (s->domain->replay.enable) kfree(s->ctx_data.tx.cache.descs); } - - mutex_unlock(&s->mutex); } /** diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index 4ebaeff16455..01e2c4cc03d4 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -122,9 +122,9 @@ bebob_card_free(struct snd_card *card) { struct snd_bebob *bebob = card->private_data; - mutex_lock(&devices_mutex); - clear_bit(bebob->card_index, devices_used); - mutex_unlock(&devices_mutex); + scoped_guard(mutex, &devices_mutex) { + clear_bit(bebob->card_index, devices_used); + } snd_bebob_stream_destroy_duplex(bebob); @@ -207,25 +207,21 @@ static int bebob_probe(struct fw_unit *unit, const struct ieee1394_device_id *en return -ENODEV; } - mutex_lock(&devices_mutex); - for (card_index = 0; card_index < SNDRV_CARDS; card_index++) { - if (!test_bit(card_index, devices_used) && enable[card_index]) - break; - } - if (card_index >= SNDRV_CARDS) { - mutex_unlock(&devices_mutex); - return -ENOENT; - } + scoped_guard(mutex, &devices_mutex) { + for (card_index = 0; card_index < SNDRV_CARDS; card_index++) { + if (!test_bit(card_index, devices_used) && enable[card_index]) + break; + } + if (card_index >= SNDRV_CARDS) + return -ENOENT; - err = snd_card_new(&unit->device, index[card_index], id[card_index], THIS_MODULE, - sizeof(*bebob), &card); - if (err < 0) { - mutex_unlock(&devices_mutex); - return err; + err = snd_card_new(&unit->device, index[card_index], id[card_index], THIS_MODULE, + sizeof(*bebob), &card); + if (err < 0) + return err; + card->private_free = bebob_card_free; + set_bit(card_index, devices_used); } - card->private_free = bebob_card_free; - set_bit(card_index, devices_used); - mutex_unlock(&devices_mutex); bebob = card->private_data; bebob->unit = fw_unit_get(unit); diff --git a/sound/firewire/bebob/bebob_hwdep.c b/sound/firewire/bebob/bebob_hwdep.c index 5779e99a6bb2..216d1fceb6e7 100644 --- a/sound/firewire/bebob/bebob_hwdep.c +++ b/sound/firewire/bebob/bebob_hwdep.c @@ -53,18 +53,14 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait) { struct snd_bebob *bebob = hwdep->private_data; - __poll_t events; poll_wait(file, &bebob->hwdep_wait, wait); - spin_lock_irq(&bebob->lock); + guard(spinlock_irq)(&bebob->lock); if (bebob->dev_lock_changed) - events = EPOLLIN | EPOLLRDNORM; + return EPOLLIN | EPOLLRDNORM; else - events = 0; - spin_unlock_irq(&bebob->lock); - - return events; + return 0; } static int @@ -90,39 +86,27 @@ hwdep_get_info(struct snd_bebob *bebob, void __user *arg) static int hwdep_lock(struct snd_bebob *bebob) { - int err; - - spin_lock_irq(&bebob->lock); + guard(spinlock_irq)(&bebob->lock); if (bebob->dev_lock_count == 0) { bebob->dev_lock_count = -1; - err = 0; + return 0; } else { - err = -EBUSY; + return -EBUSY; } - - spin_unlock_irq(&bebob->lock); - - return err; } static int hwdep_unlock(struct snd_bebob *bebob) { - int err; - - spin_lock_irq(&bebob->lock); + guard(spinlock_irq)(&bebob->lock); if (bebob->dev_lock_count == -1) { bebob->dev_lock_count = 0; - err = 0; + return 0; } else { - err = -EBADFD; + return -EBADFD; } - - spin_unlock_irq(&bebob->lock); - - return err; } static int @@ -130,10 +114,9 @@ hwdep_release(struct snd_hwdep *hwdep, struct file *file) { struct snd_bebob *bebob = hwdep->private_data; - spin_lock_irq(&bebob->lock); + guard(spinlock_irq)(&bebob->lock); if (bebob->dev_lock_count == -1) bebob->dev_lock_count = 0; - spin_unlock_irq(&bebob->lock); return 0; } diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c index 177699e1be11..376a9a175479 100644 --- a/sound/firewire/bebob/bebob_maudio.c +++ b/sound/firewire/bebob/bebob_maudio.c @@ -265,7 +265,7 @@ snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814) if (!params) return -ENOMEM; - mutex_lock(&bebob->mutex); + guard(mutex)(&bebob->mutex); bebob->maudio_special_quirk = (void *)params; params->is1814 = is1814; @@ -277,12 +277,12 @@ snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814) if (err < 0) { dev_err(&bebob->unit->device, "fail to initialize clock params: %d\n", err); - goto end; + return err; } err = add_special_controls(bebob); if (err < 0) - goto end; + return err; special_stream_formation_set(bebob); @@ -293,8 +293,6 @@ snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814) bebob->midi_input_ports = 2; bebob->midi_output_ports = 2; } -end: - mutex_unlock(&bebob->mutex); return err; } @@ -383,14 +381,12 @@ static int special_clk_ctl_put(struct snd_kcontrol *kctl, if (id >= ARRAY_SIZE(special_clk_types)) return -EINVAL; - mutex_lock(&bebob->mutex); + guard(mutex)(&bebob->mutex); err = avc_maudio_set_special_clk(bebob, id, params->dig_in_fmt, params->dig_out_fmt, params->clk_lock); - mutex_unlock(&bebob->mutex); - if (err >= 0) err = 1; @@ -456,14 +452,14 @@ static int special_dig_in_iface_ctl_get(struct snd_kcontrol *kctl, unsigned int dig_in_iface; int err, val; - mutex_lock(&bebob->mutex); + guard(mutex)(&bebob->mutex); err = avc_audio_get_selector(bebob->unit, 0x00, 0x04, &dig_in_iface); if (err < 0) { dev_err(&bebob->unit->device, "fail to get digital input interface: %d\n", err); - goto end; + return err; } /* encoded id for user value */ @@ -474,9 +470,7 @@ static int special_dig_in_iface_ctl_get(struct snd_kcontrol *kctl, val = 2; uval->value.enumerated.item[0] = val; -end: - mutex_unlock(&bebob->mutex); - return err; + return 0; } static int special_dig_in_iface_ctl_set(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uval) @@ -494,7 +488,7 @@ static int special_dig_in_iface_ctl_set(struct snd_kcontrol *kctl, dig_in_fmt = (id >> 1) & 0x01; dig_in_iface = id & 0x01; - mutex_lock(&bebob->mutex); + guard(mutex)(&bebob->mutex); err = avc_maudio_set_special_clk(bebob, params->clk_src, @@ -502,24 +496,19 @@ static int special_dig_in_iface_ctl_set(struct snd_kcontrol *kctl, params->dig_out_fmt, params->clk_lock); if (err < 0) - goto end; + return err; /* For ADAT, optical interface is only available. */ - if (params->dig_in_fmt > 0) { - err = 1; - goto end; - } + if (params->dig_in_fmt > 0) + return 1; /* For S/PDIF, optical/coaxial interfaces are selectable. */ err = avc_audio_set_selector(bebob->unit, 0x00, 0x04, dig_in_iface); if (err < 0) dev_err(&bebob->unit->device, "fail to set digital input interface: %d\n", err); - err = 1; -end: special_stream_formation_set(bebob); - mutex_unlock(&bebob->mutex); - return err; + return 1; } static const struct snd_kcontrol_new special_dig_in_iface_ctl = { .name = "Digital Input Interface", @@ -546,9 +535,9 @@ static int special_dig_out_iface_ctl_get(struct snd_kcontrol *kctl, { struct snd_bebob *bebob = snd_kcontrol_chip(kctl); struct special_params *params = bebob->maudio_special_quirk; - mutex_lock(&bebob->mutex); + + guard(mutex)(&bebob->mutex); uval->value.enumerated.item[0] = params->dig_out_fmt; - mutex_unlock(&bebob->mutex); return 0; } static int special_dig_out_iface_ctl_set(struct snd_kcontrol *kctl, @@ -563,7 +552,7 @@ static int special_dig_out_iface_ctl_set(struct snd_kcontrol *kctl, if (id >= ARRAY_SIZE(special_dig_out_iface_labels)) return -EINVAL; - mutex_lock(&bebob->mutex); + guard(mutex)(&bebob->mutex); err = avc_maudio_set_special_clk(bebob, params->clk_src, @@ -574,7 +563,6 @@ static int special_dig_out_iface_ctl_set(struct snd_kcontrol *kctl, err = 1; } - mutex_unlock(&bebob->mutex); return err; } static const struct snd_kcontrol_new special_dig_out_iface_ctl = { diff --git a/sound/firewire/bebob/bebob_midi.c b/sound/firewire/bebob/bebob_midi.c index b1425bf98c3b..678631f31d3c 100644 --- a/sound/firewire/bebob/bebob_midi.c +++ b/sound/firewire/bebob/bebob_midi.c @@ -16,15 +16,15 @@ static int midi_open(struct snd_rawmidi_substream *substream) if (err < 0) return err; - mutex_lock(&bebob->mutex); - err = snd_bebob_stream_reserve_duplex(bebob, 0, 0, 0); - if (err >= 0) { - ++bebob->substreams_counter; - err = snd_bebob_stream_start_duplex(bebob); - if (err < 0) - --bebob->substreams_counter; + scoped_guard(mutex, &bebob->mutex) { + err = snd_bebob_stream_reserve_duplex(bebob, 0, 0, 0); + if (err >= 0) { + ++bebob->substreams_counter; + err = snd_bebob_stream_start_duplex(bebob); + if (err < 0) + --bebob->substreams_counter; + } } - mutex_unlock(&bebob->mutex); if (err < 0) snd_bebob_stream_lock_release(bebob); @@ -35,10 +35,10 @@ static int midi_close(struct snd_rawmidi_substream *substream) { struct snd_bebob *bebob = substream->rmidi->private_data; - mutex_lock(&bebob->mutex); - bebob->substreams_counter--; - snd_bebob_stream_stop_duplex(bebob); - mutex_unlock(&bebob->mutex); + scoped_guard(mutex, &bebob->mutex) { + bebob->substreams_counter--; + snd_bebob_stream_stop_duplex(bebob); + } snd_bebob_stream_lock_release(bebob); return 0; @@ -47,9 +47,8 @@ static int midi_close(struct snd_rawmidi_substream *substream) static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) { struct snd_bebob *bebob = substrm->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&bebob->lock, flags); + guard(spinlock_irqsave)(&bebob->lock); if (up) amdtp_am824_midi_trigger(&bebob->tx_stream, @@ -57,16 +56,13 @@ static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) else amdtp_am824_midi_trigger(&bebob->tx_stream, substrm->number, NULL); - - spin_unlock_irqrestore(&bebob->lock, flags); } static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) { struct snd_bebob *bebob = substrm->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&bebob->lock, flags); + guard(spinlock_irqsave)(&bebob->lock); if (up) amdtp_am824_midi_trigger(&bebob->rx_stream, @@ -74,8 +70,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) else amdtp_am824_midi_trigger(&bebob->rx_stream, substrm->number, NULL); - - spin_unlock_irqrestore(&bebob->lock, flags); } static void set_midi_substream_names(struct snd_bebob *bebob, diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index 360ebf3c4ca2..692d33bac2d2 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -149,49 +149,42 @@ static int pcm_open(struct snd_pcm_substream *substream) if (err < 0) goto err_locked; - mutex_lock(&bebob->mutex); - - // When source of clock is not internal or any stream is reserved for - // transmission of PCM frames, the available sampling rate is limited - // at current one. - if (src == SND_BEBOB_CLOCK_TYPE_EXTERNAL || - (bebob->substreams_counter > 0 && d->events_per_period > 0)) { - unsigned int frames_per_period = d->events_per_period; - unsigned int frames_per_buffer = d->events_per_buffer; - unsigned int sampling_rate; - - err = spec->get(bebob, &sampling_rate); - if (err < 0) { - mutex_unlock(&bebob->mutex); - dev_err(&bebob->unit->device, - "fail to get sampling rate: %d\n", err); - goto err_locked; - } - - substream->runtime->hw.rate_min = sampling_rate; - substream->runtime->hw.rate_max = sampling_rate; - - if (frames_per_period > 0) { - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - frames_per_period, frames_per_period); + scoped_guard(mutex, &bebob->mutex) { + // When source of clock is not internal or any stream is reserved for + // transmission of PCM frames, the available sampling rate is limited + // at current one. + if (src == SND_BEBOB_CLOCK_TYPE_EXTERNAL || + (bebob->substreams_counter > 0 && d->events_per_period > 0)) { + unsigned int frames_per_period = d->events_per_period; + unsigned int frames_per_buffer = d->events_per_buffer; + unsigned int sampling_rate; + + err = spec->get(bebob, &sampling_rate); if (err < 0) { - mutex_unlock(&bebob->mutex); + dev_err(&bebob->unit->device, + "fail to get sampling rate: %d\n", err); goto err_locked; } - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - frames_per_buffer, frames_per_buffer); - if (err < 0) { - mutex_unlock(&bebob->mutex); - goto err_locked; + substream->runtime->hw.rate_min = sampling_rate; + substream->runtime->hw.rate_max = sampling_rate; + + if (frames_per_period > 0) { + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + frames_per_period, frames_per_period); + if (err < 0) + goto err_locked; + + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + frames_per_buffer, frames_per_buffer); + if (err < 0) + goto err_locked; } } } - mutex_unlock(&bebob->mutex); - snd_pcm_set_sync(substream); return 0; @@ -219,12 +212,11 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); - mutex_lock(&bebob->mutex); + guard(mutex)(&bebob->mutex); err = snd_bebob_stream_reserve_duplex(bebob, rate, frames_per_period, frames_per_buffer); if (err >= 0) ++bebob->substreams_counter; - mutex_unlock(&bebob->mutex); } return err; @@ -234,15 +226,13 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_bebob *bebob = substream->private_data; - mutex_lock(&bebob->mutex); + guard(mutex)(&bebob->mutex); if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) bebob->substreams_counter--; snd_bebob_stream_stop_duplex(bebob); - mutex_unlock(&bebob->mutex); - return 0; } diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 8629b14ded76..449cb17717f0 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -964,33 +964,24 @@ void snd_bebob_stream_lock_changed(struct snd_bebob *bebob) int snd_bebob_stream_lock_try(struct snd_bebob *bebob) { - int err; - - spin_lock_irq(&bebob->lock); + guard(spinlock_irq)(&bebob->lock); /* user land lock this */ - if (bebob->dev_lock_count < 0) { - err = -EBUSY; - goto end; - } + if (bebob->dev_lock_count < 0) + return -EBUSY; /* this is the first time */ if (bebob->dev_lock_count++ == 0) snd_bebob_stream_lock_changed(bebob); - err = 0; -end: - spin_unlock_irq(&bebob->lock); - return err; + return 0; } void snd_bebob_stream_lock_release(struct snd_bebob *bebob) { - spin_lock_irq(&bebob->lock); + guard(spinlock_irq)(&bebob->lock); if (WARN_ON(bebob->dev_lock_count <= 0)) - goto end; + return; if (--bebob->dev_lock_count == 0) snd_bebob_stream_lock_changed(bebob); -end: - spin_unlock_irq(&bebob->lock); } diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c index f5028a061a91..b2b76c7c71b3 100644 --- a/sound/firewire/cmp.c +++ b/sound/firewire/cmp.c @@ -188,32 +188,23 @@ EXPORT_SYMBOL(cmp_connection_destroy); int cmp_connection_reserve(struct cmp_connection *c, unsigned int max_payload_bytes) { - int err; - - mutex_lock(&c->mutex); + guard(mutex)(&c->mutex); - if (WARN_ON(c->resources.allocated)) { - err = -EBUSY; - goto end; - } + if (WARN_ON(c->resources.allocated)) + return -EBUSY; c->speed = min(c->max_speed, fw_parent_device(c->resources.unit)->max_speed); - err = fw_iso_resources_allocate(&c->resources, max_payload_bytes, - c->speed); -end: - mutex_unlock(&c->mutex); - - return err; + return fw_iso_resources_allocate(&c->resources, max_payload_bytes, + c->speed); } EXPORT_SYMBOL(cmp_connection_reserve); void cmp_connection_release(struct cmp_connection *c) { - mutex_lock(&c->mutex); + guard(mutex)(&c->mutex); fw_iso_resources_free(&c->resources); - mutex_unlock(&c->mutex); } EXPORT_SYMBOL(cmp_connection_release); @@ -304,12 +295,10 @@ int cmp_connection_establish(struct cmp_connection *c) { int err; - mutex_lock(&c->mutex); + guard(mutex)(&c->mutex); - if (WARN_ON(c->connected)) { - mutex_unlock(&c->mutex); + if (WARN_ON(c->connected)) return -EISCONN; - } retry_after_bus_reset: if (c->direction == CMP_OUTPUT) @@ -327,8 +316,6 @@ retry_after_bus_reset: if (err >= 0) c->connected = true; - mutex_unlock(&c->mutex); - return err; } EXPORT_SYMBOL(cmp_connection_establish); @@ -350,19 +337,15 @@ void cmp_connection_break(struct cmp_connection *c) { int err; - mutex_lock(&c->mutex); + guard(mutex)(&c->mutex); - if (!c->connected) { - mutex_unlock(&c->mutex); + if (!c->connected) return; - } err = pcr_modify(c, pcr_break_modify, NULL, SUCCEED_ON_BUS_RESET); if (err < 0) cmp_error(c, "plug is still connected\n"); c->connected = false; - - mutex_unlock(&c->mutex); } EXPORT_SYMBOL(cmp_connection_break); diff --git a/sound/firewire/dice/dice-hwdep.c b/sound/firewire/dice/dice-hwdep.c index d165dd427bd3..747ff0952483 100644 --- a/sound/firewire/dice/dice-hwdep.c +++ b/sound/firewire/dice/dice-hwdep.c @@ -55,18 +55,14 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait) { struct snd_dice *dice = hwdep->private_data; - __poll_t events; poll_wait(file, &dice->hwdep_wait, wait); - spin_lock_irq(&dice->lock); + guard(spinlock_irq)(&dice->lock); if (dice->dev_lock_changed || dice->notification_bits != 0) - events = EPOLLIN | EPOLLRDNORM; + return EPOLLIN | EPOLLRDNORM; else - events = 0; - spin_unlock_irq(&dice->lock); - - return events; + return 0; } static int hwdep_get_info(struct snd_dice *dice, void __user *arg) @@ -90,48 +86,35 @@ static int hwdep_get_info(struct snd_dice *dice, void __user *arg) static int hwdep_lock(struct snd_dice *dice) { - int err; - - spin_lock_irq(&dice->lock); + guard(spinlock_irq)(&dice->lock); if (dice->dev_lock_count == 0) { dice->dev_lock_count = -1; - err = 0; + return 0; } else { - err = -EBUSY; + return -EBUSY; } - - spin_unlock_irq(&dice->lock); - - return err; } static int hwdep_unlock(struct snd_dice *dice) { - int err; - - spin_lock_irq(&dice->lock); + guard(spinlock_irq)(&dice->lock); if (dice->dev_lock_count == -1) { dice->dev_lock_count = 0; - err = 0; + return 0; } else { - err = -EBADFD; + return -EBADFD; } - - spin_unlock_irq(&dice->lock); - - return err; } static int hwdep_release(struct snd_hwdep *hwdep, struct file *file) { struct snd_dice *dice = hwdep->private_data; - spin_lock_irq(&dice->lock); + guard(spinlock_irq)(&dice->lock); if (dice->dev_lock_count == -1) dice->dev_lock_count = 0; - spin_unlock_irq(&dice->lock); return 0; } diff --git a/sound/firewire/dice/dice-midi.c b/sound/firewire/dice/dice-midi.c index 78988e44b8bc..722bce379345 100644 --- a/sound/firewire/dice/dice-midi.c +++ b/sound/firewire/dice/dice-midi.c @@ -15,18 +15,16 @@ static int midi_open(struct snd_rawmidi_substream *substream) if (err < 0) return err; - mutex_lock(&dice->mutex); - - err = snd_dice_stream_reserve_duplex(dice, 0, 0, 0); - if (err >= 0) { - ++dice->substreams_counter; - err = snd_dice_stream_start_duplex(dice); - if (err < 0) - --dice->substreams_counter; + scoped_guard(mutex, &dice->mutex) { + err = snd_dice_stream_reserve_duplex(dice, 0, 0, 0); + if (err >= 0) { + ++dice->substreams_counter; + err = snd_dice_stream_start_duplex(dice); + if (err < 0) + --dice->substreams_counter; + } } - mutex_unlock(&dice->mutex); - if (err < 0) snd_dice_stream_lock_release(dice); @@ -37,12 +35,10 @@ static int midi_close(struct snd_rawmidi_substream *substream) { struct snd_dice *dice = substream->rmidi->private_data; - mutex_lock(&dice->mutex); - - --dice->substreams_counter; - snd_dice_stream_stop_duplex(dice); - - mutex_unlock(&dice->mutex); + scoped_guard(mutex, &dice->mutex) { + --dice->substreams_counter; + snd_dice_stream_stop_duplex(dice); + } snd_dice_stream_lock_release(dice); return 0; @@ -51,9 +47,8 @@ static int midi_close(struct snd_rawmidi_substream *substream) static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) { struct snd_dice *dice = substrm->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&dice->lock, flags); + guard(spinlock_irqsave)(&dice->lock); if (up) amdtp_am824_midi_trigger(&dice->tx_stream[0], @@ -61,16 +56,13 @@ static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) else amdtp_am824_midi_trigger(&dice->tx_stream[0], substrm->number, NULL); - - spin_unlock_irqrestore(&dice->lock, flags); } static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) { struct snd_dice *dice = substrm->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&dice->lock, flags); + guard(spinlock_irqsave)(&dice->lock); if (up) amdtp_am824_midi_trigger(&dice->rx_stream[0], @@ -78,8 +70,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) else amdtp_am824_midi_trigger(&dice->rx_stream[0], substrm->number, NULL); - - spin_unlock_irqrestore(&dice->lock, flags); } static void set_midi_substream_names(struct snd_dice *dice, diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index cfc19bd0d5dd..d5319cd2cc6f 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -196,53 +196,45 @@ static int pcm_open(struct snd_pcm_substream *substream) break; } - mutex_lock(&dice->mutex); - - // When source of clock is not internal or any stream is reserved for - // transmission of PCM frames, the available sampling rate is limited - // at current one. - if (!internal || - (dice->substreams_counter > 0 && d->events_per_period > 0)) { - unsigned int frames_per_period = d->events_per_period; - unsigned int frames_per_buffer = d->events_per_buffer; - unsigned int rate; - - err = snd_dice_transaction_get_rate(dice, &rate); - if (err < 0) { - mutex_unlock(&dice->mutex); - goto err_locked; - } - - substream->runtime->hw.rate_min = rate; - substream->runtime->hw.rate_max = rate; - - if (frames_per_period > 0) { - // For double_pcm_frame quirk. - if (rate > 96000 && !dice->disable_double_pcm_frames) { - frames_per_period *= 2; - frames_per_buffer *= 2; - } - - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - frames_per_period, frames_per_period); - if (err < 0) { - mutex_unlock(&dice->mutex); + scoped_guard(mutex, &dice->mutex) { + // When source of clock is not internal or any stream is reserved for + // transmission of PCM frames, the available sampling rate is limited + // at current one. + if (!internal || + (dice->substreams_counter > 0 && d->events_per_period > 0)) { + unsigned int frames_per_period = d->events_per_period; + unsigned int frames_per_buffer = d->events_per_buffer; + unsigned int rate; + + err = snd_dice_transaction_get_rate(dice, &rate); + if (err < 0) goto err_locked; - } - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - frames_per_buffer, frames_per_buffer); - if (err < 0) { - mutex_unlock(&dice->mutex); - goto err_locked; + substream->runtime->hw.rate_min = rate; + substream->runtime->hw.rate_max = rate; + + if (frames_per_period > 0) { + // For double_pcm_frame quirk. + if (rate > 96000 && !dice->disable_double_pcm_frames) { + frames_per_period *= 2; + frames_per_buffer *= 2; + } + + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + frames_per_period, frames_per_period); + if (err < 0) + goto err_locked; + + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + frames_per_buffer, frames_per_buffer); + if (err < 0) + goto err_locked; } } } - mutex_unlock(&dice->mutex); - snd_pcm_set_sync(substream); return 0; @@ -271,7 +263,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, unsigned int events_per_period = params_period_size(hw_params); unsigned int events_per_buffer = params_buffer_size(hw_params); - mutex_lock(&dice->mutex); + guard(mutex)(&dice->mutex); // For double_pcm_frame quirk. if (rate > 96000 && !dice->disable_double_pcm_frames) { events_per_period /= 2; @@ -281,7 +273,6 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, events_per_period, events_per_buffer); if (err >= 0) ++dice->substreams_counter; - mutex_unlock(&dice->mutex); } return err; @@ -291,15 +282,13 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_dice *dice = substream->private_data; - mutex_lock(&dice->mutex); + guard(mutex)(&dice->mutex); if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --dice->substreams_counter; snd_dice_stream_stop_duplex(dice); - mutex_unlock(&dice->mutex); - return 0; } @@ -309,9 +298,9 @@ static int capture_prepare(struct snd_pcm_substream *substream) struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device]; int err; - mutex_lock(&dice->mutex); - err = snd_dice_stream_start_duplex(dice); - mutex_unlock(&dice->mutex); + scoped_guard(mutex, &dice->mutex) { + err = snd_dice_stream_start_duplex(dice); + } if (err >= 0) amdtp_stream_pcm_prepare(stream); @@ -323,9 +312,9 @@ static int playback_prepare(struct snd_pcm_substream *substream) struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device]; int err; - mutex_lock(&dice->mutex); - err = snd_dice_stream_start_duplex(dice); - mutex_unlock(&dice->mutex); + scoped_guard(mutex, &dice->mutex) { + err = snd_dice_stream_start_duplex(dice); + } if (err >= 0) amdtp_stream_pcm_prepare(stream); diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index 4c677c8546c7..d5ffe7c82993 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c @@ -677,32 +677,23 @@ static void dice_lock_changed(struct snd_dice *dice) int snd_dice_stream_lock_try(struct snd_dice *dice) { - int err; - - spin_lock_irq(&dice->lock); + guard(spinlock_irq)(&dice->lock); - if (dice->dev_lock_count < 0) { - err = -EBUSY; - goto out; - } + if (dice->dev_lock_count < 0) + return -EBUSY; if (dice->dev_lock_count++ == 0) dice_lock_changed(dice); - err = 0; -out: - spin_unlock_irq(&dice->lock); - return err; + return 0; } void snd_dice_stream_lock_release(struct snd_dice *dice) { - spin_lock_irq(&dice->lock); + guard(spinlock_irq)(&dice->lock); if (WARN_ON(dice->dev_lock_count <= 0)) - goto out; + return; if (--dice->dev_lock_count == 0) dice_lock_changed(dice); -out: - spin_unlock_irq(&dice->lock); } diff --git a/sound/firewire/dice/dice-transaction.c b/sound/firewire/dice/dice-transaction.c index 92941ef83cd5..a3f7dfa990a4 100644 --- a/sound/firewire/dice/dice-transaction.c +++ b/sound/firewire/dice/dice-transaction.c @@ -136,7 +136,6 @@ static void dice_notification(struct fw_card *card, struct fw_request *request, { struct snd_dice *dice = callback_data; u32 bits; - unsigned long flags; if (tcode != TCODE_WRITE_QUADLET_REQUEST) { fw_send_response(card, request, RCODE_TYPE_ERROR); @@ -149,9 +148,9 @@ static void dice_notification(struct fw_card *card, struct fw_request *request, bits = be32_to_cpup(data); - spin_lock_irqsave(&dice->lock, flags); - dice->notification_bits |= bits; - spin_unlock_irqrestore(&dice->lock, flags); + scoped_guard(spinlock_irqsave, &dice->lock) { + dice->notification_bits |= bits; + } fw_send_response(card, request, RCODE_COMPLETE); diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 9675ec14271d..bcbe80344328 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -238,9 +238,8 @@ static void dice_bus_reset(struct fw_unit *unit) /* The handler address register becomes initialized. */ snd_dice_transaction_reinit(dice); - mutex_lock(&dice->mutex); + guard(mutex)(&dice->mutex); snd_dice_stream_update_duplex(dice); - mutex_unlock(&dice->mutex); } #define DICE_INTERFACE 0x000001 diff --git a/sound/firewire/digi00x/digi00x-hwdep.c b/sound/firewire/digi00x/digi00x-hwdep.c index b150607c0a0d..435d18417cf0 100644 --- a/sound/firewire/digi00x/digi00x-hwdep.c +++ b/sound/firewire/digi00x/digi00x-hwdep.c @@ -63,18 +63,14 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait) { struct snd_dg00x *dg00x = hwdep->private_data; - __poll_t events; poll_wait(file, &dg00x->hwdep_wait, wait); - spin_lock_irq(&dg00x->lock); + guard(spinlock_irq)(&dg00x->lock); if (dg00x->dev_lock_changed || dg00x->msg) - events = EPOLLIN | EPOLLRDNORM; + return EPOLLIN | EPOLLRDNORM; else - events = 0; - spin_unlock_irq(&dg00x->lock); - - return events; + return 0; } static int hwdep_get_info(struct snd_dg00x *dg00x, void __user *arg) @@ -98,48 +94,35 @@ static int hwdep_get_info(struct snd_dg00x *dg00x, void __user *arg) static int hwdep_lock(struct snd_dg00x *dg00x) { - int err; - - spin_lock_irq(&dg00x->lock); + guard(spinlock_irq)(&dg00x->lock); if (dg00x->dev_lock_count == 0) { dg00x->dev_lock_count = -1; - err = 0; + return 0; } else { - err = -EBUSY; + return -EBUSY; } - - spin_unlock_irq(&dg00x->lock); - - return err; } static int hwdep_unlock(struct snd_dg00x *dg00x) { - int err; - - spin_lock_irq(&dg00x->lock); + guard(spinlock_irq)(&dg00x->lock); if (dg00x->dev_lock_count == -1) { dg00x->dev_lock_count = 0; - err = 0; + return 0; } else { - err = -EBADFD; + return -EBADFD; } - - spin_unlock_irq(&dg00x->lock); - - return err; } static int hwdep_release(struct snd_hwdep *hwdep, struct file *file) { struct snd_dg00x *dg00x = hwdep->private_data; - spin_lock_irq(&dg00x->lock); + guard(spinlock_irq)(&dg00x->lock); if (dg00x->dev_lock_count == -1) dg00x->dev_lock_count = 0; - spin_unlock_irq(&dg00x->lock); return 0; } diff --git a/sound/firewire/digi00x/digi00x-midi.c b/sound/firewire/digi00x/digi00x-midi.c index 8f4bace16050..bcdaf003514b 100644 --- a/sound/firewire/digi00x/digi00x-midi.c +++ b/sound/firewire/digi00x/digi00x-midi.c @@ -16,15 +16,15 @@ static int midi_open(struct snd_rawmidi_substream *substream) if (err < 0) return err; - mutex_lock(&dg00x->mutex); - err = snd_dg00x_stream_reserve_duplex(dg00x, 0, 0, 0); - if (err >= 0) { - ++dg00x->substreams_counter; - err = snd_dg00x_stream_start_duplex(dg00x); - if (err < 0) - --dg00x->substreams_counter; + scoped_guard(mutex, &dg00x->mutex) { + err = snd_dg00x_stream_reserve_duplex(dg00x, 0, 0, 0); + if (err >= 0) { + ++dg00x->substreams_counter; + err = snd_dg00x_stream_start_duplex(dg00x); + if (err < 0) + --dg00x->substreams_counter; + } } - mutex_unlock(&dg00x->mutex); if (err < 0) snd_dg00x_stream_lock_release(dg00x); @@ -35,10 +35,10 @@ static int midi_close(struct snd_rawmidi_substream *substream) { struct snd_dg00x *dg00x = substream->rmidi->private_data; - mutex_lock(&dg00x->mutex); - --dg00x->substreams_counter; - snd_dg00x_stream_stop_duplex(dg00x); - mutex_unlock(&dg00x->mutex); + scoped_guard(mutex, &dg00x->mutex) { + --dg00x->substreams_counter; + snd_dg00x_stream_stop_duplex(dg00x); + } snd_dg00x_stream_lock_release(dg00x); return 0; @@ -49,21 +49,18 @@ static void midi_capture_trigger(struct snd_rawmidi_substream *substream, { struct snd_dg00x *dg00x = substream->rmidi->private_data; unsigned int port; - unsigned long flags; if (substream->rmidi->device == 0) port = substream->number; else port = 2; - spin_lock_irqsave(&dg00x->lock, flags); + guard(spinlock_irqsave)(&dg00x->lock); if (up) amdtp_dot_midi_trigger(&dg00x->tx_stream, port, substream); else amdtp_dot_midi_trigger(&dg00x->tx_stream, port, NULL); - - spin_unlock_irqrestore(&dg00x->lock, flags); } static void midi_playback_trigger(struct snd_rawmidi_substream *substream, @@ -71,21 +68,18 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substream, { struct snd_dg00x *dg00x = substream->rmidi->private_data; unsigned int port; - unsigned long flags; if (substream->rmidi->device == 0) port = substream->number; else port = 2; - spin_lock_irqsave(&dg00x->lock, flags); + guard(spinlock_irqsave)(&dg00x->lock); if (up) amdtp_dot_midi_trigger(&dg00x->rx_stream, port, substream); else amdtp_dot_midi_trigger(&dg00x->rx_stream, port, NULL); - - spin_unlock_irqrestore(&dg00x->lock, flags); } static void set_substream_names(struct snd_dg00x *dg00x, diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c index 85e65cbc00c4..75f81545d50c 100644 --- a/sound/firewire/digi00x/digi00x-pcm.c +++ b/sound/firewire/digi00x/digi00x-pcm.c @@ -127,46 +127,38 @@ static int pcm_open(struct snd_pcm_substream *substream) } } - mutex_lock(&dg00x->mutex); - - // When source of clock is not internal or any stream is reserved for - // transmission of PCM frames, the available sampling rate is limited - // at current one. - if ((clock != SND_DG00X_CLOCK_INTERNAL) || - (dg00x->substreams_counter > 0 && d->events_per_period > 0)) { - unsigned int frames_per_period = d->events_per_period; - unsigned int frames_per_buffer = d->events_per_buffer; - unsigned int rate; - - err = snd_dg00x_stream_get_external_rate(dg00x, &rate); - if (err < 0) { - mutex_unlock(&dg00x->mutex); - goto err_locked; - } - substream->runtime->hw.rate_min = rate; - substream->runtime->hw.rate_max = rate; - - if (frames_per_period > 0) { - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - frames_per_period, frames_per_period); - if (err < 0) { - mutex_unlock(&dg00x->mutex); - goto err_locked; - } - - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - frames_per_buffer, frames_per_buffer); - if (err < 0) { - mutex_unlock(&dg00x->mutex); + scoped_guard(mutex, &dg00x->mutex) { + // When source of clock is not internal or any stream is reserved for + // transmission of PCM frames, the available sampling rate is limited + // at current one. + if ((clock != SND_DG00X_CLOCK_INTERNAL) || + (dg00x->substreams_counter > 0 && d->events_per_period > 0)) { + unsigned int frames_per_period = d->events_per_period; + unsigned int frames_per_buffer = d->events_per_buffer; + unsigned int rate; + + err = snd_dg00x_stream_get_external_rate(dg00x, &rate); + if (err < 0) goto err_locked; + substream->runtime->hw.rate_min = rate; + substream->runtime->hw.rate_max = rate; + + if (frames_per_period > 0) { + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + frames_per_period, frames_per_period); + if (err < 0) + goto err_locked; + + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + frames_per_buffer, frames_per_buffer); + if (err < 0) + goto err_locked; } } } - mutex_unlock(&dg00x->mutex); - snd_pcm_set_sync(substream); return 0; @@ -195,12 +187,11 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); - mutex_lock(&dg00x->mutex); + guard(mutex)(&dg00x->mutex); err = snd_dg00x_stream_reserve_duplex(dg00x, rate, frames_per_period, frames_per_buffer); if (err >= 0) ++dg00x->substreams_counter; - mutex_unlock(&dg00x->mutex); } return err; @@ -210,15 +201,13 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_dg00x *dg00x = substream->private_data; - mutex_lock(&dg00x->mutex); + guard(mutex)(&dg00x->mutex); if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --dg00x->substreams_counter; snd_dg00x_stream_stop_duplex(dg00x); - mutex_unlock(&dg00x->mutex); - return 0; } @@ -227,14 +216,12 @@ static int pcm_capture_prepare(struct snd_pcm_substream *substream) struct snd_dg00x *dg00x = substream->private_data; int err; - mutex_lock(&dg00x->mutex); + guard(mutex)(&dg00x->mutex); err = snd_dg00x_stream_start_duplex(dg00x); if (err >= 0) amdtp_stream_pcm_prepare(&dg00x->tx_stream); - mutex_unlock(&dg00x->mutex); - return err; } @@ -243,7 +230,7 @@ static int pcm_playback_prepare(struct snd_pcm_substream *substream) struct snd_dg00x *dg00x = substream->private_data; int err; - mutex_lock(&dg00x->mutex); + guard(mutex)(&dg00x->mutex); err = snd_dg00x_stream_start_duplex(dg00x); if (err >= 0) { @@ -251,8 +238,6 @@ static int pcm_playback_prepare(struct snd_pcm_substream *substream) amdtp_dot_reset(&dg00x->rx_stream); } - mutex_unlock(&dg00x->mutex); - return err; } diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index 295163bb8abb..250ffdb26ebd 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c @@ -427,33 +427,24 @@ void snd_dg00x_stream_lock_changed(struct snd_dg00x *dg00x) int snd_dg00x_stream_lock_try(struct snd_dg00x *dg00x) { - int err; - - spin_lock_irq(&dg00x->lock); + guard(spinlock_irq)(&dg00x->lock); /* user land lock this */ - if (dg00x->dev_lock_count < 0) { - err = -EBUSY; - goto end; - } + if (dg00x->dev_lock_count < 0) + return -EBUSY; /* this is the first time */ if (dg00x->dev_lock_count++ == 0) snd_dg00x_stream_lock_changed(dg00x); - err = 0; -end: - spin_unlock_irq(&dg00x->lock); - return err; + return 0; } void snd_dg00x_stream_lock_release(struct snd_dg00x *dg00x) { - spin_lock_irq(&dg00x->lock); + guard(spinlock_irq)(&dg00x->lock); if (WARN_ON(dg00x->dev_lock_count <= 0)) - goto end; + return; if (--dg00x->dev_lock_count == 0) snd_dg00x_stream_lock_changed(dg00x); -end: - spin_unlock_irq(&dg00x->lock); } diff --git a/sound/firewire/digi00x/digi00x-transaction.c b/sound/firewire/digi00x/digi00x-transaction.c index cf0bcf1c5956..8a1667159930 100644 --- a/sound/firewire/digi00x/digi00x-transaction.c +++ b/sound/firewire/digi00x/digi00x-transaction.c @@ -11,11 +11,9 @@ static void handle_unknown_message(struct snd_dg00x *dg00x, unsigned long long offset, __be32 *buf) { - unsigned long flags; - - spin_lock_irqsave(&dg00x->lock, flags); - dg00x->msg = be32_to_cpu(*buf); - spin_unlock_irqrestore(&dg00x->lock, flags); + scoped_guard(spinlock_irqsave, &dg00x->lock) { + dg00x->msg = be32_to_cpu(*buf); + } wake_up(&dg00x->hwdep_wait); } diff --git a/sound/firewire/digi00x/digi00x.c b/sound/firewire/digi00x/digi00x.c index cebc35dcf8cd..f73a9fc8adb1 100644 --- a/sound/firewire/digi00x/digi00x.c +++ b/sound/firewire/digi00x/digi00x.c @@ -116,9 +116,8 @@ static void snd_dg00x_update(struct fw_unit *unit) snd_dg00x_transaction_reregister(dg00x); - mutex_lock(&dg00x->mutex); + guard(mutex)(&dg00x->mutex); snd_dg00x_stream_update_duplex(dg00x); - mutex_unlock(&dg00x->mutex); } static void snd_dg00x_remove(struct fw_unit *unit) diff --git a/sound/firewire/fcp.c b/sound/firewire/fcp.c index df44dd5dc4b2..e60bfd0ee4ac 100644 --- a/sound/firewire/fcp.c +++ b/sound/firewire/fcp.c @@ -242,9 +242,9 @@ int fcp_avc_transaction(struct fw_unit *unit, init_waitqueue_head(&t.wait); t.deferrable = (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03); - spin_lock_irq(&transactions_lock); - list_add_tail(&t.list, &transactions); - spin_unlock_irq(&transactions_lock); + scoped_guard(spinlock_irq, &transactions_lock) { + list_add_tail(&t.list, &transactions); + } for (;;) { tcode = command_size == 4 ? TCODE_WRITE_QUADLET_REQUEST @@ -280,9 +280,9 @@ deferred: } } - spin_lock_irq(&transactions_lock); - list_del(&t.list); - spin_unlock_irq(&transactions_lock); + scoped_guard(spinlock_irq, &transactions_lock) { + list_del(&t.list); + } return ret; } @@ -300,7 +300,7 @@ void fcp_bus_reset(struct fw_unit *unit) { struct fcp_transaction *t; - spin_lock_irq(&transactions_lock); + guard(spinlock_irq)(&transactions_lock); list_for_each_entry(t, &transactions, list) { if (t->unit == unit && (t->state == STATE_PENDING || @@ -309,7 +309,6 @@ void fcp_bus_reset(struct fw_unit *unit) wake_up(&t->wait); } } - spin_unlock_irq(&transactions_lock); } EXPORT_SYMBOL(fcp_bus_reset); @@ -341,12 +340,11 @@ static void fcp_response(struct fw_card *card, struct fw_request *request, void *data, size_t length, void *callback_data) { struct fcp_transaction *t; - unsigned long flags; if (length < 1 || (*(const u8 *)data & 0xf0) != CTS_AVC) return; - spin_lock_irqsave(&transactions_lock, flags); + guard(spinlock_irqsave)(&transactions_lock); list_for_each_entry(t, &transactions, list) { struct fw_device *device = fw_parent_device(t->unit); if (device->card != card || @@ -370,7 +368,6 @@ static void fcp_response(struct fw_card *card, struct fw_request *request, wake_up(&t->wait); } } - spin_unlock_irqrestore(&transactions_lock, flags); } static struct fw_address_handler response_register_handler = { diff --git a/sound/firewire/fireface/ff-hwdep.c b/sound/firewire/fireface/ff-hwdep.c index ca5c5dee71f2..5976abf2e1ab 100644 --- a/sound/firewire/fireface/ff-hwdep.c +++ b/sound/firewire/fireface/ff-hwdep.c @@ -72,18 +72,14 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait) { struct snd_ff *ff = hwdep->private_data; - __poll_t events; poll_wait(file, &ff->hwdep_wait, wait); - spin_lock_irq(&ff->lock); + guard(spinlock_irq)(&ff->lock); if (ff->dev_lock_changed || has_msg(ff)) - events = EPOLLIN | EPOLLRDNORM; + return EPOLLIN | EPOLLRDNORM; else - events = 0; - spin_unlock_irq(&ff->lock); - - return events; + return 0; } static int hwdep_get_info(struct snd_ff *ff, void __user *arg) @@ -107,48 +103,35 @@ static int hwdep_get_info(struct snd_ff *ff, void __user *arg) static int hwdep_lock(struct snd_ff *ff) { - int err; - - spin_lock_irq(&ff->lock); + guard(spinlock_irq)(&ff->lock); if (ff->dev_lock_count == 0) { ff->dev_lock_count = -1; - err = 0; + return 0; } else { - err = -EBUSY; + return -EBUSY; } - - spin_unlock_irq(&ff->lock); - - return err; } static int hwdep_unlock(struct snd_ff *ff) { - int err; - - spin_lock_irq(&ff->lock); + guard(spinlock_irq)(&ff->lock); if (ff->dev_lock_count == -1) { ff->dev_lock_count = 0; - err = 0; + return 0; } else { - err = -EBADFD; + return -EBADFD; } - - spin_unlock_irq(&ff->lock); - - return err; } static int hwdep_release(struct snd_hwdep *hwdep, struct file *file) { struct snd_ff *ff = hwdep->private_data; - spin_lock_irq(&ff->lock); + guard(spinlock_irq)(&ff->lock); if (ff->dev_lock_count == -1) ff->dev_lock_count = 0; - spin_unlock_irq(&ff->lock); return 0; } diff --git a/sound/firewire/fireface/ff-midi.c b/sound/firewire/fireface/ff-midi.c index da3054fdcc7d..9f6aa490e5bf 100644 --- a/sound/firewire/fireface/ff-midi.c +++ b/sound/firewire/fireface/ff-midi.c @@ -46,31 +46,25 @@ static void midi_capture_trigger(struct snd_rawmidi_substream *substream, int up) { struct snd_ff *ff = substream->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&ff->lock, flags); + guard(spinlock_irqsave)(&ff->lock); if (up) WRITE_ONCE(ff->tx_midi_substreams[substream->number], substream); else WRITE_ONCE(ff->tx_midi_substreams[substream->number], NULL); - - spin_unlock_irqrestore(&ff->lock, flags); } static void midi_playback_trigger(struct snd_rawmidi_substream *substream, int up) { struct snd_ff *ff = substream->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&ff->lock, flags); + guard(spinlock_irqsave)(&ff->lock); if (up || !ff->rx_midi_error[substream->number]) schedule_work(&ff->rx_midi_work[substream->number]); - - spin_unlock_irqrestore(&ff->lock, flags); } static void set_midi_substream_names(struct snd_rawmidi_str *stream, diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c index 63457d24a288..7ad8204fbfe8 100644 --- a/sound/firewire/fireface/ff-pcm.c +++ b/sound/firewire/fireface/ff-pcm.c @@ -156,56 +156,49 @@ static int pcm_open(struct snd_pcm_substream *substream) if (err < 0) goto release_lock; - mutex_lock(&ff->mutex); - - // When source of clock is not internal or any stream is reserved for - // transmission of PCM frames, the available sampling rate is limited - // at current one. - if (src != SND_FF_CLOCK_SRC_INTERNAL) { - for (i = 0; i < CIP_SFC_COUNT; ++i) { - if (amdtp_rate_table[i] == rate) - break; - } - - // The unit is configured at sampling frequency which packet - // streaming engine can't support. - if (i >= CIP_SFC_COUNT) { - mutex_unlock(&ff->mutex); - err = -EIO; - goto release_lock; - } - - substream->runtime->hw.rate_min = rate; - substream->runtime->hw.rate_max = rate; - } else { - if (ff->substreams_counter > 0) { - unsigned int frames_per_period = d->events_per_period; - unsigned int frames_per_buffer = d->events_per_buffer; - - rate = amdtp_rate_table[ff->rx_stream.sfc]; - substream->runtime->hw.rate_min = rate; - substream->runtime->hw.rate_max = rate; + scoped_guard(mutex, &ff->mutex) { + // When source of clock is not internal or any stream is reserved for + // transmission of PCM frames, the available sampling rate is limited + // at current one. + if (src != SND_FF_CLOCK_SRC_INTERNAL) { + for (i = 0; i < CIP_SFC_COUNT; ++i) { + if (amdtp_rate_table[i] == rate) + break; + } - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - frames_per_period, frames_per_period); - if (err < 0) { - mutex_unlock(&ff->mutex); + // The unit is configured at sampling frequency which packet + // streaming engine can't support. + if (i >= CIP_SFC_COUNT) { + err = -EIO; goto release_lock; } - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - frames_per_buffer, frames_per_buffer); - if (err < 0) { - mutex_unlock(&ff->mutex); - goto release_lock; + substream->runtime->hw.rate_min = rate; + substream->runtime->hw.rate_max = rate; + } else { + if (ff->substreams_counter > 0) { + unsigned int frames_per_period = d->events_per_period; + unsigned int frames_per_buffer = d->events_per_buffer; + + rate = amdtp_rate_table[ff->rx_stream.sfc]; + substream->runtime->hw.rate_min = rate; + substream->runtime->hw.rate_max = rate; + + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + frames_per_period, frames_per_period); + if (err < 0) + goto release_lock; + + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + frames_per_buffer, frames_per_buffer); + if (err < 0) + goto release_lock; } } } - mutex_unlock(&ff->mutex); - snd_pcm_set_sync(substream); return 0; @@ -235,12 +228,11 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); - mutex_lock(&ff->mutex); + guard(mutex)(&ff->mutex); err = snd_ff_stream_reserve_duplex(ff, rate, frames_per_period, frames_per_buffer); if (err >= 0) ++ff->substreams_counter; - mutex_unlock(&ff->mutex); } return err; @@ -250,15 +242,13 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_ff *ff = substream->private_data; - mutex_lock(&ff->mutex); + guard(mutex)(&ff->mutex); if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --ff->substreams_counter; snd_ff_stream_stop_duplex(ff); - mutex_unlock(&ff->mutex); - return 0; } @@ -268,14 +258,12 @@ static int pcm_capture_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - mutex_lock(&ff->mutex); + guard(mutex)(&ff->mutex); err = snd_ff_stream_start_duplex(ff, runtime->rate); if (err >= 0) amdtp_stream_pcm_prepare(&ff->tx_stream); - mutex_unlock(&ff->mutex); - return err; } @@ -285,14 +273,12 @@ static int pcm_playback_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - mutex_lock(&ff->mutex); + guard(mutex)(&ff->mutex); err = snd_ff_stream_start_duplex(ff, runtime->rate); if (err >= 0) amdtp_stream_pcm_prepare(&ff->rx_stream); - mutex_unlock(&ff->mutex); - return err; } diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c index 95bf405adb3d..ba42490f2b0e 100644 --- a/sound/firewire/fireface/ff-stream.c +++ b/sound/firewire/fireface/ff-stream.c @@ -253,33 +253,24 @@ void snd_ff_stream_lock_changed(struct snd_ff *ff) int snd_ff_stream_lock_try(struct snd_ff *ff) { - int err; - - spin_lock_irq(&ff->lock); + guard(spinlock_irq)(&ff->lock); /* user land lock this */ - if (ff->dev_lock_count < 0) { - err = -EBUSY; - goto end; - } + if (ff->dev_lock_count < 0) + return -EBUSY; /* this is the first time */ if (ff->dev_lock_count++ == 0) snd_ff_stream_lock_changed(ff); - err = 0; -end: - spin_unlock_irq(&ff->lock); - return err; + return 0; } void snd_ff_stream_lock_release(struct snd_ff *ff) { - spin_lock_irq(&ff->lock); + guard(spinlock_irq)(&ff->lock); if (WARN_ON(ff->dev_lock_count <= 0)) - goto end; + return; if (--ff->dev_lock_count == 0) snd_ff_stream_lock_changed(ff); -end: - spin_unlock_irq(&ff->lock); } diff --git a/sound/firewire/fireface/ff-transaction.c b/sound/firewire/fireface/ff-transaction.c index 6b89e39f4a43..436da0a3bdcc 100644 --- a/sound/firewire/fireface/ff-transaction.c +++ b/sound/firewire/fireface/ff-transaction.c @@ -132,15 +132,13 @@ static void handle_msg(struct fw_card *card, struct fw_request *request, int tco struct snd_ff *ff = callback_data; __le32 *buf = data; u32 tstamp = fw_request_get_timestamp(request); - unsigned long flag; fw_send_response(card, request, RCODE_COMPLETE); offset -= ff->async_handler.offset; - spin_lock_irqsave(&ff->lock, flag); + guard(spinlock_irqsave)(&ff->lock); ff->spec->protocol->handle_msg(ff, (unsigned int)offset, buf, length, tstamp); - spin_unlock_irqrestore(&ff->lock, flag); } static int allocate_own_address(struct snd_ff *ff, int i) diff --git a/sound/firewire/fireworks/fireworks.c b/sound/firewire/fireworks/fireworks.c index 69f722244362..3378c7dce88a 100644 --- a/sound/firewire/fireworks/fireworks.c +++ b/sound/firewire/fireworks/fireworks.c @@ -188,9 +188,9 @@ efw_card_free(struct snd_card *card) { struct snd_efw *efw = card->private_data; - mutex_lock(&devices_mutex); - clear_bit(efw->card_index, devices_used); - mutex_unlock(&devices_mutex); + scoped_guard(mutex, &devices_mutex) { + clear_bit(efw->card_index, devices_used); + } snd_efw_stream_destroy_duplex(efw); snd_efw_transaction_remove_instance(efw); @@ -207,25 +207,21 @@ static int efw_probe(struct fw_unit *unit, const struct ieee1394_device_id *entr int err; // check registered cards. - mutex_lock(&devices_mutex); - for (card_index = 0; card_index < SNDRV_CARDS; ++card_index) { - if (!test_bit(card_index, devices_used) && enable[card_index]) - break; - } - if (card_index >= SNDRV_CARDS) { - mutex_unlock(&devices_mutex); - return -ENOENT; - } - - err = snd_card_new(&unit->device, index[card_index], id[card_index], THIS_MODULE, - sizeof(*efw), &card); - if (err < 0) { - mutex_unlock(&devices_mutex); - return err; + scoped_guard(mutex, &devices_mutex) { + for (card_index = 0; card_index < SNDRV_CARDS; ++card_index) { + if (!test_bit(card_index, devices_used) && enable[card_index]) + break; + } + if (card_index >= SNDRV_CARDS) + return -ENOENT; + + err = snd_card_new(&unit->device, index[card_index], id[card_index], THIS_MODULE, + sizeof(*efw), &card); + if (err < 0) + return err; + card->private_free = efw_card_free; + set_bit(card_index, devices_used); } - card->private_free = efw_card_free; - set_bit(card_index, devices_used); - mutex_unlock(&devices_mutex); efw = card->private_data; efw->unit = fw_unit_get(unit); @@ -287,9 +283,8 @@ static void efw_update(struct fw_unit *unit) snd_efw_transaction_bus_reset(efw->unit); - mutex_lock(&efw->mutex); + guard(mutex)(&efw->mutex); snd_efw_stream_update_duplex(efw); - mutex_unlock(&efw->mutex); } static void efw_remove(struct fw_unit *unit) diff --git a/sound/firewire/fireworks/fireworks_command.c b/sound/firewire/fireworks/fireworks_command.c index 7e255fc2c6e4..2b595ee0bc35 100644 --- a/sound/firewire/fireworks/fireworks_command.c +++ b/sound/firewire/fireworks/fireworks_command.c @@ -119,14 +119,14 @@ efw_transaction(struct snd_efw *efw, unsigned int category, return -ENOMEM; /* to keep consistency of sequence number */ - spin_lock(&efw->lock); - if ((efw->seqnum < KERNEL_SEQNUM_MIN) || - (efw->seqnum >= KERNEL_SEQNUM_MAX - 2)) - efw->seqnum = KERNEL_SEQNUM_MIN; - else - efw->seqnum += 2; - seqnum = efw->seqnum; - spin_unlock(&efw->lock); + scoped_guard(spinlock, &efw->lock) { + if ((efw->seqnum < KERNEL_SEQNUM_MIN) || + (efw->seqnum >= KERNEL_SEQNUM_MAX - 2)) + efw->seqnum = KERNEL_SEQNUM_MIN; + else + efw->seqnum += 2; + seqnum = efw->seqnum; + } /* fill transaction header fields */ cmd_bytes = sizeof(struct snd_efw_transaction) + param_bytes; diff --git a/sound/firewire/fireworks/fireworks_hwdep.c b/sound/firewire/fireworks/fireworks_hwdep.c index 037833cd066e..7d6bd8ceeab3 100644 --- a/sound/firewire/fireworks/fireworks_hwdep.c +++ b/sound/firewire/fireworks/fireworks_hwdep.c @@ -103,12 +103,10 @@ hwdep_read_locked(struct snd_efw *efw, char __user *buf, long count, .lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS, }; - spin_lock_irq(&efw->lock); - - event.lock_status.status = (efw->dev_lock_count > 0); - efw->dev_lock_changed = false; - - spin_unlock_irq(&efw->lock); + scoped_guard(spinlock_irq, &efw->lock) { + event.lock_status.status = (efw->dev_lock_count > 0); + efw->dev_lock_changed = false; + } count = min_t(long, count, sizeof(event.lock_status)); @@ -192,13 +190,11 @@ hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait) poll_wait(file, &efw->hwdep_wait, wait); - spin_lock_irq(&efw->lock); + guard(spinlock_irq)(&efw->lock); if (efw->dev_lock_changed || efw->pull_ptr != efw->push_ptr) events = EPOLLIN | EPOLLRDNORM; else events = 0; - spin_unlock_irq(&efw->lock); - return events | EPOLLOUT; } @@ -225,39 +221,27 @@ hwdep_get_info(struct snd_efw *efw, void __user *arg) static int hwdep_lock(struct snd_efw *efw) { - int err; - - spin_lock_irq(&efw->lock); + guard(spinlock_irq)(&efw->lock); if (efw->dev_lock_count == 0) { efw->dev_lock_count = -1; - err = 0; + return 0; } else { - err = -EBUSY; + return -EBUSY; } - - spin_unlock_irq(&efw->lock); - - return err; } static int hwdep_unlock(struct snd_efw *efw) { - int err; - - spin_lock_irq(&efw->lock); + guard(spinlock_irq)(&efw->lock); if (efw->dev_lock_count == -1) { efw->dev_lock_count = 0; - err = 0; + return 0; } else { - err = -EBADFD; + return -EBADFD; } - - spin_unlock_irq(&efw->lock); - - return err; } static int @@ -265,10 +249,9 @@ hwdep_release(struct snd_hwdep *hwdep, struct file *file) { struct snd_efw *efw = hwdep->private_data; - spin_lock_irq(&efw->lock); + guard(spinlock_irq)(&efw->lock); if (efw->dev_lock_count == -1) efw->dev_lock_count = 0; - spin_unlock_irq(&efw->lock); return 0; } diff --git a/sound/firewire/fireworks/fireworks_midi.c b/sound/firewire/fireworks/fireworks_midi.c index 350bf4d299c2..405106a6aef9 100644 --- a/sound/firewire/fireworks/fireworks_midi.c +++ b/sound/firewire/fireworks/fireworks_midi.c @@ -14,20 +14,19 @@ static int midi_open(struct snd_rawmidi_substream *substream) err = snd_efw_stream_lock_try(efw); if (err < 0) - goto end; - - mutex_lock(&efw->mutex); - err = snd_efw_stream_reserve_duplex(efw, 0, 0, 0); - if (err >= 0) { - ++efw->substreams_counter; - err = snd_efw_stream_start_duplex(efw); - if (err < 0) - --efw->substreams_counter; + return err; + + scoped_guard(mutex, &efw->mutex) { + err = snd_efw_stream_reserve_duplex(efw, 0, 0, 0); + if (err >= 0) { + ++efw->substreams_counter; + err = snd_efw_stream_start_duplex(efw); + if (err < 0) + --efw->substreams_counter; + } } - mutex_unlock(&efw->mutex); if (err < 0) snd_efw_stream_lock_release(efw); -end: return err; } @@ -35,10 +34,10 @@ static int midi_close(struct snd_rawmidi_substream *substream) { struct snd_efw *efw = substream->rmidi->private_data; - mutex_lock(&efw->mutex); - --efw->substreams_counter; - snd_efw_stream_stop_duplex(efw); - mutex_unlock(&efw->mutex); + scoped_guard(mutex, &efw->mutex) { + --efw->substreams_counter; + snd_efw_stream_stop_duplex(efw); + } snd_efw_stream_lock_release(efw); return 0; @@ -47,9 +46,8 @@ static int midi_close(struct snd_rawmidi_substream *substream) static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) { struct snd_efw *efw = substrm->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&efw->lock, flags); + guard(spinlock_irqsave)(&efw->lock); if (up) amdtp_am824_midi_trigger(&efw->tx_stream, @@ -57,16 +55,13 @@ static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) else amdtp_am824_midi_trigger(&efw->tx_stream, substrm->number, NULL); - - spin_unlock_irqrestore(&efw->lock, flags); } static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) { struct snd_efw *efw = substrm->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&efw->lock, flags); + guard(spinlock_irqsave)(&efw->lock); if (up) amdtp_am824_midi_trigger(&efw->rx_stream, @@ -74,8 +69,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) else amdtp_am824_midi_trigger(&efw->rx_stream, substrm->number, NULL); - - spin_unlock_irqrestore(&efw->lock, flags); } static void set_midi_substream_names(struct snd_efw *efw, diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index eaf7778211de..9399293a9fe9 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -189,46 +189,38 @@ static int pcm_open(struct snd_pcm_substream *substream) if (err < 0) goto err_locked; - mutex_lock(&efw->mutex); - - // When source of clock is not internal or any stream is reserved for - // transmission of PCM frames, the available sampling rate is limited - // at current one. - if ((clock_source != SND_EFW_CLOCK_SOURCE_INTERNAL) || - (efw->substreams_counter > 0 && d->events_per_period > 0)) { - unsigned int frames_per_period = d->events_per_period; - unsigned int frames_per_buffer = d->events_per_buffer; - unsigned int sampling_rate; - - err = snd_efw_command_get_sampling_rate(efw, &sampling_rate); - if (err < 0) { - mutex_unlock(&efw->mutex); - goto err_locked; - } - substream->runtime->hw.rate_min = sampling_rate; - substream->runtime->hw.rate_max = sampling_rate; - - if (frames_per_period > 0) { - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - frames_per_period, frames_per_period); - if (err < 0) { - mutex_unlock(&efw->mutex); - goto err_locked; - } - - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - frames_per_buffer, frames_per_buffer); - if (err < 0) { - mutex_unlock(&efw->mutex); + scoped_guard(mutex, &efw->mutex) { + // When source of clock is not internal or any stream is reserved for + // transmission of PCM frames, the available sampling rate is limited + // at current one. + if ((clock_source != SND_EFW_CLOCK_SOURCE_INTERNAL) || + (efw->substreams_counter > 0 && d->events_per_period > 0)) { + unsigned int frames_per_period = d->events_per_period; + unsigned int frames_per_buffer = d->events_per_buffer; + unsigned int sampling_rate; + + err = snd_efw_command_get_sampling_rate(efw, &sampling_rate); + if (err < 0) goto err_locked; + substream->runtime->hw.rate_min = sampling_rate; + substream->runtime->hw.rate_max = sampling_rate; + + if (frames_per_period > 0) { + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + frames_per_period, frames_per_period); + if (err < 0) + goto err_locked; + + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + frames_per_buffer, frames_per_buffer); + if (err < 0) + goto err_locked; } } } - mutex_unlock(&efw->mutex); - snd_pcm_set_sync(substream); return 0; @@ -255,12 +247,11 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); - mutex_lock(&efw->mutex); + guard(mutex)(&efw->mutex); err = snd_efw_stream_reserve_duplex(efw, rate, frames_per_period, frames_per_buffer); if (err >= 0) ++efw->substreams_counter; - mutex_unlock(&efw->mutex); } return err; @@ -270,15 +261,13 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_efw *efw = substream->private_data; - mutex_lock(&efw->mutex); + guard(mutex)(&efw->mutex); if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --efw->substreams_counter; snd_efw_stream_stop_duplex(efw); - mutex_unlock(&efw->mutex); - return 0; } diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 53dbd4d4b0d0..974084e1c083 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -345,33 +345,24 @@ void snd_efw_stream_lock_changed(struct snd_efw *efw) int snd_efw_stream_lock_try(struct snd_efw *efw) { - int err; - - spin_lock_irq(&efw->lock); + guard(spinlock_irq)(&efw->lock); /* user land lock this */ - if (efw->dev_lock_count < 0) { - err = -EBUSY; - goto end; - } + if (efw->dev_lock_count < 0) + return -EBUSY; /* this is the first time */ if (efw->dev_lock_count++ == 0) snd_efw_stream_lock_changed(efw); - err = 0; -end: - spin_unlock_irq(&efw->lock); - return err; + return 0; } void snd_efw_stream_lock_release(struct snd_efw *efw) { - spin_lock_irq(&efw->lock); + guard(spinlock_irq)(&efw->lock); if (WARN_ON(efw->dev_lock_count <= 0)) - goto end; + return; if (--efw->dev_lock_count == 0) snd_efw_stream_lock_changed(efw); -end: - spin_unlock_irq(&efw->lock); } diff --git a/sound/firewire/fireworks/fireworks_transaction.c b/sound/firewire/fireworks/fireworks_transaction.c index 9f8c53b39f95..5c859773fe06 100644 --- a/sound/firewire/fireworks/fireworks_transaction.c +++ b/sound/firewire/fireworks/fireworks_transaction.c @@ -82,9 +82,9 @@ int snd_efw_transaction_run(struct fw_unit *unit, t.state = STATE_PENDING; init_waitqueue_head(&t.wait); - spin_lock_irq(&transaction_queues_lock); - list_add_tail(&t.list, &transaction_queues); - spin_unlock_irq(&transaction_queues_lock); + scoped_guard(spinlock_irq, &transaction_queues_lock) { + list_add_tail(&t.list, &transaction_queues); + } tries = 0; do { @@ -107,9 +107,9 @@ int snd_efw_transaction_run(struct fw_unit *unit, } } while (1); - spin_lock_irq(&transaction_queues_lock); - list_del(&t.list); - spin_unlock_irq(&transaction_queues_lock); + scoped_guard(spinlock_irq, &transaction_queues_lock) { + list_del(&t.list); + } return ret; } @@ -123,7 +123,7 @@ copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode) t = (struct snd_efw_transaction *)data; length = min_t(size_t, be32_to_cpu(t->length) * sizeof(u32), length); - spin_lock(&efw->lock); + guard(spinlock)(&efw->lock); if (efw->push_ptr < efw->pull_ptr) capacity = (unsigned int)(efw->pull_ptr - efw->push_ptr); @@ -134,7 +134,7 @@ copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode) /* confirm enough space for this response */ if (capacity < length) { *rcode = RCODE_CONFLICT_ERROR; - goto end; + return; } /* copy to ring buffer */ @@ -157,8 +157,6 @@ copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode) wake_up(&efw->hwdep_wait); *rcode = RCODE_COMPLETE; -end: - spin_unlock_irq(&efw->lock); } static void @@ -169,7 +167,7 @@ handle_resp_for_user(struct fw_card *card, int generation, int source, struct snd_efw *efw; unsigned int i; - spin_lock_irq(&instances_lock); + guard(spinlock_irq)(&instances_lock); for (i = 0; i < SNDRV_CARDS; i++) { efw = instances[i]; @@ -186,11 +184,9 @@ handle_resp_for_user(struct fw_card *card, int generation, int source, break; } if (i == SNDRV_CARDS) - goto end; + return; copy_resp_to_buf(efw, data, length, rcode); -end: - spin_unlock(&instances_lock); } static void @@ -199,9 +195,8 @@ handle_resp_for_kernel(struct fw_card *card, int generation, int source, { struct fw_device *device; struct transaction_queue *t; - unsigned long flags; - spin_lock_irqsave(&transaction_queues_lock, flags); + guard(spinlock_irqsave)(&transaction_queues_lock); list_for_each_entry(t, &transaction_queues, list) { device = fw_parent_device(t->unit); if ((device->card != card) || @@ -219,7 +214,6 @@ handle_resp_for_kernel(struct fw_card *card, int generation, int source, *rcode = RCODE_COMPLETE; } } - spin_unlock_irqrestore(&transaction_queues_lock, flags); } static void @@ -259,7 +253,7 @@ void snd_efw_transaction_add_instance(struct snd_efw *efw) { unsigned int i; - spin_lock_irq(&instances_lock); + guard(spinlock_irq)(&instances_lock); for (i = 0; i < SNDRV_CARDS; i++) { if (instances[i] != NULL) @@ -267,30 +261,26 @@ void snd_efw_transaction_add_instance(struct snd_efw *efw) instances[i] = efw; break; } - - spin_unlock_irq(&instances_lock); } void snd_efw_transaction_remove_instance(struct snd_efw *efw) { unsigned int i; - spin_lock_irq(&instances_lock); + guard(spinlock_irq)(&instances_lock); for (i = 0; i < SNDRV_CARDS; i++) { if (instances[i] != efw) continue; instances[i] = NULL; } - - spin_unlock_irq(&instances_lock); } void snd_efw_transaction_bus_reset(struct fw_unit *unit) { struct transaction_queue *t; - spin_lock_irq(&transaction_queues_lock); + guard(spinlock_irq)(&transaction_queues_lock); list_for_each_entry(t, &transaction_queues, list) { if ((t->unit == unit) && (t->state == STATE_PENDING)) { @@ -298,7 +288,6 @@ void snd_efw_transaction_bus_reset(struct fw_unit *unit) wake_up(&t->wait); } } - spin_unlock_irq(&transaction_queues_lock); } static struct fw_address_handler resp_register_handler = { diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index ee574b5d7406..2b7f071d593b 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c @@ -327,9 +327,8 @@ static int isight_hw_free(struct snd_pcm_substream *substream) WRITE_ONCE(isight->pcm_active, false); - mutex_lock(&isight->mutex); + guard(mutex)(&isight->mutex); isight_stop_streaming(isight); - mutex_unlock(&isight->mutex); return 0; } @@ -400,16 +399,12 @@ error: static int isight_prepare(struct snd_pcm_substream *substream) { struct isight *isight = substream->private_data; - int err; isight->buffer_pointer = 0; isight->period_counter = 0; - mutex_lock(&isight->mutex); - err = isight_start_streaming(isight); - mutex_unlock(&isight->mutex); - - return err; + guard(mutex)(&isight->mutex); + return isight_start_streaming(isight); } static int isight_trigger(struct snd_pcm_substream *substream, int cmd) @@ -677,9 +672,8 @@ static void isight_bus_reset(struct fw_unit *unit) if (fw_iso_resources_update(&isight->resources) < 0) { isight_pcm_abort(isight); - mutex_lock(&isight->mutex); + guard(mutex)(&isight->mutex); isight_stop_streaming(isight); - mutex_unlock(&isight->mutex); } } @@ -691,9 +685,9 @@ static void isight_remove(struct fw_unit *unit) snd_card_disconnect(isight->card); - mutex_lock(&isight->mutex); - isight_stop_streaming(isight); - mutex_unlock(&isight->mutex); + scoped_guard(mutex, &isight->mutex) { + isight_stop_streaming(isight); + } // Block till all of ALSA character devices are released. snd_card_free(isight->card); diff --git a/sound/firewire/iso-resources.c b/sound/firewire/iso-resources.c index 84f71b2eaa82..4f63279225c5 100644 --- a/sound/firewire/iso-resources.c +++ b/sound/firewire/iso-resources.c @@ -114,38 +114,34 @@ int fw_iso_resources_allocate(struct fw_iso_resources *r, r->bandwidth = packet_bandwidth(max_payload_bytes, speed); retry_after_bus_reset: - spin_lock_irq(&card->lock); - r->generation = card->generation; - r->bandwidth_overhead = current_bandwidth_overhead(card); - spin_unlock_irq(&card->lock); + scoped_guard(spinlock_irq, &card->lock) { + r->generation = card->generation; + r->bandwidth_overhead = current_bandwidth_overhead(card); + } err = wait_isoch_resource_delay_after_bus_reset(card); if (err < 0) return err; - mutex_lock(&r->mutex); - - bandwidth = r->bandwidth + r->bandwidth_overhead; - fw_iso_resource_manage(card, r->generation, r->channels_mask, - &channel, &bandwidth, true); - if (channel == -EAGAIN) { - mutex_unlock(&r->mutex); - goto retry_after_bus_reset; - } - if (channel >= 0) { - r->channel = channel; - r->allocated = true; - } else { - if (channel == -EBUSY) - dev_err(&r->unit->device, - "isochronous resources exhausted\n"); - else - dev_err(&r->unit->device, - "isochronous resource allocation failed\n"); + scoped_guard(mutex, &r->mutex) { + bandwidth = r->bandwidth + r->bandwidth_overhead; + fw_iso_resource_manage(card, r->generation, r->channels_mask, + &channel, &bandwidth, true); + if (channel == -EAGAIN) + goto retry_after_bus_reset; + if (channel >= 0) { + r->channel = channel; + r->allocated = true; + } else { + if (channel == -EBUSY) + dev_err(&r->unit->device, + "isochronous resources exhausted\n"); + else + dev_err(&r->unit->device, + "isochronous resource allocation failed\n"); + } } - mutex_unlock(&r->mutex); - return channel; } EXPORT_SYMBOL(fw_iso_resources_allocate); @@ -166,17 +162,15 @@ int fw_iso_resources_update(struct fw_iso_resources *r) struct fw_card *card = fw_parent_device(r->unit)->card; int bandwidth, channel; - mutex_lock(&r->mutex); + guard(mutex)(&r->mutex); - if (!r->allocated) { - mutex_unlock(&r->mutex); + if (!r->allocated) return 0; - } - spin_lock_irq(&card->lock); - r->generation = card->generation; - r->bandwidth_overhead = current_bandwidth_overhead(card); - spin_unlock_irq(&card->lock); + scoped_guard(spinlock_irq, &card->lock) { + r->generation = card->generation; + r->bandwidth_overhead = current_bandwidth_overhead(card); + } bandwidth = r->bandwidth + r->bandwidth_overhead; @@ -196,8 +190,6 @@ int fw_iso_resources_update(struct fw_iso_resources *r) "isochronous resource allocation failed\n"); } - mutex_unlock(&r->mutex); - return channel; } EXPORT_SYMBOL(fw_iso_resources_update); @@ -218,7 +210,7 @@ void fw_iso_resources_free(struct fw_iso_resources *r) return; card = fw_parent_device(r->unit)->card; - mutex_lock(&r->mutex); + guard(mutex)(&r->mutex); if (r->allocated) { bandwidth = r->bandwidth + r->bandwidth_overhead; @@ -230,7 +222,5 @@ void fw_iso_resources_free(struct fw_iso_resources *r) r->allocated = false; } - - mutex_unlock(&r->mutex); } EXPORT_SYMBOL(fw_iso_resources_free); diff --git a/sound/firewire/motu/motu-command-dsp-message-parser.c b/sound/firewire/motu/motu-command-dsp-message-parser.c index 5d8a86a12f1f..c6440e6e360b 100644 --- a/sound/firewire/motu/motu-command-dsp-message-parser.c +++ b/sound/firewire/motu/motu-command-dsp-message-parser.c @@ -87,10 +87,9 @@ void snd_motu_command_dsp_message_parser_parse(const struct amdtp_stream *s, unsigned int data_block_quadlets = s->data_block_quadlets; struct msg_parser *parser = motu->message_parser; unsigned int interval = parser->interval; - unsigned long flags; int i; - spin_lock_irqsave(&parser->lock, flags); + guard(spinlock_irqsave)(&parser->lock); for (i = 0; i < count; ++i) { __be32 *buffer = desc->ctx_payload; @@ -168,17 +167,13 @@ void snd_motu_command_dsp_message_parser_parse(const struct amdtp_stream *s, } } } - - spin_unlock_irqrestore(&parser->lock, flags); } void snd_motu_command_dsp_message_parser_copy_meter(struct snd_motu *motu, struct snd_firewire_motu_command_dsp_meter *meter) { struct msg_parser *parser = motu->message_parser; - unsigned long flags; - spin_lock_irqsave(&parser->lock, flags); + guard(spinlock_irqsave)(&parser->lock); memcpy(meter, &parser->meter, sizeof(*meter)); - spin_unlock_irqrestore(&parser->lock, flags); } diff --git a/sound/firewire/motu/motu-hwdep.c b/sound/firewire/motu/motu-hwdep.c index fa2685665db3..981c19430cb0 100644 --- a/sound/firewire/motu/motu-hwdep.c +++ b/sound/firewire/motu/motu-hwdep.c @@ -100,18 +100,14 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait) { struct snd_motu *motu = hwdep->private_data; - __poll_t events; poll_wait(file, &motu->hwdep_wait, wait); - spin_lock_irq(&motu->lock); + guard(spinlock_irq)(&motu->lock); if (motu->dev_lock_changed || motu->msg || has_dsp_event(motu)) - events = EPOLLIN | EPOLLRDNORM; + return EPOLLIN | EPOLLRDNORM; else - events = 0; - spin_unlock_irq(&motu->lock); - - return events; + return 0; } static int hwdep_get_info(struct snd_motu *motu, void __user *arg) @@ -135,48 +131,35 @@ static int hwdep_get_info(struct snd_motu *motu, void __user *arg) static int hwdep_lock(struct snd_motu *motu) { - int err; - - spin_lock_irq(&motu->lock); + guard(spinlock_irq)(&motu->lock); if (motu->dev_lock_count == 0) { motu->dev_lock_count = -1; - err = 0; + return 0; } else { - err = -EBUSY; + return -EBUSY; } - - spin_unlock_irq(&motu->lock); - - return err; } static int hwdep_unlock(struct snd_motu *motu) { - int err; - - spin_lock_irq(&motu->lock); + guard(spinlock_irq)(&motu->lock); if (motu->dev_lock_count == -1) { motu->dev_lock_count = 0; - err = 0; + return 0; } else { - err = -EBADFD; + return -EBADFD; } - - spin_unlock_irq(&motu->lock); - - return err; } static int hwdep_release(struct snd_hwdep *hwdep, struct file *file) { struct snd_motu *motu = hwdep->private_data; - spin_lock_irq(&motu->lock); + guard(spinlock_irq)(&motu->lock); if (motu->dev_lock_count == -1) motu->dev_lock_count = 0; - spin_unlock_irq(&motu->lock); return 0; } diff --git a/sound/firewire/motu/motu-midi.c b/sound/firewire/motu/motu-midi.c index eebc7e790ee2..85e3260f9349 100644 --- a/sound/firewire/motu/motu-midi.c +++ b/sound/firewire/motu/motu-midi.c @@ -15,18 +15,16 @@ static int midi_open(struct snd_rawmidi_substream *substream) if (err < 0) return err; - mutex_lock(&motu->mutex); - - err = snd_motu_stream_reserve_duplex(motu, 0, 0, 0); - if (err >= 0) { - ++motu->substreams_counter; - err = snd_motu_stream_start_duplex(motu); - if (err < 0) - --motu->substreams_counter; + scoped_guard(mutex, &motu->mutex) { + err = snd_motu_stream_reserve_duplex(motu, 0, 0, 0); + if (err >= 0) { + ++motu->substreams_counter; + err = snd_motu_stream_start_duplex(motu); + if (err < 0) + --motu->substreams_counter; + } } - mutex_unlock(&motu->mutex); - if (err < 0) snd_motu_stream_lock_release(motu); @@ -37,12 +35,10 @@ static int midi_close(struct snd_rawmidi_substream *substream) { struct snd_motu *motu = substream->rmidi->private_data; - mutex_lock(&motu->mutex); - - --motu->substreams_counter; - snd_motu_stream_stop_duplex(motu); - - mutex_unlock(&motu->mutex); + scoped_guard(mutex, &motu->mutex) { + --motu->substreams_counter; + snd_motu_stream_stop_duplex(motu); + } snd_motu_stream_lock_release(motu); return 0; @@ -51,9 +47,8 @@ static int midi_close(struct snd_rawmidi_substream *substream) static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) { struct snd_motu *motu = substrm->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&motu->lock, flags); + guard(spinlock_irqsave)(&motu->lock); if (up) amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number, @@ -61,16 +56,13 @@ static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) else amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number, NULL); - - spin_unlock_irqrestore(&motu->lock, flags); } static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) { struct snd_motu *motu = substrm->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&motu->lock, flags); + guard(spinlock_irqsave)(&motu->lock); if (up) amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number, @@ -78,8 +70,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) else amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number, NULL); - - spin_unlock_irqrestore(&motu->lock, flags); } static void set_midi_substream_names(struct snd_motu *motu, diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c index 7b4d476af348..600c571edf02 100644 --- a/sound/firewire/motu/motu-pcm.c +++ b/sound/firewire/motu/motu-pcm.c @@ -138,59 +138,56 @@ static int pcm_open(struct snd_pcm_substream *substream) if (err < 0) return err; - mutex_lock(&motu->mutex); - - err = snd_motu_stream_cache_packet_formats(motu); - if (err < 0) - goto err_locked; - - err = init_hw_info(motu, substream); - if (err < 0) - goto err_locked; + scoped_guard(mutex, &motu->mutex) { + err = snd_motu_stream_cache_packet_formats(motu); + if (err < 0) + goto err_locked; - err = snd_motu_protocol_get_clock_source(motu, &src); - if (err < 0) - goto err_locked; - - // When source of clock is not internal or any stream is reserved for - // transmission of PCM frames, the available sampling rate is limited - // at current one. - if ((src != SND_MOTU_CLOCK_SOURCE_INTERNAL && - src != SND_MOTU_CLOCK_SOURCE_SPH) || - (motu->substreams_counter > 0 && d->events_per_period > 0)) { - unsigned int frames_per_period = d->events_per_period; - unsigned int frames_per_buffer = d->events_per_buffer; - unsigned int rate; - - err = snd_motu_protocol_get_clock_rate(motu, &rate); + err = init_hw_info(motu, substream); if (err < 0) goto err_locked; - substream->runtime->hw.rate_min = rate; - substream->runtime->hw.rate_max = rate; + err = snd_motu_protocol_get_clock_source(motu, &src); + if (err < 0) + goto err_locked; - if (frames_per_period > 0) { - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - frames_per_period, frames_per_period); + // When source of clock is not internal or any stream is reserved for + // transmission of PCM frames, the available sampling rate is limited + // at current one. + if ((src != SND_MOTU_CLOCK_SOURCE_INTERNAL && + src != SND_MOTU_CLOCK_SOURCE_SPH) || + (motu->substreams_counter > 0 && d->events_per_period > 0)) { + unsigned int frames_per_period = d->events_per_period; + unsigned int frames_per_buffer = d->events_per_buffer; + unsigned int rate; + + err = snd_motu_protocol_get_clock_rate(motu, &rate); if (err < 0) goto err_locked; - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - frames_per_buffer, frames_per_buffer); - if (err < 0) - goto err_locked; + substream->runtime->hw.rate_min = rate; + substream->runtime->hw.rate_max = rate; + + if (frames_per_period > 0) { + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + frames_per_period, frames_per_period); + if (err < 0) + goto err_locked; + + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + frames_per_buffer, frames_per_buffer); + if (err < 0) + goto err_locked; + } } } snd_pcm_set_sync(substream); - mutex_unlock(&motu->mutex); - return 0; err_locked: - mutex_unlock(&motu->mutex); snd_motu_stream_lock_release(motu); return err; } @@ -215,12 +212,11 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); - mutex_lock(&motu->mutex); + guard(mutex)(&motu->mutex); err = snd_motu_stream_reserve_duplex(motu, rate, frames_per_period, frames_per_buffer); if (err >= 0) ++motu->substreams_counter; - mutex_unlock(&motu->mutex); } return err; @@ -230,15 +226,13 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_motu *motu = substream->private_data; - mutex_lock(&motu->mutex); + guard(mutex)(&motu->mutex); if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --motu->substreams_counter; snd_motu_stream_stop_duplex(motu); - mutex_unlock(&motu->mutex); - return 0; } @@ -247,9 +241,9 @@ static int capture_prepare(struct snd_pcm_substream *substream) struct snd_motu *motu = substream->private_data; int err; - mutex_lock(&motu->mutex); - err = snd_motu_stream_start_duplex(motu); - mutex_unlock(&motu->mutex); + scoped_guard(mutex, &motu->mutex) { + err = snd_motu_stream_start_duplex(motu); + } if (err >= 0) amdtp_stream_pcm_prepare(&motu->tx_stream); @@ -260,9 +254,9 @@ static int playback_prepare(struct snd_pcm_substream *substream) struct snd_motu *motu = substream->private_data; int err; - mutex_lock(&motu->mutex); - err = snd_motu_stream_start_duplex(motu); - mutex_unlock(&motu->mutex); + scoped_guard(mutex, &motu->mutex) { + err = snd_motu_stream_start_duplex(motu); + } if (err >= 0) amdtp_stream_pcm_prepare(&motu->rx_stream); diff --git a/sound/firewire/motu/motu-register-dsp-message-parser.c b/sound/firewire/motu/motu-register-dsp-message-parser.c index ef3b0b0f0dab..a8053e3ef065 100644 --- a/sound/firewire/motu/motu-register-dsp-message-parser.c +++ b/sound/firewire/motu/motu-register-dsp-message-parser.c @@ -150,10 +150,9 @@ void snd_motu_register_dsp_message_parser_parse(const struct amdtp_stream *s, struct msg_parser *parser = motu->message_parser; bool meter_pos_quirk = parser->meter_pos_quirk; unsigned int pos = parser->push_pos; - unsigned long flags; int i; - spin_lock_irqsave(&parser->lock, flags); + guard(spinlock_irqsave)(&parser->lock); for (i = 0; i < count; ++i) { __be32 *buffer = desc->ctx_payload; @@ -363,30 +362,24 @@ void snd_motu_register_dsp_message_parser_parse(const struct amdtp_stream *s, if (pos != parser->push_pos) wake_up(&motu->hwdep_wait); - - spin_unlock_irqrestore(&parser->lock, flags); } void snd_motu_register_dsp_message_parser_copy_meter(struct snd_motu *motu, struct snd_firewire_motu_register_dsp_meter *meter) { struct msg_parser *parser = motu->message_parser; - unsigned long flags; - spin_lock_irqsave(&parser->lock, flags); + guard(spinlock_irqsave)(&parser->lock); memcpy(meter, &parser->meter, sizeof(*meter)); - spin_unlock_irqrestore(&parser->lock, flags); } void snd_motu_register_dsp_message_parser_copy_parameter(struct snd_motu *motu, struct snd_firewire_motu_register_dsp_parameter *param) { struct msg_parser *parser = motu->message_parser; - unsigned long flags; - spin_lock_irqsave(&parser->lock, flags); + guard(spinlock_irqsave)(&parser->lock); memcpy(param, &parser->param, sizeof(*param)); - spin_unlock_irqrestore(&parser->lock, flags); } unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *motu) @@ -403,12 +396,11 @@ bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 { struct msg_parser *parser = motu->message_parser; unsigned int pos = parser->pull_pos; - unsigned long flags; if (pos == parser->push_pos) return false; - spin_lock_irqsave(&parser->lock, flags); + guard(spinlock_irqsave)(&parser->lock); *event = parser->event_queue[pos]; @@ -417,7 +409,5 @@ bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 pos = 0; parser->pull_pos = pos; - spin_unlock_irqrestore(&parser->lock, flags); - return true; } diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index 64aec9c3eefd..e5f21360cfb7 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -407,32 +407,23 @@ static void motu_lock_changed(struct snd_motu *motu) int snd_motu_stream_lock_try(struct snd_motu *motu) { - int err; - - spin_lock_irq(&motu->lock); + guard(spinlock_irq)(&motu->lock); - if (motu->dev_lock_count < 0) { - err = -EBUSY; - goto out; - } + if (motu->dev_lock_count < 0) + return -EBUSY; if (motu->dev_lock_count++ == 0) motu_lock_changed(motu); - err = 0; -out: - spin_unlock_irq(&motu->lock); - return err; + return 0; } void snd_motu_stream_lock_release(struct snd_motu *motu) { - spin_lock_irq(&motu->lock); + guard(spinlock_irq)(&motu->lock); if (WARN_ON(motu->dev_lock_count <= 0)) - goto out; + return; if (--motu->dev_lock_count == 0) motu_lock_changed(motu); -out: - spin_unlock_irq(&motu->lock); } diff --git a/sound/firewire/motu/motu-transaction.c b/sound/firewire/motu/motu-transaction.c index 2dc1d6e59144..804f4208cf81 100644 --- a/sound/firewire/motu/motu-transaction.c +++ b/sound/firewire/motu/motu-transaction.c @@ -51,7 +51,6 @@ static void handle_message(struct fw_card *card, struct fw_request *request, { struct snd_motu *motu = callback_data; __be32 *buf = (__be32 *)data; - unsigned long flags; if (tcode != TCODE_WRITE_QUADLET_REQUEST) { fw_send_response(card, request, RCODE_COMPLETE); @@ -63,9 +62,9 @@ static void handle_message(struct fw_card *card, struct fw_request *request, return; } - spin_lock_irqsave(&motu->lock, flags); - motu->msg = be32_to_cpu(*buf); - spin_unlock_irqrestore(&motu->lock, flags); + scoped_guard(spinlock_irqsave, &motu->lock) { + motu->msg = be32_to_cpu(*buf); + } fw_send_response(card, request, RCODE_COMPLETE); diff --git a/sound/firewire/oxfw/oxfw-hwdep.c b/sound/firewire/oxfw/oxfw-hwdep.c index 3be214d8a922..f8ac362fc73a 100644 --- a/sound/firewire/oxfw/oxfw-hwdep.c +++ b/sound/firewire/oxfw/oxfw-hwdep.c @@ -53,18 +53,14 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait) { struct snd_oxfw *oxfw = hwdep->private_data; - __poll_t events; poll_wait(file, &oxfw->hwdep_wait, wait); - spin_lock_irq(&oxfw->lock); + guard(spinlock_irq)(&oxfw->lock); if (oxfw->dev_lock_changed) - events = EPOLLIN | EPOLLRDNORM; + return EPOLLIN | EPOLLRDNORM; else - events = 0; - spin_unlock_irq(&oxfw->lock); - - return events; + return 0; } static int hwdep_get_info(struct snd_oxfw *oxfw, void __user *arg) @@ -88,48 +84,35 @@ static int hwdep_get_info(struct snd_oxfw *oxfw, void __user *arg) static int hwdep_lock(struct snd_oxfw *oxfw) { - int err; - - spin_lock_irq(&oxfw->lock); + guard(spinlock_irq)(&oxfw->lock); if (oxfw->dev_lock_count == 0) { oxfw->dev_lock_count = -1; - err = 0; + return 0; } else { - err = -EBUSY; + return -EBUSY; } - - spin_unlock_irq(&oxfw->lock); - - return err; } static int hwdep_unlock(struct snd_oxfw *oxfw) { - int err; - - spin_lock_irq(&oxfw->lock); + guard(spinlock_irq)(&oxfw->lock); if (oxfw->dev_lock_count == -1) { oxfw->dev_lock_count = 0; - err = 0; + return 0; } else { - err = -EBADFD; + return -EBADFD; } - - spin_unlock_irq(&oxfw->lock); - - return err; } static int hwdep_release(struct snd_hwdep *hwdep, struct file *file) { struct snd_oxfw *oxfw = hwdep->private_data; - spin_lock_irq(&oxfw->lock); + guard(spinlock_irq)(&oxfw->lock); if (oxfw->dev_lock_count == -1) oxfw->dev_lock_count = 0; - spin_unlock_irq(&oxfw->lock); return 0; } diff --git a/sound/firewire/oxfw/oxfw-midi.c b/sound/firewire/oxfw/oxfw-midi.c index c215fa6f7a03..a16bf885f918 100644 --- a/sound/firewire/oxfw/oxfw-midi.c +++ b/sound/firewire/oxfw/oxfw-midi.c @@ -16,18 +16,16 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) if (err < 0) return err; - mutex_lock(&oxfw->mutex); - - err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream, 0, 0, 0, 0); - if (err >= 0) { - ++oxfw->substreams_count; - err = snd_oxfw_stream_start_duplex(oxfw); - if (err < 0) - --oxfw->substreams_count; + scoped_guard(mutex, &oxfw->mutex) { + err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream, 0, 0, 0, 0); + if (err >= 0) { + ++oxfw->substreams_count; + err = snd_oxfw_stream_start_duplex(oxfw); + if (err < 0) + --oxfw->substreams_count; + } } - mutex_unlock(&oxfw->mutex); - if (err < 0) snd_oxfw_stream_lock_release(oxfw); @@ -43,16 +41,14 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) if (err < 0) return err; - mutex_lock(&oxfw->mutex); - - err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream, 0, 0, 0, 0); - if (err >= 0) { - ++oxfw->substreams_count; - err = snd_oxfw_stream_start_duplex(oxfw); + scoped_guard(mutex, &oxfw->mutex) { + err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream, 0, 0, 0, 0); + if (err >= 0) { + ++oxfw->substreams_count; + err = snd_oxfw_stream_start_duplex(oxfw); + } } - mutex_unlock(&oxfw->mutex); - if (err < 0) snd_oxfw_stream_lock_release(oxfw); @@ -63,12 +59,10 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream) { struct snd_oxfw *oxfw = substream->rmidi->private_data; - mutex_lock(&oxfw->mutex); - - --oxfw->substreams_count; - snd_oxfw_stream_stop_duplex(oxfw); - - mutex_unlock(&oxfw->mutex); + scoped_guard(mutex, &oxfw->mutex) { + --oxfw->substreams_count; + snd_oxfw_stream_stop_duplex(oxfw); + } snd_oxfw_stream_lock_release(oxfw); return 0; @@ -78,12 +72,10 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream) { struct snd_oxfw *oxfw = substream->rmidi->private_data; - mutex_lock(&oxfw->mutex); - - --oxfw->substreams_count; - snd_oxfw_stream_stop_duplex(oxfw); - - mutex_unlock(&oxfw->mutex); + scoped_guard(mutex, &oxfw->mutex) { + --oxfw->substreams_count; + snd_oxfw_stream_stop_duplex(oxfw); + } snd_oxfw_stream_lock_release(oxfw); return 0; @@ -92,9 +84,8 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream) static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) { struct snd_oxfw *oxfw = substrm->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&oxfw->lock, flags); + guard(spinlock_irqsave)(&oxfw->lock); if (up) amdtp_am824_midi_trigger(&oxfw->tx_stream, @@ -102,16 +93,13 @@ static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) else amdtp_am824_midi_trigger(&oxfw->tx_stream, substrm->number, NULL); - - spin_unlock_irqrestore(&oxfw->lock, flags); } static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) { struct snd_oxfw *oxfw = substrm->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&oxfw->lock, flags); + guard(spinlock_irqsave)(&oxfw->lock); if (up) amdtp_am824_midi_trigger(&oxfw->rx_stream, @@ -119,8 +107,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) else amdtp_am824_midi_trigger(&oxfw->rx_stream, substrm->number, NULL); - - spin_unlock_irqrestore(&oxfw->lock, flags); } static void set_midi_substream_names(struct snd_oxfw *oxfw, diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index e13dc817fc28..774b8a763795 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c @@ -181,42 +181,34 @@ static int pcm_open(struct snd_pcm_substream *substream) if (err < 0) goto err_locked; - mutex_lock(&oxfw->mutex); - - // When source of clock is not internal or any stream is reserved for - // transmission of PCM frames, the available sampling rate is limited - // at current one. - if (oxfw->substreams_count > 0 && d->events_per_period > 0) { - unsigned int frames_per_period = d->events_per_period; - unsigned int frames_per_buffer = d->events_per_buffer; - - err = limit_to_current_params(substream); - if (err < 0) { - mutex_unlock(&oxfw->mutex); - goto err_locked; - } - - if (frames_per_period > 0) { - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - frames_per_period, frames_per_period); - if (err < 0) { - mutex_unlock(&oxfw->mutex); + scoped_guard(mutex, &oxfw->mutex) { + // When source of clock is not internal or any stream is reserved for + // transmission of PCM frames, the available sampling rate is limited + // at current one. + if (oxfw->substreams_count > 0 && d->events_per_period > 0) { + unsigned int frames_per_period = d->events_per_period; + unsigned int frames_per_buffer = d->events_per_buffer; + + err = limit_to_current_params(substream); + if (err < 0) goto err_locked; - } - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - frames_per_buffer, frames_per_buffer); - if (err < 0) { - mutex_unlock(&oxfw->mutex); - goto err_locked; + if (frames_per_period > 0) { + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + frames_per_period, frames_per_period); + if (err < 0) + goto err_locked; + + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + frames_per_buffer, frames_per_buffer); + if (err < 0) + goto err_locked; } } } - mutex_unlock(&oxfw->mutex); - snd_pcm_set_sync(substream); return 0; @@ -245,13 +237,12 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); - mutex_lock(&oxfw->mutex); + guard(mutex)(&oxfw->mutex); err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream, rate, channels, frames_per_period, frames_per_buffer); if (err >= 0) ++oxfw->substreams_count; - mutex_unlock(&oxfw->mutex); } return err; @@ -268,13 +259,12 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); - mutex_lock(&oxfw->mutex); + guard(mutex)(&oxfw->mutex); err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream, rate, channels, frames_per_period, frames_per_buffer); if (err >= 0) ++oxfw->substreams_count; - mutex_unlock(&oxfw->mutex); } return err; @@ -284,30 +274,26 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream) { struct snd_oxfw *oxfw = substream->private_data; - mutex_lock(&oxfw->mutex); + guard(mutex)(&oxfw->mutex); if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --oxfw->substreams_count; snd_oxfw_stream_stop_duplex(oxfw); - mutex_unlock(&oxfw->mutex); - return 0; } static int pcm_playback_hw_free(struct snd_pcm_substream *substream) { struct snd_oxfw *oxfw = substream->private_data; - mutex_lock(&oxfw->mutex); + guard(mutex)(&oxfw->mutex); if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --oxfw->substreams_count; snd_oxfw_stream_stop_duplex(oxfw); - mutex_unlock(&oxfw->mutex); - return 0; } @@ -316,30 +302,28 @@ static int pcm_capture_prepare(struct snd_pcm_substream *substream) struct snd_oxfw *oxfw = substream->private_data; int err; - mutex_lock(&oxfw->mutex); - err = snd_oxfw_stream_start_duplex(oxfw); - mutex_unlock(&oxfw->mutex); - if (err < 0) - goto end; + scoped_guard(mutex, &oxfw->mutex) { + err = snd_oxfw_stream_start_duplex(oxfw); + if (err < 0) + return err; + } amdtp_stream_pcm_prepare(&oxfw->tx_stream); -end: - return err; + return 0; } static int pcm_playback_prepare(struct snd_pcm_substream *substream) { struct snd_oxfw *oxfw = substream->private_data; int err; - mutex_lock(&oxfw->mutex); - err = snd_oxfw_stream_start_duplex(oxfw); - mutex_unlock(&oxfw->mutex); - if (err < 0) - goto end; + scoped_guard(mutex, &oxfw->mutex) { + err = snd_oxfw_stream_start_duplex(oxfw); + if (err < 0) + return err; + } amdtp_stream_pcm_prepare(&oxfw->rx_stream); -end: - return err; + return 0; } static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 00f7feb91f92..5e36d7153a7b 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -866,33 +866,24 @@ void snd_oxfw_stream_lock_changed(struct snd_oxfw *oxfw) int snd_oxfw_stream_lock_try(struct snd_oxfw *oxfw) { - int err; - - spin_lock_irq(&oxfw->lock); + guard(spinlock_irq)(&oxfw->lock); /* user land lock this */ - if (oxfw->dev_lock_count < 0) { - err = -EBUSY; - goto end; - } + if (oxfw->dev_lock_count < 0) + return -EBUSY; /* this is the first time */ if (oxfw->dev_lock_count++ == 0) snd_oxfw_stream_lock_changed(oxfw); - err = 0; -end: - spin_unlock_irq(&oxfw->lock); - return err; + return 0; } void snd_oxfw_stream_lock_release(struct snd_oxfw *oxfw) { - spin_lock_irq(&oxfw->lock); + guard(spinlock_irq)(&oxfw->lock); if (WARN_ON(oxfw->dev_lock_count <= 0)) - goto end; + return; if (--oxfw->dev_lock_count == 0) snd_oxfw_stream_lock_changed(oxfw); -end: - spin_unlock_irq(&oxfw->lock); } diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c index 7a985f3cb8f6..5039bd79b18e 100644 --- a/sound/firewire/oxfw/oxfw.c +++ b/sound/firewire/oxfw/oxfw.c @@ -283,9 +283,8 @@ static void oxfw_bus_reset(struct fw_unit *unit) fcp_bus_reset(oxfw->unit); if (oxfw->has_output || oxfw->has_input) { - mutex_lock(&oxfw->mutex); + guard(mutex)(&oxfw->mutex); snd_oxfw_stream_update_duplex(oxfw); - mutex_unlock(&oxfw->mutex); } if (oxfw->quirks & SND_OXFW_QUIRK_SCS_TRANSACTION) diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 079afa4bd381..59c339d9b5fb 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -157,15 +157,14 @@ static void read_status_messages(struct amdtp_stream *s, if ((before ^ after) & mask) { struct snd_firewire_tascam_change *entry = &tscm->queue[tscm->push_pos]; - unsigned long flag; - - spin_lock_irqsave(&tscm->lock, flag); - entry->index = index; - entry->before = before; - entry->after = after; - if (++tscm->push_pos >= SND_TSCM_QUEUE_COUNT) - tscm->push_pos = 0; - spin_unlock_irqrestore(&tscm->lock, flag); + + scoped_guard(spinlock_irqsave, &tscm->lock) { + entry->index = index; + entry->before = before; + entry->after = after; + if (++tscm->push_pos >= SND_TSCM_QUEUE_COUNT) + tscm->push_pos = 0; + } wake_up(&tscm->hwdep_wait); } diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index 8fc30cba29d5..867b4ea1096e 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -130,18 +130,14 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait) { struct snd_tscm *tscm = hwdep->private_data; - __poll_t events; poll_wait(file, &tscm->hwdep_wait, wait); - spin_lock_irq(&tscm->lock); + guard(spinlock_irq)(&tscm->lock); if (tscm->dev_lock_changed || tscm->push_pos != tscm->pull_pos) - events = EPOLLIN | EPOLLRDNORM; + return EPOLLIN | EPOLLRDNORM; else - events = 0; - spin_unlock_irq(&tscm->lock); - - return events; + return 0; } static int hwdep_get_info(struct snd_tscm *tscm, void __user *arg) @@ -165,38 +161,26 @@ static int hwdep_get_info(struct snd_tscm *tscm, void __user *arg) static int hwdep_lock(struct snd_tscm *tscm) { - int err; - - spin_lock_irq(&tscm->lock); + guard(spinlock_irq)(&tscm->lock); if (tscm->dev_lock_count == 0) { tscm->dev_lock_count = -1; - err = 0; + return 0; } else { - err = -EBUSY; + return -EBUSY; } - - spin_unlock_irq(&tscm->lock); - - return err; } static int hwdep_unlock(struct snd_tscm *tscm) { - int err; - - spin_lock_irq(&tscm->lock); + guard(spinlock_irq)(&tscm->lock); if (tscm->dev_lock_count == -1) { tscm->dev_lock_count = 0; - err = 0; + return 0; } else { - err = -EBADFD; + return -EBADFD; } - - spin_unlock_irq(&tscm->lock); - - return err; } static int tscm_hwdep_state(struct snd_tscm *tscm, void __user *arg) @@ -211,10 +195,9 @@ static int hwdep_release(struct snd_hwdep *hwdep, struct file *file) { struct snd_tscm *tscm = hwdep->private_data; - spin_lock_irq(&tscm->lock); + guard(spinlock_irq)(&tscm->lock); if (tscm->dev_lock_count == -1) tscm->dev_lock_count = 0; - spin_unlock_irq(&tscm->lock); return 0; } diff --git a/sound/firewire/tascam/tascam-midi.c b/sound/firewire/tascam/tascam-midi.c index c57fac4f1968..1bf9d7b3da33 100644 --- a/sound/firewire/tascam/tascam-midi.c +++ b/sound/firewire/tascam/tascam-midi.c @@ -43,30 +43,24 @@ static void midi_playback_drain(struct snd_rawmidi_substream *substream) static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) { struct snd_tscm *tscm = substrm->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&tscm->lock, flags); + guard(spinlock_irqsave)(&tscm->lock); if (up) tscm->tx_midi_substreams[substrm->number] = substrm; else tscm->tx_midi_substreams[substrm->number] = NULL; - - spin_unlock_irqrestore(&tscm->lock, flags); } static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) { struct snd_tscm *tscm = substrm->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&tscm->lock, flags); + guard(spinlock_irqsave)(&tscm->lock); if (up) snd_fw_async_midi_port_run(&tscm->out_ports[substrm->number], substrm); - - spin_unlock_irqrestore(&tscm->lock, flags); } int snd_tscm_create_midi_devices(struct snd_tscm *tscm) diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c index a73003ac11e6..d885fef0c8ca 100644 --- a/sound/firewire/tascam/tascam-pcm.c +++ b/sound/firewire/tascam/tascam-pcm.c @@ -59,43 +59,35 @@ static int pcm_open(struct snd_pcm_substream *substream) if (err < 0) goto err_locked; - mutex_lock(&tscm->mutex); - - // When source of clock is not internal or any stream is reserved for - // transmission of PCM frames, the available sampling rate is limited - // at current one. - if (clock != SND_TSCM_CLOCK_INTERNAL || tscm->substreams_counter > 0) { - unsigned int frames_per_period = d->events_per_period; - unsigned int frames_per_buffer = d->events_per_buffer; - unsigned int rate; - - err = snd_tscm_stream_get_rate(tscm, &rate); - if (err < 0) { - mutex_unlock(&tscm->mutex); - goto err_locked; - } - substream->runtime->hw.rate_min = rate; - substream->runtime->hw.rate_max = rate; - - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - frames_per_period, frames_per_period); - if (err < 0) { - mutex_unlock(&tscm->mutex); - goto err_locked; - } - - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - frames_per_buffer, frames_per_buffer); - if (err < 0) { - mutex_unlock(&tscm->mutex); - goto err_locked; + scoped_guard(mutex, &tscm->mutex) { + // When source of clock is not internal or any stream is reserved for + // transmission of PCM frames, the available sampling rate is limited + // at current one. + if (clock != SND_TSCM_CLOCK_INTERNAL || tscm->substreams_counter > 0) { + unsigned int frames_per_period = d->events_per_period; + unsigned int frames_per_buffer = d->events_per_buffer; + unsigned int rate; + + err = snd_tscm_stream_get_rate(tscm, &rate); + if (err < 0) + goto err_locked; + substream->runtime->hw.rate_min = rate; + substream->runtime->hw.rate_max = rate; + + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + frames_per_period, frames_per_period); + if (err < 0) + goto err_locked; + + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + frames_per_buffer, frames_per_buffer); + if (err < 0) + goto err_locked; } } - mutex_unlock(&tscm->mutex); - snd_pcm_set_sync(substream); return 0; @@ -124,12 +116,11 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); - mutex_lock(&tscm->mutex); + guard(mutex)(&tscm->mutex); err = snd_tscm_stream_reserve_duplex(tscm, rate, frames_per_period, frames_per_buffer); if (err >= 0) ++tscm->substreams_counter; - mutex_unlock(&tscm->mutex); } return err; @@ -139,15 +130,13 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_tscm *tscm = substream->private_data; - mutex_lock(&tscm->mutex); + guard(mutex)(&tscm->mutex); if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --tscm->substreams_counter; snd_tscm_stream_stop_duplex(tscm); - mutex_unlock(&tscm->mutex); - return 0; } @@ -157,14 +146,12 @@ static int pcm_capture_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - mutex_lock(&tscm->mutex); + guard(mutex)(&tscm->mutex); err = snd_tscm_stream_start_duplex(tscm, runtime->rate); if (err >= 0) amdtp_stream_pcm_prepare(&tscm->tx_stream); - mutex_unlock(&tscm->mutex); - return err; } @@ -174,14 +161,12 @@ static int pcm_playback_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - mutex_lock(&tscm->mutex); + guard(mutex)(&tscm->mutex); err = snd_tscm_stream_start_duplex(tscm, runtime->rate); if (err >= 0) amdtp_stream_pcm_prepare(&tscm->rx_stream); - mutex_unlock(&tscm->mutex); - return err; } diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index dfe783d01d7d..9c8fddd7dee1 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -527,33 +527,24 @@ void snd_tscm_stream_lock_changed(struct snd_tscm *tscm) int snd_tscm_stream_lock_try(struct snd_tscm *tscm) { - int err; - - spin_lock_irq(&tscm->lock); + guard(spinlock_irq)(&tscm->lock); /* user land lock this */ - if (tscm->dev_lock_count < 0) { - err = -EBUSY; - goto end; - } + if (tscm->dev_lock_count < 0) + return -EBUSY; /* this is the first time */ if (tscm->dev_lock_count++ == 0) snd_tscm_stream_lock_changed(tscm); - err = 0; -end: - spin_unlock_irq(&tscm->lock); - return err; + return 0; } void snd_tscm_stream_lock_release(struct snd_tscm *tscm) { - spin_lock_irq(&tscm->lock); + guard(spinlock_irq)(&tscm->lock); if (WARN_ON(tscm->dev_lock_count <= 0)) - goto end; + return; if (--tscm->dev_lock_count == 0) snd_tscm_stream_lock_changed(tscm); -end: - spin_unlock_irq(&tscm->lock); } diff --git a/sound/firewire/tascam/tascam.c b/sound/firewire/tascam/tascam.c index 4f68bb4c58bc..f4092df8650c 100644 --- a/sound/firewire/tascam/tascam.c +++ b/sound/firewire/tascam/tascam.c @@ -158,9 +158,8 @@ static void snd_tscm_update(struct fw_unit *unit) snd_tscm_transaction_reregister(tscm); - mutex_lock(&tscm->mutex); + guard(mutex)(&tscm->mutex); snd_tscm_stream_update_duplex(tscm); - mutex_unlock(&tscm->mutex); } static void snd_tscm_remove(struct fw_unit *unit) diff --git a/sound/hda/codecs/analog.c b/sound/hda/codecs/analog.c index 33aaeb44c4dc..357ad5a6c0db 100644 --- a/sound/hda/codecs/analog.c +++ b/sound/hda/codecs/analog.c @@ -727,7 +727,7 @@ static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol, if (spec->cur_smux == val) return 0; - mutex_lock(&codec->control_mutex); + guard(mutex)(&codec->control_mutex); path = snd_hda_get_path_from_idx(codec, spec->smux_paths[spec->cur_smux]); if (path) @@ -736,7 +736,6 @@ static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol, if (path) snd_hda_activate_path(codec, path, true, true); spec->cur_smux = val; - mutex_unlock(&codec->control_mutex); return 1; } diff --git a/sound/hda/codecs/ca0132.c b/sound/hda/codecs/ca0132.c index b7d456e16c93..dd054aedd501 100644 --- a/sound/hda/codecs/ca0132.c +++ b/sound/hda/codecs/ca0132.c @@ -1684,20 +1684,14 @@ static int chipio_write(struct hda_codec *codec, struct ca0132_spec *spec = codec->spec; int err; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); /* write the address, and if successful proceed to write data */ err = chipio_write_address(codec, chip_addx); if (err < 0) - goto exit; - - err = chipio_write_data(codec, data); - if (err < 0) - goto exit; + return err; -exit: - mutex_unlock(&spec->chipio_mutex); - return err; + return chipio_write_data(codec, data); } /* @@ -1735,16 +1729,12 @@ static int chipio_write_multiple(struct hda_codec *codec, struct ca0132_spec *spec = codec->spec; int status; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); status = chipio_write_address(codec, chip_addx); if (status < 0) - goto error; - - status = chipio_write_data_multiple(codec, data, count); -error: - mutex_unlock(&spec->chipio_mutex); + return status; - return status; + return chipio_write_data_multiple(codec, data, count); } /* @@ -1757,20 +1747,14 @@ static int chipio_read(struct hda_codec *codec, struct ca0132_spec *spec = codec->spec; int err; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); /* write the address, and if successful proceed to write data */ err = chipio_write_address(codec, chip_addx); if (err < 0) - goto exit; - - err = chipio_read_data(codec, data); - if (err < 0) - goto exit; + return err; -exit: - mutex_unlock(&spec->chipio_mutex); - return err; + return chipio_read_data(codec, data); } /* @@ -1803,7 +1787,7 @@ static void chipio_set_control_param(struct hda_codec *codec, snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, VENDOR_CHIPIO_PARAM_SET, val); } else { - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); if (chipio_send(codec, VENDOR_CHIPIO_STATUS, 0) == 0) { snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, VENDOR_CHIPIO_PARAM_EX_ID_SET, @@ -1812,7 +1796,6 @@ static void chipio_set_control_param(struct hda_codec *codec, VENDOR_CHIPIO_PARAM_EX_VALUE_SET, param_val); } - mutex_unlock(&spec->chipio_mutex); } } @@ -1977,12 +1960,10 @@ static void chipio_8051_write_exram(struct hda_codec *codec, { struct ca0132_spec *spec = codec->spec; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); chipio_8051_set_address(codec, addr); chipio_8051_set_data(codec, data); - - mutex_unlock(&spec->chipio_mutex); } static void chipio_8051_write_exram_no_mutex(struct hda_codec *codec, @@ -2005,12 +1986,10 @@ static void chipio_8051_write_pll_pmu(struct hda_codec *codec, { struct ca0132_spec *spec = codec->spec; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); chipio_8051_set_address(codec, addr & 0xff); chipio_8051_set_data_pll(codec, data); - - mutex_unlock(&spec->chipio_mutex); } static void chipio_8051_write_pll_pmu_no_mutex(struct hda_codec *codec, @@ -2027,13 +2006,11 @@ static void chipio_enable_clocks(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); chipio_8051_write_pll_pmu_no_mutex(codec, 0x00, 0xff); chipio_8051_write_pll_pmu_no_mutex(codec, 0x05, 0x0b); chipio_8051_write_pll_pmu_no_mutex(codec, 0x06, 0xff); - - mutex_unlock(&spec->chipio_mutex); } /* @@ -2084,22 +2061,20 @@ static int dspio_write(struct hda_codec *codec, unsigned int scp_data) dspio_write_wait(codec); - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); status = dspio_send(codec, VENDOR_DSPIO_SCP_WRITE_DATA_LOW, scp_data & 0xffff); if (status < 0) - goto error; + return status; status = dspio_send(codec, VENDOR_DSPIO_SCP_WRITE_DATA_HIGH, scp_data >> 16); if (status < 0) - goto error; + return status; /* OK, now check if the write itself has executed*/ status = snd_hda_codec_read(codec, WIDGET_DSP_CTRL, 0, VENDOR_DSPIO_STATUS, 0); -error: - mutex_unlock(&spec->chipio_mutex); return (status == VENDOR_STATUS_DSPIO_SCP_COMMAND_QUEUE_FULL) ? -EIO : 0; @@ -4236,21 +4211,19 @@ static const unsigned int equalizer_vals_lookup[] = { static int tuning_ctl_set(struct hda_codec *codec, hda_nid_t nid, const unsigned int *lookup, int idx) { - int i = 0; + int i; - for (i = 0; i < TUNING_CTLS_COUNT; i++) - if (nid == ca0132_tuning_ctls[i].nid) - goto found; + for (i = 0; i < TUNING_CTLS_COUNT; i++) { + if (nid == ca0132_tuning_ctls[i].nid) { + CLASS(snd_hda_power, pm)(codec); + dspio_set_param(codec, ca0132_tuning_ctls[i].mid, 0x20, + ca0132_tuning_ctls[i].req, + &(lookup[idx]), sizeof(unsigned int)); + return 1; + } + } return -EINVAL; -found: - snd_hda_power_up(codec); - dspio_set_param(codec, ca0132_tuning_ctls[i].mid, 0x20, - ca0132_tuning_ctls[i].req, - &(lookup[idx]), sizeof(unsigned int)); - snd_hda_power_down(codec); - - return 1; } static int tuning_ctl_get(struct snd_kcontrol *kcontrol, @@ -4465,7 +4438,7 @@ static int ca0132_select_out(struct hda_codec *codec) codec_dbg(codec, "ca0132_select_out\n"); - snd_hda_power_up_pm(codec); + CLASS(snd_hda_power_pm, pm)(codec); auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID]; @@ -4486,12 +4459,12 @@ static int ca0132_select_out(struct hda_codec *codec) tmp = FLOAT_ONE; err = dspio_set_uint_param(codec, 0x80, 0x04, tmp); if (err < 0) - goto exit; + return err; /*enable speaker EQ*/ tmp = FLOAT_ONE; err = dspio_set_uint_param(codec, 0x8f, 0x00, tmp); if (err < 0) - goto exit; + return err; /* Setup EAPD */ snd_hda_codec_write(codec, spec->out_pins[1], 0, @@ -4519,12 +4492,12 @@ static int ca0132_select_out(struct hda_codec *codec) tmp = FLOAT_ZERO; err = dspio_set_uint_param(codec, 0x80, 0x04, tmp); if (err < 0) - goto exit; + return err; /*disable speaker EQ*/ tmp = FLOAT_ZERO; err = dspio_set_uint_param(codec, 0x8f, 0x00, tmp); if (err < 0) - goto exit; + return err; /* Setup EAPD */ snd_hda_codec_write(codec, spec->out_pins[0], 0, @@ -4548,10 +4521,7 @@ static int ca0132_select_out(struct hda_codec *codec) pin_ctl | PIN_HP); } -exit: - snd_hda_power_down_pm(codec); - - return err < 0 ? err : 0; + return 0; } static int ae5_headphone_gain_set(struct hda_codec *codec, long val); @@ -4775,7 +4745,7 @@ static int ca0132_alt_select_out(struct hda_codec *codec) codec_dbg(codec, "%s\n", __func__); - snd_hda_power_up_pm(codec); + CLASS(snd_hda_power_pm, pm)(codec); auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID]; @@ -4800,11 +4770,11 @@ static int ca0132_alt_select_out(struct hda_codec *codec) /* Begin DSP output switch, mute DSP volume. */ err = dspio_set_uint_param(codec, 0x96, SPEAKER_TUNING_MUTE, FLOAT_ONE); if (err < 0) - goto exit; + return err; err = ca0132_alt_select_out_quirk_set(codec); if (err < 0) - goto exit; + return err; switch (spec->cur_out_type) { case SPEAKER_OUT: @@ -4835,7 +4805,7 @@ static int ca0132_alt_select_out(struct hda_codec *codec) err = dspio_set_uint_param(codec, 0x80, 0x04, tmp); if (err < 0) - goto exit; + return err; break; case HEADPHONE_OUT: @@ -4862,7 +4832,7 @@ static int ca0132_alt_select_out(struct hda_codec *codec) err = dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ZERO); if (err < 0) - goto exit; + return err; break; } /* @@ -4877,7 +4847,7 @@ static int ca0132_alt_select_out(struct hda_codec *codec) /* Set speaker EQ bypass attenuation to 0. */ err = dspio_set_uint_param(codec, 0x8f, 0x01, FLOAT_ZERO); if (err < 0) - goto exit; + return err; /* * Although unused on all cards but the AE series, this is always set @@ -4886,7 +4856,7 @@ static int ca0132_alt_select_out(struct hda_codec *codec) err = dspio_set_uint_param(codec, 0x96, SPEAKER_TUNING_USE_SPEAKER_EQ, FLOAT_ZERO); if (err < 0) - goto exit; + return err; if (spec->cur_out_type == SPEAKER_OUT) err = ca0132_alt_surround_set_bass_redirection(codec, @@ -4894,24 +4864,21 @@ static int ca0132_alt_select_out(struct hda_codec *codec) else err = ca0132_alt_surround_set_bass_redirection(codec, 0); if (err < 0) - goto exit; + return err; /* Unmute DSP now that we're done with output selection. */ err = dspio_set_uint_param(codec, 0x96, SPEAKER_TUNING_MUTE, FLOAT_ZERO); if (err < 0) - goto exit; + return err; if (spec->cur_out_type == SPEAKER_OUT) { err = ca0132_alt_set_full_range_speaker(codec); if (err < 0) - goto exit; + return err; } -exit: - snd_hda_power_down_pm(codec); - - return err < 0 ? err : 0; + return 0; } static void ca0132_unsol_hp_delayed(struct work_struct *work) @@ -5059,7 +5026,7 @@ static int ca0132_select_mic(struct hda_codec *codec) codec_dbg(codec, "ca0132_select_mic\n"); - snd_hda_power_up_pm(codec); + CLASS(snd_hda_power_pm, pm)(codec); auto_jack = spec->vnode_lswitch[VNID_AMIC1_ASEL - VNODE_START_NID]; @@ -5092,8 +5059,6 @@ static int ca0132_select_mic(struct hda_codec *codec) ca0132_effects_set(codec, VOICE_FOCUS, 0); } - snd_hda_power_down_pm(codec); - return 0; } @@ -5110,7 +5075,7 @@ static int ca0132_alt_select_in(struct hda_codec *codec) codec_dbg(codec, "%s\n", __func__); - snd_hda_power_up_pm(codec); + CLASS(snd_hda_power_pm, pm)(codec); chipio_set_stream_control(codec, 0x03, 0); chipio_set_stream_control(codec, 0x04, 0); @@ -5273,7 +5238,6 @@ static int ca0132_alt_select_in(struct hda_codec *codec) } ca0132_cvoice_switch_set(codec); - snd_hda_power_down_pm(codec); return 0; } @@ -5595,13 +5559,12 @@ static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol, int ch = get_amp_channels(kcontrol); unsigned long pval; - mutex_lock(&codec->control_mutex); + guard(mutex)(&codec->control_mutex); pval = kcontrol->private_value; kcontrol->private_value = HDA_COMPOSE_AMP_VAL(shared_nid, ch, 0, dir); ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); } return ret; @@ -5611,12 +5574,10 @@ static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol, static void ca0132_alt_bass_redirection_xover_set(struct hda_codec *codec, long idx) { - snd_hda_power_up(codec); + CLASS(snd_hda_power, pm)(codec); dspio_set_param(codec, 0x96, 0x20, SPEAKER_BASS_REDIRECT_XOVER_FREQ, &(float_xbass_xover_lookup[idx]), sizeof(unsigned int)); - - snd_hda_power_down(codec); } /* @@ -5642,7 +5603,7 @@ static int ca0132_alt_slider_ctl_set(struct hda_codec *codec, hda_nid_t nid, else y = 1; - snd_hda_power_up(codec); + CLASS(snd_hda_power, pm)(codec); if (nid == XBASS_XOVER) { for (i = 0; i < OUT_EFFECTS_COUNT; i++) if (ca0132_effects[i].nid == X_BASS) @@ -5662,8 +5623,6 @@ static int ca0132_alt_slider_ctl_set(struct hda_codec *codec, hda_nid_t nid, &(lookup[idx]), sizeof(unsigned int)); } - snd_hda_power_down(codec); - return 0; } @@ -6342,12 +6301,11 @@ static int ca0132_switch_put(struct snd_kcontrol *kcontrol, hda_nid_t nid = get_amp_nid(kcontrol); int ch = get_amp_channels(kcontrol); long *valp = ucontrol->value.integer.value; - int changed = 1; codec_dbg(codec, "ca0132_switch_put: nid=0x%x, val=%ld\n", nid, *valp); - snd_hda_power_up(codec); + CLASS(snd_hda_power, pm)(codec); /* vnode */ if ((nid >= VNODE_START_NID) && (nid < VNODE_END_NID)) { if (ch & 1) { @@ -6358,30 +6316,26 @@ static int ca0132_switch_put(struct snd_kcontrol *kcontrol, spec->vnode_rswitch[nid - VNODE_START_NID] = *valp; valp++; } - changed = ca0132_vnode_switch_set(kcontrol, ucontrol); - goto exit; + return ca0132_vnode_switch_set(kcontrol, ucontrol); } /* PE */ if (nid == PLAY_ENHANCEMENT) { spec->effects_switch[nid - EFFECT_START_NID] = *valp; - changed = ca0132_pe_switch_set(codec); - goto exit; + return ca0132_pe_switch_set(codec); } /* CrystalVoice */ if (nid == CRYSTAL_VOICE) { spec->effects_switch[nid - EFFECT_START_NID] = *valp; - changed = ca0132_cvoice_switch_set(codec); - goto exit; + return ca0132_cvoice_switch_set(codec); } /* out and in effects */ if (((nid >= OUT_EFFECT_START_NID) && (nid < OUT_EFFECT_END_NID)) || ((nid >= IN_EFFECT_START_NID) && (nid < IN_EFFECT_END_NID))) { spec->effects_switch[nid - EFFECT_START_NID] = *valp; - changed = ca0132_effects_set(codec, nid, *valp); - goto exit; + return ca0132_effects_set(codec, nid, *valp); } /* mic boost */ @@ -6389,24 +6343,22 @@ static int ca0132_switch_put(struct snd_kcontrol *kcontrol, spec->cur_mic_boost = *valp; if (ca0132_use_alt_functions(spec)) { if (spec->in_enum_val != REAR_LINE_IN) - changed = ca0132_mic_boost_set(codec, *valp); + return ca0132_mic_boost_set(codec, *valp); } else { /* Mic boost does not apply to Digital Mic */ if (spec->cur_mic_type != DIGITAL_MIC) - changed = ca0132_mic_boost_set(codec, *valp); + return ca0132_mic_boost_set(codec, *valp); } - goto exit; + return 1; } if (nid == ZXR_HEADPHONE_GAIN) { spec->zxr_gain_set = *valp; if (spec->cur_out_type == HEADPHONE_OUT) - changed = zxr_headphone_gain_set(codec, *valp); + return zxr_headphone_gain_set(codec, *valp); else - changed = 0; - - goto exit; + return 0; } if (nid == SPEAKER_FULL_RANGE_FRONT || nid == SPEAKER_FULL_RANGE_REAR) { @@ -6414,7 +6366,7 @@ static int ca0132_switch_put(struct snd_kcontrol *kcontrol, if (spec->cur_out_type == SPEAKER_OUT) ca0132_alt_set_full_range_speaker(codec); - changed = 0; + return 0; } if (nid == BASS_REDIRECTION) { @@ -6422,12 +6374,10 @@ static int ca0132_switch_put(struct snd_kcontrol *kcontrol, if (spec->cur_out_type == SPEAKER_OUT) ca0132_alt_surround_set_bass_redirection(codec, *valp); - changed = 0; + return 0; } -exit: - snd_hda_power_down(codec); - return changed; + return 1; } /* @@ -6483,22 +6433,22 @@ static int ca0132_volume_info(struct snd_kcontrol *kcontrol, case VNID_SPK: /* follow shared_out info */ nid = spec->shared_out_nid; - mutex_lock(&codec->control_mutex); - pval = kcontrol->private_value; - kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir); - err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo); - kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); + scoped_guard(mutex, &codec->control_mutex) { + pval = kcontrol->private_value; + kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir); + err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo); + kcontrol->private_value = pval; + } break; case VNID_MIC: /* follow shared_mic info */ nid = spec->shared_mic_nid; - mutex_lock(&codec->control_mutex); - pval = kcontrol->private_value; - kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir); - err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo); - kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); + scoped_guard(mutex, &codec->control_mutex) { + pval = kcontrol->private_value; + kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir); + err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo); + kcontrol->private_value = pval; + } break; default: err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo); @@ -6555,15 +6505,13 @@ static int ca0132_volume_put(struct snd_kcontrol *kcontrol, int dir = get_amp_direction(kcontrol); unsigned long pval; - snd_hda_power_up(codec); - mutex_lock(&codec->control_mutex); + CLASS(snd_hda_power, pm)(codec); + guard(mutex)(&codec->control_mutex); pval = kcontrol->private_value; kcontrol->private_value = HDA_COMPOSE_AMP_VAL(shared_nid, ch, 0, dir); changed = snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); - snd_hda_power_down(codec); } return changed; @@ -6583,7 +6531,6 @@ static int ca0132_alt_volume_put(struct snd_kcontrol *kcontrol, int ch = get_amp_channels(kcontrol); long *valp = ucontrol->value.integer.value; hda_nid_t vnid = 0; - int changed; switch (nid) { case 0x02: @@ -6604,14 +6551,10 @@ static int ca0132_alt_volume_put(struct snd_kcontrol *kcontrol, valp++; } - snd_hda_power_up(codec); + CLASS(snd_hda_power, pm)(codec); ca0132_alt_dsp_volume_put(codec, vnid); - mutex_lock(&codec->control_mutex); - changed = snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); - mutex_unlock(&codec->control_mutex); - snd_hda_power_down(codec); - - return changed; + guard(mutex)(&codec->control_mutex); + return snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); } static int ca0132_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag, @@ -6629,22 +6572,22 @@ static int ca0132_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag, case VNID_SPK: /* follow shared_out tlv */ nid = spec->shared_out_nid; - mutex_lock(&codec->control_mutex); - pval = kcontrol->private_value; - kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir); - err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv); - kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); + scoped_guard(mutex, &codec->control_mutex) { + pval = kcontrol->private_value; + kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir); + err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv); + kcontrol->private_value = pval; + } break; case VNID_MIC: /* follow shared_mic tlv */ nid = spec->shared_mic_nid; - mutex_lock(&codec->control_mutex); - pval = kcontrol->private_value; - kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir); - err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv); - kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); + scoped_guard(mutex, &codec->control_mutex) { + pval = kcontrol->private_value; + kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir); + err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv); + kcontrol->private_value = pval; + } break; default: err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv); @@ -7526,12 +7469,10 @@ static void ca0132_init_analog_mic2(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); chipio_8051_write_exram_no_mutex(codec, 0x1920, 0x00); chipio_8051_write_exram_no_mutex(codec, 0x192d, 0x00); - - mutex_unlock(&spec->chipio_mutex); } static void ca0132_refresh_widget_caps(struct hda_codec *codec) @@ -7621,19 +7562,17 @@ static void ca0132_alt_start_dsp_audio_streams(struct hda_codec *codec) * Check if any of the default streams are active, and if they are, * stop them. */ - mutex_lock(&spec->chipio_mutex); - - for (i = 0; i < ARRAY_SIZE(dsp_dma_stream_ids); i++) { - chipio_get_stream_control(codec, dsp_dma_stream_ids[i], &tmp); + scoped_guard(mutex, &spec->chipio_mutex) { + for (i = 0; i < ARRAY_SIZE(dsp_dma_stream_ids); i++) { + chipio_get_stream_control(codec, dsp_dma_stream_ids[i], &tmp); - if (tmp) { - chipio_set_stream_control(codec, - dsp_dma_stream_ids[i], 0); + if (tmp) { + chipio_set_stream_control(codec, + dsp_dma_stream_ids[i], 0); + } } } - mutex_unlock(&spec->chipio_mutex); - /* * If all DSP streams are inactive, there should be no active DSP DMA * channels. Check and make sure this is the case, and if it isn't, @@ -7641,7 +7580,7 @@ static void ca0132_alt_start_dsp_audio_streams(struct hda_codec *codec) */ ca0132_alt_free_active_dma_channels(codec); - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); /* Make sure stream 0x0c is six channels. */ chipio_set_stream_channels(codec, 0x0c, 6); @@ -7653,8 +7592,6 @@ static void ca0132_alt_start_dsp_audio_streams(struct hda_codec *codec) /* Give the DSP some time to setup the DMA channel. */ msleep(75); } - - mutex_unlock(&spec->chipio_mutex); } /* @@ -7846,7 +7783,7 @@ static void sbz_connect_streams(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); codec_dbg(codec, "Connect Streams entered, mutex locked and loaded.\n"); @@ -7861,8 +7798,6 @@ static void sbz_connect_streams(struct hda_codec *codec) chipio_set_stream_control(codec, 0x14, 1); codec_dbg(codec, "Connect Streams exited, mutex released.\n"); - - mutex_unlock(&spec->chipio_mutex); } /* @@ -7876,7 +7811,7 @@ static void sbz_chipio_startup_data(struct hda_codec *codec) const struct chipio_stream_remap_data *dsp_out_remap_data; struct ca0132_spec *spec = codec->spec; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); codec_dbg(codec, "Startup Data entered, mutex locked and loaded.\n"); /* Remap DAC0's output ports. */ @@ -7901,7 +7836,6 @@ static void sbz_chipio_startup_data(struct hda_codec *codec) chipio_remap_stream(codec, dsp_out_remap_data); codec_dbg(codec, "Startup Data exited, mutex released.\n"); - mutex_unlock(&spec->chipio_mutex); } static void ca0132_alt_dsp_initial_mic_setup(struct hda_codec *codec) @@ -7993,7 +7927,7 @@ static void ae5_post_dsp_stream_setup(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x81); @@ -8011,15 +7945,13 @@ static void ae5_post_dsp_stream_setup(struct hda_codec *codec) chipio_8051_write_pll_pmu_no_mutex(codec, 0x43, 0xc7); ca0113_mmio_command_set(codec, 0x48, 0x01, 0x80); - - mutex_unlock(&spec->chipio_mutex); } static void ae5_post_dsp_startup_data(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); chipio_write_no_mutex(codec, 0x189000, 0x0001f101); chipio_write_no_mutex(codec, 0x189004, 0x0001f101); @@ -8043,15 +7975,13 @@ static void ae5_post_dsp_startup_data(struct hda_codec *codec) ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00); ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00); - - mutex_unlock(&spec->chipio_mutex); } static void ae7_post_dsp_setup_ports(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); /* Seems to share the same port remapping as the SBZ. */ chipio_remap_stream(codec, &stream_remap_data[1]); @@ -8064,15 +7994,13 @@ static void ae7_post_dsp_setup_ports(struct hda_codec *codec) ca0113_mmio_command_set(codec, 0x48, 0x12, 0xff); ca0113_mmio_command_set(codec, 0x48, 0x13, 0xff); ca0113_mmio_command_set(codec, 0x48, 0x14, 0x7f); - - mutex_unlock(&spec->chipio_mutex); } static void ae7_post_dsp_asi_stream_setup(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x81); ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00); @@ -8087,8 +8015,6 @@ static void ae7_post_dsp_asi_stream_setup(struct hda_codec *codec) chipio_set_stream_control(codec, 0x18, 1); chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 4); - - mutex_unlock(&spec->chipio_mutex); } static void ae7_post_dsp_pll_setup(struct hda_codec *codec) @@ -8116,7 +8042,7 @@ static void ae7_post_dsp_asi_setup_ports(struct hda_codec *codec) }; unsigned int i; - mutex_lock(&spec->chipio_mutex); + guard(mutex)(&spec->chipio_mutex); chipio_8051_write_pll_pmu_no_mutex(codec, 0x43, 0xc7); @@ -8178,8 +8104,6 @@ static void ae7_post_dsp_asi_setup_ports(struct hda_codec *codec) */ ae7_post_dsp_pll_setup(codec); chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7); - - mutex_unlock(&spec->chipio_mutex); } /* @@ -8664,14 +8588,13 @@ static void ca0132_process_dsp_response(struct hda_codec *codec, struct ca0132_spec *spec = codec->spec; codec_dbg(codec, "ca0132_process_dsp_response\n"); - snd_hda_power_up_pm(codec); + CLASS(snd_hda_power_pm, pm)(codec); if (spec->wait_scp) { if (dspio_get_response_data(codec) >= 0) spec->wait_scp = 0; } dspio_clear_response_queue(codec); - snd_hda_power_down_pm(codec); } static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb) @@ -9546,7 +9469,7 @@ static int ca0132_init(struct hda_codec *codec) if (ca0132_use_pci_mmio(spec)) ca0132_mmio_init(codec); - snd_hda_power_up_pm(codec); + CLASS(snd_hda_power_pm, pm)(codec); if (ca0132_quirk(spec) == QUIRK_AE5 || ca0132_quirk(spec) == QUIRK_AE7) ae5_register_set(codec); @@ -9626,8 +9549,6 @@ static int ca0132_init(struct hda_codec *codec) ca0132_pe_switch_set(codec); } - snd_hda_power_down_pm(codec); - return 0; } diff --git a/sound/hda/codecs/cirrus/cs8409.c b/sound/hda/codecs/cirrus/cs8409.c index e32b462cdc5e..2c02d3be89ee 100644 --- a/sound/hda/codecs/cirrus/cs8409.c +++ b/sound/hda/codecs/cirrus/cs8409.c @@ -92,13 +92,12 @@ static void cs8409_disable_i2c_clock(struct hda_codec *codec) { struct cs8409_spec *spec = codec->spec; - mutex_lock(&spec->i2c_mux); + guard(mutex)(&spec->i2c_mux); if (spec->i2c_clck_enabled) { cs8409_vendor_coef_set(spec->codec, 0x0, cs8409_vendor_coef_get(spec->codec, 0x0) & 0xfffffff7); spec->i2c_clck_enabled = 0; } - mutex_unlock(&spec->i2c_mux); } /* @@ -204,7 +203,7 @@ static int cs8409_i2c_read(struct sub_codec *scodec, unsigned int addr) if (scodec->suspended) return -EPERM; - mutex_lock(&spec->i2c_mux); + guard(mutex)(&spec->i2c_mux); cs8409_enable_i2c_clock(codec); cs8409_set_i2c_dev_addr(codec, scodec->addr); @@ -219,12 +218,9 @@ static int cs8409_i2c_read(struct sub_codec *scodec, unsigned int addr) /* Register in bits 15-8 and the data in 7-0 */ read_data = cs8409_vendor_coef_get(codec, CS8409_I2C_QREAD); - mutex_unlock(&spec->i2c_mux); - return read_data & 0x0ff; error: - mutex_unlock(&spec->i2c_mux); codec_err(codec, "%s() Failed 0x%02x : 0x%04x\n", __func__, scodec->addr, addr); return -EIO; } @@ -247,7 +243,7 @@ static int cs8409_i2c_bulk_read(struct sub_codec *scodec, struct cs8409_i2c_para if (scodec->suspended) return -EPERM; - mutex_lock(&spec->i2c_mux); + guard(mutex)(&spec->i2c_mux); cs8409_set_i2c_dev_addr(codec, scodec->addr); for (i = 0; i < count; i++) { @@ -264,12 +260,9 @@ static int cs8409_i2c_bulk_read(struct sub_codec *scodec, struct cs8409_i2c_para seq[i].value = cs8409_vendor_coef_get(codec, CS8409_I2C_QREAD) & 0xff; } - mutex_unlock(&spec->i2c_mux); - return 0; error: - mutex_unlock(&spec->i2c_mux); codec_err(codec, "I2C Bulk Write Failed 0x%02x\n", scodec->addr); return -EIO; } @@ -291,7 +284,7 @@ static int cs8409_i2c_write(struct sub_codec *scodec, unsigned int addr, unsigne if (scodec->suspended) return -EPERM; - mutex_lock(&spec->i2c_mux); + guard(mutex)(&spec->i2c_mux); cs8409_enable_i2c_clock(codec); cs8409_set_i2c_dev_addr(codec, scodec->addr); @@ -305,11 +298,9 @@ static int cs8409_i2c_write(struct sub_codec *scodec, unsigned int addr, unsigne if (cs8409_i2c_wait_complete(codec) < 0) goto error; - mutex_unlock(&spec->i2c_mux); return 0; error: - mutex_unlock(&spec->i2c_mux); codec_err(codec, "%s() Failed 0x%02x : 0x%04x\n", __func__, scodec->addr, addr); return -EIO; } @@ -333,7 +324,7 @@ static int cs8409_i2c_bulk_write(struct sub_codec *scodec, const struct cs8409_i if (scodec->suspended) return -EPERM; - mutex_lock(&spec->i2c_mux); + guard(mutex)(&spec->i2c_mux); cs8409_set_i2c_dev_addr(codec, scodec->addr); for (i = 0; i < count; i++) { @@ -353,12 +344,9 @@ static int cs8409_i2c_bulk_write(struct sub_codec *scodec, const struct cs8409_i fsleep(seq[i].delay); } - mutex_unlock(&spec->i2c_mux); - return 0; error: - mutex_unlock(&spec->i2c_mux); codec_err(codec, "I2C Bulk Write Failed 0x%02x\n", scodec->addr); return -EIO; } diff --git a/sound/hda/codecs/conexant.c b/sound/hda/codecs/conexant.c index c881bf213ebe..5fcbc1312c69 100644 --- a/sound/hda/codecs/conexant.c +++ b/sound/hda/codecs/conexant.c @@ -32,7 +32,7 @@ struct conexant_spec { unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */ - /* OPLC XO specific */ + /* OLPC XO specific */ bool recording; bool dc_enable; unsigned int dc_input_bias; /* offset into olpc_xo_dc_bias */ @@ -407,7 +407,7 @@ static void cxt_fixup_headset_mic(struct hda_codec *codec, } } -/* OPLC XO 1.5 fixup */ +/* OLPC XO 1.5 fixup */ /* OLPC XO-1.5 supports DC input mode (e.g. for use with analog sensors) * through the microphone jack. diff --git a/sound/hda/codecs/generic.c b/sound/hda/codecs/generic.c index a44beefe3e97..7bcf9aef8275 100644 --- a/sound/hda/codecs/generic.c +++ b/sound/hda/codecs/generic.c @@ -1118,12 +1118,11 @@ static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol, unsigned long pval; int err; - mutex_lock(&codec->control_mutex); + guard(mutex)(&codec->control_mutex); pval = kcontrol->private_value; kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); return err; } @@ -1136,7 +1135,7 @@ static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol, sync_auto_mute_bits(kcontrol, ucontrol); - mutex_lock(&codec->control_mutex); + guard(mutex)(&codec->control_mutex); pval = kcontrol->private_value; indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; for (i = 0; i < indices; i++) { @@ -1148,7 +1147,6 @@ static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol, change |= err; } kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); return err < 0 ? err : change; } @@ -1986,7 +1984,7 @@ static int parse_output_paths(struct hda_codec *codec) { struct hda_gen_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; - struct auto_pin_cfg *best_cfg; + struct auto_pin_cfg *best_cfg __free(kfree) = NULL; unsigned int val; int best_badness = INT_MAX; int badness; @@ -2002,10 +2000,8 @@ static int parse_output_paths(struct hda_codec *codec) for (;;) { badness = fill_and_eval_dacs(codec, fill_hardwired, fill_mio_first); - if (badness < 0) { - kfree(best_cfg); + if (badness < 0) return badness; - } debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n", cfg->line_out_type, fill_hardwired, fill_mio_first, badness); @@ -2098,7 +2094,6 @@ static int parse_output_paths(struct hda_codec *codec) if (spec->indep_hp && !indep_hp_possible(codec)) spec->indep_hp = 0; - kfree(best_cfg); return 0; } @@ -2249,11 +2244,9 @@ static int indep_hp_put(struct snd_kcontrol *kcontrol, unsigned int select = ucontrol->value.enumerated.item[0]; int ret = 0; - mutex_lock(&spec->pcm_mutex); - if (spec->active_streams) { - ret = -EBUSY; - goto unlock; - } + guard(mutex)(&spec->pcm_mutex); + if (spec->active_streams) + return -EBUSY; if (spec->indep_hp_enabled != select) { hda_nid_t *dacp; @@ -2285,8 +2278,6 @@ static int indep_hp_put(struct snd_kcontrol *kcontrol, call_hp_automute(codec, NULL); ret = 1; } - unlock: - mutex_unlock(&spec->pcm_mutex); return ret; } @@ -3475,22 +3466,20 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol, imux = &spec->input_mux; adc_idx = kcontrol->id.index; - mutex_lock(&codec->control_mutex); - for (i = 0; i < imux->num_items; i++) { - path = get_input_path(codec, adc_idx, i); - if (!path || !path->ctls[type]) - continue; - kcontrol->private_value = path->ctls[type]; - ret = func(kcontrol, ucontrol); - if (ret < 0) { - err = ret; - break; + scoped_guard(mutex, &codec->control_mutex) { + for (i = 0; i < imux->num_items; i++) { + path = get_input_path(codec, adc_idx, i); + if (!path || !path->ctls[type]) + continue; + kcontrol->private_value = path->ctls[type]; + ret = func(kcontrol, ucontrol); + if (ret < 0) + return ret; + if (ret > 0) + err = 1; } - if (ret > 0) - err = 1; } - mutex_unlock(&codec->control_mutex); - if (err >= 0 && spec->cap_sync_hook) + if (spec->cap_sync_hook) spec->cap_sync_hook(codec, kcontrol, ucontrol); return err; } @@ -5332,17 +5321,17 @@ static int playback_pcm_open(struct hda_pcm_stream *hinfo, struct hda_gen_spec *spec = codec->spec; int err; - mutex_lock(&spec->pcm_mutex); + guard(mutex)(&spec->pcm_mutex); err = snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, hinfo); - if (!err) { - spec->active_streams |= 1 << STREAM_MULTI_OUT; - call_pcm_playback_hook(hinfo, codec, substream, - HDA_GEN_PCM_ACT_OPEN); - } - mutex_unlock(&spec->pcm_mutex); - return err; + if (err < 0) + return err; + + spec->active_streams |= 1 << STREAM_MULTI_OUT; + call_pcm_playback_hook(hinfo, codec, substream, + HDA_GEN_PCM_ACT_OPEN); + return 0; } static int playback_pcm_prepare(struct hda_pcm_stream *hinfo, @@ -5381,11 +5370,11 @@ static int playback_pcm_close(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct hda_gen_spec *spec = codec->spec; - mutex_lock(&spec->pcm_mutex); + + guard(mutex)(&spec->pcm_mutex); spec->active_streams &= ~(1 << STREAM_MULTI_OUT); call_pcm_playback_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE); - mutex_unlock(&spec->pcm_mutex); return 0; } @@ -5434,14 +5423,13 @@ static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo, struct hda_gen_spec *spec = codec->spec; int err = 0; - mutex_lock(&spec->pcm_mutex); + guard(mutex)(&spec->pcm_mutex); if (spec->indep_hp && !spec->indep_hp_enabled) err = -EBUSY; else spec->active_streams |= 1 << STREAM_INDEP_HP; call_pcm_playback_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN); - mutex_unlock(&spec->pcm_mutex); return err; } @@ -5450,11 +5438,11 @@ static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct hda_gen_spec *spec = codec->spec; - mutex_lock(&spec->pcm_mutex); + + guard(mutex)(&spec->pcm_mutex); spec->active_streams &= ~(1 << STREAM_INDEP_HP); call_pcm_playback_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE); - mutex_unlock(&spec->pcm_mutex); return 0; } diff --git a/sound/hda/codecs/hdmi/hdmi.c b/sound/hda/codecs/hdmi/hdmi.c index 44576b30f699..dc38bfd9dba5 100644 --- a/sound/hda/codecs/hdmi/hdmi.c +++ b/sound/hda/codecs/hdmi/hdmi.c @@ -145,18 +145,15 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; pcm_idx = kcontrol->private_value; - mutex_lock(&spec->pcm_lock); + guard(mutex)(&spec->pcm_lock); per_pin = pcm_idx_to_pin(spec, pcm_idx); if (!per_pin) { /* no pin is bound to the pcm */ uinfo->count = 0; - goto unlock; + return 0; } eld = &per_pin->sink_eld; uinfo->count = eld->eld_valid ? eld->eld_size : 0; - - unlock: - mutex_unlock(&spec->pcm_lock); return 0; } @@ -168,24 +165,22 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, struct hdmi_spec_per_pin *per_pin; struct hdmi_eld *eld; int pcm_idx; - int err = 0; pcm_idx = kcontrol->private_value; - mutex_lock(&spec->pcm_lock); + guard(mutex)(&spec->pcm_lock); per_pin = pcm_idx_to_pin(spec, pcm_idx); if (!per_pin) { /* no pin is bound to the pcm */ memset(ucontrol->value.bytes.data, 0, ARRAY_SIZE(ucontrol->value.bytes.data)); - goto unlock; + return 0; } eld = &per_pin->sink_eld; if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) || eld->eld_size > ELD_MAX_SIZE) { snd_BUG(); - err = -EINVAL; - goto unlock; + return -EINVAL; } memset(ucontrol->value.bytes.data, 0, @@ -193,10 +188,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, if (eld->eld_valid) memcpy(ucontrol->value.bytes.data, eld->eld_buffer, eld->eld_size); - - unlock: - mutex_unlock(&spec->pcm_lock); - return err; + return 0; } static const struct snd_kcontrol_new eld_bytes_ctl = { @@ -295,10 +287,9 @@ static void print_eld_info(struct snd_info_entry *entry, { struct hdmi_spec_per_pin *per_pin = entry->private_data; - mutex_lock(&per_pin->lock); + guard(mutex)(&per_pin->lock); snd_hdmi_print_eld_info(&per_pin->sink_eld, buffer, per_pin->pin_nid, per_pin->dev_id, per_pin->cvt_nid); - mutex_unlock(&per_pin->lock); } static void write_eld_info(struct snd_info_entry *entry, @@ -306,9 +297,8 @@ static void write_eld_info(struct snd_info_entry *entry, { struct hdmi_spec_per_pin *per_pin = entry->private_data; - mutex_lock(&per_pin->lock); + guard(mutex)(&per_pin->lock); snd_hdmi_write_eld_info(&per_pin->sink_eld, buffer); - mutex_unlock(&per_pin->lock); } static int eld_proc_new(struct hdmi_spec_per_pin *per_pin, int index) @@ -599,9 +589,8 @@ void snd_hda_hdmi_check_presence_and_report(struct hda_codec *codec, if (pin_idx < 0) return; - mutex_lock(&spec->pcm_lock); + guard(mutex)(&spec->pcm_lock); hdmi_present_sense(get_pin(spec, pin_idx), 1); - mutex_unlock(&spec->pcm_lock); } EXPORT_SYMBOL_NS_GPL(snd_hda_hdmi_check_presence_and_report, "SND_HDA_CODEC_HDMI"); @@ -907,19 +896,17 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, if (pcm_idx < 0) return -EINVAL; - mutex_lock(&spec->pcm_lock); + guard(mutex)(&spec->pcm_lock); pin_idx = hinfo_to_pin_index(codec, hinfo); /* no pin is assigned to the PCM * PA need pcm open successfully when probe */ - if (pin_idx < 0) { - err = hdmi_pcm_open_no_pin(hinfo, codec, substream); - goto unlock; - } + if (pin_idx < 0) + return hdmi_pcm_open_no_pin(hinfo, codec, substream); err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, false); if (err < 0) - goto unlock; + return err; per_cvt = get_cvt(spec, cvt_idx); /* Claim converter */ @@ -960,8 +947,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, per_cvt->assigned = false; hinfo->nid = 0; snd_hda_spdif_ctls_unassign(codec, pcm_idx); - err = -ENODEV; - goto unlock; + return -ENODEV; } } @@ -973,9 +959,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); - unlock: - mutex_unlock(&spec->pcm_lock); - return err; + return 0; } /* @@ -1270,20 +1254,19 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, * the unsolicited response to avoid custom WARs. */ int present; - int ret; #ifdef CONFIG_PM if (dev->power.runtime_status == RPM_SUSPENDING) return; #endif - ret = snd_hda_power_up_pm(codec); - if (ret < 0 && pm_runtime_suspended(dev)) - goto out; + CLASS(snd_hda_power_pm, pm)(codec); + if (pm.err < 0 && pm_runtime_suspended(dev)) + return; present = snd_hda_jack_pin_sense(codec, pin_nid, dev_id); - mutex_lock(&per_pin->lock); + guard(mutex)(&per_pin->lock); eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); if (eld->monitor_present) eld->eld_valid = !!(present & AC_PINSENSE_ELDV); @@ -1301,9 +1284,6 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, } update_eld(codec, per_pin, eld, repoll); - mutex_unlock(&per_pin->lock); - out: - snd_hda_power_down_pm(codec); } static void silent_stream_enable(struct hda_codec *codec, @@ -1318,27 +1298,25 @@ static void silent_stream_enable(struct hda_codec *codec, * have to be done without mutex held. */ - err = snd_hda_power_up_pm(codec); - if (err < 0 && err != -EACCES) { + CLASS(snd_hda_power_pm, pm)(codec); + if (pm.err < 0 && pm.err != -EACCES) { codec_err(codec, - "Failed to power up codec for silent stream enable ret=[%d]\n", err); - snd_hda_power_down_pm(codec); + "Failed to power up codec for silent stream enable ret=[%d]\n", pm.err); return; } - mutex_lock(&per_pin->lock); + guard(mutex)(&per_pin->lock); if (per_pin->setup) { codec_dbg(codec, "hdmi: PCM already open, no silent stream\n"); - err = -EBUSY; - goto unlock_out; + return; } pin_idx = pin_id_to_pin_index(codec, per_pin->pin_nid, per_pin->dev_id); err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, true); if (err) { codec_err(codec, "hdmi: no free converter to enable silent mode\n"); - goto unlock_out; + return; } per_cvt = get_cvt(spec, cvt_idx); @@ -1358,11 +1336,6 @@ static void silent_stream_enable(struct hda_codec *codec, pin_cvt_fixup(codec, per_pin, 0); spec->ops.silent_stream(codec, per_pin, true); - - unlock_out: - mutex_unlock(&per_pin->lock); - - snd_hda_power_down_pm(codec); } static void silent_stream_disable(struct hda_codec *codec, @@ -1370,20 +1343,19 @@ static void silent_stream_disable(struct hda_codec *codec, { struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_cvt *per_cvt; - int cvt_idx, err; + int cvt_idx; - err = snd_hda_power_up_pm(codec); - if (err < 0 && err != -EACCES) { + CLASS(snd_hda_power_pm, pm)(codec); + if (pm.err < 0 && pm.err != -EACCES) { codec_err(codec, "Failed to power up codec for silent stream disable ret=[%d]\n", - err); - snd_hda_power_down_pm(codec); + pm.err); return; } - mutex_lock(&per_pin->lock); + guard(mutex)(&per_pin->lock); if (!per_pin->silent_stream) - goto unlock_out; + return; codec_dbg(codec, "HDMI: disable silent stream on pin-NID=0x%x cvt-NID=0x%x\n", per_pin->pin_nid, per_pin->cvt_nid); @@ -1398,11 +1370,6 @@ static void silent_stream_disable(struct hda_codec *codec, per_pin->cvt_nid = 0; per_pin->silent_stream = false; - - unlock_out: - mutex_unlock(&per_pin->lock); - - snd_hda_power_down_pm(codec); } /* update ELD and jack state via audio component */ @@ -1413,16 +1380,16 @@ static void sync_eld_via_acomp(struct hda_codec *codec, struct hdmi_eld *eld = &spec->temp_eld; bool monitor_prev, monitor_next; - mutex_lock(&per_pin->lock); - eld->monitor_present = false; - monitor_prev = per_pin->sink_eld.monitor_present; - eld->eld_size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid, - per_pin->dev_id, &eld->monitor_present, - eld->eld_buffer, ELD_MAX_SIZE); - eld->eld_valid = (eld->eld_size > 0); - update_eld(codec, per_pin, eld, 0); - monitor_next = per_pin->sink_eld.monitor_present; - mutex_unlock(&per_pin->lock); + scoped_guard(mutex, &per_pin->lock) { + eld->monitor_present = false; + monitor_prev = per_pin->sink_eld.monitor_present; + eld->eld_size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid, + per_pin->dev_id, &eld->monitor_present, + eld->eld_buffer, ELD_MAX_SIZE); + eld->eld_valid = (eld->eld_size > 0); + update_eld(codec, per_pin, eld, 0); + monitor_next = per_pin->sink_eld.monitor_present; + } if (spec->silent_stream_type) { if (!monitor_prev && monitor_next) @@ -1458,9 +1425,8 @@ static void hdmi_repoll_eld(struct work_struct *work) if (per_pin->repoll_count++ > 6) per_pin->repoll_count = 0; - mutex_lock(&spec->pcm_lock); + guard(mutex)(&spec->pcm_lock); hdmi_present_sense(per_pin, per_pin->repoll_count); - mutex_unlock(&spec->pcm_lock); } static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) @@ -1655,20 +1621,15 @@ EXPORT_SYMBOL_NS_GPL(snd_hda_hdmi_parse_codec, "SND_HDA_CODEC_HDMI"); static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) { struct hda_spdif_out *spdif; - bool non_pcm; - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); spdif = snd_hda_spdif_out_of_nid(codec, cvt_nid); /* Add sanity check to pass klockwork check. * This should never happen. */ - if (WARN_ON(spdif == NULL)) { - mutex_unlock(&codec->spdif_mutex); + if (WARN_ON(spdif == NULL)) return true; - } - non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO); - mutex_unlock(&codec->spdif_mutex); - return non_pcm; + return !!(spdif->status & IEC958_AES0_NONAUDIO); } /* @@ -1688,9 +1649,8 @@ int snd_hda_hdmi_generic_pcm_prepare(struct hda_pcm_stream *hinfo, struct snd_pcm_runtime *runtime = substream->runtime; bool non_pcm; int pinctl, stripe; - int err = 0; - mutex_lock(&spec->pcm_lock); + guard(mutex)(&spec->pcm_lock); pin_idx = hinfo_to_pin_index(codec, hinfo); if (pin_idx < 0) { /* when pcm is not bound to a pin skip pin setup and return 0 @@ -1699,7 +1659,7 @@ int snd_hda_hdmi_generic_pcm_prepare(struct hda_pcm_stream *hinfo, pin_cvt_fixup(codec, NULL, cvt_nid); snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format); - goto unlock; + return 0; } per_pin = get_pin(spec, pin_idx); @@ -1721,20 +1681,20 @@ int snd_hda_hdmi_generic_pcm_prepare(struct hda_pcm_stream *hinfo, per_pin->dev_id, runtime->rate); non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); - mutex_lock(&per_pin->lock); - per_pin->channels = substream->runtime->channels; - per_pin->setup = true; + scoped_guard(mutex, &per_pin->lock) { + per_pin->channels = substream->runtime->channels; + per_pin->setup = true; + + if (get_wcaps(codec, cvt_nid) & AC_WCAP_STRIPE) { + stripe = snd_hdac_get_stream_stripe_ctl(&codec->bus->core, + substream); + snd_hda_codec_write(codec, cvt_nid, 0, + AC_VERB_SET_STRIPE_CONTROL, + stripe); + } - if (get_wcaps(codec, cvt_nid) & AC_WCAP_STRIPE) { - stripe = snd_hdac_get_stream_stripe_ctl(&codec->bus->core, - substream); - snd_hda_codec_write(codec, cvt_nid, 0, - AC_VERB_SET_STRIPE_CONTROL, - stripe); + snd_hda_hdmi_setup_audio_infoframe(codec, per_pin, non_pcm); } - - snd_hda_hdmi_setup_audio_infoframe(codec, per_pin, non_pcm); - mutex_unlock(&per_pin->lock); if (spec->dyn_pin_out) { snd_hda_set_dev_select(codec, per_pin->pin_nid, per_pin->dev_id); @@ -1746,11 +1706,8 @@ int snd_hda_hdmi_generic_pcm_prepare(struct hda_pcm_stream *hinfo, } /* snd_hda_set_dev_select() has been called before */ - err = spec->ops.setup_stream(codec, cvt_nid, per_pin->pin_nid, - per_pin->dev_id, stream_tag, format); - unlock: - mutex_unlock(&spec->pcm_lock); - return err; + return spec->ops.setup_stream(codec, cvt_nid, per_pin->pin_nid, + per_pin->dev_id, stream_tag, format); } EXPORT_SYMBOL_NS_GPL(snd_hda_hdmi_generic_pcm_prepare, "SND_HDA_CODEC_HDMI"); @@ -1772,20 +1729,15 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, struct hdmi_spec_per_cvt *per_cvt; struct hdmi_spec_per_pin *per_pin; int pinctl; - int err = 0; - mutex_lock(&spec->pcm_lock); + guard(mutex)(&spec->pcm_lock); if (hinfo->nid) { pcm_idx = hinfo_to_pcm_index(codec, hinfo); - if (snd_BUG_ON(pcm_idx < 0)) { - err = -EINVAL; - goto unlock; - } + if (snd_BUG_ON(pcm_idx < 0)) + return -EINVAL; cvt_idx = cvt_nid_to_cvt_index(codec, hinfo->nid); - if (snd_BUG_ON(cvt_idx < 0)) { - err = -EINVAL; - goto unlock; - } + if (snd_BUG_ON(cvt_idx < 0)) + return -EINVAL; per_cvt = get_cvt(spec, cvt_idx); per_cvt->assigned = false; hinfo->nid = 0; @@ -1800,7 +1752,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, * hdmi_pcm_open() */ if (pin_idx < 0) - goto unlock; + return 0; per_pin = get_pin(spec, pin_idx); @@ -1814,19 +1766,15 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, pinctl & ~PIN_OUT); } - mutex_lock(&per_pin->lock); + guard(mutex)(&per_pin->lock); per_pin->chmap_set = false; memset(per_pin->chmap, 0, sizeof(per_pin->chmap)); per_pin->setup = false; per_pin->channels = 0; - mutex_unlock(&per_pin->lock); } -unlock: - mutex_unlock(&spec->pcm_lock); - - return err; + return 0; } static const struct hda_pcm_ops generic_ops = { @@ -1871,12 +1819,11 @@ static void hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx, if (!per_pin) return; - mutex_lock(&per_pin->lock); + guard(mutex)(&per_pin->lock); per_pin->chmap_set = true; memcpy(per_pin->chmap, chmap, ARRAY_SIZE(per_pin->chmap)); if (prepared) snd_hda_hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm); - mutex_unlock(&per_pin->lock); } static bool is_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx) @@ -2045,7 +1992,7 @@ int snd_hda_hdmi_generic_init(struct hda_codec *codec) struct hdmi_spec *spec = codec->spec; int pin_idx; - mutex_lock(&spec->bind_lock); + guard(mutex)(&spec->bind_lock); for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); hda_nid_t pin_nid = per_pin->pin_nid; @@ -2058,7 +2005,6 @@ int snd_hda_hdmi_generic_init(struct hda_codec *codec) snd_hda_jack_detect_enable_callback_mst(codec, pin_nid, dev_id, jack_callback); } - mutex_unlock(&spec->bind_lock); return 0; } EXPORT_SYMBOL_NS_GPL(snd_hda_hdmi_generic_init, "SND_HDA_CODEC_HDMI"); @@ -2229,7 +2175,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp, int i; spec = container_of(acomp->audio_ops, struct hdmi_spec, drm_audio_ops); - mutex_lock(&spec->bind_lock); + guard(mutex)(&spec->bind_lock); spec->use_acomp_notifier = use_acomp; spec->codec->relaxed_resume = use_acomp; spec->codec->bus->keep_power = 0; @@ -2239,7 +2185,6 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp, get_pin(spec, i)->pin_nid, get_pin(spec, i)->dev_id, use_acomp); - mutex_unlock(&spec->bind_lock); } /* enable / disable the notifier via master bind / unbind */ diff --git a/sound/hda/codecs/hdmi/nvhdmi-mcp.c b/sound/hda/codecs/hdmi/nvhdmi-mcp.c index fbcea6d1850e..8fd8d76fa72f 100644 --- a/sound/hda/codecs/hdmi/nvhdmi-mcp.c +++ b/sound/hda/codecs/hdmi/nvhdmi-mcp.c @@ -131,7 +131,7 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo, struct hda_spdif_out *spdif; struct hdmi_spec_per_cvt *per_cvt; - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); per_cvt = get_cvt(spec, 0); spdif = snd_hda_spdif_out_of_nid(codec, per_cvt->cvt_nid); @@ -215,7 +215,6 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo, nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs); - mutex_unlock(&codec->spdif_mutex); return 0; } diff --git a/sound/hda/codecs/realtek/alc268.c b/sound/hda/codecs/realtek/alc268.c index e489cdc98eb8..4b565fb7bd1c 100644 --- a/sound/hda/codecs/realtek/alc268.c +++ b/sound/hda/codecs/realtek/alc268.c @@ -12,7 +12,7 @@ static int alc268_beep_switch_put(struct snd_kcontrol *kcontrol, unsigned long pval; int err; - mutex_lock(&codec->control_mutex); + guard(mutex)(&codec->control_mutex); pval = kcontrol->private_value; kcontrol->private_value = (pval & ~0xff) | 0x0f; err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); @@ -21,7 +21,6 @@ static int alc268_beep_switch_put(struct snd_kcontrol *kcontrol, err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); } kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); return err; } diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c index f267437c9698..3c42f66fe000 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -872,8 +872,7 @@ static void alc294_init(struct hda_codec *codec) struct alc_spec *spec = codec->spec; /* required only at boot or S4 resume time */ - if (!spec->done_hp_init || - codec->core.dev.power.power_state.event == PM_EVENT_RESTORE) { + if (!spec->done_hp_init || is_s4_resume(codec)) { alc294_hp_init(codec); spec->done_hp_init = true; } @@ -1224,9 +1223,8 @@ static void alc_update_vref_led(struct hda_codec *codec, hda_nid_t pin, pinval &= ~AC_PINCTL_VREFEN; pinval |= on ? AC_PINCTL_VREF_80 : AC_PINCTL_VREF_HIZ; /* temporarily power up/down for setting VREF */ - snd_hda_power_up_pm(codec); + CLASS(snd_hda_power_pm, pm)(codec); snd_hda_set_pin_ctl_cache(codec, pin, pinval); - snd_hda_power_down_pm(codec); } /* update mute-LED according to the speaker mute state via mic VREF pin */ @@ -6487,6 +6485,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x89c6, "Zbook Fury 17 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x89ca, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), SND_PCI_QUIRK(0x103c, 0x89d3, "HP EliteBook 645 G9 (MB 89D2)", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), + SND_PCI_QUIRK(0x103c, 0x89da, "HP Spectre x360 14t-ea100", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX), SND_PCI_QUIRK(0x103c, 0x89e7, "HP Elite x2 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8a0f, "HP Pavilion 14-ec1xxx", ALC287_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8a20, "HP Laptop 15s-fq5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), diff --git a/sound/hda/codecs/realtek/realtek.c b/sound/hda/codecs/realtek/realtek.c index b6feccfd45a9..ca377a5adadb 100644 --- a/sound/hda/codecs/realtek/realtek.c +++ b/sound/hda/codecs/realtek/realtek.c @@ -7,26 +7,6 @@ #include <linux/module.h> #include "realtek.h" -/* - * COEF access helper functions - */ - -static void coef_mutex_lock(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - snd_hda_power_up_pm(codec); - mutex_lock(&spec->coef_mutex); -} - -static void coef_mutex_unlock(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - mutex_unlock(&spec->coef_mutex); - snd_hda_power_down_pm(codec); -} - static int __alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, unsigned int coef_idx) { @@ -40,12 +20,8 @@ static int __alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, unsigned int coef_idx) { - unsigned int val; - - coef_mutex_lock(codec); - val = __alc_read_coefex_idx(codec, nid, coef_idx); - coef_mutex_unlock(codec); - return val; + guard(coef_mutex)(codec); + return __alc_read_coefex_idx(codec, nid, coef_idx); } EXPORT_SYMBOL_NS_GPL(alc_read_coefex_idx, "SND_HDA_CODEC_REALTEK"); @@ -59,9 +35,8 @@ static void __alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, unsigned int coef_idx, unsigned int coef_val) { - coef_mutex_lock(codec); + guard(coef_mutex)(codec); __alc_write_coefex_idx(codec, nid, coef_idx, coef_val); - coef_mutex_unlock(codec); } EXPORT_SYMBOL_NS_GPL(alc_write_coefex_idx, "SND_HDA_CODEC_REALTEK"); @@ -80,9 +55,8 @@ void alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid, unsigned int coef_idx, unsigned int mask, unsigned int bits_set) { - coef_mutex_lock(codec); + guard(coef_mutex)(codec); __alc_update_coefex_idx(codec, nid, coef_idx, mask, bits_set); - coef_mutex_unlock(codec); } EXPORT_SYMBOL_NS_GPL(alc_update_coefex_idx, "SND_HDA_CODEC_REALTEK"); @@ -99,7 +73,7 @@ EXPORT_SYMBOL_NS_GPL(alc_get_coef0, "SND_HDA_CODEC_REALTEK"); void alc_process_coef_fw(struct hda_codec *codec, const struct coef_fw *fw) { - coef_mutex_lock(codec); + guard(coef_mutex)(codec); for (; fw->nid; fw++) { if (fw->mask == (unsigned short)-1) __alc_write_coefex_idx(codec, fw->nid, fw->idx, fw->val); @@ -107,7 +81,6 @@ void alc_process_coef_fw(struct hda_codec *codec, const struct coef_fw *fw) __alc_update_coefex_idx(codec, fw->nid, fw->idx, fw->mask, fw->val); } - coef_mutex_unlock(codec); } EXPORT_SYMBOL_NS_GPL(alc_process_coef_fw, "SND_HDA_CODEC_REALTEK"); @@ -242,7 +215,7 @@ void alc_update_knob_master(struct hda_codec *codec, { unsigned int val; struct snd_kcontrol *kctl; - struct snd_ctl_elem_value *uctl; + struct snd_ctl_elem_value *uctl __free(kfree) = NULL; kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume"); if (!kctl) @@ -256,7 +229,6 @@ void alc_update_knob_master(struct hda_codec *codec, uctl->value.integer.value[0] = val; uctl->value.integer.value[1] = val; kctl->put(kctl, uctl); - kfree(uctl); } EXPORT_SYMBOL_NS_GPL(alc_update_knob_master, "SND_HDA_CODEC_REALTEK"); diff --git a/sound/hda/codecs/realtek/realtek.h b/sound/hda/codecs/realtek/realtek.h index ee893da0c486..b2a919904c4c 100644 --- a/sound/hda/codecs/realtek/realtek.h +++ b/sound/hda/codecs/realtek/realtek.h @@ -295,4 +295,25 @@ void alc233_alc662_fixup_lenovo_dual_codecs(struct hda_codec *codec, void alc_fixup_dell_xps13(struct hda_codec *codec, const struct hda_fixup *fix, int action); +/* + * COEF access helper functions + */ +static inline void coef_mutex_lock(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + + snd_hda_power_up_pm(codec); + mutex_lock(&spec->coef_mutex); +} + +static inline void coef_mutex_unlock(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + + mutex_unlock(&spec->coef_mutex); + snd_hda_power_down_pm(codec); +} + +DEFINE_GUARD(coef_mutex, struct hda_codec *, coef_mutex_lock(_T), coef_mutex_unlock(_T)) + #endif /* __HDA_REALTEK_H */ diff --git a/sound/hda/codecs/side-codecs/cirrus_scodec_test.c b/sound/hda/codecs/side-codecs/cirrus_scodec_test.c index 9ba14c09c07f..3cca750857b6 100644 --- a/sound/hda/codecs/side-codecs/cirrus_scodec_test.c +++ b/sound/hda/codecs/side-codecs/cirrus_scodec_test.c @@ -69,7 +69,7 @@ static int cirrus_scodec_test_gpio_set_config(struct gpio_chip *gc, unsigned long config) { switch (pinconf_to_config_param(config)) { - case PIN_CONFIG_OUTPUT: + case PIN_CONFIG_LEVEL: case PIN_CONFIG_OUTPUT_ENABLE: return -EOPNOTSUPP; default: diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda.c b/sound/hda/codecs/side-codecs/cs35l41_hda.c index 37f2cdc8ce82..c04208e685a0 100644 --- a/sound/hda/codecs/side-codecs/cs35l41_hda.c +++ b/sound/hda/codecs/side-codecs/cs35l41_hda.c @@ -624,11 +624,10 @@ static void cs35l41_remove_dsp(struct cs35l41_hda *cs35l41) cancel_work_sync(&cs35l41->fw_load_work); - mutex_lock(&cs35l41->fw_mutex); + guard(mutex)(&cs35l41->fw_mutex); cs35l41_shutdown_dsp(cs35l41); cs_dsp_remove(dsp); cs35l41->halo_initialized = false; - mutex_unlock(&cs35l41->fw_mutex); } /* Protection release cycle to get the speaker out of Safe-Mode */ @@ -790,9 +789,9 @@ static void cs35l41_hda_pre_playback_hook(struct device *dev, int action) switch (action) { case HDA_GEN_PCM_ACT_CLEANUP: - mutex_lock(&cs35l41->fw_mutex); - cs35l41_hda_pause_start(dev); - mutex_unlock(&cs35l41->fw_mutex); + scoped_guard(mutex, &cs35l41->fw_mutex) { + cs35l41_hda_pause_start(dev); + } break; default: break; @@ -813,24 +812,24 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action) pm_runtime_get_sync(dev); break; case HDA_GEN_PCM_ACT_PREPARE: - mutex_lock(&cs35l41->fw_mutex); - cs35l41_hda_play_start(dev); - mutex_unlock(&cs35l41->fw_mutex); + scoped_guard(mutex, &cs35l41->fw_mutex) { + cs35l41_hda_play_start(dev); + } break; case HDA_GEN_PCM_ACT_CLEANUP: - mutex_lock(&cs35l41->fw_mutex); - cs35l41_hda_pause_done(dev); - mutex_unlock(&cs35l41->fw_mutex); + scoped_guard(mutex, &cs35l41->fw_mutex) { + cs35l41_hda_pause_done(dev); + } break; case HDA_GEN_PCM_ACT_CLOSE: - mutex_lock(&cs35l41->fw_mutex); - if (!cs35l41->cs_dsp.running && cs35l41->request_fw_load && - !cs35l41->fw_request_ongoing) { - dev_info(dev, "Requesting Firmware Load after HDA_GEN_PCM_ACT_CLOSE\n"); - cs35l41->fw_request_ongoing = true; - schedule_work(&cs35l41->fw_load_work); + scoped_guard(mutex, &cs35l41->fw_mutex) { + if (!cs35l41->cs_dsp.running && cs35l41->request_fw_load && + !cs35l41->fw_request_ongoing) { + dev_info(dev, "Requesting Firmware Load after HDA_GEN_PCM_ACT_CLOSE\n"); + cs35l41->fw_request_ongoing = true; + schedule_work(&cs35l41->fw_load_work); + } } - mutex_unlock(&cs35l41->fw_mutex); /* * Playback must be finished for all amps before we start runtime suspend. @@ -849,9 +848,9 @@ static void cs35l41_hda_post_playback_hook(struct device *dev, int action) switch (action) { case HDA_GEN_PCM_ACT_PREPARE: - mutex_lock(&cs35l41->fw_mutex); - cs35l41_hda_play_done(dev); - mutex_unlock(&cs35l41->fw_mutex); + scoped_guard(mutex, &cs35l41->fw_mutex) { + cs35l41_hda_play_done(dev); + } break; default: break; @@ -917,13 +916,12 @@ static int cs35l41_verify_id(struct cs35l41_hda *cs35l41, unsigned int *regid, u static int cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41) { - mutex_lock(&cs35l41->fw_mutex); + guard(mutex)(&cs35l41->fw_mutex); if (cs35l41->cs_dsp.running) { cs35l41->cs_dsp.running = false; cs35l41->cs_dsp.booted = false; } regcache_mark_dirty(cs35l41->regmap); - mutex_unlock(&cs35l41->fw_mutex); return 0; } @@ -939,10 +937,9 @@ static int cs35l41_system_suspend_prep(struct device *dev) return 0; /* don't block the whole system suspend */ } - mutex_lock(&cs35l41->fw_mutex); + guard(mutex)(&cs35l41->fw_mutex); if (cs35l41->playback_started) cs35l41_hda_pause_start(dev); - mutex_unlock(&cs35l41->fw_mutex); return 0; } @@ -959,10 +956,10 @@ static int cs35l41_system_suspend(struct device *dev) return 0; /* don't block the whole system suspend */ } - mutex_lock(&cs35l41->fw_mutex); - if (cs35l41->playback_started) - cs35l41_hda_pause_done(dev); - mutex_unlock(&cs35l41->fw_mutex); + scoped_guard(mutex, &cs35l41->fw_mutex) { + if (cs35l41->playback_started) + cs35l41_hda_pause_done(dev); + } ret = pm_runtime_force_suspend(dev); if (ret) { @@ -1047,13 +1044,12 @@ static int cs35l41_system_resume(struct device *dev) return ret; } - mutex_lock(&cs35l41->fw_mutex); + guard(mutex)(&cs35l41->fw_mutex); if (cs35l41->request_fw_load && !cs35l41->fw_request_ongoing) { cs35l41->fw_request_ongoing = true; schedule_work(&cs35l41->fw_load_work); } - mutex_unlock(&cs35l41->fw_mutex); return ret; } @@ -1070,7 +1066,7 @@ static int cs35l41_runtime_idle(struct device *dev) static int cs35l41_runtime_suspend(struct device *dev) { struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); - int ret = 0; + int ret; dev_dbg(cs35l41->dev, "Runtime Suspend\n"); @@ -1079,13 +1075,13 @@ static int cs35l41_runtime_suspend(struct device *dev) return 0; } - mutex_lock(&cs35l41->fw_mutex); + guard(mutex)(&cs35l41->fw_mutex); if (cs35l41->cs_dsp.running) { ret = cs35l41_enter_hibernate(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type); if (ret) - goto err; + return ret; } else { cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type); } @@ -1093,17 +1089,14 @@ static int cs35l41_runtime_suspend(struct device *dev) regcache_cache_only(cs35l41->regmap, true); regcache_mark_dirty(cs35l41->regmap); -err: - mutex_unlock(&cs35l41->fw_mutex); - - return ret; + return 0; } static int cs35l41_runtime_resume(struct device *dev) { struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); unsigned int regid, reg_revid; - int ret = 0; + int ret; dev_dbg(cs35l41->dev, "Runtime Resume\n"); @@ -1112,7 +1105,7 @@ static int cs35l41_runtime_resume(struct device *dev) return 0; } - mutex_lock(&cs35l41->fw_mutex); + guard(mutex)(&cs35l41->fw_mutex); regcache_cache_only(cs35l41->regmap, false); @@ -1120,13 +1113,13 @@ static int cs35l41_runtime_resume(struct device *dev) ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap); if (ret) { dev_warn(cs35l41->dev, "Unable to exit Hibernate."); - goto err; + return ret; } } ret = cs35l41_verify_id(cs35l41, ®id, ®_revid); if (ret) - goto err; + return ret; /* Test key needs to be unlocked to allow the OTP settings to re-apply */ cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap); @@ -1134,7 +1127,7 @@ static int cs35l41_runtime_resume(struct device *dev) cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap); if (ret) { dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret); - goto err; + return ret; } if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) @@ -1142,22 +1135,14 @@ static int cs35l41_runtime_resume(struct device *dev) dev_dbg(cs35l41->dev, "CS35L41 Resumed (%x), Revision: %02X\n", regid, reg_revid); -err: - mutex_unlock(&cs35l41->fw_mutex); - - return ret; + return 0; } static int cs35l41_hda_read_ctl(struct cs_dsp *dsp, const char *name, int type, unsigned int alg, void *buf, size_t len) { - int ret; - - mutex_lock(&dsp->pwr_lock); - ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(dsp, name, type, alg), 0, buf, len); - mutex_unlock(&dsp->pwr_lock); - - return ret; + guard(mutex)(&dsp->pwr_lock); + return cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(dsp, name, type, alg), 0, buf, len); } static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41) @@ -1272,16 +1257,15 @@ static void cs35l41_fw_load_work(struct work_struct *work) pm_runtime_get_sync(cs35l41->dev); - mutex_lock(&cs35l41->fw_mutex); - - /* Recheck if playback is ongoing, mutex will block playback during firmware loading */ - if (cs35l41->playback_started) - dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback. Retrying...\n"); - else - cs35l41_load_firmware(cs35l41, cs35l41->request_fw_load); + scoped_guard(mutex, &cs35l41->fw_mutex) { + /* Recheck if playback is ongoing, mutex will block playback during firmware loading */ + if (cs35l41->playback_started) + dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback. Retrying...\n"); + else + cs35l41_load_firmware(cs35l41, cs35l41->request_fw_load); - cs35l41->fw_request_ongoing = false; - mutex_unlock(&cs35l41->fw_mutex); + cs35l41->fw_request_ongoing = false; + } pm_runtime_put_autosuspend(cs35l41->dev); } diff --git a/sound/hda/codecs/side-codecs/cs35l56_hda.c b/sound/hda/codecs/side-codecs/cs35l56_hda.c index 36fa62a41984..5bb1c4ebeaf3 100644 --- a/sound/hda/codecs/side-codecs/cs35l56_hda.c +++ b/sound/hda/codecs/side-codecs/cs35l56_hda.c @@ -1049,6 +1049,7 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id) goto err; } + cs35l56->base.type = hid & 0xff; cs35l56->base.cal_index = -1; cs35l56_init_cs_dsp(&cs35l56->base, &cs35l56->cs_dsp); diff --git a/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c b/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c index d10209e4eddd..1072f17385ac 100644 --- a/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c +++ b/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c @@ -27,8 +27,6 @@ static int cs35l56_hda_i2c_probe(struct i2c_client *clt) cs35l56->base.can_hibernate = true; #endif - cs35l56->base.fw_reg = &cs35l56_fw_reg; - cs35l56->base.regmap = devm_regmap_init_i2c(clt, &cs35l56_regmap_i2c); if (IS_ERR(cs35l56->base.regmap)) { ret = PTR_ERR(cs35l56->base.regmap); diff --git a/sound/hda/codecs/side-codecs/cs35l56_hda_spi.c b/sound/hda/codecs/side-codecs/cs35l56_hda_spi.c index f57533d3d728..f802c83c57b4 100644 --- a/sound/hda/codecs/side-codecs/cs35l56_hda_spi.c +++ b/sound/hda/codecs/side-codecs/cs35l56_hda_spi.c @@ -30,8 +30,6 @@ static int cs35l56_hda_spi_probe(struct spi_device *spi) cs35l56->base.can_hibernate = true; #endif - cs35l56->base.fw_reg = &cs35l56_fw_reg; - cs35l56->base.regmap = devm_regmap_init_spi(spi, &cs35l56_regmap_spi); if (IS_ERR(cs35l56->base.regmap)) { ret = PTR_ERR(cs35l56->base.regmap); diff --git a/sound/hda/codecs/side-codecs/hda_component.c b/sound/hda/codecs/side-codecs/hda_component.c index 71860e2d6377..bcf47a301697 100644 --- a/sound/hda/codecs/side-codecs/hda_component.c +++ b/sound/hda/codecs/side-codecs/hda_component.c @@ -21,13 +21,12 @@ void hda_component_acpi_device_notify(struct hda_component_parent *parent, struct hda_component *comp; int i; - mutex_lock(&parent->mutex); + guard(mutex)(&parent->mutex); for (i = 0; i < ARRAY_SIZE(parent->comps); i++) { comp = hda_component_from_index(parent, i); if (comp->dev && comp->acpi_notify) comp->acpi_notify(acpi_device_handle(comp->adev), event, comp->dev); } - mutex_unlock(&parent->mutex); } EXPORT_SYMBOL_NS_GPL(hda_component_acpi_device_notify, "SND_HDA_SCODEC_COMPONENT"); @@ -89,7 +88,7 @@ void hda_component_manager_playback_hook(struct hda_component_parent *parent, in struct hda_component *comp; int i; - mutex_lock(&parent->mutex); + guard(mutex)(&parent->mutex); for (i = 0; i < ARRAY_SIZE(parent->comps); i++) { comp = hda_component_from_index(parent, i); if (comp->dev && comp->pre_playback_hook) @@ -105,7 +104,6 @@ void hda_component_manager_playback_hook(struct hda_component_parent *parent, in if (comp->dev && comp->post_playback_hook) comp->post_playback_hook(comp->dev, action); } - mutex_unlock(&parent->mutex); } EXPORT_SYMBOL_NS_GPL(hda_component_manager_playback_hook, "SND_HDA_SCODEC_COMPONENT"); @@ -138,16 +136,11 @@ static int hda_comp_match_dev_name(struct device *dev, void *data) int hda_component_manager_bind(struct hda_codec *cdc, struct hda_component_parent *parent) { - int ret; - /* Init shared and component specific data */ memset(parent->comps, 0, sizeof(parent->comps)); - mutex_lock(&parent->mutex); - ret = component_bind_all(hda_codec_dev(cdc), parent); - mutex_unlock(&parent->mutex); - - return ret; + guard(mutex)(&parent->mutex); + return component_bind_all(hda_codec_dev(cdc), parent); } EXPORT_SYMBOL_NS_GPL(hda_component_manager_bind, "SND_HDA_SCODEC_COMPONENT"); diff --git a/sound/hda/codecs/side-codecs/hda_component.h b/sound/hda/codecs/side-codecs/hda_component.h index 7ee37154749f..075137a73bae 100644 --- a/sound/hda/codecs/side-codecs/hda_component.h +++ b/sound/hda/codecs/side-codecs/hda_component.h @@ -95,9 +95,8 @@ static inline struct hda_component *hda_component_from_index(struct hda_componen static inline void hda_component_manager_unbind(struct hda_codec *cdc, struct hda_component_parent *parent) { - mutex_lock(&parent->mutex); + guard(mutex)(&parent->mutex); component_unbind_all(hda_codec_dev(cdc), parent); - mutex_unlock(&parent->mutex); } #endif /* ifndef __HDA_COMPONENT_H__ */ diff --git a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c index b5b7a1e82b75..4dea442d8c30 100644 --- a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c +++ b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c @@ -26,6 +26,7 @@ #include <sound/tlv.h> #include <sound/tas2770-tlv.h> #include <sound/tas2781-tlv.h> +#include <sound/tas5825-tlv.h> #include "hda_local.h" #include "hda_auto_parser.h" @@ -50,6 +51,7 @@ enum device_chip_id { HDA_TAS2563, HDA_TAS2770, HDA_TAS2781, + HDA_TAS5825, HDA_OTHERS }; @@ -156,16 +158,16 @@ static void tas2781_hda_playback_hook(struct device *dev, int action) switch (action) { case HDA_GEN_PCM_ACT_OPEN: pm_runtime_get_sync(dev); - mutex_lock(&tas_hda->priv->codec_lock); - tasdevice_tuning_switch(tas_hda->priv, 0); - tas_hda->priv->playback_started = true; - mutex_unlock(&tas_hda->priv->codec_lock); + scoped_guard(mutex, &tas_hda->priv->codec_lock) { + tasdevice_tuning_switch(tas_hda->priv, 0); + tas_hda->priv->playback_started = true; + } break; case HDA_GEN_PCM_ACT_CLOSE: - mutex_lock(&tas_hda->priv->codec_lock); - tasdevice_tuning_switch(tas_hda->priv, 1); - tas_hda->priv->playback_started = false; - mutex_unlock(&tas_hda->priv->codec_lock); + scoped_guard(mutex, &tas_hda->priv->codec_lock) { + tasdevice_tuning_switch(tas_hda->priv, 1); + tas_hda->priv->playback_started = false; + } pm_runtime_put_autosuspend(dev); break; @@ -182,15 +184,13 @@ static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; int ret; - mutex_lock(&tas_priv->codec_lock); + guard(mutex)(&tas_priv->codec_lock); ret = tasdevice_amp_getvol(tas_priv, ucontrol, mc); dev_dbg(tas_priv->dev, "%s: kcontrol %s: %ld\n", __func__, kcontrol->id.name, ucontrol->value.integer.value[0]); - mutex_unlock(&tas_priv->codec_lock); - return ret; } @@ -200,19 +200,14 @@ static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol, struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - int ret; - mutex_lock(&tas_priv->codec_lock); + guard(mutex)(&tas_priv->codec_lock); dev_dbg(tas_priv->dev, "%s: kcontrol %s: -> %ld\n", __func__, kcontrol->id.name, ucontrol->value.integer.value[0]); /* The check of the given value is in tasdevice_amp_putvol. */ - ret = tasdevice_amp_putvol(tas_priv, ucontrol, mc); - - mutex_unlock(&tas_priv->codec_lock); - - return ret; + return tasdevice_amp_putvol(tas_priv, ucontrol, mc); } static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol, @@ -220,14 +215,12 @@ static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol, { struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas_priv->codec_lock); + guard(mutex)(&tas_priv->codec_lock); ucontrol->value.integer.value[0] = (int)tas_priv->force_fwload_status; dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", __func__, kcontrol->id.name, tas_priv->force_fwload_status); - mutex_unlock(&tas_priv->codec_lock); - return 0; } @@ -237,7 +230,7 @@ static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol, struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); bool change, val = (bool)ucontrol->value.integer.value[0]; - mutex_lock(&tas_priv->codec_lock); + guard(mutex)(&tas_priv->codec_lock); dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", __func__, kcontrol->id.name, @@ -250,8 +243,6 @@ static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol, tas_priv->force_fwload_status = val; } - mutex_unlock(&tas_priv->codec_lock); - return change; } @@ -272,6 +263,17 @@ static const struct snd_kcontrol_new tas2781_snd_controls[] = { tas2781_force_fwload_get, tas2781_force_fwload_put), }; +static const struct snd_kcontrol_new tas5825_snd_controls[] = { + ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS5825_AMP_LEVEL, + 0, 0, 31, 1, tas2781_amp_getvol, + tas2781_amp_putvol, tas5825_amp_tlv), + ACARD_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS5825_DVC_LEVEL, + 0, 0, 254, 1, tas2781_amp_getvol, + tas2781_amp_putvol, tas5825_dvc_tlv), + ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0, + tas2781_force_fwload_get, tas2781_force_fwload_put), +}; + static const struct snd_kcontrol_new tasdevice_prof_ctrl = { .name = "Speaker Profile Id", .iface = SNDRV_CTL_ELEM_IFACE_CARD, @@ -364,7 +366,7 @@ static int tas2563_save_calibration(struct tas2781_hda *h) } if (cd->total_sz != offset) { - dev_err(p->dev, "%s: tot_size(%lu) and offset(%u) dismatch\n", + dev_err(p->dev, "%s: tot_size(%lu) and offset(%u) mismatch\n", __func__, cd->total_sz, offset); return -EINVAL; } @@ -509,6 +511,12 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context) ARRAY_SIZE(tas2781_snd_controls)); tasdevice_dspfw_init(context); break; + case HDA_TAS5825: + tasdev_add_kcontrols(tas_priv, hda_priv->snd_ctls, codec, + &tas5825_snd_controls[0], + ARRAY_SIZE(tas5825_snd_controls)); + tasdevice_dspfw_init(context); + break; case HDA_TAS2563: tasdevice_dspfw_init(context); break; @@ -636,6 +644,7 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt) } else if (strstarts(dev_name(&clt->dev), "i2c-TXNW2781:00-tas2781-hda.0")) { device_name = "TXNW2781"; + hda_priv->hda_chip_id = HDA_TAS2781; hda_priv->save_calibration = tas2781_save_calibration; tas_hda->priv->global_addr = TAS2781_GLOBAL_ADDR; } else if (strstr(dev_name(&clt->dev), "INT8866")) { @@ -647,6 +656,13 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt) hda_priv->hda_chip_id = HDA_TAS2563; hda_priv->save_calibration = tas2563_save_calibration; tas_hda->priv->global_addr = TAS2563_GLOBAL_ADDR; + } else if (strstarts(dev_name(&clt->dev), "i2c-TXNW5825")) { + /* + * TAS5825, integrated on-chip DSP without + * global I2C address and calibration supported. + */ + device_name = "TXNW5825"; + hda_priv->hda_chip_id = HDA_TAS5825; } else { return -ENODEV; } @@ -692,7 +708,7 @@ static int tas2781_runtime_suspend(struct device *dev) dev_dbg(tas_hda->dev, "Runtime Suspend\n"); - mutex_lock(&tas_hda->priv->codec_lock); + guard(mutex)(&tas_hda->priv->codec_lock); /* The driver powers up the amplifiers at module load time. * Stop the playback if it's unused. @@ -702,8 +718,6 @@ static int tas2781_runtime_suspend(struct device *dev) tas_hda->priv->playback_started = false; } - mutex_unlock(&tas_hda->priv->codec_lock); - return 0; } @@ -713,12 +727,10 @@ static int tas2781_runtime_resume(struct device *dev) dev_dbg(tas_hda->dev, "Runtime Resume\n"); - mutex_lock(&tas_hda->priv->codec_lock); + guard(mutex)(&tas_hda->priv->codec_lock); tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog); - mutex_unlock(&tas_hda->priv->codec_lock); - return 0; } @@ -728,14 +740,12 @@ static int tas2781_system_suspend(struct device *dev) dev_dbg(tas_hda->priv->dev, "System Suspend\n"); - mutex_lock(&tas_hda->priv->codec_lock); + guard(mutex)(&tas_hda->priv->codec_lock); /* Shutdown chip before system suspend */ if (tas_hda->priv->playback_started) tasdevice_tuning_switch(tas_hda->priv, 1); - mutex_unlock(&tas_hda->priv->codec_lock); - /* * Reset GPIO may be shared, so cannot reset here. * However beyond this point, amps may be powered down. @@ -750,7 +760,7 @@ static int tas2781_system_resume(struct device *dev) dev_dbg(tas_hda->priv->dev, "System Resume\n"); - mutex_lock(&tas_hda->priv->codec_lock); + guard(mutex)(&tas_hda->priv->codec_lock); for (i = 0; i < tas_hda->priv->ndev; i++) { tas_hda->priv->tasdevice[i].cur_book = -1; @@ -763,8 +773,6 @@ static int tas2781_system_resume(struct device *dev) if (tas_hda->priv->playback_started) tasdevice_tuning_switch(tas_hda->priv, 0); - mutex_unlock(&tas_hda->priv->codec_lock); - return 0; } @@ -783,6 +791,7 @@ static const struct acpi_device_id tas2781_acpi_hda_match[] = { {"TIAS2781", 0 }, {"TXNW2770", 0 }, {"TXNW2781", 0 }, + {"TXNW5825", 0 }, {} }; MODULE_DEVICE_TABLE(acpi, tas2781_acpi_hda_match); diff --git a/sound/hda/common/codec.c b/sound/hda/common/codec.c index eb268d442201..c6d44168c7f9 100644 --- a/sound/hda/common/codec.c +++ b/sound/hda/common/codec.c @@ -8,6 +8,7 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/slab.h> +#include <linux/minmax.h> #include <linux/mutex.h> #include <linux/module.h> #include <linux/pm.h> @@ -31,6 +32,22 @@ #define codec_has_clkstop(codec) \ ((codec)->core.power_caps & AC_PWRST_CLKSTOP) +static int call_exec_verb(struct hda_bus *bus, struct hda_codec *codec, + unsigned int cmd, unsigned int flags, + unsigned int *res) +{ + int err; + + CLASS(snd_hda_power_pm, pm)(codec); + guard(mutex)(&bus->core.cmd_mutex); + if (flags & HDA_RW_NO_RESPONSE_FALLBACK) + bus->no_response_fallback = 1; + err = snd_hdac_bus_exec_verb_unlocked(&bus->core, codec->core.addr, + cmd, res); + bus->no_response_fallback = 0; + return err; +} + /* * Send and receive a verb - passed to exec_verb override for hdac_device */ @@ -45,15 +62,7 @@ static int codec_exec_verb(struct hdac_device *dev, unsigned int cmd, return -1; again: - snd_hda_power_up_pm(codec); - mutex_lock(&bus->core.cmd_mutex); - if (flags & HDA_RW_NO_RESPONSE_FALLBACK) - bus->no_response_fallback = 1; - err = snd_hdac_bus_exec_verb_unlocked(&bus->core, codec->core.addr, - cmd, res); - bus->no_response_fallback = 0; - mutex_unlock(&bus->core.cmd_mutex); - snd_hda_power_down_pm(codec); + err = call_exec_verb(bus, codec, cmd, flags, res); if (!codec_in_pm(codec) && res && err == -EAGAIN) { if (bus->response_reset) { codec_dbg(codec, @@ -300,7 +309,7 @@ EXPORT_SYMBOL_GPL(snd_hda_get_conn_index); unsigned int snd_hda_get_num_devices(struct hda_codec *codec, hda_nid_t nid) { unsigned int wcaps = get_wcaps(codec, nid); - unsigned int parm; + int parm; if (!codec->dp_mst || !(wcaps & AC_WCAP_DIGITAL) || get_wcaps_type(wcaps) != AC_WID_PIN) @@ -323,18 +332,16 @@ EXPORT_SYMBOL_GPL(snd_hda_get_num_devices); * Copy the device list. This info is dynamic and so not cached. * Currently called only from hda_proc.c, so not exported. */ -int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, - u8 *dev_list, int max_devices) +unsigned int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, + u8 *dev_list, unsigned int max_devices) { - unsigned int parm; - int i, dev_len, devices; + unsigned int parm, i, dev_len, devices; parm = snd_hda_get_num_devices(codec, nid); if (!parm) /* not multi-stream capable */ return 0; - dev_len = parm + 1; - dev_len = dev_len < max_devices ? dev_len : max_devices; + dev_len = min(parm + 1, max_devices); devices = 0; while (devices < dev_len) { @@ -523,11 +530,11 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid) #ifdef CONFIG_SND_HDA_RECONFIG { unsigned int cfg = 0; - mutex_lock(&codec->user_mutex); - pin = look_up_pincfg(codec, &codec->user_pins, nid); - if (pin) - cfg = pin->cfg; - mutex_unlock(&codec->user_mutex); + scoped_guard(mutex, &codec->user_mutex) { + pin = look_up_pincfg(codec, &codec->user_pins, nid); + if (pin) + cfg = pin->cfg; + } if (cfg) return cfg; } @@ -634,12 +641,11 @@ static void hda_jackpoll_work(struct work_struct *work) return; /* the power-up/down sequence triggers the runtime resume */ - snd_hda_power_up(codec); + CLASS(snd_hda_power, pm)(codec); /* update jacks manually if polling is required, too */ snd_hda_jack_set_dirty_all(codec); snd_hda_jack_poll_all(codec); schedule_delayed_work(&codec->jackpoll_work, codec->jackpoll_interval); - snd_hda_power_down(codec); } /* release all pincfg lists */ @@ -1742,9 +1748,9 @@ int snd_hda_lock_devices(struct hda_bus *bus) struct snd_card *card = bus->card; struct hda_codec *codec; - spin_lock(&card->files_lock); + guard(spinlock)(&card->files_lock); if (card->shutdown) - goto err_unlock; + return -EINVAL; card->shutdown = 1; if (!list_empty(&card->ctl_files)) goto err_clear; @@ -1759,13 +1765,10 @@ int snd_hda_lock_devices(struct hda_bus *bus) goto err_clear; } } - spin_unlock(&card->files_lock); return 0; err_clear: card->shutdown = 0; - err_unlock: - spin_unlock(&card->files_lock); return -EINVAL; } EXPORT_SYMBOL_GPL(snd_hda_lock_devices); @@ -1778,9 +1781,8 @@ void snd_hda_unlock_devices(struct hda_bus *bus) { struct snd_card *card = bus->card; - spin_lock(&card->files_lock); + guard(spinlock)(&card->files_lock); card->shutdown = 0; - spin_unlock(&card->files_lock); } EXPORT_SYMBOL_GPL(snd_hda_unlock_devices); @@ -1852,14 +1854,14 @@ static int check_follower_present(struct hda_codec *codec, /* call kctl->put with the given value(s) */ static int put_kctl_with_value(struct snd_kcontrol *kctl, int val) { - struct snd_ctl_elem_value *ucontrol; + struct snd_ctl_elem_value *ucontrol __free(kfree) = NULL; + ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL); if (!ucontrol) return -ENOMEM; ucontrol->value.integer.value[0] = val; ucontrol->value.integer.value[1] = val; kctl->put(kctl, ucontrol); - kfree(ucontrol); return 0; } @@ -2172,13 +2174,12 @@ static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol, if (WARN_ON(codec->spdif_out.used <= idx)) return -EINVAL; - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); spdif = snd_array_elem(&codec->spdif_out, idx); ucontrol->value.iec958.status[0] = spdif->status & 0xff; ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff; ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff; ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff; - mutex_unlock(&codec->spdif_mutex); return 0; } @@ -2281,7 +2282,7 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, if (WARN_ON(codec->spdif_out.used <= idx)) return -EINVAL; - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); spdif = snd_array_elem(&codec->spdif_out, idx); nid = spdif->nid; spdif->status = ucontrol->value.iec958.status[0] | @@ -2294,7 +2295,6 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, spdif->ctls = val; if (change && nid != (u16)-1) set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff); - mutex_unlock(&codec->spdif_mutex); return change; } @@ -2309,10 +2309,9 @@ static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol, if (WARN_ON(codec->spdif_out.used <= idx)) return -EINVAL; - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); spdif = snd_array_elem(&codec->spdif_out, idx); ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE; - mutex_unlock(&codec->spdif_mutex); return 0; } @@ -2339,7 +2338,7 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, if (WARN_ON(codec->spdif_out.used <= idx)) return -EINVAL; - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); spdif = snd_array_elem(&codec->spdif_out, idx); nid = spdif->nid; val = spdif->ctls & ~AC_DIG1_ENABLE; @@ -2349,7 +2348,6 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, spdif->ctls = val; if (change && nid != (u16)-1) set_spdif_ctls(codec, nid, val & 0xff, -1); - mutex_unlock(&codec->spdif_mutex); return change; } @@ -2494,10 +2492,9 @@ void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx) if (WARN_ON(codec->spdif_out.used <= idx)) return; - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); spdif = snd_array_elem(&codec->spdif_out, idx); spdif->nid = (u16)-1; - mutex_unlock(&codec->spdif_mutex); } EXPORT_SYMBOL_GPL(snd_hda_spdif_ctls_unassign); @@ -2516,14 +2513,13 @@ void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid) if (WARN_ON(codec->spdif_out.used <= idx)) return; - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); spdif = snd_array_elem(&codec->spdif_out, idx); if (spdif->nid != nid) { spdif->nid = nid; val = spdif->ctls; set_spdif_ctls(codec, nid, val & 0xff, (val >> 8) & 0xff); } - mutex_unlock(&codec->spdif_mutex); } EXPORT_SYMBOL_GPL(snd_hda_spdif_ctls_assign); @@ -2598,14 +2594,13 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, unsigned int val = !!ucontrol->value.integer.value[0]; int change; - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); change = codec->spdif_in_enable != val; if (change) { codec->spdif_in_enable = val; snd_hdac_regmap_write(&codec->core, nid, AC_VERB_SET_DIGI_CONVERT_1, val); } - mutex_unlock(&codec->spdif_mutex); return change; } @@ -3175,7 +3170,8 @@ int snd_hda_codec_prepare(struct hda_codec *codec, struct snd_pcm_substream *substream) { int ret; - mutex_lock(&codec->bus->prepare_mutex); + + guard(mutex)(&codec->bus->prepare_mutex); if (hinfo->ops.prepare) ret = hinfo->ops.prepare(hinfo, codec, stream, format, substream); @@ -3183,7 +3179,6 @@ int snd_hda_codec_prepare(struct hda_codec *codec, ret = -ENODEV; if (ret >= 0) purify_inactive_streams(codec); - mutex_unlock(&codec->bus->prepare_mutex); return ret; } EXPORT_SYMBOL_GPL(snd_hda_codec_prepare); @@ -3200,10 +3195,9 @@ void snd_hda_codec_cleanup(struct hda_codec *codec, struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { - mutex_lock(&codec->bus->prepare_mutex); + guard(mutex)(&codec->bus->prepare_mutex); if (hinfo->ops.cleanup) hinfo->ops.cleanup(hinfo, codec, substream); - mutex_unlock(&codec->bus->prepare_mutex); } EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup); @@ -3633,12 +3627,11 @@ static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid) int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout) { - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); if (mout->dig_out_used == HDA_DIG_ANALOG_DUP) /* already opened as analog dup; reset it once */ cleanup_dig_out_stream(codec, mout->dig_out_nid); mout->dig_out_used = HDA_DIG_EXCLUSIVE; - mutex_unlock(&codec->spdif_mutex); return 0; } EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_open); @@ -3657,9 +3650,8 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, unsigned int format, struct snd_pcm_substream *substream) { - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format); - mutex_unlock(&codec->spdif_mutex); return 0; } EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_prepare); @@ -3672,9 +3664,8 @@ EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_prepare); int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec, struct hda_multi_out *mout) { - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); cleanup_dig_out_stream(codec, mout->dig_out_nid); - mutex_unlock(&codec->spdif_mutex); return 0; } EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_cleanup); @@ -3687,9 +3678,8 @@ EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_cleanup); int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout) { - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); mout->dig_out_used = 0; - mutex_unlock(&codec->spdif_mutex); return 0; } EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_close); @@ -3729,7 +3719,7 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec, NULL, &mout->spdif_maxbps); } - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); if (mout->share_spdif) { if ((runtime->hw.rates & mout->spdif_rates) && (runtime->hw.formats & mout->spdif_formats)) { @@ -3742,7 +3732,6 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec, /* FIXME: need notify? */ } } - mutex_unlock(&codec->spdif_mutex); } return snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); @@ -3771,23 +3760,23 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_spdif_out *spdif; int i; - mutex_lock(&codec->spdif_mutex); - spdif = snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid); - if (mout->dig_out_nid && mout->share_spdif && - mout->dig_out_used != HDA_DIG_EXCLUSIVE) { - if (chs == 2 && spdif != NULL && - snd_hda_is_supported_format(codec, mout->dig_out_nid, - format) && - !(spdif->status & IEC958_AES0_NONAUDIO)) { - mout->dig_out_used = HDA_DIG_ANALOG_DUP; - setup_dig_out_stream(codec, mout->dig_out_nid, - stream_tag, format); - } else { - mout->dig_out_used = 0; - cleanup_dig_out_stream(codec, mout->dig_out_nid); + scoped_guard(mutex, &codec->spdif_mutex) { + spdif = snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid); + if (mout->dig_out_nid && mout->share_spdif && + mout->dig_out_used != HDA_DIG_EXCLUSIVE) { + if (chs == 2 && spdif != NULL && + snd_hda_is_supported_format(codec, mout->dig_out_nid, + format) && + !(spdif->status & IEC958_AES0_NONAUDIO)) { + mout->dig_out_used = HDA_DIG_ANALOG_DUP; + setup_dig_out_stream(codec, mout->dig_out_nid, + stream_tag, format); + } else { + mout->dig_out_used = 0; + cleanup_dig_out_stream(codec, mout->dig_out_nid); + } } } - mutex_unlock(&codec->spdif_mutex); /* front */ snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, @@ -3854,12 +3843,11 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, if (mout->extra_out_nid[i]) snd_hda_codec_cleanup_stream(codec, mout->extra_out_nid[i]); - mutex_lock(&codec->spdif_mutex); + guard(mutex)(&codec->spdif_mutex); if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) { cleanup_dig_out_stream(codec, mout->dig_out_nid); mout->dig_out_used = 0; } - mutex_unlock(&codec->spdif_mutex); return 0; } EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_cleanup); diff --git a/sound/hda/common/controller.c b/sound/hda/common/controller.c index 84387ed761be..b1cfd9bd4dcb 100644 --- a/sound/hda/common/controller.c +++ b/sound/hda/common/controller.c @@ -32,8 +32,11 @@ #include "controller_trace.h" /* DSP lock helpers */ -#define dsp_lock(dev) snd_hdac_dsp_lock(azx_stream(dev)) -#define dsp_unlock(dev) snd_hdac_dsp_unlock(azx_stream(dev)) +#ifdef CONFIG_SND_HDA_DSP_LOADER +#define guard_dsp_lock(dev) guard(snd_hdac_dsp_lock)(azx_stream(dev)) +#else +#define guard_dsp_lock(dev) do {} while (0) +#endif #define dsp_is_locked(dev) snd_hdac_stream_is_locked(azx_stream(dev)) /* assign a stream for the PCM */ @@ -93,12 +96,12 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) struct azx_dev *azx_dev = get_azx_dev(substream); trace_azx_pcm_close(chip, azx_dev); - mutex_lock(&chip->open_mutex); - azx_release_device(azx_dev); - if (hinfo->ops.close) - hinfo->ops.close(hinfo, apcm->codec, substream); - snd_hda_power_down(apcm->codec); - mutex_unlock(&chip->open_mutex); + scoped_guard(mutex, &chip->open_mutex) { + azx_release_device(azx_dev); + if (hinfo->ops.close) + hinfo->ops.close(hinfo, apcm->codec, substream); + snd_hda_power_down(apcm->codec); + } snd_hda_codec_pcm_put(apcm->info); return 0; } @@ -110,14 +113,11 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, struct azx *chip = apcm->chip; struct azx_dev *azx_dev = get_azx_dev(substream); struct hdac_stream *hdas = azx_stream(azx_dev); - int ret = 0; trace_azx_pcm_hw_params(chip, azx_dev); - dsp_lock(azx_dev); - if (dsp_is_locked(azx_dev)) { - ret = -EBUSY; - goto unlock; - } + guard_dsp_lock(azx_dev); + if (dsp_is_locked(azx_dev)) + return -EBUSY; /* Set up BDLEs here, return -ENOMEM if too many BDLEs are required */ hdas->bufsize = params_buffer_bytes(hw_params); @@ -127,11 +127,9 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, (hw_params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) && (hw_params->flags & SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP); if (snd_hdac_stream_setup_periods(hdas) < 0) - ret = -ENOMEM; + return -ENOMEM; -unlock: - dsp_unlock(azx_dev); - return ret; + return 0; } static int azx_pcm_hw_free(struct snd_pcm_substream *substream) @@ -141,14 +139,13 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); /* reset BDL address */ - dsp_lock(azx_dev); + guard_dsp_lock(azx_dev); if (!dsp_is_locked(azx_dev)) snd_hdac_stream_cleanup(azx_stream(azx_dev)); snd_hda_codec_cleanup(apcm->codec, hinfo, substream); azx_stream(azx_dev)->prepared = 0; - dsp_unlock(azx_dev); return 0; } @@ -166,11 +163,9 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) unsigned short ctls = spdif ? spdif->ctls : 0; trace_azx_pcm_prepare(chip, azx_dev); - dsp_lock(azx_dev); - if (dsp_is_locked(azx_dev)) { - err = -EBUSY; - goto unlock; - } + guard_dsp_lock(azx_dev); + if (dsp_is_locked(azx_dev)) + return -EBUSY; snd_hdac_stream_reset(azx_stream(azx_dev)); bits = snd_hdac_stream_format_bits(runtime->format, SNDRV_PCM_SUBFORMAT_STD, hinfo->maxbps); @@ -180,13 +175,12 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) dev_err(chip->card->dev, "invalid format_val, rate=%d, ch=%d, format=%d\n", runtime->rate, runtime->channels, runtime->format); - err = -EINVAL; - goto unlock; + return -EINVAL; } err = snd_hdac_stream_set_params(azx_stream(azx_dev), format_val); if (err < 0) - goto unlock; + return err; snd_hdac_stream_setup(azx_stream(azx_dev), false); @@ -197,12 +191,11 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) stream_tag -= chip->capture_streams; err = snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag, azx_dev->core.format_val, substream); + if (err < 0) + return err; - unlock: - if (!err) - azx_stream(azx_dev)->prepared = 1; - dsp_unlock(azx_dev); - return err; + azx_stream(azx_dev)->prepared = 1; + return 0; } static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) @@ -252,31 +245,29 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) snd_pcm_trigger_done(s, substream); } - spin_lock(&bus->reg_lock); + scoped_guard(spinlock, &bus->reg_lock) { + /* first, set SYNC bits of corresponding streams */ + snd_hdac_stream_sync_trigger(hstr, true, sbits, sync_reg); - /* first, set SYNC bits of corresponding streams */ - snd_hdac_stream_sync_trigger(hstr, true, sbits, sync_reg); - - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - azx_dev = get_azx_dev(s); - if (start) { - azx_dev->insufficient = 1; - snd_hdac_stream_start(azx_stream(azx_dev)); - } else { - snd_hdac_stream_stop(azx_stream(azx_dev)); + snd_pcm_group_for_each_entry(s, substream) { + if (s->pcm->card != substream->pcm->card) + continue; + azx_dev = get_azx_dev(s); + if (start) { + azx_dev->insufficient = 1; + snd_hdac_stream_start(azx_stream(azx_dev)); + } else { + snd_hdac_stream_stop(azx_stream(azx_dev)); + } } } - spin_unlock(&bus->reg_lock); snd_hdac_stream_sync(hstr, start, sbits); - spin_lock(&bus->reg_lock); + guard(spinlock)(&bus->reg_lock); /* reset SYNC bits */ snd_hdac_stream_sync_trigger(hstr, false, sbits, sync_reg); snd_hdac_stream_timecounter_init(hstr, sbits, start); - spin_unlock(&bus->reg_lock); return 0; } @@ -971,19 +962,18 @@ int snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format, azx_dev = azx_get_dsp_loader_dev(chip); hstr = azx_stream(azx_dev); - spin_lock_irq(&bus->reg_lock); - if (hstr->opened) { - chip->saved_azx_dev = *azx_dev; - saved = true; + scoped_guard(spinlock_irq, &bus->reg_lock) { + if (hstr->opened) { + chip->saved_azx_dev = *azx_dev; + saved = true; + } } - spin_unlock_irq(&bus->reg_lock); err = snd_hdac_dsp_prepare(hstr, format, byte_size, bufp); if (err < 0) { - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); if (saved) *azx_dev = chip->saved_azx_dev; - spin_unlock_irq(&bus->reg_lock); return err; } @@ -1014,11 +1004,10 @@ void snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec, return; snd_hdac_dsp_cleanup(hstr, dmab); - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); if (hstr->opened) *azx_dev = chip->saved_azx_dev; hstr->locked = false; - spin_unlock_irq(&bus->reg_lock); } EXPORT_SYMBOL_GPL(snd_hda_codec_load_dsp_cleanup); #endif /* CONFIG_SND_HDA_DSP_LOADER */ @@ -1079,10 +1068,10 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) if (!pm_runtime_active(chip->card->dev)) return IRQ_NONE; - spin_lock(&bus->reg_lock); + guard(spinlock)(&bus->reg_lock); if (chip->disabled) - goto unlock; + return IRQ_NONE; do { status = azx_readl(chip, INTSTS); @@ -1114,9 +1103,6 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) } } while (active && ++repeat < 10); - unlock: - spin_unlock(&bus->reg_lock); - return IRQ_RETVAL(handled); } EXPORT_SYMBOL_GPL(azx_interrupt); @@ -1136,12 +1122,12 @@ static int probe_codec(struct azx *chip, int addr) int err; unsigned int res = -1; - mutex_lock(&bus->cmd_mutex); - chip->probing = 1; - azx_send_cmd(bus, cmd); - err = azx_get_response(bus, addr, &res); - chip->probing = 0; - mutex_unlock(&bus->cmd_mutex); + scoped_guard(mutex, &bus->cmd_mutex) { + chip->probing = 1; + azx_send_cmd(bus, cmd); + err = azx_get_response(bus, addr, &res); + chip->probing = 0; + } if (err < 0 || res == -1) return -EIO; dev_dbg(chip->card->dev, "codec #%d probed OK\n", addr); diff --git a/sound/hda/common/proc.c b/sound/hda/common/proc.c index 00c2eeb2c472..5f3f61519ba6 100644 --- a/sound/hda/common/proc.c +++ b/sound/hda/common/proc.c @@ -716,16 +716,15 @@ static void print_device_list(struct snd_info_buffer *buffer, { int i, curr = -1; u8 dev_list[AC_MAX_DEV_LIST_LEN]; - int devlist_len; + unsigned int devlist_len; devlist_len = snd_hda_get_devices(codec, nid, dev_list, AC_MAX_DEV_LIST_LEN); - snd_iprintf(buffer, " Devices: %d\n", devlist_len); - if (devlist_len <= 0) + snd_iprintf(buffer, " Devices: %u\n", devlist_len); + if (devlist_len == 0) return; - curr = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_DEVICE_SEL, 0); + curr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DEVICE_SEL, 0); for (i = 0; i < devlist_len; i++) { if (i == curr) @@ -782,7 +781,7 @@ static void print_codec_info(struct snd_info_entry *entry, fg = codec->core.afg; if (!fg) return; - snd_hda_power_up(codec); + CLASS(snd_hda_power, pm)(codec); snd_iprintf(buffer, "Default PCM:\n"); print_pcm_caps(buffer, codec, fg); snd_iprintf(buffer, "Default Amp-In caps: "); @@ -795,7 +794,6 @@ static void print_codec_info(struct snd_info_entry *entry, nodes = snd_hda_get_sub_nodes(codec, fg, &nid); if (! nid || nodes < 0) { snd_iprintf(buffer, "Invalid AFG subtree\n"); - snd_hda_power_down(codec); return; } @@ -932,7 +930,6 @@ static void print_codec_info(struct snd_info_entry *entry, kfree(conn); } - snd_hda_power_down(codec); } /* diff --git a/sound/hda/common/sysfs.c b/sound/hda/common/sysfs.c index 140e24bf4d7f..f8c8483fd5e5 100644 --- a/sound/hda/common/sysfs.c +++ b/sound/hda/common/sysfs.c @@ -81,12 +81,12 @@ static ssize_t pin_configs_show(struct hda_codec *codec, { const struct hda_pincfg *pin; int i, len = 0; - mutex_lock(&codec->user_mutex); + + guard(mutex)(&codec->user_mutex); snd_array_for_each(list, i, pin) { len += sysfs_emit_at(buf, len, "0x%02x 0x%08x\n", pin->nid, pin->cfg); } - mutex_unlock(&codec->user_mutex); return len; } @@ -129,21 +129,18 @@ static int reconfig_codec(struct hda_codec *codec) { int err; - snd_hda_power_up(codec); + CLASS(snd_hda_power, pm)(codec); codec_info(codec, "hda-codec: reconfiguring\n"); err = snd_hda_codec_reset(codec); if (err < 0) { codec_err(codec, "The codec is being used, can't reconfigure.\n"); - goto error; + return err; } err = device_reprobe(hda_codec_dev(codec)); if (err < 0) - goto error; - err = snd_card_register(codec->card); - error: - snd_hda_power_down(codec); - return err; + return err; + return snd_card_register(codec->card); } /* @@ -218,12 +215,12 @@ static ssize_t init_verbs_show(struct device *dev, struct hda_codec *codec = dev_get_drvdata(dev); const struct hda_verb *v; int i, len = 0; - mutex_lock(&codec->user_mutex); + + guard(mutex)(&codec->user_mutex); snd_array_for_each(&codec->init_verbs, i, v) { len += sysfs_emit_at(buf, len, "0x%02x 0x%03x 0x%04x\n", v->nid, v->verb, v->param); } - mutex_unlock(&codec->user_mutex); return len; } @@ -236,16 +233,13 @@ static int parse_init_verbs(struct hda_codec *codec, const char *buf) return -EINVAL; if (!nid || !verb) return -EINVAL; - mutex_lock(&codec->user_mutex); + guard(mutex)(&codec->user_mutex); v = snd_array_new(&codec->init_verbs); - if (!v) { - mutex_unlock(&codec->user_mutex); + if (!v) return -ENOMEM; - } v->nid = nid; v->verb = verb; v->param = param; - mutex_unlock(&codec->user_mutex); return 0; } @@ -267,12 +261,12 @@ static ssize_t hints_show(struct device *dev, struct hda_codec *codec = dev_get_drvdata(dev); const struct hda_hint *hint; int i, len = 0; - mutex_lock(&codec->user_mutex); + + guard(mutex)(&codec->user_mutex); snd_array_for_each(&codec->hints, i, hint) { len += sysfs_emit_at(buf, len, "%s = %s\n", hint->key, hint->val); } - mutex_unlock(&codec->user_mutex); return len; } @@ -305,9 +299,9 @@ static void remove_trail_spaces(char *str) static int parse_hints(struct hda_codec *codec, const char *buf) { - char *key, *val; + char *key __free(kfree) = NULL; + char *val; struct hda_hint *hint; - int err = 0; buf = skip_spaces(buf); if (!*buf || *buf == '#' || *buf == '\n') @@ -319,39 +313,29 @@ static int parse_hints(struct hda_codec *codec, const char *buf) return -ENOMEM; /* extract key and val */ val = strchr(key, '='); - if (!val) { - kfree(key); + if (!val) return -EINVAL; - } *val++ = 0; val = skip_spaces(val); remove_trail_spaces(key); remove_trail_spaces(val); - mutex_lock(&codec->user_mutex); + guard(mutex)(&codec->user_mutex); hint = get_hint(codec, key); if (hint) { /* replace */ kfree(hint->key); - hint->key = key; - hint->val = val; - goto unlock; + goto replace; } /* allocate a new hint entry */ if (codec->hints.used >= MAX_HINTS) - hint = NULL; - else - hint = snd_array_new(&codec->hints); - if (hint) { - hint->key = key; - hint->val = val; - } else { - err = -ENOMEM; - } - unlock: - mutex_unlock(&codec->user_mutex); - if (err) - kfree(key); - return err; + return -ENOMEM; + hint = snd_array_new(&codec->hints); + if (!hint) + return -ENOMEM; + replace: + hint->key = no_free_ptr(key); + hint->val = val; + return 0; } static ssize_t hints_store(struct device *dev, @@ -375,16 +359,14 @@ static ssize_t user_pin_configs_show(struct device *dev, static int parse_user_pin_configs(struct hda_codec *codec, const char *buf) { - int nid, cfg, err; + int nid, cfg; if (sscanf(buf, "%i %i", &nid, &cfg) != 2) return -EINVAL; if (!nid) return -EINVAL; - mutex_lock(&codec->user_mutex); - err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg); - mutex_unlock(&codec->user_mutex); - return err; + guard(mutex)(&codec->user_mutex); + return snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg); } static ssize_t user_pin_configs_store(struct device *dev, @@ -432,26 +414,19 @@ EXPORT_SYMBOL_GPL(snd_hda_get_hint); int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key) { const char *p; - int ret; - mutex_lock(&codec->user_mutex); + guard(mutex)(&codec->user_mutex); p = snd_hda_get_hint(codec, key); if (!p || !*p) - ret = -ENOENT; - else { - switch (toupper(*p)) { - case 'T': /* true */ - case 'Y': /* yes */ - case '1': - ret = 1; - break; - default: - ret = 0; - break; - } + return -ENOENT; + switch (toupper(*p)) { + case 'T': /* true */ + case 'Y': /* yes */ + case '1': + return 1; + default: + return 0; } - mutex_unlock(&codec->user_mutex); - return ret; } EXPORT_SYMBOL_GPL(snd_hda_get_bool_hint); @@ -469,20 +444,17 @@ int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp) { const char *p; unsigned long val; - int ret; - mutex_lock(&codec->user_mutex); + guard(mutex)(&codec->user_mutex); p = snd_hda_get_hint(codec, key); if (!p) - ret = -ENOENT; + return -ENOENT; else if (kstrtoul(p, 0, &val)) - ret = -EINVAL; + return -EINVAL; else { *valp = val; - ret = 0; + return 0; } - mutex_unlock(&codec->user_mutex); - return ret; } EXPORT_SYMBOL_GPL(snd_hda_get_int_hint); #endif /* CONFIG_SND_HDA_RECONFIG */ diff --git a/sound/hda/controllers/intel.c b/sound/hda/controllers/intel.c index 1bb3ff55b115..48c52a207024 100644 --- a/sound/hda/controllers/intel.c +++ b/sound/hda/controllers/intel.c @@ -764,12 +764,11 @@ static void azx_clear_irq_pending(struct azx *chip) struct hdac_bus *bus = azx_bus(chip); struct hdac_stream *s; - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); list_for_each_entry(s, &bus->stream_list, list) { struct azx_dev *azx_dev = stream_to_azx_dev(s); azx_dev->irq_pending = 0; } - spin_unlock_irq(&bus->reg_lock); } static int azx_acquire_irq(struct azx *chip, int do_disconnect) @@ -915,17 +914,17 @@ static void azx_shutdown_chip(struct azx *chip) static void azx_add_card_list(struct azx *chip) { struct hda_intel *hda = container_of(chip, struct hda_intel, chip); - mutex_lock(&card_list_lock); + + guard(mutex)(&card_list_lock); list_add(&hda->list, &card_list); - mutex_unlock(&card_list_lock); } static void azx_del_card_list(struct azx *chip) { struct hda_intel *hda = container_of(chip, struct hda_intel, chip); - mutex_lock(&card_list_lock); + + guard(mutex)(&card_list_lock); list_del_init(&hda->list); - mutex_unlock(&card_list_lock); } /* trigger power-save check at writing parameter */ @@ -942,7 +941,7 @@ static int __maybe_unused param_set_xint(const char *val, const struct kernel_pa if (pm_blacklist > 0) return 0; - mutex_lock(&card_list_lock); + guard(mutex)(&card_list_lock); list_for_each_entry(hda, &card_list, list) { chip = &hda->chip; if (!hda->probe_continued || chip->disabled || @@ -950,7 +949,6 @@ static int __maybe_unused param_set_xint(const char *val, const struct kernel_pa continue; snd_hda_set_power_save(&chip->bus, power_save * 1000); } - mutex_unlock(&card_list_lock); return 0; } diff --git a/sound/hda/core/bus.c b/sound/hda/core/bus.c index d497414a5538..9b196c915f37 100644 --- a/sound/hda/core/bus.c +++ b/sound/hda/core/bus.c @@ -87,12 +87,8 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_exit); int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, unsigned int cmd, unsigned int *res) { - int err; - - mutex_lock(&bus->cmd_mutex); - err = snd_hdac_bus_exec_verb_unlocked(bus, addr, cmd, res); - mutex_unlock(&bus->cmd_mutex); - return err; + guard(mutex)(&bus->cmd_mutex); + return snd_hdac_bus_exec_verb_unlocked(bus, addr, cmd, res); } /** diff --git a/sound/hda/core/component.c b/sound/hda/core/component.c index 9c82a2864a2f..04755903880e 100644 --- a/sound/hda/core/component.c +++ b/sound/hda/core/component.c @@ -69,14 +69,14 @@ void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable) dev_dbg(bus->dev, "display power %s\n", str_enable_disable(enable)); - mutex_lock(&bus->lock); + guard(mutex)(&bus->lock); if (enable) set_bit(idx, &bus->display_power_status); else clear_bit(idx, &bus->display_power_status); if (!acomp || !acomp->ops) - goto unlock; + return; if (bus->display_power_status) { if (!bus->display_power_active) { @@ -99,8 +99,6 @@ void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable) bus->display_power_active = 0; } } - unlock: - mutex_unlock(&bus->lock); } EXPORT_SYMBOL_GPL(snd_hdac_display_power); diff --git a/sound/hda/core/controller.c b/sound/hda/core/controller.c index b5c833b9f8b9..a7c00ad80117 100644 --- a/sound/hda/core/controller.c +++ b/sound/hda/core/controller.c @@ -44,7 +44,7 @@ void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus) { WARN_ON_ONCE(!bus->rb.area); - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); /* CORB set up */ bus->corb.addr = bus->rb.addr; bus->corb.buf = (__le32 *)bus->rb.area; @@ -86,7 +86,6 @@ void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus) snd_hdac_chip_writeb(bus, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN); /* Accept unsolicited responses */ snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL); - spin_unlock_irq(&bus->reg_lock); } EXPORT_SYMBOL_GPL(snd_hdac_bus_init_cmd_io); @@ -112,18 +111,17 @@ static void hdac_wait_for_cmd_dmas(struct hdac_bus *bus) */ void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus) { - spin_lock_irq(&bus->reg_lock); - /* disable ringbuffer DMAs */ - snd_hdac_chip_writeb(bus, RIRBCTL, 0); - snd_hdac_chip_writeb(bus, CORBCTL, 0); - spin_unlock_irq(&bus->reg_lock); + scoped_guard(spinlock_irq, &bus->reg_lock) { + /* disable ringbuffer DMAs */ + snd_hdac_chip_writeb(bus, RIRBCTL, 0); + snd_hdac_chip_writeb(bus, CORBCTL, 0); + } hdac_wait_for_cmd_dmas(bus); - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); /* disable unsolicited responses */ snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, 0); - spin_unlock_irq(&bus->reg_lock); } EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_cmd_io); @@ -171,9 +169,8 @@ static int snd_hdac_bus_send_cmd_pio(struct hdac_bus *bus, unsigned int val) { unsigned int addr = azx_command_addr(val); int timeout = 50; - int ret = -EIO; - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); while (timeout--) { /* check ICB bit */ @@ -184,8 +181,7 @@ static int snd_hdac_bus_send_cmd_pio(struct hdac_bus *bus, unsigned int val) /* Set ICB bit */ snd_hdac_chip_updatew(bus, IRS, AZX_IRS_BUSY, AZX_IRS_BUSY); - ret = snd_hdac_bus_wait_for_pio_response(bus, addr); - goto out; + return snd_hdac_bus_wait_for_pio_response(bus, addr); } udelay(1); } @@ -193,10 +189,7 @@ static int snd_hdac_bus_send_cmd_pio(struct hdac_bus *bus, unsigned int val) dev_dbg_ratelimited(bus->dev, "send_cmd_pio timeout: IRS=%#x, val=%#x\n", snd_hdac_chip_readw(bus, IRS), val); -out: - spin_unlock_irq(&bus->reg_lock); - - return ret; + return -EIO; } /** @@ -228,7 +221,7 @@ static int snd_hdac_bus_send_cmd_corb(struct hdac_bus *bus, unsigned int val) unsigned int addr = azx_command_addr(val); unsigned int wp, rp; - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); bus->last_cmd[azx_command_addr(val)] = val; @@ -236,7 +229,6 @@ static int snd_hdac_bus_send_cmd_corb(struct hdac_bus *bus, unsigned int val) wp = snd_hdac_chip_readw(bus, CORBWP); if (wp == 0xffff) { /* something wrong, controller likely turned to D3 */ - spin_unlock_irq(&bus->reg_lock); return -EIO; } wp++; @@ -245,7 +237,6 @@ static int snd_hdac_bus_send_cmd_corb(struct hdac_bus *bus, unsigned int val) rp = snd_hdac_chip_readw(bus, CORBRP); if (wp == rp) { /* oops, it's full */ - spin_unlock_irq(&bus->reg_lock); return -EAGAIN; } @@ -253,8 +244,6 @@ static int snd_hdac_bus_send_cmd_corb(struct hdac_bus *bus, unsigned int val) bus->corb.buf[wp] = cpu_to_le32(val); snd_hdac_chip_writew(bus, CORBWP, wp); - spin_unlock_irq(&bus->reg_lock); - return 0; } @@ -333,21 +322,20 @@ static int snd_hdac_bus_get_response_rirb(struct hdac_bus *bus, timeout = jiffies + msecs_to_jiffies(1000); for (loopcounter = 0;; loopcounter++) { - spin_lock_irq(&bus->reg_lock); - if (!bus->polling_mode) - prepare_to_wait(&bus->rirb_wq, &wait, - TASK_UNINTERRUPTIBLE); - if (bus->polling_mode) - snd_hdac_bus_update_rirb(bus); - if (!bus->rirb.cmds[addr]) { - if (res) - *res = bus->rirb.res[addr]; /* the last value */ + scoped_guard(spinlock_irq, &bus->reg_lock) { if (!bus->polling_mode) - finish_wait(&bus->rirb_wq, &wait); - spin_unlock_irq(&bus->reg_lock); - return 0; + prepare_to_wait(&bus->rirb_wq, &wait, + TASK_UNINTERRUPTIBLE); + if (bus->polling_mode) + snd_hdac_bus_update_rirb(bus); + if (!bus->rirb.cmds[addr]) { + if (res) + *res = bus->rirb.res[addr]; /* the last value */ + if (!bus->polling_mode) + finish_wait(&bus->rirb_wq, &wait); + return 0; + } } - spin_unlock_irq(&bus->reg_lock); if (time_after(jiffies, timeout)) break; #define LOOP_COUNT_MAX 3000 diff --git a/sound/hda/core/device.c b/sound/hda/core/device.c index 018f9e176b1b..160c8d0453b0 100644 --- a/sound/hda/core/device.c +++ b/sound/hda/core/device.c @@ -147,9 +147,9 @@ int snd_hdac_device_register(struct hdac_device *codec) err = device_add(&codec->dev); if (err < 0) return err; - mutex_lock(&codec->widget_lock); - err = hda_widget_sysfs_init(codec); - mutex_unlock(&codec->widget_lock); + scoped_guard(mutex, &codec->widget_lock) { + err = hda_widget_sysfs_init(codec); + } if (err < 0) { device_del(&codec->dev); return err; @@ -166,9 +166,9 @@ EXPORT_SYMBOL_GPL(snd_hdac_device_register); void snd_hdac_device_unregister(struct hdac_device *codec) { if (device_is_registered(&codec->dev)) { - mutex_lock(&codec->widget_lock); - hda_widget_sysfs_exit(codec); - mutex_unlock(&codec->widget_lock); + scoped_guard(mutex, &codec->widget_lock) { + hda_widget_sysfs_exit(codec); + } device_del(&codec->dev); snd_hdac_bus_remove_device(codec->bus, codec); } @@ -411,25 +411,22 @@ int snd_hdac_refresh_widgets(struct hdac_device *codec) * Serialize against multiple threads trying to update the sysfs * widgets array. */ - mutex_lock(&codec->widget_lock); + guard(mutex)(&codec->widget_lock); nums = snd_hdac_get_sub_nodes(codec, codec->afg, &start_nid); if (!start_nid || nums <= 0 || nums >= 0xff) { dev_err(&codec->dev, "cannot read sub nodes for FG 0x%02x\n", codec->afg); - err = -EINVAL; - goto unlock; + return -EINVAL; } err = hda_widget_sysfs_reinit(codec, start_nid, nums); if (err < 0) - goto unlock; + return err; codec->num_nodes = nums; codec->start_nid = start_nid; codec->end_nid = start_nid + nums; -unlock: - mutex_unlock(&codec->widget_lock); - return err; + return 0; } EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets); diff --git a/sound/hda/core/ext/controller.c b/sound/hda/core/ext/controller.c index c84754434d16..9eea3ea2dae0 100644 --- a/sound/hda/core/ext/controller.c +++ b/sound/hda/core/ext/controller.c @@ -300,7 +300,7 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, unsigned long codec_mask; int ret = 0; - mutex_lock(&bus->lock); + guard(mutex)(&bus->lock); /* * if we move from 0 to 1, count will be 1 so power up this link @@ -331,7 +331,6 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, bus->codec_mask = codec_mask; } - mutex_unlock(&bus->lock); return ret; } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_get); @@ -343,7 +342,7 @@ int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *hlink_tmp; bool link_up = false; - mutex_lock(&bus->lock); + guard(mutex)(&bus->lock); /* * if we move from 1 to 0, count will be 0 @@ -369,7 +368,6 @@ int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, } } - mutex_unlock(&bus->lock); return ret; } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_put); diff --git a/sound/hda/core/ext/stream.c b/sound/hda/core/ext/stream.c index a3ac738f1130..b4759198e51d 100644 --- a/sound/hda/core/ext/stream.c +++ b/sound/hda/core/ext/stream.c @@ -163,9 +163,8 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_decouple_locked); void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, struct hdac_ext_stream *hext_stream, bool decouple) { - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); snd_hdac_ext_stream_decouple_locked(bus, hext_stream, decouple); - spin_unlock_irq(&bus->reg_lock); } EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_decouple); @@ -265,7 +264,7 @@ hdac_ext_link_dma_stream_assign(struct hdac_bus *bus, return NULL; } - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); list_for_each_entry(hstream, &bus->stream_list, list) { struct hdac_ext_stream *hext_stream = container_of(hstream, struct hdac_ext_stream, @@ -285,7 +284,6 @@ hdac_ext_link_dma_stream_assign(struct hdac_bus *bus, res->link_locked = 1; res->link_substream = substream; } - spin_unlock_irq(&bus->reg_lock); return res; } @@ -301,7 +299,7 @@ hdac_ext_host_dma_stream_assign(struct hdac_bus *bus, return NULL; } - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); list_for_each_entry(hstream, &bus->stream_list, list) { struct hdac_ext_stream *hext_stream = container_of(hstream, struct hdac_ext_stream, @@ -320,7 +318,6 @@ hdac_ext_host_dma_stream_assign(struct hdac_bus *bus, res->hstream.running = 0; res->hstream.substream = substream; } - spin_unlock_irq(&bus->reg_lock); return res; } @@ -387,22 +384,22 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *hext_stream, int type) break; case HDAC_EXT_STREAM_TYPE_HOST: - spin_lock_irq(&bus->reg_lock); - /* couple link only if not in use */ - if (!hext_stream->link_locked) - snd_hdac_ext_stream_decouple_locked(bus, hext_stream, false); - snd_hdac_stream_release_locked(&hext_stream->hstream); - spin_unlock_irq(&bus->reg_lock); + scoped_guard(spinlock_irq, &bus->reg_lock) { + /* couple link only if not in use */ + if (!hext_stream->link_locked) + snd_hdac_ext_stream_decouple_locked(bus, hext_stream, false); + snd_hdac_stream_release_locked(&hext_stream->hstream); + } break; case HDAC_EXT_STREAM_TYPE_LINK: - spin_lock_irq(&bus->reg_lock); - /* couple host only if not in use */ - if (!hext_stream->hstream.opened) - snd_hdac_ext_stream_decouple_locked(bus, hext_stream, false); - hext_stream->link_locked = 0; - hext_stream->link_substream = NULL; - spin_unlock_irq(&bus->reg_lock); + scoped_guard(spinlock_irq, &bus->reg_lock) { + /* couple host only if not in use */ + if (!hext_stream->hstream.opened) + snd_hdac_ext_stream_decouple_locked(bus, hext_stream, false); + hext_stream->link_locked = 0; + hext_stream->link_substream = NULL; + } break; default: @@ -427,7 +424,7 @@ struct hdac_ext_stream *snd_hdac_ext_cstream_assign(struct hdac_bus *bus, struct hdac_ext_stream *res = NULL; struct hdac_stream *hstream; - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); list_for_each_entry(hstream, &bus->stream_list, list) { struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream); @@ -446,7 +443,6 @@ struct hdac_ext_stream *snd_hdac_ext_cstream_assign(struct hdac_bus *bus, res->hstream.running = 0; res->hstream.cstream = cstream; } - spin_unlock_irq(&bus->reg_lock); return res; } diff --git a/sound/hda/core/regmap.c b/sound/hda/core/regmap.c index 97cee096a286..e7b866fc52c1 100644 --- a/sound/hda/core/regmap.c +++ b/sound/hda/core/regmap.c @@ -425,15 +425,11 @@ EXPORT_SYMBOL_GPL(snd_hdac_regmap_add_vendor_verb); static int reg_raw_write(struct hdac_device *codec, unsigned int reg, unsigned int val) { - int err; - - mutex_lock(&codec->regmap_lock); + guard(mutex)(&codec->regmap_lock); if (!codec->regmap) - err = hda_reg_write(codec, reg, val); + return hda_reg_write(codec, reg, val); else - err = regmap_write(codec->regmap, reg, val); - mutex_unlock(&codec->regmap_lock); - return err; + return regmap_write(codec->regmap, reg, val); } /* a helper macro to call @func_call; retry with power-up if failed */ @@ -466,15 +462,11 @@ EXPORT_SYMBOL_GPL(snd_hdac_regmap_write_raw); static int reg_raw_read(struct hdac_device *codec, unsigned int reg, unsigned int *val, bool uncached) { - int err; - - mutex_lock(&codec->regmap_lock); + guard(mutex)(&codec->regmap_lock); if (uncached || !codec->regmap) - err = hda_reg_read(codec, reg, val); + return hda_reg_read(codec, reg, val); else - err = regmap_read(codec->regmap, reg, val); - mutex_unlock(&codec->regmap_lock); - return err; + return regmap_read(codec->regmap, reg, val); } static int __snd_hdac_regmap_read_raw(struct hdac_device *codec, @@ -515,7 +507,7 @@ static int reg_raw_update(struct hdac_device *codec, unsigned int reg, bool change; int err; - mutex_lock(&codec->regmap_lock); + guard(mutex)(&codec->regmap_lock); if (codec->regmap) { err = regmap_update_bits_check(codec->regmap, reg, mask, val, &change); @@ -533,7 +525,6 @@ static int reg_raw_update(struct hdac_device *codec, unsigned int reg, } } } - mutex_unlock(&codec->regmap_lock); return err; } @@ -556,17 +547,14 @@ EXPORT_SYMBOL_GPL(snd_hdac_regmap_update_raw); static int reg_raw_update_once(struct hdac_device *codec, unsigned int reg, unsigned int mask, unsigned int val) { - int err = 0; - if (!codec->regmap) return reg_raw_update(codec, reg, mask, val); - mutex_lock(&codec->regmap_lock); + guard(mutex)(&codec->regmap_lock); /* Discard any updates to already initialised registers. */ if (!regcache_reg_cached(codec->regmap, reg)) - err = regmap_update_bits(codec->regmap, reg, mask, val); - mutex_unlock(&codec->regmap_lock); - return err; + return regmap_update_bits(codec->regmap, reg, mask, val); + return 0; } /** @@ -593,9 +581,8 @@ EXPORT_SYMBOL_GPL(snd_hdac_regmap_update_raw_once); */ void snd_hdac_regmap_sync(struct hdac_device *codec) { - mutex_lock(&codec->regmap_lock); + guard(mutex)(&codec->regmap_lock); if (codec->regmap) regcache_sync(codec->regmap); - mutex_unlock(&codec->regmap_lock); } EXPORT_SYMBOL_GPL(snd_hdac_regmap_sync); diff --git a/sound/hda/core/stream.c b/sound/hda/core/stream.c index 4a87bef8834f..579ec544ef4a 100644 --- a/sound/hda/core/stream.c +++ b/sound/hda/core/stream.c @@ -370,7 +370,7 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, if (substream->pcm) key |= (substream->pcm->device << 16); - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); list_for_each_entry(azx_dev, &bus->stream_list, list) { if (azx_dev->direction != substream->stream) continue; @@ -389,7 +389,6 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, res->assigned_key = key; res->substream = substream; } - spin_unlock_irq(&bus->reg_lock); return res; } EXPORT_SYMBOL_GPL(snd_hdac_stream_assign); @@ -419,9 +418,8 @@ void snd_hdac_stream_release(struct hdac_stream *azx_dev) { struct hdac_bus *bus = azx_dev->bus; - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); snd_hdac_stream_release_locked(azx_dev); - spin_unlock_irq(&bus->reg_lock); } EXPORT_SYMBOL_GPL(snd_hdac_stream_release); @@ -922,15 +920,12 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, struct hdac_bus *bus = azx_dev->bus; int err; - snd_hdac_dsp_lock(azx_dev); - spin_lock_irq(&bus->reg_lock); - if (azx_dev->running || azx_dev->locked) { - spin_unlock_irq(&bus->reg_lock); - err = -EBUSY; - goto unlock; + guard(snd_hdac_dsp_lock)(azx_dev); + scoped_guard(spinlock_irq, &bus->reg_lock) { + if (azx_dev->running || azx_dev->locked) + return -EBUSY; + azx_dev->locked = true; } - azx_dev->locked = true; - spin_unlock_irq(&bus->reg_lock); err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev, byte_size, bufp); @@ -951,17 +946,14 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, goto error; snd_hdac_stream_setup(azx_dev, true); - snd_hdac_dsp_unlock(azx_dev); return azx_dev->stream_tag; error: snd_dma_free_pages(bufp); err_alloc: - spin_lock_irq(&bus->reg_lock); - azx_dev->locked = false; - spin_unlock_irq(&bus->reg_lock); - unlock: - snd_hdac_dsp_unlock(azx_dev); + scoped_guard(spinlock_irq, &bus->reg_lock) { + azx_dev->locked = false; + } return err; } EXPORT_SYMBOL_GPL(snd_hdac_dsp_prepare); @@ -993,7 +985,7 @@ void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev, if (!dmab->area || !azx_dev->locked) return; - snd_hdac_dsp_lock(azx_dev); + guard(snd_hdac_dsp_lock)(azx_dev); /* reset BDL address */ snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0); snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0); @@ -1005,10 +997,8 @@ void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev, snd_dma_free_pages(dmab); dmab->area = NULL; - spin_lock_irq(&bus->reg_lock); + guard(spinlock_irq)(&bus->reg_lock); azx_dev->locked = false; - spin_unlock_irq(&bus->reg_lock); - snd_hdac_dsp_unlock(azx_dev); } EXPORT_SYMBOL_GPL(snd_hdac_dsp_cleanup); #endif /* CONFIG_SND_HDA_DSP_LOADER */ diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c index c1f7447a4d11..70b3f7e17f9e 100644 --- a/sound/i2c/other/ak4113.c +++ b/sound/i2c/other/ak4113.c @@ -127,9 +127,9 @@ void snd_ak4113_reinit(struct ak4113 *chip) { if (atomic_inc_return(&chip->wq_processing) == 1) cancel_delayed_work_sync(&chip->work); - mutex_lock(&chip->reinit_mutex); - ak4113_init_regs(chip); - mutex_unlock(&chip->reinit_mutex); + scoped_guard(mutex, &chip->reinit_mutex) { + ak4113_init_regs(chip); + } /* bring up statistics / event queing */ if (atomic_dec_and_test(&chip->wq_processing)) schedule_delayed_work(&chip->work, HZ / 10); @@ -185,11 +185,10 @@ static int snd_ak4113_in_error_get(struct snd_kcontrol *kcontrol, { struct ak4113 *chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); ucontrol->value.integer.value[0] = chip->errors[kcontrol->private_value]; chip->errors[kcontrol->private_value] = 0; - spin_unlock_irq(&chip->lock); return 0; } @@ -235,14 +234,13 @@ static int snd_ak4113_rx_put(struct snd_kcontrol *kcontrol, int change; u8 old_val; - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); old_val = chip->regmap[AK4113_REG_IO1]; change = ucontrol->value.integer.value[0] != AK4113_IPS(old_val); if (change) reg_write(chip, AK4113_REG_IO1, (old_val & (~AK4113_IPS(0xff))) | (AK4113_IPS(ucontrol->value.integer.value[0]))); - spin_unlock_irq(&chip->lock); return change; } @@ -532,27 +530,27 @@ int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags) goto __rate; rcs0 = reg_read(ak4113, AK4113_REG_RCS0); rcs2 = reg_read(ak4113, AK4113_REG_RCS2); - spin_lock_irqsave(&ak4113->lock, _flags); - if (rcs0 & AK4113_PAR) - ak4113->errors[AK4113_PARITY_ERRORS]++; - if (rcs0 & AK4113_V) - ak4113->errors[AK4113_V_BIT_ERRORS]++; - if (rcs2 & AK4113_CCRC) - ak4113->errors[AK4113_CCRC_ERRORS]++; - if (rcs2 & AK4113_QCRC) - ak4113->errors[AK4113_QCRC_ERRORS]++; - c0 = (ak4113->rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | - AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)) ^ - (rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | - AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)); - c1 = (ak4113->rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM | - AK4113_DAT | 0xf0)) ^ - (rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM | - AK4113_DAT | 0xf0)); - ak4113->rcs0 = rcs0 & ~(AK4113_QINT | AK4113_CINT | AK4113_STC); - ak4113->rcs1 = rcs1; - ak4113->rcs2 = rcs2; - spin_unlock_irqrestore(&ak4113->lock, _flags); + scoped_guard(spinlock_irqsave, &ak4113->lock) { + if (rcs0 & AK4113_PAR) + ak4113->errors[AK4113_PARITY_ERRORS]++; + if (rcs0 & AK4113_V) + ak4113->errors[AK4113_V_BIT_ERRORS]++; + if (rcs2 & AK4113_CCRC) + ak4113->errors[AK4113_CCRC_ERRORS]++; + if (rcs2 & AK4113_QCRC) + ak4113->errors[AK4113_QCRC_ERRORS]++; + c0 = (ak4113->rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | + AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)) ^ + (rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | + AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)); + c1 = (ak4113->rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM | + AK4113_DAT | 0xf0)) ^ + (rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM | + AK4113_DAT | 0xf0)); + ak4113->rcs0 = rcs0 & ~(AK4113_QINT | AK4113_CINT | AK4113_STC); + ak4113->rcs1 = rcs1; + ak4113->rcs2 = rcs2; + } if (rcs0 & AK4113_PAR) snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index 7c493681f3cb..0e3a272c1490 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c @@ -132,9 +132,9 @@ void snd_ak4114_reinit(struct ak4114 *chip) { if (atomic_inc_return(&chip->wq_processing) == 1) cancel_delayed_work_sync(&chip->work); - mutex_lock(&chip->reinit_mutex); - ak4114_init_regs(chip); - mutex_unlock(&chip->reinit_mutex); + scoped_guard(mutex, &chip->reinit_mutex) { + ak4114_init_regs(chip); + } /* bring up statistics / event queing */ if (atomic_dec_and_test(&chip->wq_processing)) schedule_delayed_work(&chip->work, HZ / 10); @@ -170,11 +170,10 @@ static int snd_ak4114_in_error_get(struct snd_kcontrol *kcontrol, { struct ak4114 *chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); ucontrol->value.integer.value[0] = chip->errors[kcontrol->private_value]; chip->errors[kcontrol->private_value] = 0; - spin_unlock_irq(&chip->lock); return 0; } @@ -552,21 +551,21 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) if (flags & AK4114_CHECK_NO_STAT) goto __rate; rcs0 = reg_read(ak4114, AK4114_REG_RCS0); - spin_lock_irqsave(&ak4114->lock, _flags); - if (rcs0 & AK4114_PAR) - ak4114->errors[AK4114_PARITY_ERRORS]++; - if (rcs1 & AK4114_V) - ak4114->errors[AK4114_V_BIT_ERRORS]++; - if (rcs1 & AK4114_CCRC) - ak4114->errors[AK4114_CCRC_ERRORS]++; - if (rcs1 & AK4114_QCRC) - ak4114->errors[AK4114_QCRC_ERRORS]++; - c0 = (ak4114->rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)) ^ - (rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)); - c1 = (ak4114->rcs1 & 0xf0) ^ (rcs1 & 0xf0); - ak4114->rcs0 = rcs0 & ~(AK4114_QINT | AK4114_CINT); - ak4114->rcs1 = rcs1; - spin_unlock_irqrestore(&ak4114->lock, _flags); + scoped_guard(spinlock_irqsave, &ak4114->lock) { + if (rcs0 & AK4114_PAR) + ak4114->errors[AK4114_PARITY_ERRORS]++; + if (rcs1 & AK4114_V) + ak4114->errors[AK4114_V_BIT_ERRORS]++; + if (rcs1 & AK4114_CCRC) + ak4114->errors[AK4114_CCRC_ERRORS]++; + if (rcs1 & AK4114_QCRC) + ak4114->errors[AK4114_QCRC_ERRORS]++; + c0 = (ak4114->rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)) ^ + (rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)); + c1 = (ak4114->rcs1 & 0xf0) ^ (rcs1 & 0xf0); + ak4114->rcs0 = rcs0 & ~(AK4114_QINT | AK4114_CINT); + ak4114->rcs1 = rcs1; + } ak4114_notify(ak4114, rcs0, rcs1, c0, c1); if (ak4114->change_callback && (c0 | c1) != 0) diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index cd380db195ef..d2ec20f885f0 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c @@ -144,11 +144,10 @@ static int snd_ak4117_in_error_get(struct snd_kcontrol *kcontrol, { struct ak4117 *chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); ucontrol->value.integer.value[0] = chip->errors[kcontrol->private_value]; chip->errors[kcontrol->private_value] = 0; - spin_unlock_irq(&chip->lock); return 0; } @@ -192,12 +191,11 @@ static int snd_ak4117_rx_put(struct snd_kcontrol *kcontrol, int change; u8 old_val; - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); old_val = chip->regmap[AK4117_REG_IO]; change = !!ucontrol->value.integer.value[0] != ((old_val & AK4117_IPS) ? 1 : 0); if (change) reg_write(chip, AK4117_REG_IO, (old_val & ~AK4117_IPS) | (ucontrol->value.integer.value[0] ? AK4117_IPS : 0)); - spin_unlock_irq(&chip->lock); return change; } @@ -441,23 +439,23 @@ int snd_ak4117_check_rate_and_errors(struct ak4117 *ak4117, unsigned int flags) goto __rate; rcs0 = reg_read(ak4117, AK4117_REG_RCS0); rcs2 = reg_read(ak4117, AK4117_REG_RCS2); - spin_lock_irqsave(&ak4117->lock, _flags); - if (rcs0 & AK4117_PAR) - ak4117->errors[AK4117_PARITY_ERRORS]++; - if (rcs0 & AK4117_V) - ak4117->errors[AK4117_V_BIT_ERRORS]++; - if (rcs2 & AK4117_CCRC) - ak4117->errors[AK4117_CCRC_ERRORS]++; - if (rcs2 & AK4117_QCRC) - ak4117->errors[AK4117_QCRC_ERRORS]++; - c0 = (ak4117->rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)) ^ - (rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)); - c1 = (ak4117->rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)) ^ - (rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)); - ak4117->rcs0 = rcs0 & ~(AK4117_QINT | AK4117_CINT | AK4117_STC); - ak4117->rcs1 = rcs1; - ak4117->rcs2 = rcs2; - spin_unlock_irqrestore(&ak4117->lock, _flags); + scoped_guard(spinlock_irqsave, &ak4117->lock) { + if (rcs0 & AK4117_PAR) + ak4117->errors[AK4117_PARITY_ERRORS]++; + if (rcs0 & AK4117_V) + ak4117->errors[AK4117_V_BIT_ERRORS]++; + if (rcs2 & AK4117_CCRC) + ak4117->errors[AK4117_CCRC_ERRORS]++; + if (rcs2 & AK4117_QCRC) + ak4117->errors[AK4117_QCRC_ERRORS]++; + c0 = (ak4117->rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)) ^ + (rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)); + c1 = (ak4117->rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)) ^ + (rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)); + ak4117->rcs0 = rcs0 & ~(AK4117_QINT | AK4117_CINT | AK4117_STC); + ak4117->rcs1 = rcs1; + ak4117->rcs2 = rcs2; + } if (rcs0 & AK4117_PAR) snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[0]->id); diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 400ae547bcba..50f62304de61 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c @@ -96,14 +96,10 @@ static unsigned char snd_ad1816a_get_format(struct snd_ad1816a *chip, static int snd_ad1816a_open(struct snd_ad1816a *chip, unsigned int mode) { - unsigned long flags; + guard(spinlock_irqsave)(&chip->lock); - spin_lock_irqsave(&chip->lock, flags); - - if (chip->mode & mode) { - spin_unlock_irqrestore(&chip->lock, flags); + if (chip->mode & mode) return -EAGAIN; - } switch ((mode &= AD1816A_MODE_OPEN)) { case AD1816A_MODE_PLAYBACK: @@ -126,15 +122,12 @@ static int snd_ad1816a_open(struct snd_ad1816a *chip, unsigned int mode) } chip->mode |= mode; - spin_unlock_irqrestore(&chip->lock, flags); return 0; } static void snd_ad1816a_close(struct snd_ad1816a *chip, unsigned int mode) { - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); switch ((mode &= AD1816A_MODE_OPEN)) { case AD1816A_MODE_PLAYBACK: @@ -158,8 +151,6 @@ static void snd_ad1816a_close(struct snd_ad1816a *chip, unsigned int mode) chip->mode &= ~mode; if (!(chip->mode & AD1816A_MODE_OPEN)) chip->mode = 0; - - spin_unlock_irqrestore(&chip->lock, flags); } @@ -171,19 +162,19 @@ static int snd_ad1816a_trigger(struct snd_ad1816a *chip, unsigned char what, switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_STOP: - spin_lock(&chip->lock); - cmd = (cmd == SNDRV_PCM_TRIGGER_START) ? 0xff: 0x00; - /* if (what & AD1816A_PLAYBACK_ENABLE) */ - /* That is not valid, because playback and capture enable - * are the same bit pattern, just to different addresses - */ - if (! iscapture) - snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, - AD1816A_PLAYBACK_ENABLE, cmd); - else - snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, - AD1816A_CAPTURE_ENABLE, cmd); - spin_unlock(&chip->lock); + scoped_guard(spinlock, &chip->lock) { + cmd = (cmd == SNDRV_PCM_TRIGGER_START) ? 0xff: 0x00; + /* if (what & AD1816A_PLAYBACK_ENABLE) */ + /* That is not valid, because playback and capture enable + * are the same bit pattern, just to different addresses + */ + if (!iscapture) + snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, + AD1816A_PLAYBACK_ENABLE, cmd); + else + snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, + AD1816A_CAPTURE_ENABLE, cmd); + } break; default: dev_warn(chip->card->dev, "invalid trigger mode 0x%x.\n", what); @@ -210,11 +201,10 @@ static int snd_ad1816a_capture_trigger(struct snd_pcm_substream *substream, int static int snd_ad1816a_playback_prepare(struct snd_pcm_substream *substream) { struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - unsigned long flags; struct snd_pcm_runtime *runtime = substream->runtime; unsigned int size, rate; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); chip->p_dma_size = size = snd_pcm_lib_buffer_bytes(substream); snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, @@ -234,19 +224,16 @@ static int snd_ad1816a_playback_prepare(struct snd_pcm_substream *substream) snd_ad1816a_write(chip, AD1816A_PLAYBACK_BASE_COUNT, snd_pcm_lib_period_bytes(substream) / 4 - 1); - - spin_unlock_irqrestore(&chip->lock, flags); return 0; } static int snd_ad1816a_capture_prepare(struct snd_pcm_substream *substream) { struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - unsigned long flags; struct snd_pcm_runtime *runtime = substream->runtime; unsigned int size, rate; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); chip->c_dma_size = size = snd_pcm_lib_buffer_bytes(substream); snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, @@ -266,8 +253,6 @@ static int snd_ad1816a_capture_prepare(struct snd_pcm_substream *substream) snd_ad1816a_write(chip, AD1816A_CAPTURE_BASE_COUNT, snd_pcm_lib_period_bytes(substream) / 4 - 1); - - spin_unlock_irqrestore(&chip->lock, flags); return 0; } @@ -298,9 +283,9 @@ static irqreturn_t snd_ad1816a_interrupt(int irq, void *dev_id) struct snd_ad1816a *chip = dev_id; unsigned char status; - spin_lock(&chip->lock); - status = snd_ad1816a_in(chip, AD1816A_INTERRUPT_STATUS); - spin_unlock(&chip->lock); + scoped_guard(spinlock, &chip->lock) { + status = snd_ad1816a_in(chip, AD1816A_INTERRUPT_STATUS); + } if ((status & AD1816A_PLAYBACK_IRQ_PENDING) && chip->playback_substream) snd_pcm_period_elapsed(chip->playback_substream); @@ -311,9 +296,9 @@ static irqreturn_t snd_ad1816a_interrupt(int irq, void *dev_id) if ((status & AD1816A_TIMER_IRQ_PENDING) && chip->timer) snd_timer_interrupt(chip->timer, chip->timer->sticks); - spin_lock(&chip->lock); - snd_ad1816a_out(chip, AD1816A_INTERRUPT_STATUS, 0x00); - spin_unlock(&chip->lock); + scoped_guard(spinlock, &chip->lock) { + snd_ad1816a_out(chip, AD1816A_INTERRUPT_STATUS, 0x00); + } return IRQ_HANDLED; } @@ -381,9 +366,9 @@ static unsigned long snd_ad1816a_timer_resolution(struct snd_timer *timer) static int snd_ad1816a_timer_start(struct snd_timer *timer) { unsigned short bits; - unsigned long flags; struct snd_ad1816a *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->lock, flags); + + guard(spinlock_irqsave)(&chip->lock); bits = snd_ad1816a_read(chip, AD1816A_INTERRUPT_ENABLE); if (!(bits & AD1816A_TIMER_ENABLE)) { @@ -393,20 +378,16 @@ static int snd_ad1816a_timer_start(struct snd_timer *timer) snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, AD1816A_TIMER_ENABLE, 0xffff); } - spin_unlock_irqrestore(&chip->lock, flags); return 0; } static int snd_ad1816a_timer_stop(struct snd_timer *timer) { - unsigned long flags; struct snd_ad1816a *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, AD1816A_TIMER_ENABLE, 0x0000); - - spin_unlock_irqrestore(&chip->lock, flags); return 0; } @@ -474,9 +455,7 @@ static int snd_ad1816a_capture_close(struct snd_pcm_substream *substream) static void snd_ad1816a_init(struct snd_ad1816a *chip) { - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); snd_ad1816a_out(chip, AD1816A_INTERRUPT_STATUS, 0x00); snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, @@ -488,40 +467,32 @@ static void snd_ad1816a_init(struct snd_ad1816a *chip) AD1816A_CAPTURE_NOT_EQUAL | AD1816A_WSS_ENABLE, 0xffff); snd_ad1816a_write(chip, AD1816A_DSP_CONFIG, 0x0000); snd_ad1816a_write(chip, AD1816A_POWERDOWN_CTRL, 0x0000); - - spin_unlock_irqrestore(&chip->lock, flags); } #ifdef CONFIG_PM void snd_ad1816a_suspend(struct snd_ad1816a *chip) { int reg; - unsigned long flags; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); for (reg = 0; reg < 48; reg++) chip->image[reg] = snd_ad1816a_read(chip, reg); - spin_unlock_irqrestore(&chip->lock, flags); } void snd_ad1816a_resume(struct snd_ad1816a *chip) { int reg; - unsigned long flags; snd_ad1816a_init(chip); - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); for (reg = 0; reg < 48; reg++) snd_ad1816a_write(chip, reg, chip->image[reg]); - spin_unlock_irqrestore(&chip->lock, flags); } #endif static int snd_ad1816a_probe(struct snd_ad1816a *chip) { - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); switch (chip->version = snd_ad1816a_read(chip, AD1816A_VERSION_ID)) { case 0: @@ -536,8 +507,6 @@ static int snd_ad1816a_probe(struct snd_ad1816a *chip) default: chip->hardware = AD1816A_HW_AUTO; } - - spin_unlock_irqrestore(&chip->lock, flags); return 0; } @@ -679,12 +648,10 @@ static int snd_ad1816a_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_el static int snd_ad1816a_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; unsigned short val; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); val = snd_ad1816a_read(chip, AD1816A_ADC_SOURCE_SEL); - spin_unlock_irqrestore(&chip->lock, flags); ucontrol->value.enumerated.item[0] = (val >> 12) & 7; ucontrol->value.enumerated.item[1] = (val >> 4) & 7; return 0; @@ -693,7 +660,6 @@ static int snd_ad1816a_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ele static int snd_ad1816a_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; unsigned short val; int change; @@ -702,10 +668,9 @@ static int snd_ad1816a_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ele return -EINVAL; val = (ucontrol->value.enumerated.item[0] << 12) | (ucontrol->value.enumerated.item[1] << 4); - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); change = snd_ad1816a_read(chip, AD1816A_ADC_SOURCE_SEL) != val; snd_ad1816a_write(chip, AD1816A_ADC_SOURCE_SEL, val); - spin_unlock_irqrestore(&chip->lock, flags); return change; } @@ -735,15 +700,13 @@ static int snd_ad1816a_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl static int snd_ad1816a_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); ucontrol->value.integer.value[0] = (snd_ad1816a_read(chip, reg) >> shift) & mask; - spin_unlock_irqrestore(&chip->lock, flags); if (invert) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; return 0; @@ -752,7 +715,6 @@ static int snd_ad1816a_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_ad1816a_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; @@ -764,12 +726,11 @@ static int snd_ad1816a_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ if (invert) val = mask - val; val <<= shift; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); old_val = snd_ad1816a_read(chip, reg); val = (old_val & ~(mask << shift)) | val; change = val != old_val; snd_ad1816a_write(chip, reg, val); - spin_unlock_irqrestore(&chip->lock, flags); return change; } @@ -800,7 +761,6 @@ static int snd_ad1816a_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl static int snd_ad1816a_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift_left = (kcontrol->private_value >> 8) & 0x0f; int shift_right = (kcontrol->private_value >> 12) & 0x0f; @@ -808,11 +768,10 @@ static int snd_ad1816a_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ int invert = (kcontrol->private_value >> 24) & 0xff; unsigned short val; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); val = snd_ad1816a_read(chip, reg); ucontrol->value.integer.value[0] = (val >> shift_left) & mask; ucontrol->value.integer.value[1] = (val >> shift_right) & mask; - spin_unlock_irqrestore(&chip->lock, flags); if (invert) { ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; @@ -823,7 +782,6 @@ static int snd_ad1816a_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_ad1816a_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift_left = (kcontrol->private_value >> 8) & 0x0f; int shift_right = (kcontrol->private_value >> 12) & 0x0f; @@ -840,12 +798,11 @@ static int snd_ad1816a_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ } val1 <<= shift_left; val2 <<= shift_right; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); old_val = snd_ad1816a_read(chip, reg); val1 = (old_val & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2; change = val1 != old_val; snd_ad1816a_write(chip, reg, val1); - spin_unlock_irqrestore(&chip->lock, flags); return change; } diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index e681c2c82474..3d1f19321b9e 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -269,18 +269,17 @@ static const unsigned char cmi8330_sb_init_values[][2] = { static int cmi8330_add_sb_mixers(struct snd_sb *chip) { int idx, err; - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, 0x00, 0x00); /* mixer reset */ - spin_unlock_irqrestore(&chip->mixer_lock, flags); + scoped_guard(spinlock_irqsave, &chip->mixer_lock) { + snd_sbmixer_write(chip, 0x00, 0x00); /* mixer reset */ + } /* mute and zero volume channels */ for (idx = 0; idx < ARRAY_SIZE(cmi8330_sb_init_values); idx++) { - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, cmi8330_sb_init_values[idx][0], - cmi8330_sb_init_values[idx][1]); - spin_unlock_irqrestore(&chip->mixer_lock, flags); + scoped_guard(spinlock_irqsave, &chip->mixer_lock) { + snd_sbmixer_write(chip, cmi8330_sb_init_values[idx][0], + cmi8330_sb_init_values[idx][1]); + } } for (idx = 0; idx < ARRAY_SIZE(cmi8330_sb_mixers); idx++) { diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index eaaf39aae526..e2c29e831020 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c @@ -169,10 +169,9 @@ static void snd_cs4236_playback_format(struct snd_wss *chip, struct snd_pcm_hw_params *params, unsigned char pdfr) { - unsigned long flags; unsigned char rate = divisor_to_rate_register(params->rate_den); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); /* set fast playback format change and clean playback FIFO */ snd_wss_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x10); @@ -180,17 +179,15 @@ static void snd_cs4236_playback_format(struct snd_wss *chip, snd_wss_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] & ~0x10); snd_cs4236_ext_out(chip, CS4236_DAC_RATE, rate); - spin_unlock_irqrestore(&chip->reg_lock, flags); } static void snd_cs4236_capture_format(struct snd_wss *chip, struct snd_pcm_hw_params *params, unsigned char cdfr) { - unsigned long flags; unsigned char rate = divisor_to_rate_register(params->rate_den); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); /* set fast capture format change and clean capture FIFO */ snd_wss_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x20); @@ -198,7 +195,6 @@ static void snd_cs4236_capture_format(struct snd_wss *chip, snd_wss_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] & ~0x20); snd_cs4236_ext_out(chip, CS4236_ADC_RATE, rate); - spin_unlock_irqrestore(&chip->reg_lock, flags); } #ifdef CONFIG_PM @@ -206,48 +202,45 @@ static void snd_cs4236_capture_format(struct snd_wss *chip, static void snd_cs4236_suspend(struct snd_wss *chip) { int reg; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); for (reg = 0; reg < 32; reg++) chip->image[reg] = snd_wss_in(chip, reg); for (reg = 0; reg < 18; reg++) chip->eimage[reg] = snd_cs4236_ext_in(chip, CS4236_I23VAL(reg)); for (reg = 2; reg < 9; reg++) chip->cimage[reg] = snd_cs4236_ctrl_in(chip, reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); } static void snd_cs4236_resume(struct snd_wss *chip) { int reg; - unsigned long flags; snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - for (reg = 0; reg < 32; reg++) { - switch (reg) { - case CS4236_EXT_REG: - case CS4231_VERSION: - case 27: /* why? CS4235 - master left */ - case 29: /* why? CS4235 - master right */ - break; - default: - snd_wss_out(chip, reg, chip->image[reg]); - break; + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + for (reg = 0; reg < 32; reg++) { + switch (reg) { + case CS4236_EXT_REG: + case CS4231_VERSION: + case 27: /* why? CS4235 - master left */ + case 29: /* why? CS4235 - master right */ + break; + default: + snd_wss_out(chip, reg, chip->image[reg]); + break; + } } - } - for (reg = 0; reg < 18; reg++) - snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), chip->eimage[reg]); - for (reg = 2; reg < 9; reg++) { - switch (reg) { - case 7: - break; - default: - snd_cs4236_ctrl_out(chip, reg, chip->cimage[reg]); + for (reg = 0; reg < 18; reg++) + snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), chip->eimage[reg]); + for (reg = 2; reg < 9; reg++) { + switch (reg) { + case 7: + break; + default: + snd_cs4236_ctrl_out(chip, reg, chip->cimage[reg]); + } } } - spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); } @@ -403,15 +396,13 @@ static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(reg)] >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); if (invert) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; return 0; @@ -420,7 +411,6 @@ static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; @@ -432,11 +422,10 @@ static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (invert) val = mask - val; val <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); val = (chip->eimage[CS4236_REG(reg)] & ~(mask << shift)) | val; change = val != chip->eimage[CS4236_REG(reg)]; snd_cs4236_ext_out(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } @@ -449,15 +438,13 @@ static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.integer.value[0] = (chip->cimage[reg] >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); if (invert) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; return 0; @@ -466,7 +453,6 @@ static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; @@ -478,11 +464,10 @@ static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_ if (invert) val = mask - val; val <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); val = (chip->cimage[reg] & ~(mask << shift)) | val; change = val != chip->cimage[reg]; snd_cs4236_ctrl_out(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } @@ -516,7 +501,6 @@ static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int shift_left = (kcontrol->private_value >> 16) & 0x07; @@ -524,10 +508,9 @@ static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e int mask = (kcontrol->private_value >> 24) & 0xff; int invert = (kcontrol->private_value >> 22) & 1; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(left_reg)] >> shift_left) & mask; ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); if (invert) { ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; @@ -538,7 +521,6 @@ static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int shift_left = (kcontrol->private_value >> 16) & 0x07; @@ -556,7 +538,7 @@ static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e } val1 <<= shift_left; val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (left_reg != right_reg) { val1 = (chip->eimage[CS4236_REG(left_reg)] & ~(mask << shift_left)) | val1; val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2; @@ -568,7 +550,6 @@ static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e change = val1 != chip->eimage[CS4236_REG(left_reg)]; snd_cs4236_ext_out(chip, left_reg, val1); } - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } @@ -592,7 +573,6 @@ static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int shift_left = (kcontrol->private_value >> 16) & 0x07; @@ -600,10 +580,9 @@ static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_ int mask = (kcontrol->private_value >> 24) & 0xff; int invert = (kcontrol->private_value >> 22) & 1; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask; ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); if (invert) { ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; @@ -614,7 +593,6 @@ static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int shift_left = (kcontrol->private_value >> 16) & 0x07; @@ -632,13 +610,12 @@ static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_ } val1 <<= shift_left; val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2; change = val1 != chip->image[left_reg] || val2 != chip->eimage[CS4236_REG(right_reg)]; snd_wss_out(chip, left_reg, val1); snd_cs4236_ext_out(chip, right_reg, val2); - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } @@ -658,31 +635,27 @@ static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol) static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.integer.value[0] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & 0x7f); ucontrol->value.integer.value[1] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & 0x7f); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int change; unsigned short val1, val2; val1 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[0] & 0x7f); val2 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[1] & 0x7f); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); val1 = (chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & ~0x7f) | val1; val2 = (chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & ~0x7f) | val2; change = val1 != chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] || val2 != chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)]; snd_cs4236_ext_out(chip, CS4236_LEFT_MASTER, val1); snd_cs4236_ext_out(chip, CS4236_RIGHT_MASTER, val2); - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } @@ -719,31 +692,27 @@ static inline int snd_cs4235_mixer_output_accu_set_volume(int vol) static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.integer.value[0] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_LEFT_MASTER]); ucontrol->value.integer.value[1] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_RIGHT_MASTER]); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int change; unsigned short val1, val2; val1 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[0]); val2 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[1]); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); val1 = (chip->image[CS4235_LEFT_MASTER] & ~(3 << 5)) | val1; val2 = (chip->image[CS4235_RIGHT_MASTER] & ~(3 << 5)) | val2; change = val1 != chip->image[CS4235_LEFT_MASTER] || val2 != chip->image[CS4235_RIGHT_MASTER]; snd_wss_out(chip, CS4235_LEFT_MASTER, val1); snd_wss_out(chip, CS4235_RIGHT_MASTER, val2); - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } @@ -929,9 +898,8 @@ WSS_DOUBLE("Analog Loopback Switch", 0, static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0; #if 0 dev_dbg(chip->card->dev, @@ -943,33 +911,30 @@ static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct sn snd_cs4236_ctrl_in(chip, 6), snd_cs4236_ctrl_in(chip, 8)); #endif - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int change; unsigned short enable, val; enable = ucontrol->value.integer.value[0] & 1; - mutex_lock(&chip->mce_mutex); + guard(mutex)(&chip->mce_mutex); snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1); - change = val != chip->image[CS4231_ALT_FEATURE_1]; - snd_wss_out(chip, CS4231_ALT_FEATURE_1, val); - val = snd_cs4236_ctrl_in(chip, 4) | 0xc0; - snd_cs4236_ctrl_out(chip, 4, val); - udelay(100); - val &= ~0x40; - snd_cs4236_ctrl_out(chip, 4, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1); + change = val != chip->image[CS4231_ALT_FEATURE_1]; + snd_wss_out(chip, CS4231_ALT_FEATURE_1, val); + val = snd_cs4236_ctrl_in(chip, 4) | 0xc0; + snd_cs4236_ctrl_out(chip, 4, val); + udelay(100); + val &= ~0x40; + snd_cs4236_ctrl_out(chip, 4, val); + } snd_wss_mce_down(chip); - mutex_unlock(&chip->mce_mutex); #if 0 dev_dbg(chip->card->dev, diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index 2ef183f197ad..59987dbc9ae9 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c @@ -105,7 +105,6 @@ EXPORT_SYMBOL(snd_es1688_reset); static int snd_es1688_probe(struct snd_es1688 *chip) { - unsigned long flags; unsigned short major, minor; int i; @@ -113,39 +112,36 @@ static int snd_es1688_probe(struct snd_es1688 *chip) * initialization sequence */ - spin_lock_irqsave(&chip->reg_lock, flags); /* Some ESS1688 cards need this */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE0)); /* ENABLE0 */ - - if (snd_es1688_reset(chip) < 0) { - dev_dbg(chip->card->dev, "ESS: [0x%lx] reset failed... 0x%x\n", - chip->port, inb(ES1688P(chip, READ))); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return -ENODEV; - } - snd_es1688_dsp_command(chip, 0xe7); /* return identification */ - - for (i = 1000, major = minor = 0; i; i--) { - if (inb(ES1688P(chip, DATA_AVAIL)) & 0x80) { - if (major == 0) { - major = inb(ES1688P(chip, READ)); - } else { - minor = inb(ES1688P(chip, READ)); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { /* Some ESS1688 cards need this */ + inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ + inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ + inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ + inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */ + inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ + inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */ + inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ + inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ + inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */ + inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ + inb(ES1688P(chip, ENABLE0)); /* ENABLE0 */ + + if (snd_es1688_reset(chip) < 0) { + dev_dbg(chip->card->dev, "ESS: [0x%lx] reset failed... 0x%x\n", + chip->port, inb(ES1688P(chip, READ))); + return -ENODEV; + } + snd_es1688_dsp_command(chip, 0xe7); /* return identification */ + + for (i = 1000, major = minor = 0; i; i--) { + if (inb(ES1688P(chip, DATA_AVAIL)) & 0x80) { + if (major == 0) + major = inb(ES1688P(chip, READ)); + else + minor = inb(ES1688P(chip, READ)); } } } - spin_unlock_irqrestore(&chip->reg_lock, flags); - dev_dbg(chip->card->dev, "ESS: [0x%lx] found.. major = 0x%x, minor = 0x%x\n", chip->port, major, minor); @@ -169,15 +165,15 @@ static int snd_es1688_probe(struct snd_es1688 *chip) return -ENODEV; } - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xb1, 0x10); /* disable IRQ */ - snd_es1688_write(chip, 0xb2, 0x00); /* disable DMA */ - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_es1688_write(chip, 0xb1, 0x10); /* disable IRQ */ + snd_es1688_write(chip, 0xb2, 0x00); /* disable DMA */ + } /* enable joystick, but disable OPL3 */ - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_es1688_mixer_write(chip, 0x40, 0x01); - spin_unlock_irqrestore(&chip->mixer_lock, flags); + scoped_guard(spinlock_irqsave, &chip->mixer_lock) { + snd_es1688_mixer_write(chip, 0x40, 0x01); + } return 0; } @@ -185,7 +181,6 @@ static int snd_es1688_probe(struct snd_es1688 *chip) static int snd_es1688_init(struct snd_es1688 * chip, int enable) { static const int irqs[16] = {-1, -1, 0, -1, -1, 1, -1, 2, -1, 0, 3, -1, -1, -1, -1, -1}; - unsigned long flags; int cfg, irq_bits, dma, dma_bits, tmp, tmp1; /* ok.. setup MPU-401 port and joystick and OPL3 */ @@ -214,14 +209,14 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) } } } - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_mixer_write(chip, 0x40, cfg); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_es1688_mixer_write(chip, 0x40, cfg); + } /* --- */ - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_read(chip, 0xb1); - snd_es1688_read(chip, 0xb2); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_es1688_read(chip, 0xb1); + snd_es1688_read(chip, 0xb2); + } if (enable) { cfg = 0xf0; /* enable only DMA counter interrupt */ irq_bits = irqs[chip->irq & 0x0f]; @@ -235,9 +230,9 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) #endif return -EINVAL; } - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xb1, cfg | (irq_bits << 2)); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_es1688_write(chip, 0xb1, cfg | (irq_bits << 2)); + } cfg = 0xf0; /* extended mode DMA enable */ dma = chip->dma8; if (dma > 3 || dma == 2) { @@ -254,20 +249,20 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) if (dma != 3) dma_bits++; } - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xb2, cfg | (dma_bits << 2)); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_es1688_write(chip, 0xb2, cfg | (dma_bits << 2)); + } } else { - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xb1, 0x10); /* disable IRQ */ - snd_es1688_write(chip, 0xb2, 0x00); /* disable DMA */ - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_es1688_write(chip, 0xb1, 0x10); /* disable IRQ */ + snd_es1688_write(chip, 0xb2, 0x00); /* disable DMA */ + } + } + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_es1688_read(chip, 0xb1); + snd_es1688_read(chip, 0xb2); + snd_es1688_reset(chip); } - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_read(chip, 0xb1); - snd_es1688_read(chip, 0xb2); - snd_es1688_reset(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } @@ -320,74 +315,70 @@ static int snd_es1688_trigger(struct snd_es1688 *chip, int cmd, unsigned char va } else if (cmd != SNDRV_PCM_TRIGGER_START) { return -EINVAL; } - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); chip->trigger_value = value; val = snd_es1688_read(chip, 0xb8); - if ((val < 0) || (val & 0x0f) == value) { - spin_unlock(&chip->reg_lock); + if ((val < 0) || (val & 0x0f) == value) return -EINVAL; /* something is wrong */ - } #if 0 dev_dbg(chip->card->dev, "trigger: val = 0x%x, value = 0x%x\n", val, value); dev_dbg(chip->card->dev, "trigger: pointer = 0x%x\n", snd_dma_pointer(chip->dma8, chip->dma_size)); #endif snd_es1688_write(chip, 0xb8, (val & 0xf0) | value); - spin_unlock(&chip->reg_lock); return 0; } static int snd_es1688_playback_prepare(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_es1688 *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned int size = snd_pcm_lib_buffer_bytes(substream); unsigned int count = snd_pcm_lib_period_bytes(substream); chip->dma_size = size; - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_reset(chip); - snd_es1688_set_rate(chip, substream); - snd_es1688_write(chip, 0xb8, 4); /* auto init DMA mode */ - snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels)); - snd_es1688_write(chip, 0xb9, 2); /* demand mode (4 bytes/request) */ - if (runtime->channels == 1) { - if (snd_pcm_format_width(runtime->format) == 8) { - /* 8. bit mono */ - snd_es1688_write(chip, 0xb6, 0x80); - snd_es1688_write(chip, 0xb7, 0x51); - snd_es1688_write(chip, 0xb7, 0xd0); - } else { - /* 16. bit mono */ - snd_es1688_write(chip, 0xb6, 0x00); - snd_es1688_write(chip, 0xb7, 0x71); - snd_es1688_write(chip, 0xb7, 0xf4); - } - } else { - if (snd_pcm_format_width(runtime->format) == 8) { - /* 8. bit stereo */ - snd_es1688_write(chip, 0xb6, 0x80); - snd_es1688_write(chip, 0xb7, 0x51); - snd_es1688_write(chip, 0xb7, 0x98); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_es1688_reset(chip); + snd_es1688_set_rate(chip, substream); + snd_es1688_write(chip, 0xb8, 4); /* auto init DMA mode */ + snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels)); + snd_es1688_write(chip, 0xb9, 2); /* demand mode (4 bytes/request) */ + if (runtime->channels == 1) { + if (snd_pcm_format_width(runtime->format) == 8) { + /* 8. bit mono */ + snd_es1688_write(chip, 0xb6, 0x80); + snd_es1688_write(chip, 0xb7, 0x51); + snd_es1688_write(chip, 0xb7, 0xd0); + } else { + /* 16. bit mono */ + snd_es1688_write(chip, 0xb6, 0x00); + snd_es1688_write(chip, 0xb7, 0x71); + snd_es1688_write(chip, 0xb7, 0xf4); + } } else { - /* 16. bit stereo */ - snd_es1688_write(chip, 0xb6, 0x00); - snd_es1688_write(chip, 0xb7, 0x71); - snd_es1688_write(chip, 0xb7, 0xbc); + if (snd_pcm_format_width(runtime->format) == 8) { + /* 8. bit stereo */ + snd_es1688_write(chip, 0xb6, 0x80); + snd_es1688_write(chip, 0xb7, 0x51); + snd_es1688_write(chip, 0xb7, 0x98); + } else { + /* 16. bit stereo */ + snd_es1688_write(chip, 0xb6, 0x00); + snd_es1688_write(chip, 0xb7, 0x71); + snd_es1688_write(chip, 0xb7, 0xbc); + } } + snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50); + snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50); + snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKON); } - snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50); - snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50); - snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKON); - spin_unlock_irqrestore(&chip->reg_lock, flags); /* --- */ count = -count; snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xa4, (unsigned char) count); - snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8)); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_es1688_write(chip, 0xa4, (unsigned char) count); + snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8)); + } return 0; } @@ -400,51 +391,50 @@ static int snd_es1688_playback_trigger(struct snd_pcm_substream *substream, static int snd_es1688_capture_prepare(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_es1688 *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned int size = snd_pcm_lib_buffer_bytes(substream); unsigned int count = snd_pcm_lib_period_bytes(substream); chip->dma_size = size; - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_reset(chip); - snd_es1688_set_rate(chip, substream); - snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKOFF); - snd_es1688_write(chip, 0xb8, 0x0e); /* auto init DMA mode */ - snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels)); - snd_es1688_write(chip, 0xb9, 2); /* demand mode (4 bytes/request) */ - if (runtime->channels == 1) { - if (snd_pcm_format_width(runtime->format) == 8) { - /* 8. bit mono */ - snd_es1688_write(chip, 0xb7, 0x51); - snd_es1688_write(chip, 0xb7, 0xd0); - } else { - /* 16. bit mono */ - snd_es1688_write(chip, 0xb7, 0x71); - snd_es1688_write(chip, 0xb7, 0xf4); - } - } else { - if (snd_pcm_format_width(runtime->format) == 8) { - /* 8. bit stereo */ - snd_es1688_write(chip, 0xb7, 0x51); - snd_es1688_write(chip, 0xb7, 0x98); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_es1688_reset(chip); + snd_es1688_set_rate(chip, substream); + snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKOFF); + snd_es1688_write(chip, 0xb8, 0x0e); /* auto init DMA mode */ + snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels)); + snd_es1688_write(chip, 0xb9, 2); /* demand mode (4 bytes/request) */ + if (runtime->channels == 1) { + if (snd_pcm_format_width(runtime->format) == 8) { + /* 8. bit mono */ + snd_es1688_write(chip, 0xb7, 0x51); + snd_es1688_write(chip, 0xb7, 0xd0); + } else { + /* 16. bit mono */ + snd_es1688_write(chip, 0xb7, 0x71); + snd_es1688_write(chip, 0xb7, 0xf4); + } } else { - /* 16. bit stereo */ - snd_es1688_write(chip, 0xb7, 0x71); - snd_es1688_write(chip, 0xb7, 0xbc); + if (snd_pcm_format_width(runtime->format) == 8) { + /* 8. bit stereo */ + snd_es1688_write(chip, 0xb7, 0x51); + snd_es1688_write(chip, 0xb7, 0x98); + } else { + /* 16. bit stereo */ + snd_es1688_write(chip, 0xb7, 0x71); + snd_es1688_write(chip, 0xb7, 0xbc); + } } + snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50); + snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50); } - snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50); - snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50); - spin_unlock_irqrestore(&chip->reg_lock, flags); /* --- */ count = -count; snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xa4, (unsigned char) count); - snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8)); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_es1688_write(chip, 0xa4, (unsigned char) count); + snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8)); + } return 0; } @@ -738,19 +728,17 @@ static int snd_es1688_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem static int snd_es1688_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; unsigned char oval, nval; int change; if (ucontrol->value.enumerated.item[0] > 8) return -EINVAL; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); oval = snd_es1688_mixer_read(chip, ES1688_REC_DEV); nval = (ucontrol->value.enumerated.item[0] & 7) | (oval & ~15); change = nval != oval; if (change) snd_es1688_mixer_write(chip, ES1688_REC_DEV, nval); - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } @@ -774,15 +762,13 @@ static int snd_es1688_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_es1688_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.integer.value[0] = (snd_es1688_mixer_read(chip, reg) >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); if (invert) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; return 0; @@ -791,7 +777,6 @@ static int snd_es1688_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_es1688_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; @@ -803,13 +788,12 @@ static int snd_es1688_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (invert) nval = mask - nval; nval <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); oval = snd_es1688_mixer_read(chip, reg); nval = (oval & ~(mask << shift)) | nval; change = nval != oval; if (change) snd_es1688_mixer_write(chip, reg, nval); - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } @@ -833,7 +817,6 @@ static int snd_es1688_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_es1688_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int shift_left = (kcontrol->private_value >> 16) & 0x07; @@ -842,7 +825,7 @@ static int snd_es1688_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e int invert = (kcontrol->private_value >> 22) & 1; unsigned char left, right; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (left_reg < 0xa0) left = snd_es1688_mixer_read(chip, left_reg); else @@ -854,7 +837,6 @@ static int snd_es1688_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e right = snd_es1688_read(chip, right_reg); } else right = left; - spin_unlock_irqrestore(&chip->reg_lock, flags); ucontrol->value.integer.value[0] = (left >> shift_left) & mask; ucontrol->value.integer.value[1] = (right >> shift_right) & mask; if (invert) { @@ -867,7 +849,6 @@ static int snd_es1688_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_es1688_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int shift_left = (kcontrol->private_value >> 16) & 0x07; @@ -885,7 +866,7 @@ static int snd_es1688_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e } val1 <<= shift_left; val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (left_reg != right_reg) { if (left_reg < 0xa0) oval1 = snd_es1688_mixer_read(chip, left_reg); @@ -923,7 +904,6 @@ static int snd_es1688_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e } } - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 3e89a84c6244..1da7b400a17b 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -185,16 +185,13 @@ static int snd_es18xx_dsp_get_byte(struct snd_es18xx *chip) static int snd_es18xx_write(struct snd_es18xx *chip, unsigned char reg, unsigned char data) { - unsigned long flags; int ret; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ret = snd_es18xx_dsp_command(chip, reg); if (ret < 0) - goto end; + return ret; ret = snd_es18xx_dsp_command(chip, data); - end: - spin_unlock_irqrestore(&chip->reg_lock, flags); #ifdef REG_DEBUG dev_dbg(chip->card->dev, "Reg %02x set to %02x\n", reg, data); #endif @@ -203,22 +200,20 @@ static int snd_es18xx_write(struct snd_es18xx *chip, static int snd_es18xx_read(struct snd_es18xx *chip, unsigned char reg) { - unsigned long flags; int ret, data; - spin_lock_irqsave(&chip->reg_lock, flags); + + guard(spinlock_irqsave)(&chip->reg_lock); ret = snd_es18xx_dsp_command(chip, 0xC0); if (ret < 0) - goto end; + return ret; ret = snd_es18xx_dsp_command(chip, reg); if (ret < 0) - goto end; + return ret; data = snd_es18xx_dsp_get_byte(chip); ret = data; #ifdef REG_DEBUG dev_dbg(chip->card->dev, "Reg %02x now is %02x (%d)\n", reg, data, ret); #endif - end: - spin_unlock_irqrestore(&chip->reg_lock, flags); return ret; } @@ -228,47 +223,41 @@ static int snd_es18xx_bits(struct snd_es18xx *chip, unsigned char reg, { int ret; unsigned char old, new, oval; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + + guard(spinlock_irqsave)(&chip->reg_lock); ret = snd_es18xx_dsp_command(chip, 0xC0); if (ret < 0) - goto end; + return ret; ret = snd_es18xx_dsp_command(chip, reg); if (ret < 0) - goto end; + return ret; ret = snd_es18xx_dsp_get_byte(chip); - if (ret < 0) { - goto end; - } + if (ret < 0) + return ret; old = ret; oval = old & mask; if (val != oval) { ret = snd_es18xx_dsp_command(chip, reg); if (ret < 0) - goto end; + return ret; new = (old & ~mask) | (val & mask); ret = snd_es18xx_dsp_command(chip, new); if (ret < 0) - goto end; + return ret; #ifdef REG_DEBUG dev_dbg(chip->card->dev, "Reg %02x was %02x, set to %02x (%d)\n", reg, old, new, ret); #endif } - ret = oval; - end: - spin_unlock_irqrestore(&chip->reg_lock, flags); - return ret; + return oval; } static inline void snd_es18xx_mixer_write(struct snd_es18xx *chip, unsigned char reg, unsigned char data) { - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); + guard(spinlock_irqsave)(&chip->mixer_lock); outb(reg, chip->port + 0x04); outb(data, chip->port + 0x05); - spin_unlock_irqrestore(&chip->mixer_lock, flags); #ifdef REG_DEBUG dev_dbg(chip->card->dev, "Mixer reg %02x set to %02x\n", reg, data); #endif @@ -276,12 +265,11 @@ static inline void snd_es18xx_mixer_write(struct snd_es18xx *chip, static inline int snd_es18xx_mixer_read(struct snd_es18xx *chip, unsigned char reg) { - unsigned long flags; int data; - spin_lock_irqsave(&chip->mixer_lock, flags); + + guard(spinlock_irqsave)(&chip->mixer_lock); outb(reg, chip->port + 0x04); data = inb(chip->port + 0x05); - spin_unlock_irqrestore(&chip->mixer_lock, flags); #ifdef REG_DEBUG dev_dbg(chip->card->dev, "Mixer reg %02x now is %02x\n", reg, data); #endif @@ -293,8 +281,8 @@ static inline int snd_es18xx_mixer_bits(struct snd_es18xx *chip, unsigned char r unsigned char mask, unsigned char val) { unsigned char old, new, oval; - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); + + guard(spinlock_irqsave)(&chip->mixer_lock); outb(reg, chip->port + 0x04); old = inb(chip->port + 0x05); oval = old & mask; @@ -306,7 +294,6 @@ static inline int snd_es18xx_mixer_bits(struct snd_es18xx *chip, unsigned char r reg, old, new); #endif } - spin_unlock_irqrestore(&chip->mixer_lock, flags); return oval; } @@ -314,14 +301,13 @@ static inline int snd_es18xx_mixer_writable(struct snd_es18xx *chip, unsigned ch unsigned char mask) { int old, expected, new; - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); + + guard(spinlock_irqsave)(&chip->mixer_lock); outb(reg, chip->port + 0x04); old = inb(chip->port + 0x05); expected = old ^ mask; outb(expected, chip->port + 0x05); new = inb(chip->port + 0x05); - spin_unlock_irqrestore(&chip->mixer_lock, flags); #ifdef REG_DEBUG dev_dbg(chip->card->dev, "Mixer reg %02x was %02x, set to %02x, now is %02x\n", reg, old, expected, new); diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c index bb5a4e2fbfb3..ffc69e26227e 100644 --- a/sound/isa/gus/gus_dma.c +++ b/sound/isa/gus/gus_dma.c @@ -11,12 +11,9 @@ static void snd_gf1_dma_ack(struct snd_gus_card * gus) { - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL, 0x00); snd_gf1_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL); - spin_unlock_irqrestore(&gus->reg_lock, flags); } static void snd_gf1_dma_program(struct snd_gus_card * gus, @@ -25,7 +22,6 @@ static void snd_gf1_dma_program(struct snd_gus_card * gus, unsigned int count, unsigned int cmd) { - unsigned long flags; unsigned int address; unsigned char dma_cmd; unsigned int address_high; @@ -70,7 +66,7 @@ static void snd_gf1_dma_program(struct snd_gus_card * gus, "address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n", address << 1, count, dma_cmd); #endif - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); if (gus->gf1.enh_mode) { address_high = ((address >> 16) & 0x000000f0) | (address & 0x0000000f); snd_gf1_write16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW, (unsigned short) (address >> 4)); @@ -78,7 +74,6 @@ static void snd_gf1_dma_program(struct snd_gus_card * gus, } else snd_gf1_write16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW, (unsigned short) (address >> 4)); snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL, dma_cmd); - spin_unlock_irqrestore(&gus->reg_lock, flags); } static struct snd_gf1_dma_block *snd_gf1_dma_next_block(struct snd_gus_card * gus) @@ -120,16 +115,15 @@ static void snd_gf1_dma_interrupt(struct snd_gus_card * gus) snd_gf1_dma_ack(gus); if (gus->gf1.dma_ack) gus->gf1.dma_ack(gus, gus->gf1.dma_private_data); - spin_lock(&gus->dma_lock); - if (gus->gf1.dma_data_pcm == NULL && - gus->gf1.dma_data_synth == NULL) { - gus->gf1.dma_ack = NULL; - gus->gf1.dma_flags &= ~SNDRV_GF1_DMA_TRIGGER; - spin_unlock(&gus->dma_lock); - return; + scoped_guard(spinlock, &gus->dma_lock) { + if (gus->gf1.dma_data_pcm == NULL && + gus->gf1.dma_data_synth == NULL) { + gus->gf1.dma_ack = NULL; + gus->gf1.dma_flags &= ~SNDRV_GF1_DMA_TRIGGER; + return; + } + block = snd_gf1_dma_next_block(gus); } - block = snd_gf1_dma_next_block(gus); - spin_unlock(&gus->dma_lock); if (!block) return; snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); @@ -143,18 +137,15 @@ static void snd_gf1_dma_interrupt(struct snd_gus_card * gus) int snd_gf1_dma_init(struct snd_gus_card * gus) { - mutex_lock(&gus->dma_mutex); + guard(mutex)(&gus->dma_mutex); gus->gf1.dma_shared++; - if (gus->gf1.dma_shared > 1) { - mutex_unlock(&gus->dma_mutex); + if (gus->gf1.dma_shared > 1) return 0; - } gus->gf1.interrupt_handler_dma_write = snd_gf1_dma_interrupt; gus->gf1.dma_data_pcm = gus->gf1.dma_data_pcm_last = gus->gf1.dma_data_synth = gus->gf1.dma_data_synth_last = NULL; - mutex_unlock(&gus->dma_mutex); return 0; } @@ -162,7 +153,7 @@ int snd_gf1_dma_done(struct snd_gus_card * gus) { struct snd_gf1_dma_block *block; - mutex_lock(&gus->dma_mutex); + guard(mutex)(&gus->dma_mutex); gus->gf1.dma_shared--; if (!gus->gf1.dma_shared) { snd_dma_disable(gus->gf1.dma1); @@ -179,7 +170,6 @@ int snd_gf1_dma_done(struct snd_gus_card * gus) gus->gf1.dma_data_pcm_last = gus->gf1.dma_data_synth_last = NULL; } - mutex_unlock(&gus->dma_mutex); return 0; } @@ -188,8 +178,8 @@ int snd_gf1_dma_transfer_block(struct snd_gus_card * gus, int atomic, int synth) { - unsigned long flags; struct snd_gf1_dma_block *block; + struct snd_gf1_dma_block *free_block = NULL; block = kmalloc(sizeof(*block), atomic ? GFP_ATOMIC : GFP_KERNEL); if (!block) @@ -210,34 +200,36 @@ int snd_gf1_dma_transfer_block(struct snd_gus_card * gus, "gus->gf1.dma_data_pcm = 0x%lx\n", (long)gus->gf1.dma_data_pcm); - spin_lock_irqsave(&gus->dma_lock, flags); - if (synth) { - if (gus->gf1.dma_data_synth_last) { - gus->gf1.dma_data_synth_last->next = block; - gus->gf1.dma_data_synth_last = block; + scoped_guard(spinlock_irqsave, &gus->dma_lock) { + if (synth) { + if (gus->gf1.dma_data_synth_last) { + gus->gf1.dma_data_synth_last->next = block; + gus->gf1.dma_data_synth_last = block; + } else { + gus->gf1.dma_data_synth = + gus->gf1.dma_data_synth_last = block; + } } else { - gus->gf1.dma_data_synth = - gus->gf1.dma_data_synth_last = block; + if (gus->gf1.dma_data_pcm_last) { + gus->gf1.dma_data_pcm_last->next = block; + gus->gf1.dma_data_pcm_last = block; + } else { + gus->gf1.dma_data_pcm = + gus->gf1.dma_data_pcm_last = block; + } } - } else { - if (gus->gf1.dma_data_pcm_last) { - gus->gf1.dma_data_pcm_last->next = block; - gus->gf1.dma_data_pcm_last = block; - } else { - gus->gf1.dma_data_pcm = - gus->gf1.dma_data_pcm_last = block; + if (!(gus->gf1.dma_flags & SNDRV_GF1_DMA_TRIGGER)) { + gus->gf1.dma_flags |= SNDRV_GF1_DMA_TRIGGER; + free_block = snd_gf1_dma_next_block(gus); } } - if (!(gus->gf1.dma_flags & SNDRV_GF1_DMA_TRIGGER)) { - gus->gf1.dma_flags |= SNDRV_GF1_DMA_TRIGGER; - block = snd_gf1_dma_next_block(gus); - spin_unlock_irqrestore(&gus->dma_lock, flags); - if (block == NULL) - return 0; - snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); - kfree(block); - return 0; + + if (free_block) { + snd_gf1_dma_program(gus, free_block->addr, free_block->buf_addr, + free_block->count, + (unsigned short)free_block->cmd); + kfree(free_block); } - spin_unlock_irqrestore(&gus->dma_lock, flags); + return 0; } diff --git a/sound/isa/gus/gus_dram.c b/sound/isa/gus/gus_dram.c index 5cebc0119d0a..50fe738ee3ea 100644 --- a/sound/isa/gus/gus_dram.c +++ b/sound/isa/gus/gus_dram.c @@ -13,7 +13,6 @@ static int snd_gus_dram_poke(struct snd_gus_card *gus, char __user *_buffer, unsigned int address, unsigned int size) { - unsigned long flags; unsigned int size1, size2; char buffer[256], *pbuffer; @@ -22,11 +21,10 @@ static int snd_gus_dram_poke(struct snd_gus_card *gus, char __user *_buffer, if (copy_from_user(buffer, _buffer, size1)) return -EFAULT; if (gus->interwave) { - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); snd_gf1_dram_addr(gus, address); outsb(GUSP(gus, DRAM), buffer, size1); - spin_unlock_irqrestore(&gus->reg_lock, flags); address += size1; } else { pbuffer = buffer; @@ -51,19 +49,17 @@ static int snd_gus_dram_peek(struct snd_gus_card *gus, char __user *_buffer, unsigned int address, unsigned int size, int rom) { - unsigned long flags; unsigned int size1, size2; char buffer[256], *pbuffer; while (size > 0) { size1 = size > sizeof(buffer) ? sizeof(buffer) : size; if (gus->interwave) { - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, rom ? 0x03 : 0x01); snd_gf1_dram_addr(gus, address); insb(GUSP(gus, DRAM), buffer, size1); snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); - spin_unlock_irqrestore(&gus->reg_lock, flags); address += size1; } else { pbuffer = buffer; diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c index f167eb8d516b..3e6f35084f26 100644 --- a/sound/isa/gus/gus_io.c +++ b/sound/isa/gus/gus_io.c @@ -177,55 +177,36 @@ unsigned int snd_gf1_read_addr(struct snd_gus_card * gus, void snd_gf1_i_ctrl_stop(struct snd_gus_card * gus, unsigned char reg) { - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); __snd_gf1_ctrl_stop(gus, reg); - spin_unlock_irqrestore(&gus->reg_lock, flags); } void snd_gf1_i_write8(struct snd_gus_card * gus, unsigned char reg, unsigned char data) { - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); __snd_gf1_write8(gus, reg, data); - spin_unlock_irqrestore(&gus->reg_lock, flags); } unsigned char snd_gf1_i_look8(struct snd_gus_card * gus, unsigned char reg) { - unsigned long flags; - unsigned char res; - - spin_lock_irqsave(&gus->reg_lock, flags); - res = __snd_gf1_look8(gus, reg); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; + guard(spinlock_irqsave)(&gus->reg_lock); + return __snd_gf1_look8(gus, reg); } void snd_gf1_i_write16(struct snd_gus_card * gus, unsigned char reg, unsigned int data) { - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); __snd_gf1_write16(gus, reg, data); - spin_unlock_irqrestore(&gus->reg_lock, flags); } unsigned short snd_gf1_i_look16(struct snd_gus_card * gus, unsigned char reg) { - unsigned long flags; - unsigned short res; - - spin_lock_irqsave(&gus->reg_lock, flags); - res = __snd_gf1_look16(gus, reg); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; + guard(spinlock_irqsave)(&gus->reg_lock); + return __snd_gf1_look16(gus, reg); } void snd_gf1_dram_addr(struct snd_gus_card * gus, unsigned int addr) @@ -242,9 +223,7 @@ void snd_gf1_dram_addr(struct snd_gus_card * gus, unsigned int addr) void snd_gf1_poke(struct snd_gus_card * gus, unsigned int addr, unsigned char data) { - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); mb(); outw((unsigned short) addr, gus->gf1.reg_data16); @@ -254,15 +233,11 @@ void snd_gf1_poke(struct snd_gus_card * gus, unsigned int addr, unsigned char da outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); mb(); outb(data, gus->gf1.reg_dram); - spin_unlock_irqrestore(&gus->reg_lock, flags); } unsigned char snd_gf1_peek(struct snd_gus_card * gus, unsigned int addr) { - unsigned long flags; - unsigned char res; - - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); mb(); outw((unsigned short) addr, gus->gf1.reg_data16); @@ -271,20 +246,16 @@ unsigned char snd_gf1_peek(struct snd_gus_card * gus, unsigned int addr) mb(); outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); mb(); - res = inb(gus->gf1.reg_dram); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; + return inb(gus->gf1.reg_dram); } #if 0 void snd_gf1_pokew(struct snd_gus_card * gus, unsigned int addr, unsigned short data) { - unsigned long flags; - if (!gus->interwave) dev_dbg(gus->card->dev, "%s - GF1!!!\n", __func__); - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); mb(); outw((unsigned short) addr, gus->gf1.reg_data16); @@ -296,17 +267,13 @@ void snd_gf1_pokew(struct snd_gus_card * gus, unsigned int addr, unsigned short outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel); mb(); outw(data, gus->gf1.reg_data16); - spin_unlock_irqrestore(&gus->reg_lock, flags); } unsigned short snd_gf1_peekw(struct snd_gus_card * gus, unsigned int addr) { - unsigned long flags; - unsigned short res; - if (!gus->interwave) dev_dbg(gus->card->dev, "%s - GF1!!!\n", __func__); - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); mb(); outw((unsigned short) addr, gus->gf1.reg_data16); @@ -317,23 +284,20 @@ unsigned short snd_gf1_peekw(struct snd_gus_card * gus, unsigned int addr) mb(); outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel); mb(); - res = inw(gus->gf1.reg_data16); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; + return inw(gus->gf1.reg_data16); } void snd_gf1_dram_setmem(struct snd_gus_card * gus, unsigned int addr, unsigned short value, unsigned int count) { unsigned long port; - unsigned long flags; if (!gus->interwave) dev_dbg(gus->card->dev, "%s - GF1!!!\n", __func__); addr &= ~1; count >>= 1; port = GUSP(gus, GF1DATALOW); - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); mb(); outw((unsigned short) addr, gus->gf1.reg_data16); @@ -345,7 +309,6 @@ void snd_gf1_dram_setmem(struct snd_gus_card * gus, unsigned int addr, outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel); while (count--) outw(value, port); - spin_unlock_irqrestore(&gus->reg_lock, flags); } #endif /* 0 */ diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 873ef4046cd6..5f50a39c6f16 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c @@ -42,16 +42,14 @@ static int snd_gus_joystick_get(struct snd_kcontrol *kcontrol, struct snd_ctl_el static int snd_gus_joystick_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; int change; unsigned char nval; nval = ucontrol->value.integer.value[0] & 31; - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); change = gus->joystick_dac != nval; gus->joystick_dac = nval; snd_gf1_write8(gus, SNDRV_GF1_GB_JOYSTICK_DAC_LEVEL, gus->joystick_dac); - spin_unlock_irqrestore(&gus->reg_lock, flags); return change; } @@ -249,7 +247,6 @@ static int snd_gus_detect_memory(struct snd_gus_card * gus) static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches) { struct snd_card *card; - unsigned long flags; int irq, dma1, dma2; static const unsigned char irqs[16] = {0, 0, 1, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7}; @@ -292,34 +289,34 @@ static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches) card->mixer.mix_ctrl_reg |= 0x10; #endif - spin_lock_irqsave(&gus->reg_lock, flags); - outb(5, GUSP(gus, REGCNTRLS)); - outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(0x00, GUSP(gus, IRQDMACNTRLREG)); - outb(0, GUSP(gus, REGCNTRLS)); - spin_unlock_irqrestore(&gus->reg_lock, flags); + scoped_guard(spinlock_irqsave, &gus->reg_lock) { + outb(5, GUSP(gus, REGCNTRLS)); + outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); + outb(0x00, GUSP(gus, IRQDMACNTRLREG)); + outb(0, GUSP(gus, REGCNTRLS)); + } udelay(100); - spin_lock_irqsave(&gus->reg_lock, flags); - outb(0x00 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(dma1, GUSP(gus, IRQDMACNTRLREG)); - if (latches) { - outb(0x40 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(irq, GUSP(gus, IRQDMACNTRLREG)); + scoped_guard(spinlock_irqsave, &gus->reg_lock) { + outb(0x00 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); + outb(dma1, GUSP(gus, IRQDMACNTRLREG)); + if (latches) { + outb(0x40 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); + outb(irq, GUSP(gus, IRQDMACNTRLREG)); + } } - spin_unlock_irqrestore(&gus->reg_lock, flags); udelay(100); - spin_lock_irqsave(&gus->reg_lock, flags); - outb(0x00 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(dma1, GUSP(gus, IRQDMACNTRLREG)); - if (latches) { - outb(0x40 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(irq, GUSP(gus, IRQDMACNTRLREG)); + scoped_guard(spinlock_irqsave, &gus->reg_lock) { + outb(0x00 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); + outb(dma1, GUSP(gus, IRQDMACNTRLREG)); + if (latches) { + outb(0x40 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); + outb(irq, GUSP(gus, IRQDMACNTRLREG)); + } } - spin_unlock_irqrestore(&gus->reg_lock, flags); snd_gf1_delay(gus); @@ -327,26 +324,25 @@ static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches) gus->mix_cntrl_reg |= 0x08; /* enable latches */ else gus->mix_cntrl_reg &= ~0x08; /* disable latches */ - spin_lock_irqsave(&gus->reg_lock, flags); - outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(0, GUSP(gus, GF1PAGE)); - spin_unlock_irqrestore(&gus->reg_lock, flags); + scoped_guard(spinlock_irqsave, &gus->reg_lock) { + outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); + outb(0, GUSP(gus, GF1PAGE)); + } return 0; } static int snd_gus_check_version(struct snd_gus_card * gus) { - unsigned long flags; unsigned char val, rev; struct snd_card *card; card = gus->card; - spin_lock_irqsave(&gus->reg_lock, flags); - outb(0x20, GUSP(gus, REGCNTRLS)); - val = inb(GUSP(gus, REGCNTRLS)); - rev = inb(GUSP(gus, BOARDVERSION)); - spin_unlock_irqrestore(&gus->reg_lock, flags); + scoped_guard(spinlock_irqsave, &gus->reg_lock) { + outb(0x20, GUSP(gus, REGCNTRLS)); + val = inb(GUSP(gus, REGCNTRLS)); + rev = inb(GUSP(gus, BOARDVERSION)); + } dev_dbg(card->dev, "GF1 [0x%lx] init - val = 0x%x, rev = 0x%x\n", gus->gf1.port, val, rev); strscpy(card->driver, "GUS"); strscpy(card->longname, "Gravis UltraSound Classic (2.4)"); @@ -447,4 +443,3 @@ EXPORT_SYMBOL(snd_gf1_translate_freq); EXPORT_SYMBOL(snd_gf1_mem_alloc); EXPORT_SYMBOL(snd_gf1_mem_xfree); EXPORT_SYMBOL(snd_gf1_mem_free); -EXPORT_SYMBOL(snd_gf1_mem_lock); diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index 054058779db6..8d95d8d5abdf 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c @@ -15,15 +15,6 @@ static void snd_gf1_mem_info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer); #endif -void snd_gf1_mem_lock(struct snd_gf1_mem * alloc, int xup) -{ - if (!xup) { - mutex_lock(&alloc->memory_mutex); - } else { - mutex_unlock(&alloc->memory_mutex); - } -} - static struct snd_gf1_mem_block * snd_gf1_mem_xalloc(struct snd_gf1_mem *alloc, struct snd_gf1_mem_block *block, const char *name) @@ -50,7 +41,6 @@ snd_gf1_mem_xalloc(struct snd_gf1_mem *alloc, struct snd_gf1_mem_block *block, alloc->first = nblock; else nblock->prev->next = nblock; - mutex_unlock(&alloc->memory_mutex); return nblock; } pblock = pblock->next; @@ -71,7 +61,6 @@ int snd_gf1_mem_xfree(struct snd_gf1_mem * alloc, struct snd_gf1_mem_block * blo { if (block->share) { /* ok.. shared block */ block->share--; - mutex_unlock(&alloc->memory_mutex); return 0; } if (alloc->first == block) { @@ -183,7 +172,7 @@ struct snd_gf1_mem_block *snd_gf1_mem_alloc(struct snd_gf1_mem * alloc, int owne { struct snd_gf1_mem_block block, *nblock; - snd_gf1_mem_lock(alloc, 0); + guard(mutex)(&alloc->memory_mutex); if (share_id != NULL) { nblock = snd_gf1_mem_share(alloc, share_id); if (nblock != NULL) { @@ -193,36 +182,27 @@ struct snd_gf1_mem_block *snd_gf1_mem_alloc(struct snd_gf1_mem * alloc, int owne goto __std; } nblock->share++; - snd_gf1_mem_lock(alloc, 1); return NULL; } } __std: - if (snd_gf1_mem_find(alloc, &block, size, w_16, align) < 0) { - snd_gf1_mem_lock(alloc, 1); + if (snd_gf1_mem_find(alloc, &block, size, w_16, align) < 0) return NULL; - } if (share_id != NULL) memcpy(&block.share_id, share_id, sizeof(block.share_id)); block.owner = owner; nblock = snd_gf1_mem_xalloc(alloc, &block, name); - snd_gf1_mem_lock(alloc, 1); return nblock; } int snd_gf1_mem_free(struct snd_gf1_mem * alloc, unsigned int address) { - int result; struct snd_gf1_mem_block *block; - snd_gf1_mem_lock(alloc, 0); + guard(mutex)(&alloc->memory_mutex); block = snd_gf1_mem_look(alloc, address); - if (block) { - result = snd_gf1_mem_xfree(alloc, block); - snd_gf1_mem_lock(alloc, 1); - return result; - } - snd_gf1_mem_lock(alloc, 1); + if (block) + return snd_gf1_mem_xfree(alloc, block); return -EINVAL; } @@ -282,7 +262,7 @@ static void snd_gf1_mem_info_read(struct snd_info_entry *entry, gus = entry->private_data; alloc = &gus->gf1.mem_alloc; - mutex_lock(&alloc->memory_mutex); + guard(mutex)(&alloc->memory_mutex); snd_iprintf(buffer, "8-bit banks : \n "); for (i = 0; i < 4; i++) snd_iprintf(buffer, "0x%06x (%04ik)%s", alloc->banks_8[i].address, alloc->banks_8[i].size >> 10, i + 1 < 4 ? "," : ""); @@ -326,7 +306,6 @@ static void snd_gf1_mem_info_read(struct snd_info_entry *entry, } snd_iprintf(buffer, " Total: memory = %i, used = %i, free = %i\n", total, used, total - used); - mutex_unlock(&alloc->memory_mutex); #if 0 ultra_iprintf(buffer, " Verify: free = %i, max 8-bit block = %i, max 16-bit block = %i\n", ultra_memory_free_size(card, &card->gf1.mem_alloc), diff --git a/sound/isa/gus/gus_mixer.c b/sound/isa/gus/gus_mixer.c index 60c3a8219770..9bfdb4e45a5d 100644 --- a/sound/isa/gus/gus_mixer.c +++ b/sound/isa/gus/gus_mixer.c @@ -37,7 +37,6 @@ static int snd_gf1_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem static int snd_gf1_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; int shift = kcontrol->private_value & 0xff; int invert = (kcontrol->private_value >> 8) & 1; int change; @@ -47,13 +46,12 @@ static int snd_gf1_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem if (invert) nval ^= 1; nval <<= shift; - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); oval = gus->mix_cntrl_reg; nval = (oval & ~(1 << shift)) | nval; change = nval != oval; outb(gus->mix_cntrl_reg = nval, GUSP(gus, MIXCNTRLREG)); outb(gus->gf1.active_voice = 0, GUSP(gus, GF1PAGE)); - spin_unlock_irqrestore(&gus->reg_lock, flags); return change; } @@ -75,14 +73,12 @@ static int snd_ics_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ele static int snd_ics_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; int addr = kcontrol->private_value & 0xff; unsigned char left, right; - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); left = gus->gf1.ics_regs[addr][0]; right = gus->gf1.ics_regs[addr][1]; - spin_unlock_irqrestore(&gus->reg_lock, flags); ucontrol->value.integer.value[0] = left & 127; ucontrol->value.integer.value[1] = right & 127; return 0; @@ -91,14 +87,13 @@ static int snd_ics_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem static int snd_ics_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; int addr = kcontrol->private_value & 0xff; int change; unsigned char val1, val2, oval1, oval2; val1 = ucontrol->value.integer.value[0] & 127; val2 = ucontrol->value.integer.value[1] & 127; - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); oval1 = gus->gf1.ics_regs[addr][0]; oval2 = gus->gf1.ics_regs[addr][1]; change = val1 != oval1 || val2 != oval2; @@ -116,7 +111,6 @@ static int snd_ics_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem outb(2, GUSP(gus, MIXDATAPORT)); outb(addr | 3, GUSP(gus, MIXCNTRLPORT)); outb((unsigned char) val2, GUSP(gus, MIXDATAPORT)); - spin_unlock_irqrestore(&gus->reg_lock, flags); return change; } diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index 8b9b7b8d92b2..9249cbff30f3 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c @@ -89,7 +89,6 @@ static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct gus_pcm_private *pcmp = runtime->private_data; struct snd_gus_card * gus = pcmp->gus; - unsigned long flags; unsigned char voice_ctrl, ramp_ctrl; unsigned short rate; unsigned int curr, begin, end; @@ -97,14 +96,12 @@ static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream) unsigned char pan; unsigned int voice; - spin_lock_irqsave(&pcmp->lock, flags); - if (pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE) { - spin_unlock_irqrestore(&pcmp->lock, flags); - return; + scoped_guard(spinlock_irqsave, &pcmp->lock) { + if (pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE) + return; + pcmp->flags |= SNDRV_GF1_PCM_PFLG_ACTIVE; + pcmp->final_volume = 0; } - pcmp->flags |= SNDRV_GF1_PCM_PFLG_ACTIVE; - pcmp->final_volume = 0; - spin_unlock_irqrestore(&pcmp->lock, flags); rate = snd_gf1_translate_freq(gus, runtime->rate << 4); /* enable WAVE IRQ */ voice_ctrl = snd_pcm_format_width(runtime->format) == 16 ? 0x24 : 0x20; @@ -121,7 +118,7 @@ static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream) end -= snd_pcm_format_width(runtime->format) == 16 ? 2 : 1; pan = runtime->channels == 2 ? (!voice ? 1 : 14) : 8; vol = !voice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number); snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, pan); snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, rate); @@ -137,9 +134,9 @@ static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream) snd_gf1_delay(gus); snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl); } - spin_unlock_irqrestore(&gus->reg_lock, flags); } - spin_lock_irqsave(&gus->reg_lock, flags); + + guard(spinlock_irqsave)(&gus->reg_lock); for (voice = 0; voice < pcmp->voices; voice++) { snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number); if (gus->gf1.enh_mode) @@ -156,7 +153,6 @@ static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream) voice_ctrl &= ~0x20; /* disable IRQ for next voice */ } } - spin_unlock_irqrestore(&gus->reg_lock, flags); } static void snd_gf1_pcm_interrupt_wave(struct snd_gus_card * gus, @@ -182,52 +178,52 @@ static void snd_gf1_pcm_interrupt_wave(struct snd_gus_card * gus, gus = pcmp->gus; runtime = pcmp->substream->runtime; - spin_lock(&gus->reg_lock); - snd_gf1_select_voice(gus, pvoice->number); - voice_ctrl = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL) & ~0x8b; - ramp_ctrl = (snd_gf1_read8(gus, SNDRV_GF1_VB_VOLUME_CONTROL) & ~0xa4) | 0x03; + scoped_guard(spinlock, &gus->reg_lock) { + snd_gf1_select_voice(gus, pvoice->number); + voice_ctrl = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL) & ~0x8b; + ramp_ctrl = (snd_gf1_read8(gus, SNDRV_GF1_VB_VOLUME_CONTROL) & ~0xa4) | 0x03; #if 0 - snd_gf1_select_voice(gus, pvoice->number); - dev_dbg(gus->card->dev, "position = 0x%x\n", - (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); - snd_gf1_select_voice(gus, pcmp->pvoices[1]->number); - dev_dbg(gus->card->dev, "position = 0x%x\n", - (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); - snd_gf1_select_voice(gus, pvoice->number); + snd_gf1_select_voice(gus, pvoice->number); + dev_dbg(gus->card->dev, "position = 0x%x\n", + (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); + snd_gf1_select_voice(gus, pcmp->pvoices[1]->number); + dev_dbg(gus->card->dev, "position = 0x%x\n", + (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); + snd_gf1_select_voice(gus, pvoice->number); #endif - pcmp->bpos++; - pcmp->bpos %= pcmp->blocks; - if (pcmp->bpos + 1 >= pcmp->blocks) { /* last block? */ - voice_ctrl |= 0x08; /* enable loop */ - } else { - ramp_ctrl |= 0x04; /* enable rollover */ - } - end = pcmp->memory + (((pcmp->bpos + 1) * pcmp->block_size) / runtime->channels); - end -= voice_ctrl & 4 ? 2 : 1; - step = pcmp->dma_size / runtime->channels; - voice_ctrl |= 0x20; - if (!pcmp->final_volume) { - ramp_ctrl |= 0x20; - ramp_ctrl &= ~0x03; - } - for (idx = 0; idx < pcmp->voices; idx++, end += step) { - snd_gf1_select_voice(gus, pcmp->pvoices[idx]->number); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, end << 4, voice_ctrl & 4); - snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl); - voice_ctrl &= ~0x20; - } - if (!gus->gf1.enh_mode) { - snd_gf1_delay(gus); + pcmp->bpos++; + pcmp->bpos %= pcmp->blocks; + if (pcmp->bpos + 1 >= pcmp->blocks) { /* last block? */ + voice_ctrl |= 0x08; /* enable loop */ + } else { + ramp_ctrl |= 0x04; /* enable rollover */ + } + end = pcmp->memory + (((pcmp->bpos + 1) * pcmp->block_size) / runtime->channels); + end -= voice_ctrl & 4 ? 2 : 1; + step = pcmp->dma_size / runtime->channels; voice_ctrl |= 0x20; - for (idx = 0; idx < pcmp->voices; idx++) { + if (!pcmp->final_volume) { + ramp_ctrl |= 0x20; + ramp_ctrl &= ~0x03; + } + for (idx = 0; idx < pcmp->voices; idx++, end += step) { snd_gf1_select_voice(gus, pcmp->pvoices[idx]->number); + snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, end << 4, voice_ctrl & 4); snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl); snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl); voice_ctrl &= ~0x20; } + if (!gus->gf1.enh_mode) { + snd_gf1_delay(gus); + voice_ctrl |= 0x20; + for (idx = 0; idx < pcmp->voices; idx++) { + snd_gf1_select_voice(gus, pcmp->pvoices[idx]->number); + snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl); + snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl); + voice_ctrl &= ~0x20; + } + } } - spin_unlock(&gus->reg_lock); snd_pcm_period_elapsed(pcmp->substream); #if 0 @@ -252,10 +248,10 @@ static void snd_gf1_pcm_interrupt_volume(struct snd_gus_card * gus, struct gus_pcm_private *pcmp = pvoice->private_data; /* stop ramp, but leave rollover bit untouched */ - spin_lock(&gus->reg_lock); - snd_gf1_select_voice(gus, pvoice->number); - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); - spin_unlock(&gus->reg_lock); + scoped_guard(spinlock, &gus->reg_lock) { + snd_gf1_select_voice(gus, pvoice->number); + snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); + } if (pcmp == NULL) return; /* are we active? */ @@ -266,11 +262,10 @@ static void snd_gf1_pcm_interrupt_volume(struct snd_gus_card * gus, if (pcmp->substream == NULL) return; vol = !cvoice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; - spin_lock(&gus->reg_lock); + guard(spinlock)(&gus->reg_lock); snd_gf1_select_voice(gus, pvoice->number); snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol); pcmp->final_volume = 1; - spin_unlock(&gus->reg_lock); } static void snd_gf1_pcm_volume_change(struct snd_gus_card * gus) @@ -282,7 +277,6 @@ static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf, int w16, int invert) { unsigned int len; - unsigned long flags; while (count > 0) { len = count; @@ -290,7 +284,7 @@ static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf, len = 512; count -= len; if (gus->interwave) { - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01 | (invert ? 0x08 : 0x00)); snd_gf1_dram_addr(gus, pos); if (w16) { @@ -299,7 +293,6 @@ static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf, } else { outsb(GUSP(gus, DRAM), buf, len); } - spin_unlock_irqrestore(&gus->reg_lock, flags); buf += 512; pos += 512; } else { @@ -479,9 +472,9 @@ static int snd_gf1_pcm_playback_trigger(struct snd_pcm_substream *substream, if (cmd == SNDRV_PCM_TRIGGER_START) { snd_gf1_pcm_trigger_up(substream); } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - spin_lock(&pcmp->lock); - pcmp->flags &= ~SNDRV_GF1_PCM_PFLG_ACTIVE; - spin_unlock(&pcmp->lock); + scoped_guard(spinlock, &pcmp->lock) { + pcmp->flags &= ~SNDRV_GF1_PCM_PFLG_ACTIVE; + } voice = pcmp->pvoices[0]->number; snd_gf1_stop_voices(gus, voice, voice); if (pcmp->pvoices[1]) { @@ -503,7 +496,7 @@ static snd_pcm_uframes_t snd_gf1_pcm_playback_pointer(struct snd_pcm_substream * unsigned char voice_ctrl; pos = 0; - spin_lock(&gus->reg_lock); + guard(spinlock)(&gus->reg_lock); if (pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE) { snd_gf1_select_voice(gus, pcmp->pvoices[0]->number); voice_ctrl = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); @@ -512,7 +505,6 @@ static snd_pcm_uframes_t snd_gf1_pcm_playback_pointer(struct snd_pcm_substream * pos <<= 1; pos = bytes_to_frames(runtime, pos); } - spin_unlock(&gus->reg_lock); return pos; } @@ -572,10 +564,9 @@ static int snd_gf1_pcm_capture_trigger(struct snd_pcm_substream *substream, return -EINVAL; } - spin_lock(&gus->reg_lock); + guard(spinlock)(&gus->reg_lock); snd_gf1_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, val); snd_gf1_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL); - spin_unlock(&gus->reg_lock); return 0; } @@ -724,19 +715,16 @@ static int snd_gf1_pcm_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl static int snd_gf1_pcm_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; - spin_lock_irqsave(&gus->pcm_volume_level_lock, flags); + guard(spinlock_irqsave)(&gus->pcm_volume_level_lock); ucontrol->value.integer.value[0] = gus->gf1.pcm_volume_level_left1; ucontrol->value.integer.value[1] = gus->gf1.pcm_volume_level_right1; - spin_unlock_irqrestore(&gus->pcm_volume_level_lock, flags); return 0; } static int snd_gf1_pcm_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; int change; unsigned int idx; unsigned short val1, val2, vol; @@ -745,33 +733,32 @@ static int snd_gf1_pcm_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ val1 = ucontrol->value.integer.value[0] & 127; val2 = ucontrol->value.integer.value[1] & 127; - spin_lock_irqsave(&gus->pcm_volume_level_lock, flags); - change = val1 != gus->gf1.pcm_volume_level_left1 || - val2 != gus->gf1.pcm_volume_level_right1; - gus->gf1.pcm_volume_level_left1 = val1; - gus->gf1.pcm_volume_level_right1 = val2; - gus->gf1.pcm_volume_level_left = snd_gf1_lvol_to_gvol_raw(val1 << 9) << 4; - gus->gf1.pcm_volume_level_right = snd_gf1_lvol_to_gvol_raw(val2 << 9) << 4; - spin_unlock_irqrestore(&gus->pcm_volume_level_lock, flags); + scoped_guard(spinlock_irqsave, &gus->pcm_volume_level_lock) { + change = val1 != gus->gf1.pcm_volume_level_left1 || + val2 != gus->gf1.pcm_volume_level_right1; + gus->gf1.pcm_volume_level_left1 = val1; + gus->gf1.pcm_volume_level_right1 = val2; + gus->gf1.pcm_volume_level_left = snd_gf1_lvol_to_gvol_raw(val1 << 9) << 4; + gus->gf1.pcm_volume_level_right = snd_gf1_lvol_to_gvol_raw(val2 << 9) << 4; + } /* are we active? */ - spin_lock_irqsave(&gus->voice_alloc, flags); - for (idx = 0; idx < 32; idx++) { - pvoice = &gus->gf1.voices[idx]; - if (!pvoice->pcm) - continue; - pcmp = pvoice->private_data; - if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE)) - continue; - /* load real volume - better precision */ - spin_lock(&gus->reg_lock); - snd_gf1_select_voice(gus, pvoice->number); - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); - vol = pvoice == pcmp->pvoices[0] ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; - snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol); - pcmp->final_volume = 1; - spin_unlock(&gus->reg_lock); + scoped_guard(spinlock_irqsave, &gus->voice_alloc) { + for (idx = 0; idx < 32; idx++) { + pvoice = &gus->gf1.voices[idx]; + if (!pvoice->pcm) + continue; + pcmp = pvoice->private_data; + if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE)) + continue; + /* load real volume - better precision */ + guard(spinlock)(&gus->reg_lock); + snd_gf1_select_voice(gus, pvoice->number); + snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); + vol = pvoice == pcmp->pvoices[0] ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; + snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol); + pcmp->final_volume = 1; + } } - spin_unlock_irqrestore(&gus->voice_alloc, flags); return change; } diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c index 326bc6028885..5cbace8369f8 100644 --- a/sound/isa/gus/gus_reset.c +++ b/sound/isa/gus/gus_reset.c @@ -83,26 +83,20 @@ void snd_gf1_set_default_handlers(struct snd_gus_card * gus, unsigned int what) static void snd_gf1_clear_regs(struct snd_gus_card * gus) { - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); inb(GUSP(gus, IRQSTAT)); snd_gf1_write8(gus, 0x41, 0); /* DRAM DMA Control Register */ snd_gf1_write8(gus, 0x45, 0); /* Timer Control */ snd_gf1_write8(gus, 0x49, 0); /* Sampling Control Register */ - spin_unlock_irqrestore(&gus->reg_lock, flags); } static void snd_gf1_look_regs(struct snd_gus_card * gus) { - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); snd_gf1_look8(gus, 0x41); /* DRAM DMA Control Register */ snd_gf1_look8(gus, 0x49); /* Sampling Control Register */ inb(GUSP(gus, IRQSTAT)); snd_gf1_read8(gus, 0x0f); /* IRQ Source Register */ - spin_unlock_irqrestore(&gus->reg_lock, flags); } /* @@ -111,9 +105,7 @@ static void snd_gf1_look_regs(struct snd_gus_card * gus) void snd_gf1_smart_stop_voice(struct snd_gus_card * gus, unsigned short voice) { - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); snd_gf1_select_voice(gus, voice); #if 0 dev_dbg(gus->card->dev, @@ -122,14 +114,11 @@ void snd_gf1_smart_stop_voice(struct snd_gus_card * gus, unsigned short voice) #endif snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); - spin_unlock_irqrestore(&gus->reg_lock, flags); } void snd_gf1_stop_voice(struct snd_gus_card * gus, unsigned short voice) { - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); snd_gf1_select_voice(gus, voice); #if 0 dev_dbg(gus->card->dev, @@ -140,13 +129,11 @@ void snd_gf1_stop_voice(struct snd_gus_card * gus, unsigned short voice) snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); if (gus->gf1.enh_mode) snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, 0); - spin_unlock_irqrestore(&gus->reg_lock, flags); } static void snd_gf1_clear_voices(struct snd_gus_card * gus, unsigned short v_min, unsigned short v_max) { - unsigned long flags; unsigned int daddr; unsigned short i, w_16; @@ -156,7 +143,7 @@ static void snd_gf1_clear_voices(struct snd_gus_card * gus, unsigned short v_min if (gus->gf1.syn_voices) gus->gf1.syn_voices[i].flags = ~VFLG_DYNAMIC; #endif - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); snd_gf1_select_voice(gus, i); snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); /* Voice Control Register = voice stop */ snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); /* Volume Ramp Control Register = ramp off */ @@ -177,19 +164,17 @@ static void snd_gf1_clear_voices(struct snd_gus_card * gus, unsigned short v_min snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME, 0); snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME_FINAL, 0); } - spin_unlock_irqrestore(&gus->reg_lock, flags); } } void snd_gf1_stop_voices(struct snd_gus_card * gus, unsigned short v_min, unsigned short v_max) { - unsigned long flags; short i, ramp_ok; unsigned short ramp_end; if (!in_interrupt()) { /* this can't be done in interrupt */ for (i = v_min, ramp_ok = 0; i <= v_max; i++) { - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); snd_gf1_select_voice(gus, i); ramp_end = snd_gf1_read16(gus, 9) >> 8; if (ramp_end > SNDRV_GF1_MIN_OFFSET) { @@ -203,7 +188,6 @@ void snd_gf1_stop_voices(struct snd_gus_card * gus, unsigned short v_min, unsign snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, 0x40); } } - spin_unlock_irqrestore(&gus->reg_lock, flags); } msleep_interruptible(50); } @@ -236,21 +220,17 @@ static void snd_gf1_alloc_voice_use(struct snd_gus_card * gus, struct snd_gus_voice *snd_gf1_alloc_voice(struct snd_gus_card * gus, int type, int client, int port) { struct snd_gus_voice *pvoice; - unsigned long flags; int idx; - spin_lock_irqsave(&gus->voice_alloc, flags); + guard(spinlock_irqsave)(&gus->voice_alloc); if (type == SNDRV_GF1_VOICE_TYPE_PCM) { - if (gus->gf1.pcm_alloc_voices >= gus->gf1.pcm_channels) { - spin_unlock_irqrestore(&gus->voice_alloc, flags); + if (gus->gf1.pcm_alloc_voices >= gus->gf1.pcm_channels) return NULL; - } } for (idx = 0; idx < 32; idx++) { pvoice = &gus->gf1.voices[idx]; if (!pvoice->use) { snd_gf1_alloc_voice_use(gus, pvoice, type, client, port); - spin_unlock_irqrestore(&gus->voice_alloc, flags); return pvoice; } } @@ -259,32 +239,29 @@ struct snd_gus_voice *snd_gf1_alloc_voice(struct snd_gus_card * gus, int type, i if (pvoice->midi && !pvoice->client) { snd_gf1_clear_voices(gus, pvoice->number, pvoice->number); snd_gf1_alloc_voice_use(gus, pvoice, type, client, port); - spin_unlock_irqrestore(&gus->voice_alloc, flags); return pvoice; } } - spin_unlock_irqrestore(&gus->voice_alloc, flags); return NULL; } void snd_gf1_free_voice(struct snd_gus_card * gus, struct snd_gus_voice *voice) { - unsigned long flags; void (*private_free)(struct snd_gus_voice *voice); if (voice == NULL || !voice->use) return; snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_VOICE | voice->number); snd_gf1_clear_voices(gus, voice->number, voice->number); - spin_lock_irqsave(&gus->voice_alloc, flags); - private_free = voice->private_free; - voice->private_free = NULL; - voice->private_data = NULL; - if (voice->pcm) - gus->gf1.pcm_alloc_voices--; - voice->use = voice->pcm = 0; - voice->sample_ops = NULL; - spin_unlock_irqrestore(&gus->voice_alloc, flags); + scoped_guard(spinlock_irqsave, &gus->voice_alloc) { + private_free = voice->private_free; + voice->private_free = NULL; + voice->private_data = NULL; + if (voice->pcm) + gus->gf1.pcm_alloc_voices--; + voice->use = voice->pcm = 0; + voice->sample_ops = NULL; + } if (private_free) private_free(voice); } @@ -295,7 +272,6 @@ void snd_gf1_free_voice(struct snd_gus_card * gus, struct snd_gus_voice *voice) int snd_gf1_start(struct snd_gus_card * gus) { - unsigned long flags; unsigned int i; snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ @@ -344,10 +320,10 @@ int snd_gf1_start(struct snd_gus_card * gus) } while ((snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ) & 0xc0) != 0xc0); - spin_lock_irqsave(&gus->reg_lock, flags); - outb(gus->gf1.active_voice = 0, GUSP(gus, GF1PAGE)); - outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - spin_unlock_irqrestore(&gus->reg_lock, flags); + scoped_guard(spinlock_irqsave, &gus->reg_lock) { + outb(gus->gf1.active_voice = 0, GUSP(gus, GF1PAGE)); + outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); + } snd_gf1_timers_init(gus); snd_gf1_look_regs(gus); diff --git a/sound/isa/gus/gus_timer.c b/sound/isa/gus/gus_timer.c index 7267fb5bf8e5..e3a8847e02cf 100644 --- a/sound/isa/gus/gus_timer.c +++ b/sound/isa/gus/gus_timer.c @@ -16,33 +16,29 @@ static int snd_gf1_timer1_start(struct snd_timer * timer) { - unsigned long flags; unsigned char tmp; unsigned int ticks; struct snd_gus_card *gus; gus = snd_timer_chip(timer); - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); ticks = timer->sticks; tmp = (gus->gf1.timer_enabled |= 4); snd_gf1_write8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1, 256 - ticks); /* timer 1 count */ snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* enable timer 1 IRQ */ snd_gf1_adlib_write(gus, 0x04, tmp >> 2); /* timer 2 start */ - spin_unlock_irqrestore(&gus->reg_lock, flags); return 0; } static int snd_gf1_timer1_stop(struct snd_timer * timer) { - unsigned long flags; unsigned char tmp; struct snd_gus_card *gus; gus = snd_timer_chip(timer); - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); tmp = (gus->gf1.timer_enabled &= ~4); snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* disable timer #1 */ - spin_unlock_irqrestore(&gus->reg_lock, flags); return 0; } @@ -52,33 +48,29 @@ static int snd_gf1_timer1_stop(struct snd_timer * timer) static int snd_gf1_timer2_start(struct snd_timer * timer) { - unsigned long flags; unsigned char tmp; unsigned int ticks; struct snd_gus_card *gus; gus = snd_timer_chip(timer); - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); ticks = timer->sticks; tmp = (gus->gf1.timer_enabled |= 8); snd_gf1_write8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2, 256 - ticks); /* timer 2 count */ snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* enable timer 2 IRQ */ snd_gf1_adlib_write(gus, 0x04, tmp >> 2); /* timer 2 start */ - spin_unlock_irqrestore(&gus->reg_lock, flags); return 0; } static int snd_gf1_timer2_stop(struct snd_timer * timer) { - unsigned long flags; unsigned char tmp; struct snd_gus_card *gus; gus = snd_timer_chip(timer); - spin_lock_irqsave(&gus->reg_lock, flags); + guard(spinlock_irqsave)(&gus->reg_lock); tmp = (gus->gf1.timer_enabled &= ~8); snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* disable timer #1 */ - spin_unlock_irqrestore(&gus->reg_lock, flags); return 0; } diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c index e207f274f240..770d8f3e4cff 100644 --- a/sound/isa/gus/gus_uart.c +++ b/sound/isa/gus/gus_uart.c @@ -49,13 +49,12 @@ static void snd_gf1_interrupt_midi_in(struct snd_gus_card * gus) static void snd_gf1_interrupt_midi_out(struct snd_gus_card * gus) { char byte; - unsigned long flags; /* try unlock output */ if (snd_gf1_uart_stat(gus) & 0x01) snd_gf1_interrupt_midi_in(gus); - spin_lock_irqsave(&gus->uart_cmd_lock, flags); + guard(spinlock_irqsave)(&gus->uart_cmd_lock); if (snd_gf1_uart_stat(gus) & 0x02) { /* Tx FIFO free? */ if (snd_rawmidi_transmit(gus->midi_substream_output, &byte, 1) != 1) { /* no other bytes or error */ snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x20); /* disable Tx interrupt */ @@ -63,7 +62,6 @@ static void snd_gf1_interrupt_midi_out(struct snd_gus_card * gus) snd_gf1_uart_put(gus, byte); } } - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); } static void snd_gf1_uart_reset(struct snd_gus_card * gus, int close) @@ -77,17 +75,15 @@ static void snd_gf1_uart_reset(struct snd_gus_card * gus, int close) static int snd_gf1_uart_output_open(struct snd_rawmidi_substream *substream) { - unsigned long flags; struct snd_gus_card *gus; gus = substream->rmidi->private_data; - spin_lock_irqsave(&gus->uart_cmd_lock, flags); + guard(spinlock_irqsave)(&gus->uart_cmd_lock); if (!(gus->gf1.uart_cmd & 0x80)) { /* input active? */ snd_gf1_uart_reset(gus, 0); } gus->gf1.interrupt_handler_midi_out = snd_gf1_interrupt_midi_out; gus->midi_substream_output = substream; - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); #if 0 dev_dbg(gus->card->dev, "write init - cmd = 0x%x, stat = 0x%x\n", @@ -98,12 +94,11 @@ static int snd_gf1_uart_output_open(struct snd_rawmidi_substream *substream) static int snd_gf1_uart_input_open(struct snd_rawmidi_substream *substream) { - unsigned long flags; struct snd_gus_card *gus; int i; gus = substream->rmidi->private_data; - spin_lock_irqsave(&gus->uart_cmd_lock, flags); + guard(spinlock_irqsave)(&gus->uart_cmd_lock); if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out) { snd_gf1_uart_reset(gus, 0); } @@ -115,7 +110,6 @@ static int snd_gf1_uart_input_open(struct snd_rawmidi_substream *substream) if (i >= 1000) dev_err(gus->card->dev, "gus midi uart init read - cleanup error\n"); } - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); #if 0 dev_dbg(gus->card->dev, "read init - enable = %i, cmd = 0x%x, stat = 0x%x\n", @@ -130,42 +124,37 @@ static int snd_gf1_uart_input_open(struct snd_rawmidi_substream *substream) static int snd_gf1_uart_output_close(struct snd_rawmidi_substream *substream) { - unsigned long flags; struct snd_gus_card *gus; gus = substream->rmidi->private_data; - spin_lock_irqsave(&gus->uart_cmd_lock, flags); + guard(spinlock_irqsave)(&gus->uart_cmd_lock); if (gus->gf1.interrupt_handler_midi_in != snd_gf1_interrupt_midi_in) snd_gf1_uart_reset(gus, 1); snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_MIDI_OUT); gus->midi_substream_output = NULL; - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); return 0; } static int snd_gf1_uart_input_close(struct snd_rawmidi_substream *substream) { - unsigned long flags; struct snd_gus_card *gus; gus = substream->rmidi->private_data; - spin_lock_irqsave(&gus->uart_cmd_lock, flags); + guard(spinlock_irqsave)(&gus->uart_cmd_lock); if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out) snd_gf1_uart_reset(gus, 1); snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_MIDI_IN); gus->midi_substream_input = NULL; - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); return 0; } static void snd_gf1_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) { struct snd_gus_card *gus; - unsigned long flags; gus = substream->rmidi->private_data; - spin_lock_irqsave(&gus->uart_cmd_lock, flags); + guard(spinlock_irqsave)(&gus->uart_cmd_lock); if (up) { if ((gus->gf1.uart_cmd & 0x80) == 0) snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd | 0x80); /* enable Rx interrupts */ @@ -173,7 +162,6 @@ static void snd_gf1_uart_input_trigger(struct snd_rawmidi_substream *substream, if (gus->gf1.uart_cmd & 0x80) snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x80); /* disable Rx interrupts */ } - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); } static void snd_gf1_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index 28827a2e6cbd..ed921b89b00a 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c @@ -145,7 +145,6 @@ static int snd_gusextreme_gus_card_create(struct snd_card *card, static int snd_gusextreme_detect(struct snd_gus_card *gus, struct snd_es1688 *es1688) { - unsigned long flags; unsigned char d; /* @@ -162,17 +161,17 @@ static int snd_gusextreme_detect(struct snd_gus_card *gus, * 0x260 = 2,2,1 */ - spin_lock_irqsave(&es1688->mixer_lock, flags); - snd_es1688_mixer_write(es1688, 0x40, 0x0b); /* don't change!!! */ - spin_unlock_irqrestore(&es1688->mixer_lock, flags); - - spin_lock_irqsave(&es1688->reg_lock, flags); - outb(gus->gf1.port & 0x040 ? 2 : 0, ES1688P(es1688, INIT1)); - outb(0, 0x201); - outb(gus->gf1.port & 0x020 ? 2 : 0, ES1688P(es1688, INIT1)); - outb(0, 0x201); - outb(gus->gf1.port & 0x010 ? 3 : 1, ES1688P(es1688, INIT1)); - spin_unlock_irqrestore(&es1688->reg_lock, flags); + scoped_guard(spinlock_irqsave, &es1688->mixer_lock) { + snd_es1688_mixer_write(es1688, 0x40, 0x0b); /* don't change!!! */ + } + + scoped_guard(spinlock_irqsave, &es1688->reg_lock) { + outb(gus->gf1.port & 0x040 ? 2 : 0, ES1688P(es1688, INIT1)); + outb(0, 0x201); + outb(gus->gf1.port & 0x020 ? 2 : 0, ES1688P(es1688, INIT1)); + outb(0, 0x201); + outb(gus->gf1.port & 0x010 ? 3 : 1, ES1688P(es1688, INIT1)); + } udelay(100); diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 0e0bcd85a648..18adcd35e117 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -239,7 +239,6 @@ static int snd_interwave_detect(struct snd_interwave *iwcard, #endif ) { - unsigned long flags; unsigned char rev1, rev2; int d; @@ -257,12 +256,12 @@ static int snd_interwave_detect(struct snd_interwave *iwcard, dev_dbg(gus->card->dev, "[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } - spin_lock_irqsave(&gus->reg_lock, flags); - rev1 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER); - snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, ~rev1); - rev2 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER); - snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, rev1); - spin_unlock_irqrestore(&gus->reg_lock, flags); + scoped_guard(spinlock_irqsave, &gus->reg_lock) { + rev1 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER); + snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, ~rev1); + rev2 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER); + snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, rev1); + } dev_dbg(gus->card->dev, "[0x%lx] InterWave check - rev1=0x%x, rev2=0x%x\n", gus->gf1.port, rev1, rev2); @@ -457,18 +456,16 @@ static void snd_interwave_detect_memory(struct snd_gus_card *gus) static void snd_interwave_init(int dev, struct snd_gus_card *gus) { - unsigned long flags; - /* ok.. some InterWave specific initialization */ - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, 0x00); - snd_gf1_write8(gus, SNDRV_GF1_GB_COMPATIBILITY, 0x1f); - snd_gf1_write8(gus, SNDRV_GF1_GB_DECODE_CONTROL, 0x49); - snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, 0x11); - snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A, 0x00); - snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B, 0x30); - snd_gf1_write8(gus, SNDRV_GF1_GB_EMULATION_IRQ, 0x00); - spin_unlock_irqrestore(&gus->reg_lock, flags); + scoped_guard(spinlock_irqsave, &gus->reg_lock) { + snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, 0x00); + snd_gf1_write8(gus, SNDRV_GF1_GB_COMPATIBILITY, 0x1f); + snd_gf1_write8(gus, SNDRV_GF1_GB_DECODE_CONTROL, 0x49); + snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, 0x11); + snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A, 0x00); + snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B, 0x30); + snd_gf1_write8(gus, SNDRV_GF1_GB_EMULATION_IRQ, 0x00); + } gus->equal_irq = 1; gus->codec_flag = 1; gus->interwave = 1; diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c index 8c1d2e27854b..5e350234d572 100644 --- a/sound/isa/msnd/msnd.c +++ b/sound/isa/msnd/msnd.c @@ -76,15 +76,11 @@ static int snd_msnd_wait_HC0(struct snd_msnd *dev) int snd_msnd_send_dsp_cmd(struct snd_msnd *dev, u8 cmd) { - unsigned long flags; - - spin_lock_irqsave(&dev->lock, flags); + guard(spinlock_irqsave)(&dev->lock); if (snd_msnd_wait_HC0(dev) == 0) { outb(cmd, dev->io + HP_CVR); - spin_unlock_irqrestore(&dev->lock, flags); return 0; } - spin_unlock_irqrestore(&dev->lock, flags); dev_dbg(dev->card->dev, LOGNAME ": Send DSP command timeout\n"); @@ -133,14 +129,12 @@ EXPORT_SYMBOL(snd_msnd_upload_host); int snd_msnd_enable_irq(struct snd_msnd *dev) { - unsigned long flags; - if (dev->irq_ref++) return 0; dev_dbg(dev->card->dev, LOGNAME ": Enabling IRQ\n"); - spin_lock_irqsave(&dev->lock, flags); + guard(spinlock_irqsave)(&dev->lock); if (snd_msnd_wait_TXDE(dev) == 0) { outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR); if (dev->type == msndClassic) @@ -151,10 +145,8 @@ int snd_msnd_enable_irq(struct snd_msnd *dev) enable_irq(dev->irq); snd_msnd_init_queue(dev->DSPQ, dev->dspq_data_buff, dev->dspq_buff_size); - spin_unlock_irqrestore(&dev->lock, flags); return 0; } - spin_unlock_irqrestore(&dev->lock, flags); dev_dbg(dev->card->dev, LOGNAME ": Enable IRQ failed\n"); @@ -164,8 +156,6 @@ EXPORT_SYMBOL(snd_msnd_enable_irq); int snd_msnd_disable_irq(struct snd_msnd *dev) { - unsigned long flags; - if (--dev->irq_ref > 0) return 0; @@ -175,16 +165,14 @@ int snd_msnd_disable_irq(struct snd_msnd *dev) dev_dbg(dev->card->dev, LOGNAME ": Disabling IRQ\n"); - spin_lock_irqsave(&dev->lock, flags); + guard(spinlock_irqsave)(&dev->lock); if (snd_msnd_wait_TXDE(dev) == 0) { outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR); if (dev->type == msndClassic) outb(HPIRQ_NONE, dev->io + HP_IRQM); disable_irq(dev->irq); - spin_unlock_irqrestore(&dev->lock, flags); return 0; } - spin_unlock_irqrestore(&dev->lock, flags); dev_dbg(dev->card->dev, LOGNAME ": Disable IRQ failed\n"); @@ -376,7 +364,6 @@ static void snd_msnd_capture_reset_queue(struct snd_msnd *chip, { int n; void __iomem *pDAQ; - /* unsigned long flags; */ /* snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); */ @@ -388,11 +375,11 @@ static void snd_msnd_capture_reset_queue(struct snd_msnd *chip, chip->DARQ + JQS_wTail); #if 0 /* Critical section: bank 1 access. this is how the OSS driver does it:*/ - spin_lock_irqsave(&chip->lock, flags); - outb(HPBLKSEL_1, chip->io + HP_BLKS); - memset_io(chip->mappedbase, 0, DAR_BUFF_SIZE * 3); - outb(HPBLKSEL_0, chip->io + HP_BLKS); - spin_unlock_irqrestore(&chip->lock, flags); + scoped_guard(spinlock_irqsave, &chip->lock) { + outb(HPBLKSEL_1, chip->io + HP_BLKS); + memset_io(chip->mappedbase, 0, DAR_BUFF_SIZE * 3); + outb(HPBLKSEL_0, chip->io + HP_BLKS); + } #endif chip->capturePeriodBytes = pcm_count; diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 969bbb18657b..c4eec391cd29 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -300,7 +300,6 @@ static int snd_msnd_init_sma(struct snd_msnd *chip) { static int initted; u16 mastVolLeft, mastVolRight; - unsigned long flags; #ifdef MSND_CLASSIC outb(chip->memid, chip->io + HP_MEMM); @@ -317,11 +316,11 @@ static int snd_msnd_init_sma(struct snd_msnd *chip) memset_io(chip->mappedbase, 0, 0x8000); /* Critical section: bank 1 access */ - spin_lock_irqsave(&chip->lock, flags); - outb(HPBLKSEL_1, chip->io + HP_BLKS); - memset_io(chip->mappedbase, 0, 0x8000); - outb(HPBLKSEL_0, chip->io + HP_BLKS); - spin_unlock_irqrestore(&chip->lock, flags); + scoped_guard(spinlock_irqsave, &chip->lock) { + outb(HPBLKSEL_1, chip->io + HP_BLKS); + memset_io(chip->mappedbase, 0, 0x8000); + outb(HPBLKSEL_0, chip->io + HP_BLKS); + } /* Digital audio play queue */ chip->DAPQ = chip->mappedbase + DAPQ_OFFSET; diff --git a/sound/isa/msnd/msnd_pinnacle_mixer.c b/sound/isa/msnd/msnd_pinnacle_mixer.c index 2f1bb5a2b376..ec354483b9f8 100644 --- a/sound/isa/msnd/msnd_pinnacle_mixer.c +++ b/sound/isa/msnd/msnd_pinnacle_mixer.c @@ -136,14 +136,12 @@ static int snd_msndmix_volume_get(struct snd_kcontrol *kcontrol, { struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); int addr = kcontrol->private_value; - unsigned long flags; - spin_lock_irqsave(&msnd->mixer_lock, flags); + guard(spinlock_irqsave)(&msnd->mixer_lock); ucontrol->value.integer.value[0] = msnd->left_levels[addr] * 100; ucontrol->value.integer.value[0] /= 0xFFFF; ucontrol->value.integer.value[1] = msnd->right_levels[addr] * 100; ucontrol->value.integer.value[1] /= 0xFFFF; - spin_unlock_irqrestore(&msnd->mixer_lock, flags); return 0; } @@ -253,15 +251,13 @@ static int snd_msndmix_volume_put(struct snd_kcontrol *kcontrol, struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); int change, addr = kcontrol->private_value; int left, right; - unsigned long flags; left = ucontrol->value.integer.value[0] % 101; right = ucontrol->value.integer.value[1] % 101; - spin_lock_irqsave(&msnd->mixer_lock, flags); + guard(spinlock_irqsave)(&msnd->mixer_lock); change = msnd->left_levels[addr] != left || msnd->right_levels[addr] != right; snd_msndmix_set(msnd, addr, left, right); - spin_unlock_irqrestore(&msnd->mixer_lock, flags); return change; } diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 5e8e1326d5c0..8c1767697b62 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -172,13 +172,8 @@ static unsigned char __snd_opl3sa2_read(struct snd_opl3sa2 *chip, unsigned char /* read control port (with spinlock) */ static unsigned char snd_opl3sa2_read(struct snd_opl3sa2 *chip, unsigned char reg) { - unsigned long flags; - unsigned char result; - - spin_lock_irqsave(&chip->reg_lock, flags); - result = __snd_opl3sa2_read(chip, reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return result; + guard(spinlock_irqsave)(&chip->reg_lock); + return __snd_opl3sa2_read(chip, reg); } /* write control port (w/o spinlock) */ @@ -195,10 +190,8 @@ static void __snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, uns /* write control port (with spinlock) */ static void snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsigned char value) { - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); __snd_opl3sa2_write(chip, reg, value); - spin_unlock_irqrestore(&chip->reg_lock, flags); } static int snd_opl3sa2_detect(struct snd_card *card) @@ -336,15 +329,13 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id) static int snd_opl3sa2_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.integer.value[0] = (chip->ctlregs[reg] >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); if (invert) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; return 0; @@ -353,7 +344,6 @@ static int snd_opl3sa2_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_opl3sa2_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; @@ -365,12 +355,11 @@ static int snd_opl3sa2_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ if (invert) val = mask - val; val <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); oval = chip->ctlregs[reg]; val = (oval & ~(mask << shift)) | val; change = val != oval; __snd_opl3sa2_write(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } @@ -391,7 +380,6 @@ static int snd_opl3sa2_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_opl3sa2_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int shift_left = (kcontrol->private_value >> 16) & 0x07; @@ -399,10 +387,9 @@ static int snd_opl3sa2_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ int mask = (kcontrol->private_value >> 24) & 0xff; int invert = (kcontrol->private_value >> 22) & 1; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.integer.value[0] = (chip->ctlregs[left_reg] >> shift_left) & mask; ucontrol->value.integer.value[1] = (chip->ctlregs[right_reg] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); if (invert) { ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; @@ -413,7 +400,6 @@ static int snd_opl3sa2_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_opl3sa2_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int shift_left = (kcontrol->private_value >> 16) & 0x07; @@ -431,7 +417,7 @@ static int snd_opl3sa2_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ } val1 <<= shift_left; val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (left_reg != right_reg) { oval1 = chip->ctlregs[left_reg]; oval2 = chip->ctlregs[right_reg]; @@ -446,7 +432,6 @@ static int snd_opl3sa2_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ change = val1 != oval1; __snd_opl3sa2_write(chip, left_reg, val1); } - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index ad7180d7c0c2..c320af3e9a05 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -822,10 +822,9 @@ static int snd_miro_init(struct snd_miro *chip, static unsigned char snd_miro_read(struct snd_miro *chip, unsigned char reg) { - unsigned long flags; unsigned char retval = 0xff; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); outb(chip->password, chip->mc_base + chip->pwd_reg); switch (chip->hardware) { @@ -846,16 +845,13 @@ static unsigned char snd_miro_read(struct snd_miro *chip, dev_err(chip->card->dev, "sorry, no support for %d\n", chip->hardware); } - spin_unlock_irqrestore(&chip->lock, flags); return retval; } static void snd_miro_write(struct snd_miro *chip, unsigned char reg, unsigned char value) { - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); outb(chip->password, chip->mc_base + chip->pwd_reg); switch (chip->hardware) { @@ -875,8 +871,6 @@ static void snd_miro_write(struct snd_miro *chip, unsigned char reg, default: dev_err(chip->card->dev, "sorry, no support for %d\n", chip->hardware); } - - spin_unlock_irqrestore(&chip->lock, flags); } static inline void snd_miro_write_mask(struct snd_miro *chip, @@ -1013,7 +1007,6 @@ static int snd_miro_configure(struct snd_miro *chip) unsigned char dma_bits; unsigned char mpu_port_bits = 0; unsigned char mpu_irq_bits; - unsigned long flags; snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */ @@ -1109,9 +1102,9 @@ __skip_base: } dma_bits |= 0x04; - spin_lock_irqsave(&chip->lock, flags); - outb(irq_bits << 3 | dma_bits, chip->wss_base); - spin_unlock_irqrestore(&chip->lock, flags); + scoped_guard(spinlock_irqsave, &chip->lock) { + outb(irq_bits << 3 | dma_bits, chip->wss_base); + } __skip_resources: if (chip->hardware > OPTi9XX_HW_82C928) { diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 328d043a1619..abaa3ed3ab5c 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -228,10 +228,9 @@ static int snd_opti9xx_init(struct snd_opti9xx *chip, static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, unsigned char reg) { - unsigned long flags; unsigned char retval = 0xff; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); outb(chip->password, chip->mc_base + chip->pwd_reg); switch (chip->hardware) { @@ -265,16 +264,13 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, dev_err(chip->card->dev, "chip %d not supported\n", chip->hardware); } - spin_unlock_irqrestore(&chip->lock, flags); return retval; } static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, unsigned char value) { - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); outb(chip->password, chip->mc_base + chip->pwd_reg); switch (chip->hardware) { @@ -307,8 +303,6 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, default: dev_err(chip->card->dev, "chip %d not supported\n", chip->hardware); } - - spin_unlock_irqrestore(&chip->lock, flags); } @@ -659,9 +653,6 @@ static int snd_opti9xx_read_check(struct snd_card *card, struct snd_opti9xx *chip) { unsigned char value; -#ifdef OPTi93X - unsigned long flags; -#endif chip->res_mc_base = devm_request_region(card->dev, chip->mc_base, @@ -680,10 +671,10 @@ static int snd_opti9xx_read_check(struct snd_card *card, if (!chip->res_mc_indir) return -EBUSY; - spin_lock_irqsave(&chip->lock, flags); - outb(chip->password, chip->mc_base + chip->pwd_reg); - outb(((chip->mc_indir_index & 0x1f0) >> 4), chip->mc_base); - spin_unlock_irqrestore(&chip->lock, flags); + scoped_guard(spinlock_irqsave, &chip->lock) { + outb(chip->password, chip->mc_base + chip->pwd_reg); + outb(((chip->mc_indir_index & 0x1f0) >> 4), chip->mc_base); + } value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)); snd_opti9xx_write(chip, OPTi9XX_MC_REG(7), 0xff - value); diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index 312b217491d4..12c296ee34ec 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c @@ -35,60 +35,49 @@ /* Write a word */ void snd_emu8000_poke(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val) { - unsigned long flags; - spin_lock_irqsave(&emu->reg_lock, flags); + guard(spinlock_irqsave)(&emu->reg_lock); if (reg != emu->last_reg) { outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */ emu->last_reg = reg; } outw((unsigned short)val, port); /* Send data */ - spin_unlock_irqrestore(&emu->reg_lock, flags); } /* Read a word */ unsigned short snd_emu8000_peek(struct snd_emu8000 *emu, unsigned int port, unsigned int reg) { - unsigned short res; - unsigned long flags; - spin_lock_irqsave(&emu->reg_lock, flags); + guard(spinlock_irqsave)(&emu->reg_lock); if (reg != emu->last_reg) { outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */ emu->last_reg = reg; } - res = inw(port); /* Read data */ - spin_unlock_irqrestore(&emu->reg_lock, flags); - return res; + return inw(port); /* Read data */ } /* Write a double word */ void snd_emu8000_poke_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val) { - unsigned long flags; - spin_lock_irqsave(&emu->reg_lock, flags); + guard(spinlock_irqsave)(&emu->reg_lock); if (reg != emu->last_reg) { outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */ emu->last_reg = reg; } outw((unsigned short)val, port); /* Send low word of data */ outw((unsigned short)(val>>16), port+2); /* Send high word of data */ - spin_unlock_irqrestore(&emu->reg_lock, flags); } /* Read a double word */ unsigned int snd_emu8000_peek_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg) { unsigned short low; - unsigned int res; - unsigned long flags; - spin_lock_irqsave(&emu->reg_lock, flags); + + guard(spinlock_irqsave)(&emu->reg_lock); if (reg != emu->last_reg) { outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */ emu->last_reg = reg; } low = inw(port); /* Read low word of data */ - res = low + (inw(port+2) << 16); - spin_unlock_irqrestore(&emu->reg_lock, flags); - return res; + return low + (inw(port+2) << 16); } /* @@ -456,8 +445,6 @@ skip_detect: /*exported*/ void snd_emu8000_init_fm(struct snd_emu8000 *emu) { - unsigned long flags; - /* Initialize the last two channels for DRAM refresh and producing the reverb and chorus effects for Yamaha OPL-3 synthesizer */ @@ -479,12 +466,12 @@ snd_emu8000_init_fm(struct snd_emu8000 *emu) snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0); - spin_lock_irqsave(&emu->reg_lock, flags); - while (!(inw(EMU8000_PTR(emu)) & 0x1000)) - ; - while ((inw(EMU8000_PTR(emu)) & 0x1000)) - ; - spin_unlock_irqrestore(&emu->reg_lock, flags); + scoped_guard(spinlock_irqsave, &emu->reg_lock) { + while (!(inw(EMU8000_PTR(emu)) & 0x1000)) + ; + while ((inw(EMU8000_PTR(emu)) & 0x1000)) + ; + } snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0x4828); /* this is really odd part.. */ outb(0x3C, EMU8000_PTR(emu)); @@ -838,20 +825,19 @@ static int mixer_bass_treble_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int mixer_bass_treble_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - unsigned long flags; int change; unsigned short val1; val1 = ucontrol->value.integer.value[0] % 12; - spin_lock_irqsave(&emu->control_lock, flags); - if (kcontrol->private_value) { - change = val1 != emu->treble_level; - emu->treble_level = val1; - } else { - change = val1 != emu->bass_level; - emu->bass_level = val1; + scoped_guard(spinlock_irqsave, &emu->control_lock) { + if (kcontrol->private_value) { + change = val1 != emu->treble_level; + emu->treble_level = val1; + } else { + change = val1 != emu->bass_level; + emu->bass_level = val1; + } } - spin_unlock_irqrestore(&emu->control_lock, flags); snd_emu8000_update_equalizer(emu); return change; } @@ -899,21 +885,20 @@ static int mixer_chorus_reverb_get(struct snd_kcontrol *kcontrol, struct snd_ctl static int mixer_chorus_reverb_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - unsigned long flags; int change; unsigned short val1; - spin_lock_irqsave(&emu->control_lock, flags); - if (kcontrol->private_value) { - val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_CHORUS_NUMBERS; - change = val1 != emu->chorus_mode; - emu->chorus_mode = val1; - } else { - val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_REVERB_NUMBERS; - change = val1 != emu->reverb_mode; - emu->reverb_mode = val1; + scoped_guard(spinlock_irqsave, &emu->control_lock) { + if (kcontrol->private_value) { + val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_CHORUS_NUMBERS; + change = val1 != emu->chorus_mode; + emu->chorus_mode = val1; + } else { + val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_REVERB_NUMBERS; + change = val1 != emu->reverb_mode; + emu->reverb_mode = val1; + } } - spin_unlock_irqrestore(&emu->control_lock, flags); if (change) { if (kcontrol->private_value) snd_emu8000_update_chorus_mode(emu); @@ -966,20 +951,19 @@ static int mixer_fm_depth_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem static int mixer_fm_depth_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - unsigned long flags; int change; unsigned short val1; val1 = ucontrol->value.integer.value[0] % 256; - spin_lock_irqsave(&emu->control_lock, flags); - if (kcontrol->private_value) { - change = val1 != emu->fm_chorus_depth; - emu->fm_chorus_depth = val1; - } else { - change = val1 != emu->fm_reverb_depth; - emu->fm_reverb_depth = val1; + scoped_guard(spinlock_irqsave, &emu->control_lock) { + if (kcontrol->private_value) { + change = val1 != emu->fm_chorus_depth; + emu->fm_chorus_depth = val1; + } else { + change = val1 != emu->fm_reverb_depth; + emu->fm_reverb_depth = val1; + } } - spin_unlock_irqrestore(&emu->control_lock, flags); if (change) snd_emu8000_init_fm(emu); return change; diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index 215bbcd0360e..656a655d618d 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c @@ -184,28 +184,30 @@ static void emu8k_pcm_timer_func(struct timer_list *t) { struct snd_emu8k_pcm *rec = timer_container_of(rec, t, timer); int ptr, delta; + bool period_elapsed = false; + + scoped_guard(spinlock, &rec->timer_lock) { + /* update the current pointer */ + ptr = emu8k_get_curpos(rec, 0); + if (ptr < rec->last_ptr) + delta = ptr + rec->buf_size - rec->last_ptr; + else + delta = ptr - rec->last_ptr; + rec->period_pos += delta; + rec->last_ptr = ptr; + + /* reprogram timer */ + mod_timer(&rec->timer, jiffies + 1); - spin_lock(&rec->timer_lock); - /* update the current pointer */ - ptr = emu8k_get_curpos(rec, 0); - if (ptr < rec->last_ptr) - delta = ptr + rec->buf_size - rec->last_ptr; - else - delta = ptr - rec->last_ptr; - rec->period_pos += delta; - rec->last_ptr = ptr; - - /* reprogram timer */ - mod_timer(&rec->timer, jiffies + 1); + /* update period */ + if (rec->period_pos >= (int)rec->period_size) { + rec->period_pos %= rec->period_size; + period_elapsed = true; + } + } - /* update period */ - if (rec->period_pos >= (int)rec->period_size) { - rec->period_pos %= rec->period_size; - spin_unlock(&rec->timer_lock); + if (period_elapsed) snd_pcm_period_elapsed(rec->substream); - return; - } - spin_unlock(&rec->timer_lock); } @@ -321,7 +323,6 @@ static void setup_voice(struct snd_emu8k_pcm *rec, int ch) */ static void start_voice(struct snd_emu8k_pcm *rec, int ch) { - unsigned long flags; struct snd_emu8000 *hw = rec->emu; unsigned int temp, aux; int pt = calc_pitch_target(rec->pitch); @@ -343,12 +344,11 @@ static void start_voice(struct snd_emu8k_pcm *rec, int ch) EMU8000_CPF_WRITE(hw, ch, pt << 16); /* start timer */ - spin_lock_irqsave(&rec->timer_lock, flags); + guard(spinlock_irqsave)(&rec->timer_lock); if (! rec->timer_running) { mod_timer(&rec->timer, jiffies + 1); rec->timer_running = 1; } - spin_unlock_irqrestore(&rec->timer_lock, flags); } /* @@ -356,18 +356,16 @@ static void start_voice(struct snd_emu8k_pcm *rec, int ch) */ static void stop_voice(struct snd_emu8k_pcm *rec, int ch) { - unsigned long flags; struct snd_emu8000 *hw = rec->emu; EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F); /* stop timer */ - spin_lock_irqsave(&rec->timer_lock, flags); + guard(spinlock_irqsave)(&rec->timer_lock); if (rec->timer_running) { timer_delete(&rec->timer); rec->timer_running = 0; } - spin_unlock_irqrestore(&rec->timer_lock, flags); } static int emu8k_pcm_trigger(struct snd_pcm_substream *subs, int cmd) diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 752762117338..208d1942a015 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -310,7 +310,6 @@ static int snd_sb16_probe(struct snd_card *card, int dev) #ifdef CONFIG_SND_SB16_CSP struct snd_hwdep *xcsp = NULL; #endif - unsigned long flags; int err; xirq = irq[dev]; @@ -421,11 +420,11 @@ static int snd_sb16_probe(struct snd_card *card, int dev) #endif /* setup Mic AGC */ - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, SB_DSP4_MIC_AGC, - (snd_sbmixer_read(chip, SB_DSP4_MIC_AGC) & 0x01) | - (mic_agc[dev] ? 0x00 : 0x01)); - spin_unlock_irqrestore(&chip->mixer_lock, flags); + scoped_guard(spinlock_irqsave, &chip->mixer_lock) { + snd_sbmixer_write(chip, SB_DSP4_MIC_AGC, + (snd_sbmixer_read(chip, SB_DSP4_MIC_AGC) & 0x01) | + (mic_agc[dev] ? 0x00 : 0x01)); + } err = snd_card_register(card); if (err < 0) diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 7034072c80d4..9ad71a9fc18d 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -265,14 +265,10 @@ static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file) */ static int snd_sb_csp_use(struct snd_sb_csp * p) { - mutex_lock(&p->access_mutex); - if (p->used) { - mutex_unlock(&p->access_mutex); + guard(mutex)(&p->access_mutex); + if (p->used) return -EAGAIN; - } p->used++; - mutex_unlock(&p->access_mutex); - return 0; } @@ -282,10 +278,8 @@ static int snd_sb_csp_use(struct snd_sb_csp * p) */ static int snd_sb_csp_unuse(struct snd_sb_csp * p) { - mutex_lock(&p->access_mutex); + guard(mutex)(&p->access_mutex); p->used--; - mutex_unlock(&p->access_mutex); - return 0; } @@ -307,7 +301,6 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, __le32 item_type; struct desc_header funcdesc_h; - unsigned long flags; int err; if (copy_from_user(&info, mcode, sizeof(info))) @@ -435,10 +428,9 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, p->acc_rates = le16_to_cpu(funcdesc_h.flags_rates); /* Decouple CSP from IRQ and DMAREQ lines */ - spin_lock_irqsave(&p->chip->reg_lock, flags); + guard(spinlock_irqsave)(&p->chip->reg_lock); set_mode_register(p->chip, 0xfc); set_mode_register(p->chip, 0x00); - spin_unlock_irqrestore(&p->chip->reg_lock, flags); /* finished loading successfully */ p->running = SNDRV_SB_CSP_ST_LOADED; /* set LOADED flag */ @@ -548,10 +540,8 @@ static int set_mode_register(struct snd_sb *chip, unsigned char mode) static int csp_detect(struct snd_sb *chip, int *version) { unsigned char csp_test1, csp_test2; - unsigned long flags; - int result = -ENODEV; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); set_codec_parameter(chip, 0x00, 0x00); set_mode_register(chip, 0xfc); /* 0xfc = ?? */ @@ -560,23 +550,21 @@ static int csp_detect(struct snd_sb *chip, int *version) set_register(chip, 0x83, ~csp_test1); csp_test2 = read_register(chip, 0x83); if (csp_test2 != (csp_test1 ^ 0xff)) - goto __fail; + return -ENODEV; set_register(chip, 0x83, csp_test1); csp_test2 = read_register(chip, 0x83); if (csp_test2 != csp_test1) - goto __fail; + return -ENODEV; set_mode_register(chip, 0x00); /* 0x00 = ? */ *version = get_version(chip); snd_sbdsp_reset(chip); /* reset DSP after getversion! */ if (*version >= 0x10 && *version <= 0x1f) - result = 0; /* valid version id */ + return 0; /* valid version id */ - __fail: - spin_unlock_irqrestore(&chip->reg_lock, flags); - return result; + return -ENODEV; } /* @@ -614,14 +602,12 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int { int status, i; int err; - int result = -EIO; - unsigned long flags; - spin_lock_irqsave(&p->chip->reg_lock, flags); + guard(spinlock_irqsave)(&p->chip->reg_lock); snd_sbdsp_command(p->chip, 0x01); /* CSP download command */ if (snd_sbdsp_get_byte(p->chip)) { dev_dbg(p->chip->card->dev, "%s: Download command failed\n", __func__); - goto __fail; + return -EIO; } /* Send CSP low byte (size - 1) */ snd_sbdsp_command(p->chip, (unsigned char)(size - 1)); @@ -631,10 +617,10 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int /* load from kernel space */ while (size--) { if (!snd_sbdsp_command(p->chip, *buf++)) - goto __fail; + return -EIO; } if (snd_sbdsp_get_byte(p->chip)) - goto __fail; + return -EIO; if (load_flags & SNDRV_SB_CSP_LOAD_INITBLOCK) { i = 0; @@ -650,7 +636,7 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int dev_dbg(p->chip->card->dev, "%s: Microcode initialization failed\n", __func__); - goto __fail; + return -EIO; } } else { /* @@ -658,24 +644,21 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int * Start CSP chip if no 16bit DMA channel is set - some kind * of autorun or perhaps a bugfix? */ - spin_lock(&p->chip->mixer_lock); - status = snd_sbmixer_read(p->chip, SB_DSP4_DMASETUP); - spin_unlock(&p->chip->mixer_lock); + scoped_guard(spinlock, &p->chip->mixer_lock) { + status = snd_sbmixer_read(p->chip, SB_DSP4_DMASETUP); + } if (!(status & (SB_DMASETUP_DMA7 | SB_DMASETUP_DMA6 | SB_DMASETUP_DMA5))) { err = (set_codec_parameter(p->chip, 0xaa, 0x00) || set_codec_parameter(p->chip, 0xff, 0x00)); snd_sbdsp_reset(p->chip); /* really! */ if (err) - goto __fail; + return -EIO; set_mode_register(p->chip, 0xc0); /* c0 = STOP */ set_mode_register(p->chip, 0x70); /* 70 = RUN */ } } - result = 0; - __fail: - spin_unlock_irqrestore(&p->chip->reg_lock, flags); - return result; + return 0; } static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags) @@ -722,7 +705,6 @@ static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags) */ static int snd_sb_csp_autoload(struct snd_sb_csp * p, snd_pcm_format_t pcm_sfmt, int play_rec_mode) { - unsigned long flags; int err = 0; /* if CSP is running or manually loaded then exit */ @@ -763,10 +745,9 @@ static int snd_sb_csp_autoload(struct snd_sb_csp * p, snd_pcm_format_t pcm_sfmt, default: /* Decouple CSP from IRQ and DMAREQ lines */ if (p->running & SNDRV_SB_CSP_ST_AUTO) { - spin_lock_irqsave(&p->chip->reg_lock, flags); + guard(spinlock_irqsave)(&p->chip->reg_lock); set_mode_register(p->chip, 0xfc); set_mode_register(p->chip, 0x00); - spin_unlock_irqrestore(&p->chip->reg_lock, flags); p->running = 0; /* clear autoloaded flag */ } return -EINVAL; @@ -798,7 +779,6 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel unsigned char s_type; /* sample type */ unsigned char mixL, mixR; int result = -EIO; - unsigned long flags; if (!(p->running & (SNDRV_SB_CSP_ST_LOADED | SNDRV_SB_CSP_ST_AUTO))) { dev_dbg(dev, "%s: Microcode not loaded\n", __func__); @@ -818,55 +798,54 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel } /* Mute PCM volume */ - spin_lock_irqsave(&p->chip->mixer_lock, flags); - mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV); - mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7); - spin_unlock_irqrestore(&p->chip->mixer_lock, flags); - - spin_lock(&p->chip->reg_lock); - set_mode_register(p->chip, 0xc0); /* c0 = STOP */ - set_mode_register(p->chip, 0x70); /* 70 = RUN */ - - s_type = 0x00; - if (channels == SNDRV_SB_CSP_MONO) - s_type = 0x11; /* 000n 000n (n = 1 if mono) */ - if (sample_width == SNDRV_SB_CSP_SAMPLE_8BIT) - s_type |= 0x22; /* 00dX 00dX (d = 1 if 8 bit samples) */ - - if (set_codec_parameter(p->chip, 0x81, s_type)) { - dev_dbg(dev, "%s: Set sample type command failed\n", __func__); - goto __fail; + scoped_guard(spinlock_irqsave, &p->chip->mixer_lock) { + mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV); + mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1); + snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7); + snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7); } - if (set_codec_parameter(p->chip, 0x80, 0x00)) { - dev_dbg(dev, "%s: Codec start command failed\n", __func__); - goto __fail; - } - p->run_width = sample_width; - p->run_channels = channels; - p->running |= SNDRV_SB_CSP_ST_RUNNING; + scoped_guard(spinlock, &p->chip->reg_lock) { + set_mode_register(p->chip, 0xc0); /* c0 = STOP */ + set_mode_register(p->chip, 0x70); /* 70 = RUN */ - if (p->mode & SNDRV_SB_CSP_MODE_QSOUND) { - set_codec_parameter(p->chip, 0xe0, 0x01); - /* enable QSound decoder */ - set_codec_parameter(p->chip, 0x00, 0xff); - set_codec_parameter(p->chip, 0x01, 0xff); - p->running |= SNDRV_SB_CSP_ST_QSOUND; - /* set QSound startup value */ - snd_sb_csp_qsound_transfer(p); - } - result = 0; + s_type = 0x00; + if (channels == SNDRV_SB_CSP_MONO) + s_type = 0x11; /* 000n 000n (n = 1 if mono) */ + if (sample_width == SNDRV_SB_CSP_SAMPLE_8BIT) + s_type |= 0x22; /* 00dX 00dX (d = 1 if 8 bit samples) */ - __fail: - spin_unlock(&p->chip->reg_lock); + if (set_codec_parameter(p->chip, 0x81, s_type)) { + dev_dbg(dev, "%s: Set sample type command failed\n", __func__); + break; + } + if (set_codec_parameter(p->chip, 0x80, 0x00)) { + dev_dbg(dev, "%s: Codec start command failed\n", __func__); + break; + } + p->run_width = sample_width; + p->run_channels = channels; + + p->running |= SNDRV_SB_CSP_ST_RUNNING; + + if (p->mode & SNDRV_SB_CSP_MODE_QSOUND) { + set_codec_parameter(p->chip, 0xe0, 0x01); + /* enable QSound decoder */ + set_codec_parameter(p->chip, 0x00, 0xff); + set_codec_parameter(p->chip, 0x01, 0xff); + p->running |= SNDRV_SB_CSP_ST_QSOUND; + /* set QSound startup value */ + snd_sb_csp_qsound_transfer(p); + } + result = 0; + } /* restore PCM volume */ - spin_lock_irqsave(&p->chip->mixer_lock, flags); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR); - spin_unlock_irqrestore(&p->chip->mixer_lock, flags); + if (result < 0) { + guard(spinlock_irqsave)(&p->chip->mixer_lock); + snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL); + snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR); + } return result; } @@ -878,36 +857,35 @@ static int snd_sb_csp_stop(struct snd_sb_csp * p) { int result; unsigned char mixL, mixR; - unsigned long flags; if (!(p->running & SNDRV_SB_CSP_ST_RUNNING)) return 0; /* Mute PCM volume */ - spin_lock_irqsave(&p->chip->mixer_lock, flags); - mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV); - mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7); - spin_unlock_irqrestore(&p->chip->mixer_lock, flags); - - spin_lock(&p->chip->reg_lock); - if (p->running & SNDRV_SB_CSP_ST_QSOUND) { - set_codec_parameter(p->chip, 0xe0, 0x01); - /* disable QSound decoder */ - set_codec_parameter(p->chip, 0x00, 0x00); - set_codec_parameter(p->chip, 0x01, 0x00); + scoped_guard(spinlock_irqsave, &p->chip->mixer_lock) { + mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV); + mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1); + snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7); + snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7); + } + + scoped_guard(spinlock, &p->chip->reg_lock) { + if (p->running & SNDRV_SB_CSP_ST_QSOUND) { + set_codec_parameter(p->chip, 0xe0, 0x01); + /* disable QSound decoder */ + set_codec_parameter(p->chip, 0x00, 0x00); + set_codec_parameter(p->chip, 0x01, 0x00); - p->running &= ~SNDRV_SB_CSP_ST_QSOUND; + p->running &= ~SNDRV_SB_CSP_ST_QSOUND; + } + result = set_mode_register(p->chip, 0xc0); /* c0 = STOP */ } - result = set_mode_register(p->chip, 0xc0); /* c0 = STOP */ - spin_unlock(&p->chip->reg_lock); /* restore PCM volume */ - spin_lock_irqsave(&p->chip->mixer_lock, flags); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR); - spin_unlock_irqrestore(&p->chip->mixer_lock, flags); + scoped_guard(spinlock_irqsave, &p->chip->mixer_lock) { + snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL); + snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR); + } if (!(result)) p->running &= ~(SNDRV_SB_CSP_ST_PAUSED | SNDRV_SB_CSP_ST_RUNNING); @@ -920,14 +898,13 @@ static int snd_sb_csp_stop(struct snd_sb_csp * p) static int snd_sb_csp_pause(struct snd_sb_csp * p) { int result; - unsigned long flags; if (!(p->running & SNDRV_SB_CSP_ST_RUNNING)) return -EBUSY; - spin_lock_irqsave(&p->chip->reg_lock, flags); - result = set_codec_parameter(p->chip, 0x80, 0xff); - spin_unlock_irqrestore(&p->chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &p->chip->reg_lock) { + result = set_codec_parameter(p->chip, 0x80, 0xff); + } if (!(result)) p->running |= SNDRV_SB_CSP_ST_PAUSED; @@ -940,14 +917,13 @@ static int snd_sb_csp_pause(struct snd_sb_csp * p) static int snd_sb_csp_restart(struct snd_sb_csp * p) { int result; - unsigned long flags; if (!(p->running & SNDRV_SB_CSP_ST_PAUSED)) return -EBUSY; - spin_lock_irqsave(&p->chip->reg_lock, flags); - result = set_codec_parameter(p->chip, 0x80, 0x00); - spin_unlock_irqrestore(&p->chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &p->chip->reg_lock) { + result = set_codec_parameter(p->chip, 0x80, 0x00); + } if (!(result)) p->running &= ~SNDRV_SB_CSP_ST_PAUSED; @@ -973,15 +949,13 @@ static int snd_sb_qsound_switch_get(struct snd_kcontrol *kcontrol, struct snd_ct static int snd_sb_qsound_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); - unsigned long flags; int change; unsigned char nval; nval = ucontrol->value.integer.value[0] & 0x01; - spin_lock_irqsave(&p->q_lock, flags); + guard(spinlock_irqsave)(&p->q_lock); change = p->q_enabled != nval; p->q_enabled = nval; - spin_unlock_irqrestore(&p->q_lock, flags); return change; } @@ -997,19 +971,16 @@ static int snd_sb_qsound_space_info(struct snd_kcontrol *kcontrol, struct snd_ct static int snd_sb_qsound_space_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); - unsigned long flags; - spin_lock_irqsave(&p->q_lock, flags); + guard(spinlock_irqsave)(&p->q_lock); ucontrol->value.integer.value[0] = p->qpos_left; ucontrol->value.integer.value[1] = p->qpos_right; - spin_unlock_irqrestore(&p->q_lock, flags); return 0; } static int snd_sb_qsound_space_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); - unsigned long flags; int change; unsigned char nval1, nval2; @@ -1019,12 +990,11 @@ static int snd_sb_qsound_space_put(struct snd_kcontrol *kcontrol, struct snd_ctl nval2 = ucontrol->value.integer.value[1]; if (nval2 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT) nval2 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT; - spin_lock_irqsave(&p->q_lock, flags); + guard(spinlock_irqsave)(&p->q_lock); change = p->qpos_left != nval1 || p->qpos_right != nval2; p->qpos_left = nval1; p->qpos_right = nval2; p->qpos_changed = change; - spin_unlock_irqrestore(&p->q_lock, flags); return change; } @@ -1080,7 +1050,6 @@ static int snd_sb_qsound_build(struct snd_sb_csp * p) static void snd_sb_qsound_destroy(struct snd_sb_csp * p) { struct snd_card *card; - unsigned long flags; if (snd_BUG_ON(!p)) return; @@ -1093,9 +1062,8 @@ static void snd_sb_qsound_destroy(struct snd_sb_csp * p) p->qsound_space = NULL; /* cancel pending transfer of QSound parameters */ - spin_lock_irqsave (&p->q_lock, flags); + guard(spinlock_irqsave)(&p->q_lock); p->qpos_changed = 0; - spin_unlock_irqrestore (&p->q_lock, flags); } /* @@ -1106,7 +1074,7 @@ static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p) { int err = -ENXIO; - spin_lock(&p->q_lock); + guard(spinlock)(&p->q_lock); if (p->running & SNDRV_SB_CSP_ST_QSOUND) { set_codec_parameter(p->chip, 0xe0, 0x01); /* left channel */ @@ -1118,7 +1086,6 @@ static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p) err = 0; } p->qpos_changed = 0; - spin_unlock(&p->q_lock); return err; } diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index 5a083eecaa6b..4d64db4f5852 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c @@ -130,9 +130,8 @@ static void snd_sb16_csp_update(struct snd_sb *chip) struct snd_sb_csp *csp = chip->csp; if (csp->qpos_changed) { - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); csp->ops.csp_qsound_transfer (csp); - spin_unlock(&chip->reg_lock); } } } @@ -213,9 +212,7 @@ static void snd_sb16_setup_rate(struct snd_sb *chip, unsigned short rate, int channel) { - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (chip->mode & (channel == SNDRV_PCM_STREAM_PLAYBACK ? SB_MODE_PLAYBACK_16 : SB_MODE_CAPTURE_16)) snd_sb_ack_16bit(chip); else @@ -229,12 +226,10 @@ static void snd_sb16_setup_rate(struct snd_sb *chip, snd_sbdsp_command(chip, rate >> 8); snd_sbdsp_command(chip, rate & 0xff); } - spin_unlock_irqrestore(&chip->reg_lock, flags); } static int snd_sb16_playback_prepare(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_sb *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned char format; @@ -253,7 +248,7 @@ static int snd_sb16_playback_prepare(struct snd_pcm_substream *substream) snd_dma_program(dma, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); count = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (chip->mode & SB_MODE_PLAYBACK_16) { count >>= 1; count--; @@ -270,7 +265,6 @@ static int snd_sb16_playback_prepare(struct snd_pcm_substream *substream) snd_sbdsp_command(chip, count >> 8); snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); } - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } @@ -278,9 +272,8 @@ static int snd_sb16_playback_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_sb *chip = snd_pcm_substream_chip(substream); - int result = 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -296,15 +289,13 @@ static int snd_sb16_playback_trigger(struct snd_pcm_substream *substream, chip->mode &= ~SB_RATE_LOCK_PLAYBACK; break; default: - result = -EINVAL; + return -EINVAL; } - spin_unlock(&chip->reg_lock); - return result; + return 0; } static int snd_sb16_capture_prepare(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_sb *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned char format; @@ -322,7 +313,7 @@ static int snd_sb16_capture_prepare(struct snd_pcm_substream *substream) snd_dma_program(dma, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); count = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (chip->mode & SB_MODE_CAPTURE_16) { count >>= 1; count--; @@ -339,7 +330,6 @@ static int snd_sb16_capture_prepare(struct snd_pcm_substream *substream) snd_sbdsp_command(chip, count >> 8); snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); } - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } @@ -347,9 +337,8 @@ static int snd_sb16_capture_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_sb *chip = snd_pcm_substream_chip(substream); - int result = 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -365,10 +354,9 @@ static int snd_sb16_capture_trigger(struct snd_pcm_substream *substream, chip->mode &= ~SB_RATE_LOCK_CAPTURE; break; default: - result = -EINVAL; + return -EINVAL; } - spin_unlock(&chip->reg_lock); - return result; + return 0; } irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id) @@ -377,9 +365,9 @@ irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id) unsigned char status; int ok; - spin_lock(&chip->mixer_lock); - status = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS); - spin_unlock(&chip->mixer_lock); + scoped_guard(spinlock, &chip->mixer_lock) { + status = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS); + } if ((status & SB_IRQTYPE_MPUIN) && chip->rmidi_callback) chip->rmidi_callback(irq, chip->rmidi->private_data); if (status & SB_IRQTYPE_8BIT) { @@ -393,11 +381,11 @@ irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id) snd_pcm_period_elapsed(chip->capture_substream); ok++; } - spin_lock(&chip->reg_lock); - if (!ok) - snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); - snd_sb_ack_8bit(chip); - spin_unlock(&chip->reg_lock); + scoped_guard(spinlock, &chip->reg_lock) { + if (!ok) + snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); + snd_sb_ack_8bit(chip); + } } if (status & SB_IRQTYPE_16BIT) { ok = 0; @@ -410,11 +398,11 @@ irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id) snd_pcm_period_elapsed(chip->capture_substream); ok++; } - spin_lock(&chip->reg_lock); - if (!ok) - snd_sbdsp_command(chip, SB_DSP_DMA16_OFF); - snd_sb_ack_16bit(chip); - spin_unlock(&chip->reg_lock); + scoped_guard(spinlock, &chip->reg_lock) { + if (!ok) + snd_sbdsp_command(chip, SB_DSP_DMA16_OFF); + snd_sb_ack_16bit(chip); + } } return IRQ_HANDLED; } @@ -491,15 +479,12 @@ static const struct snd_pcm_hardware snd_sb16_capture = static int snd_sb16_playback_open(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_sb *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->mode & SB_MODE_PLAYBACK) { - spin_unlock_irqrestore(&chip->open_lock, flags); + guard(spinlock_irqsave)(&chip->open_lock); + if (chip->mode & SB_MODE_PLAYBACK) return -EAGAIN; - } runtime->hw = snd_sb16_playback; /* skip if 16 bit DMA was reserved for capture */ @@ -533,7 +518,6 @@ static int snd_sb16_playback_open(struct snd_pcm_substream *substream) runtime->hw.period_bytes_max = 64 * 1024; goto __open_ok; } - spin_unlock_irqrestore(&chip->open_lock, flags); return -EAGAIN; __open_ok: @@ -547,34 +531,28 @@ static int snd_sb16_playback_open(struct snd_pcm_substream *substream) if (chip->mode & SB_RATE_LOCK) runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate; chip->playback_substream = substream; - spin_unlock_irqrestore(&chip->open_lock, flags); return 0; } static int snd_sb16_playback_close(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_sb *chip = snd_pcm_substream_chip(substream); snd_sb16_csp_playback_close(chip); - spin_lock_irqsave(&chip->open_lock, flags); + guard(spinlock_irqsave)(&chip->open_lock); chip->playback_substream = NULL; chip->mode &= ~SB_MODE_PLAYBACK; - spin_unlock_irqrestore(&chip->open_lock, flags); return 0; } static int snd_sb16_capture_open(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_sb *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->mode & SB_MODE_CAPTURE) { - spin_unlock_irqrestore(&chip->open_lock, flags); + guard(spinlock_irqsave)(&chip->open_lock); + if (chip->mode & SB_MODE_CAPTURE) return -EAGAIN; - } runtime->hw = snd_sb16_capture; /* skip if 16 bit DMA was reserved for playback */ @@ -608,7 +586,6 @@ static int snd_sb16_capture_open(struct snd_pcm_substream *substream) runtime->hw.period_bytes_max = 64 * 1024; goto __open_ok; } - spin_unlock_irqrestore(&chip->open_lock, flags); return -EAGAIN; __open_ok: @@ -622,20 +599,17 @@ static int snd_sb16_capture_open(struct snd_pcm_substream *substream) if (chip->mode & SB_RATE_LOCK) runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate; chip->capture_substream = substream; - spin_unlock_irqrestore(&chip->open_lock, flags); return 0; } static int snd_sb16_capture_close(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_sb *chip = snd_pcm_substream_chip(substream); snd_sb16_csp_capture_close(chip); - spin_lock_irqsave(&chip->open_lock, flags); + guard(spinlock_irqsave)(&chip->open_lock); chip->capture_substream = NULL; chip->mode &= ~SB_MODE_CAPTURE; - spin_unlock_irqrestore(&chip->open_lock, flags); return 0; } @@ -688,18 +662,15 @@ static int snd_sb16_dma_control_info(struct snd_kcontrol *kcontrol, struct snd_c static int snd_sb16_dma_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.enumerated.item[0] = snd_sb16_get_dma_mode(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } static int snd_sb16_dma_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; unsigned char nval, oval; int change; @@ -709,11 +680,11 @@ static int snd_sb16_dma_control_put(struct snd_kcontrol *kcontrol, struct snd_ct nval = ucontrol->value.enumerated.item[0]; if (nval > 2) return -EINVAL; - spin_lock_irqsave(&chip->reg_lock, flags); - oval = snd_sb16_get_dma_mode(chip); - change = nval != oval; - snd_sb16_set_dma_mode(chip, nval); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + oval = snd_sb16_get_dma_mode(chip); + change = nval != oval; + snd_sb16_set_dma_mode(chip, nval); + } if (change) { snd_dma_disable(chip->dma8); snd_dma_disable(chip->dma16); @@ -735,14 +706,13 @@ static const struct snd_kcontrol_new snd_sb16_dma_control = { int snd_sb16dsp_configure(struct snd_sb * chip) { - unsigned long flags; unsigned char irqreg = 0, dmareg = 0, mpureg; unsigned char realirq, realdma, realmpureg; /* note: mpu register should be present only on SB16 Vibra soundcards */ - spin_lock_irqsave(&chip->mixer_lock, flags); - mpureg = snd_sbmixer_read(chip, SB_DSP4_MPUSETUP) & ~0x06; - spin_unlock_irqrestore(&chip->mixer_lock, flags); + scoped_guard(spinlock_irqsave, &chip->mixer_lock) { + mpureg = snd_sbmixer_read(chip, SB_DSP4_MPUSETUP) & ~0x06; + } switch (chip->irq) { case 2: case 9: @@ -800,18 +770,17 @@ int snd_sb16dsp_configure(struct snd_sb * chip) default: mpureg |= 0x02; /* disable MPU */ } - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, SB_DSP4_IRQSETUP, irqreg); - realirq = snd_sbmixer_read(chip, SB_DSP4_IRQSETUP); + scoped_guard(spinlock_irqsave, &chip->mixer_lock) { + snd_sbmixer_write(chip, SB_DSP4_IRQSETUP, irqreg); + realirq = snd_sbmixer_read(chip, SB_DSP4_IRQSETUP); - snd_sbmixer_write(chip, SB_DSP4_DMASETUP, dmareg); - realdma = snd_sbmixer_read(chip, SB_DSP4_DMASETUP); + snd_sbmixer_write(chip, SB_DSP4_DMASETUP, dmareg); + realdma = snd_sbmixer_read(chip, SB_DSP4_DMASETUP); - snd_sbmixer_write(chip, SB_DSP4_MPUSETUP, mpureg); - realmpureg = snd_sbmixer_read(chip, SB_DSP4_MPUSETUP); - - spin_unlock_irqrestore(&chip->mixer_lock, flags); + snd_sbmixer_write(chip, SB_DSP4_MPUSETUP, mpureg); + realmpureg = snd_sbmixer_read(chip, SB_DSP4_MPUSETUP); + } if ((~realirq) & irqreg || (~realdma) & dmareg) { dev_err(chip->card->dev, "SB16 [0x%lx]: unable to set DMA & IRQ (PnP device?)\n", diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c index 2ed176a5a574..a4b5725255cf 100644 --- a/sound/isa/sb/sb8_main.c +++ b/sound/isa/sb/sb8_main.c @@ -89,7 +89,6 @@ static int snd_sb8_hw_constraint_channels_rate(struct snd_pcm_hw_params *params, static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_sb *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned int mixreg, rate, size, count; @@ -142,48 +141,48 @@ static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream) } size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream); count = chip->p_period_size = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON); - if (chip->hardware == SB_HW_JAZZ16) - snd_sbdsp_command(chip, format); - else if (stereo) { - /* set playback stereo mode */ - spin_lock(&chip->mixer_lock); - mixreg = snd_sbmixer_read(chip, SB_DSP_STEREO_SW); - snd_sbmixer_write(chip, SB_DSP_STEREO_SW, mixreg | 0x02); - spin_unlock(&chip->mixer_lock); - - /* Soundblaster hardware programming reference guide, 3-23 */ - snd_sbdsp_command(chip, SB_DSP_DMA8_EXIT); - runtime->dma_area[0] = 0x80; - snd_dma_program(dma, runtime->dma_addr, 1, DMA_MODE_WRITE); - /* force interrupt */ - snd_sbdsp_command(chip, SB_DSP_OUTPUT); - snd_sbdsp_command(chip, 0); - snd_sbdsp_command(chip, 0); - } - snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE); - if (stereo) { - snd_sbdsp_command(chip, 256 - runtime->rate_den / 2); - spin_lock(&chip->mixer_lock); - /* save output filter status and turn it off */ - mixreg = snd_sbmixer_read(chip, SB_DSP_PLAYBACK_FILT); - snd_sbmixer_write(chip, SB_DSP_PLAYBACK_FILT, mixreg | 0x20); - spin_unlock(&chip->mixer_lock); - /* just use force_mode16 for temporary storate... */ - chip->force_mode16 = mixreg; - } else { - snd_sbdsp_command(chip, 256 - runtime->rate_den); - } - if (chip->playback_format != SB_DSP_OUTPUT) { - if (chip->mode & SB_MODE_PLAYBACK_16) - count /= 2; - count--; - snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON); + if (chip->hardware == SB_HW_JAZZ16) + snd_sbdsp_command(chip, format); + else if (stereo) { + /* set playback stereo mode */ + scoped_guard(spinlock, &chip->mixer_lock) { + mixreg = snd_sbmixer_read(chip, SB_DSP_STEREO_SW); + snd_sbmixer_write(chip, SB_DSP_STEREO_SW, mixreg | 0x02); + } + + /* Soundblaster hardware programming reference guide, 3-23 */ + snd_sbdsp_command(chip, SB_DSP_DMA8_EXIT); + runtime->dma_area[0] = 0x80; + snd_dma_program(dma, runtime->dma_addr, 1, DMA_MODE_WRITE); + /* force interrupt */ + snd_sbdsp_command(chip, SB_DSP_OUTPUT); + snd_sbdsp_command(chip, 0); + snd_sbdsp_command(chip, 0); + } + snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE); + if (stereo) { + snd_sbdsp_command(chip, 256 - runtime->rate_den / 2); + scoped_guard(spinlock, &chip->mixer_lock) { + /* save output filter status and turn it off */ + mixreg = snd_sbmixer_read(chip, SB_DSP_PLAYBACK_FILT); + snd_sbmixer_write(chip, SB_DSP_PLAYBACK_FILT, mixreg | 0x20); + } + /* just use force_mode16 for temporary storate... */ + chip->force_mode16 = mixreg; + } else { + snd_sbdsp_command(chip, 256 - runtime->rate_den); + } + if (chip->playback_format != SB_DSP_OUTPUT) { + if (chip->mode & SB_MODE_PLAYBACK_16) + count /= 2; + count--; + snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE); + snd_sbdsp_command(chip, count & 0xff); + snd_sbdsp_command(chip, count >> 8); + } } - spin_unlock_irqrestore(&chip->reg_lock, flags); snd_dma_program(dma, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); return 0; @@ -192,11 +191,10 @@ static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream) static int snd_sb8_playback_trigger(struct snd_pcm_substream *substream, int cmd) { - unsigned long flags; struct snd_sb *chip = snd_pcm_substream_chip(substream); unsigned int count; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: snd_sbdsp_command(chip, chip->playback_format); @@ -211,23 +209,20 @@ static int snd_sb8_playback_trigger(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; snd_sbdsp_reset(chip); if (runtime->channels > 1) { - spin_lock(&chip->mixer_lock); + guard(spinlock)(&chip->mixer_lock); /* restore output filter and set hardware to mono mode */ snd_sbmixer_write(chip, SB_DSP_STEREO_SW, chip->force_mode16 & ~0x02); - spin_unlock(&chip->mixer_lock); } } else { snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); } snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); } - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_sb *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned int mixreg, rate, size, count; @@ -281,34 +276,34 @@ static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream) } size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream); count = chip->c_period_size = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); - if (chip->hardware == SB_HW_JAZZ16) - snd_sbdsp_command(chip, format); - else if (stereo) - snd_sbdsp_command(chip, SB_DSP_STEREO_8BIT); - snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE); - if (stereo) { - snd_sbdsp_command(chip, 256 - runtime->rate_den / 2); - spin_lock(&chip->mixer_lock); - /* save input filter status and turn it off */ - mixreg = snd_sbmixer_read(chip, SB_DSP_CAPTURE_FILT); - snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, mixreg | 0x20); - spin_unlock(&chip->mixer_lock); - /* just use force_mode16 for temporary storate... */ - chip->force_mode16 = mixreg; - } else { - snd_sbdsp_command(chip, 256 - runtime->rate_den); - } - if (chip->capture_format != SB_DSP_INPUT) { - if (chip->mode & SB_MODE_PLAYBACK_16) - count /= 2; - count--; - snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); + if (chip->hardware == SB_HW_JAZZ16) + snd_sbdsp_command(chip, format); + else if (stereo) + snd_sbdsp_command(chip, SB_DSP_STEREO_8BIT); + snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE); + if (stereo) { + snd_sbdsp_command(chip, 256 - runtime->rate_den / 2); + scoped_guard(spinlock, &chip->mixer_lock) { + /* save input filter status and turn it off */ + mixreg = snd_sbmixer_read(chip, SB_DSP_CAPTURE_FILT); + snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, mixreg | 0x20); + } + /* just use force_mode16 for temporary storate... */ + chip->force_mode16 = mixreg; + } else { + snd_sbdsp_command(chip, 256 - runtime->rate_den); + } + if (chip->capture_format != SB_DSP_INPUT) { + if (chip->mode & SB_MODE_PLAYBACK_16) + count /= 2; + count--; + snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE); + snd_sbdsp_command(chip, count & 0xff); + snd_sbdsp_command(chip, count >> 8); + } } - spin_unlock_irqrestore(&chip->reg_lock, flags); snd_dma_program(dma, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); return 0; @@ -317,11 +312,10 @@ static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream) static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream, int cmd) { - unsigned long flags; struct snd_sb *chip = snd_pcm_substream_chip(substream); unsigned int count; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: snd_sbdsp_command(chip, chip->capture_format); @@ -337,9 +331,9 @@ static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream, snd_sbdsp_reset(chip); if (runtime->channels > 1) { /* restore input filter status */ - spin_lock(&chip->mixer_lock); - snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, chip->force_mode16); - spin_unlock(&chip->mixer_lock); + scoped_guard(spinlock, &chip->mixer_lock) { + snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, chip->force_mode16); + } /* set hardware to mono mode */ snd_sbdsp_command(chip, SB_DSP_MONO_8BIT); } @@ -348,7 +342,6 @@ static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream, } snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); } - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } @@ -464,15 +457,12 @@ static int snd_sb8_open(struct snd_pcm_substream *substream) { struct snd_sb *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->open) { - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; + scoped_guard(spinlock_irqsave, &chip->open_lock) { + if (chip->open) + return -EAGAIN; + chip->open |= SB_OPEN_PCM; } - chip->open |= SB_OPEN_PCM; - spin_unlock_irqrestore(&chip->open_lock, flags); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { chip->playback_substream = substream; runtime->hw = snd_sb8_playback; @@ -525,18 +515,16 @@ static int snd_sb8_open(struct snd_pcm_substream *substream) static int snd_sb8_close(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_sb *chip = snd_pcm_substream_chip(substream); chip->playback_substream = NULL; chip->capture_substream = NULL; - spin_lock_irqsave(&chip->open_lock, flags); + guard(spinlock_irqsave)(&chip->open_lock); chip->open &= ~SB_OPEN_PCM; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) chip->mode &= ~SB_MODE_PLAYBACK; else chip->mode &= ~SB_MODE_CAPTURE; - spin_unlock_irqrestore(&chip->open_lock, flags); return 0; } diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c index 637079a2f02a..1d41f2470697 100644 --- a/sound/isa/sb/sb8_midi.c +++ b/sound/isa/sb/sb8_midi.c @@ -35,7 +35,7 @@ irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb *chip) return IRQ_NONE; } - spin_lock(&chip->midi_input_lock); + guard(spinlock)(&chip->midi_input_lock); while (max-- > 0) { if (inb(SBP(chip, DATA_AVAIL)) & 0x80) { byte = inb(SBP(chip, READ)); @@ -44,108 +44,90 @@ irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb *chip) } } } - spin_unlock(&chip->midi_input_lock); return IRQ_HANDLED; } static int snd_sb8dsp_midi_input_open(struct snd_rawmidi_substream *substream) { - unsigned long flags; struct snd_sb *chip; unsigned int valid_open_flags; chip = substream->rmidi->private_data; valid_open_flags = chip->hardware >= SB_HW_20 ? SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER : 0; - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->open & ~valid_open_flags) { - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - } - chip->open |= SB_OPEN_MIDI_INPUT; - chip->midi_substream_input = substream; - if (!(chip->open & SB_OPEN_MIDI_OUTPUT)) { - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sbdsp_reset(chip); /* reset DSP */ - if (chip->hardware >= SB_HW_20) - snd_sbdsp_command(chip, SB_DSP_MIDI_UART_IRQ); - } else { - spin_unlock_irqrestore(&chip->open_lock, flags); + scoped_guard(spinlock_irqsave, &chip->open_lock) { + if (chip->open & ~valid_open_flags) + return -EAGAIN; + chip->open |= SB_OPEN_MIDI_INPUT; + chip->midi_substream_input = substream; + if (chip->open & SB_OPEN_MIDI_OUTPUT) + return 0; } + snd_sbdsp_reset(chip); /* reset DSP */ + if (chip->hardware >= SB_HW_20) + snd_sbdsp_command(chip, SB_DSP_MIDI_UART_IRQ); return 0; } static int snd_sb8dsp_midi_output_open(struct snd_rawmidi_substream *substream) { - unsigned long flags; struct snd_sb *chip; unsigned int valid_open_flags; chip = substream->rmidi->private_data; valid_open_flags = chip->hardware >= SB_HW_20 ? SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER : 0; - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->open & ~valid_open_flags) { - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - } - chip->open |= SB_OPEN_MIDI_OUTPUT; - chip->midi_substream_output = substream; - if (!(chip->open & SB_OPEN_MIDI_INPUT)) { - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sbdsp_reset(chip); /* reset DSP */ - if (chip->hardware >= SB_HW_20) - snd_sbdsp_command(chip, SB_DSP_MIDI_UART_IRQ); - } else { - spin_unlock_irqrestore(&chip->open_lock, flags); + scoped_guard(spinlock_irqsave, &chip->open_lock) { + if (chip->open & ~valid_open_flags) + return -EAGAIN; + chip->open |= SB_OPEN_MIDI_OUTPUT; + chip->midi_substream_output = substream; + if (chip->open & SB_OPEN_MIDI_INPUT) + return 0; } + snd_sbdsp_reset(chip); /* reset DSP */ + if (chip->hardware >= SB_HW_20) + snd_sbdsp_command(chip, SB_DSP_MIDI_UART_IRQ); return 0; } static int snd_sb8dsp_midi_input_close(struct snd_rawmidi_substream *substream) { - unsigned long flags; struct snd_sb *chip; chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->open_lock, flags); - chip->open &= ~(SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER); - chip->midi_substream_input = NULL; - if (!(chip->open & SB_OPEN_MIDI_OUTPUT)) { - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sbdsp_reset(chip); /* reset DSP */ - } else { - spin_unlock_irqrestore(&chip->open_lock, flags); + scoped_guard(spinlock_irqsave, &chip->open_lock) { + chip->open &= ~(SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER); + chip->midi_substream_input = NULL; + if (chip->open & SB_OPEN_MIDI_OUTPUT) + return 0; } + snd_sbdsp_reset(chip); /* reset DSP */ return 0; } static int snd_sb8dsp_midi_output_close(struct snd_rawmidi_substream *substream) { - unsigned long flags; struct snd_sb *chip; chip = substream->rmidi->private_data; timer_delete_sync(&chip->midi_timer); - spin_lock_irqsave(&chip->open_lock, flags); - chip->open &= ~(SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER); - chip->midi_substream_output = NULL; - if (!(chip->open & SB_OPEN_MIDI_INPUT)) { - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sbdsp_reset(chip); /* reset DSP */ - } else { - spin_unlock_irqrestore(&chip->open_lock, flags); + scoped_guard(spinlock_irqsave, &chip->open_lock) { + chip->open &= ~(SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER); + chip->midi_substream_output = NULL; + if (chip->open & SB_OPEN_MIDI_INPUT) + return 0; } + snd_sbdsp_reset(chip); /* reset DSP */ return 0; } static void snd_sb8dsp_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct snd_sb *chip; chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->open_lock, flags); + guard(spinlock_irqsave)(&chip->open_lock); if (up) { if (!(chip->open & SB_OPEN_MIDI_INPUT_TRIGGER)) { if (chip->hardware < SB_HW_20) @@ -159,12 +141,10 @@ static void snd_sb8dsp_midi_input_trigger(struct snd_rawmidi_substream *substrea chip->open &= ~SB_OPEN_MIDI_INPUT_TRIGGER; } } - spin_unlock_irqrestore(&chip->open_lock, flags); } static void snd_sb8dsp_midi_output_write(struct snd_rawmidi_substream *substream) { - unsigned long flags; struct snd_sb *chip; char byte; int max = 32; @@ -172,11 +152,10 @@ static void snd_sb8dsp_midi_output_write(struct snd_rawmidi_substream *substream /* how big is Tx FIFO? */ chip = substream->rmidi->private_data; while (max-- > 0) { - spin_lock_irqsave(&chip->open_lock, flags); + guard(spinlock_irqsave)(&chip->open_lock); if (snd_rawmidi_transmit_peek(substream, &byte, 1) != 1) { chip->open &= ~SB_OPEN_MIDI_OUTPUT_TRIGGER; timer_delete(&chip->midi_timer); - spin_unlock_irqrestore(&chip->open_lock, flags); break; } if (chip->hardware >= SB_HW_20) { @@ -185,7 +164,6 @@ static void snd_sb8dsp_midi_output_write(struct snd_rawmidi_substream *substream ; if (timeout == 0) { /* Tx FIFO full - try again later */ - spin_unlock_irqrestore(&chip->open_lock, flags); break; } outb(byte, SBP(chip, WRITE)); @@ -194,7 +172,6 @@ static void snd_sb8dsp_midi_output_write(struct snd_rawmidi_substream *substream snd_sbdsp_command(chip, byte); } snd_rawmidi_transmit_ack(substream, 1); - spin_unlock_irqrestore(&chip->open_lock, flags); } } @@ -202,32 +179,30 @@ static void snd_sb8dsp_midi_output_timer(struct timer_list *t) { struct snd_sb *chip = timer_container_of(chip, t, midi_timer); struct snd_rawmidi_substream *substream = chip->midi_substream_output; - unsigned long flags; - spin_lock_irqsave(&chip->open_lock, flags); - mod_timer(&chip->midi_timer, 1 + jiffies); - spin_unlock_irqrestore(&chip->open_lock, flags); + scoped_guard(spinlock_irqsave, &chip->open_lock) { + mod_timer(&chip->midi_timer, 1 + jiffies); + } snd_sb8dsp_midi_output_write(substream); } static void snd_sb8dsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct snd_sb *chip; chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->open_lock, flags); - if (up) { - if (!(chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER)) { - mod_timer(&chip->midi_timer, 1 + jiffies); - chip->open |= SB_OPEN_MIDI_OUTPUT_TRIGGER; - } - } else { - if (chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER) { - chip->open &= ~SB_OPEN_MIDI_OUTPUT_TRIGGER; + scoped_guard(spinlock_irqsave, &chip->open_lock) { + if (up) { + if (!(chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER)) { + mod_timer(&chip->midi_timer, 1 + jiffies); + chip->open |= SB_OPEN_MIDI_OUTPUT_TRIGGER; + } + } else { + if (chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER) { + chip->open &= ~SB_OPEN_MIDI_OUTPUT_TRIGGER; + } } } - spin_unlock_irqrestore(&chip->open_lock, flags); if (up) snd_sb8dsp_midi_output_write(substream); diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index a4d5bf3d145f..f2848559e6da 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c @@ -94,23 +94,18 @@ static int snd_sbdsp_probe(struct snd_sb * chip) int version; int major, minor; char *str; - unsigned long flags; /* * initialization sequence */ - spin_lock_irqsave(&chip->reg_lock, flags); - if (snd_sbdsp_reset(chip) < 0) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return -ENODEV; - } - version = snd_sbdsp_version(chip); - if (version < 0) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return -ENODEV; + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + if (snd_sbdsp_reset(chip) < 0) + return -ENODEV; + version = snd_sbdsp_version(chip); + if (version < 0) + return -ENODEV; } - spin_unlock_irqrestore(&chip->reg_lock, flags); major = version >> 8; minor = version & 0xff; dev_dbg(chip->card->dev, "SB [0x%lx]: DSP chip found, version = %i.%i\n", diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index b2709ed134b4..95173b18cee3 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c @@ -57,15 +57,13 @@ static int snd_sbmixer_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 16) & 0xff; int mask = (kcontrol->private_value >> 24) & 0xff; unsigned char val; - spin_lock_irqsave(&sb->mixer_lock, flags); + guard(spinlock_irqsave)(&sb->mixer_lock); val = (snd_sbmixer_read(sb, reg) >> shift) & mask; - spin_unlock_irqrestore(&sb->mixer_lock, flags); ucontrol->value.integer.value[0] = val; return 0; } @@ -73,7 +71,6 @@ static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_sbmixer_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 16) & 0x07; int mask = (kcontrol->private_value >> 24) & 0xff; @@ -81,13 +78,12 @@ static int snd_sbmixer_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ unsigned char val, oval; val = (ucontrol->value.integer.value[0] & mask) << shift; - spin_lock_irqsave(&sb->mixer_lock, flags); + guard(spinlock_irqsave)(&sb->mixer_lock); oval = snd_sbmixer_read(sb, reg); val = (oval & ~(mask << shift)) | val; change = val != oval; if (change) snd_sbmixer_write(sb, reg, val); - spin_unlock_irqrestore(&sb->mixer_lock, flags); return change; } @@ -109,7 +105,6 @@ static int snd_sbmixer_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl static int snd_sbmixer_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int left_shift = (kcontrol->private_value >> 16) & 0x07; @@ -117,10 +112,9 @@ static int snd_sbmixer_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ int mask = (kcontrol->private_value >> 24) & 0xff; unsigned char left, right; - spin_lock_irqsave(&sb->mixer_lock, flags); + guard(spinlock_irqsave)(&sb->mixer_lock); left = (snd_sbmixer_read(sb, left_reg) >> left_shift) & mask; right = (snd_sbmixer_read(sb, right_reg) >> right_shift) & mask; - spin_unlock_irqrestore(&sb->mixer_lock, flags); ucontrol->value.integer.value[0] = left; ucontrol->value.integer.value[1] = right; return 0; @@ -129,7 +123,6 @@ static int snd_sbmixer_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_sbmixer_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int left_shift = (kcontrol->private_value >> 16) & 0x07; @@ -140,7 +133,7 @@ static int snd_sbmixer_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ left = (ucontrol->value.integer.value[0] & mask) << left_shift; right = (ucontrol->value.integer.value[1] & mask) << right_shift; - spin_lock_irqsave(&sb->mixer_lock, flags); + guard(spinlock_irqsave)(&sb->mixer_lock); if (left_reg == right_reg) { oleft = snd_sbmixer_read(sb, left_reg); left = (oleft & ~((mask << left_shift) | (mask << right_shift))) | left | right; @@ -158,7 +151,6 @@ static int snd_sbmixer_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ snd_sbmixer_write(sb, right_reg, right); } } - spin_unlock_irqrestore(&sb->mixer_lock, flags); return change; } @@ -178,12 +170,11 @@ static int snd_dt019x_input_sw_info(struct snd_kcontrol *kcontrol, struct snd_ct static int snd_dt019x_input_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; unsigned char oval; - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW); - spin_unlock_irqrestore(&sb->mixer_lock, flags); + scoped_guard(spinlock_irqsave, &sb->mixer_lock) { + oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW); + } switch (oval & 0x07) { case SB_DT019X_CAP_CD: ucontrol->value.enumerated.item[0] = 0; @@ -214,7 +205,6 @@ static int snd_dt019x_input_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl static int snd_dt019x_input_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; int change; unsigned char nval, oval; @@ -239,12 +229,11 @@ static int snd_dt019x_input_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl default: nval = SB_DT019X_CAP_MAIN; } - spin_lock_irqsave(&sb->mixer_lock, flags); + guard(spinlock_irqsave)(&sb->mixer_lock); oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW); change = nval != oval; if (change) snd_sbmixer_write(sb, SB_DT019X_CAPTURE_SW, nval); - spin_unlock_irqrestore(&sb->mixer_lock, flags); return change; } @@ -266,12 +255,10 @@ static int snd_als4k_mono_capture_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; unsigned char oval; - spin_lock_irqsave(&sb->mixer_lock, flags); + guard(spinlock_irqsave)(&sb->mixer_lock); oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL); - spin_unlock_irqrestore(&sb->mixer_lock, flags); oval >>= 6; if (oval > 2) oval = 2; @@ -284,13 +271,12 @@ static int snd_als4k_mono_capture_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; int change; unsigned char nval, oval; if (ucontrol->value.enumerated.item[0] > 2) return -EINVAL; - spin_lock_irqsave(&sb->mixer_lock, flags); + guard(spinlock_irqsave)(&sb->mixer_lock); oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL); nval = (oval & ~(3 << 6)) @@ -298,7 +284,6 @@ static int snd_als4k_mono_capture_route_put(struct snd_kcontrol *kcontrol, change = nval != oval; if (change) snd_sbmixer_write(sb, SB_ALS4000_MONO_IO_CTRL, nval); - spin_unlock_irqrestore(&sb->mixer_lock, flags); return change; } @@ -319,12 +304,10 @@ static int snd_sb8mixer_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_sb8mixer_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; unsigned char oval; - spin_lock_irqsave(&sb->mixer_lock, flags); + guard(spinlock_irqsave)(&sb->mixer_lock); oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE); - spin_unlock_irqrestore(&sb->mixer_lock, flags); switch ((oval >> 0x01) & 0x03) { case SB_DSP_MIXS_CD: ucontrol->value.enumerated.item[0] = 1; @@ -342,7 +325,6 @@ static int snd_sb8mixer_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_el static int snd_sb8mixer_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; int change; unsigned char nval, oval; @@ -359,13 +341,12 @@ static int snd_sb8mixer_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_el nval = SB_DSP_MIXS_MIC; } nval <<= 1; - spin_lock_irqsave(&sb->mixer_lock, flags); + guard(spinlock_irqsave)(&sb->mixer_lock); oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE); nval |= oval & ~0x06; change = nval != oval; if (change) snd_sbmixer_write(sb, SB_DSP_CAPTURE_SOURCE, nval); - spin_unlock_irqrestore(&sb->mixer_lock, flags); return change; } @@ -385,17 +366,15 @@ static int snd_sb16mixer_info_input_sw(struct snd_kcontrol *kcontrol, struct snd static int snd_sb16mixer_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg1 = kcontrol->private_value & 0xff; int reg2 = (kcontrol->private_value >> 8) & 0xff; int left_shift = (kcontrol->private_value >> 16) & 0x0f; int right_shift = (kcontrol->private_value >> 24) & 0x0f; unsigned char val1, val2; - spin_lock_irqsave(&sb->mixer_lock, flags); + guard(spinlock_irqsave)(&sb->mixer_lock); val1 = snd_sbmixer_read(sb, reg1); val2 = snd_sbmixer_read(sb, reg2); - spin_unlock_irqrestore(&sb->mixer_lock, flags); ucontrol->value.integer.value[0] = (val1 >> left_shift) & 0x01; ucontrol->value.integer.value[1] = (val2 >> left_shift) & 0x01; ucontrol->value.integer.value[2] = (val1 >> right_shift) & 0x01; @@ -406,7 +385,6 @@ static int snd_sb16mixer_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ static int snd_sb16mixer_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg1 = kcontrol->private_value & 0xff; int reg2 = (kcontrol->private_value >> 8) & 0xff; int left_shift = (kcontrol->private_value >> 16) & 0x0f; @@ -414,7 +392,7 @@ static int snd_sb16mixer_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ int change; unsigned char val1, val2, oval1, oval2; - spin_lock_irqsave(&sb->mixer_lock, flags); + guard(spinlock_irqsave)(&sb->mixer_lock); oval1 = snd_sbmixer_read(sb, reg1); oval2 = snd_sbmixer_read(sb, reg2); val1 = oval1 & ~((1 << left_shift) | (1 << right_shift)); @@ -428,7 +406,6 @@ static int snd_sb16mixer_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ snd_sbmixer_write(sb, reg1, val1); snd_sbmixer_write(sb, reg2, val2); } - spin_unlock_irqrestore(&sb->mixer_lock, flags); return change; } @@ -697,20 +674,18 @@ static int snd_sbmixer_init(struct snd_sb *chip, int map_count, char *name) { - unsigned long flags; struct snd_card *card = chip->card; int idx, err; /* mixer reset */ - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, 0x00, 0x00); - spin_unlock_irqrestore(&chip->mixer_lock, flags); + scoped_guard(spinlock_irqsave, &chip->mixer_lock) { + snd_sbmixer_write(chip, 0x00, 0x00); + } /* mute and zero volume channels */ for (idx = 0; idx < map_count; idx++) { - spin_lock_irqsave(&chip->mixer_lock, flags); + guard(spinlock_irqsave)(&chip->mixer_lock); snd_sbmixer_write(chip, map[idx][0], map[idx][1]); - spin_unlock_irqrestore(&chip->mixer_lock, flags); } for (idx = 0; idx < controls_count; idx++) { diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 709a1659d66f..a31ca75774a6 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -200,11 +200,8 @@ static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg, static void sscape_write(struct soundscape *s, enum GA_REG reg, unsigned char val) { - unsigned long flags; - - spin_lock_irqsave(&s->lock, flags); + guard(spinlock_irqsave)(&s->lock); sscape_write_unsafe(s->io_base, reg, val); - spin_unlock_irqrestore(&s->lock, flags); } /* @@ -367,12 +364,11 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout) unsigned long end_time = jiffies + msecs_to_jiffies(timeout); do { - unsigned long flags; int x; - spin_lock_irqsave(&s->lock, flags); - x = host_read_unsafe(s->io_base); - spin_unlock_irqrestore(&s->lock, flags); + scoped_guard(spinlock_irqsave, &s->lock) { + x = host_read_unsafe(s->io_base); + } if (x == 0xfe || x == 0xff) return 1; @@ -394,12 +390,11 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout) unsigned long end_time = jiffies + msecs_to_jiffies(timeout); do { - unsigned long flags; int x; - spin_lock_irqsave(&s->lock, flags); - x = host_read_unsafe(s->io_base); - spin_unlock_irqrestore(&s->lock, flags); + scoped_guard(spinlock_irqsave, &s->lock) { + x = host_read_unsafe(s->io_base); + } if (x == 0xfe) return 1; @@ -415,7 +410,6 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout) static int upload_dma_data(struct soundscape *s, const unsigned char *data, size_t size) { - unsigned long flags; struct snd_dma_buffer dma; int ret; unsigned char val; @@ -423,62 +417,57 @@ static int upload_dma_data(struct soundscape *s, const unsigned char *data, if (!get_dmabuf(s, &dma, PAGE_ALIGN(32 * 1024))) return -ENOMEM; - spin_lock_irqsave(&s->lock, flags); - - /* - * Reset the board ... - */ - val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val & 0x3f); - - /* - * Enable the DMA channels and configure them ... - */ - val = (s->chip->dma1 << 4) | DMA_8BIT; - sscape_write_unsafe(s->io_base, GA_DMAA_REG, val); - sscape_write_unsafe(s->io_base, GA_DMAB_REG, 0x20); - - /* - * Take the board out of reset ... - */ - val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x80); + scoped_guard(spinlock_irqsave, &s->lock) { - /* - * Upload the firmware to the SoundScape - * board through the DMA channel ... - */ - while (size != 0) { - unsigned long len; + /* + * Reset the board ... + */ + val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); + sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val & 0x3f); - len = min(size, dma.bytes); - memcpy(dma.area, data, len); - data += len; - size -= len; + /* + * Enable the DMA channels and configure them ... + */ + val = (s->chip->dma1 << 4) | DMA_8BIT; + sscape_write_unsafe(s->io_base, GA_DMAA_REG, val); + sscape_write_unsafe(s->io_base, GA_DMAB_REG, 0x20); - snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE); - sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG); - if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) { - /* - * Don't forget to release this spinlock we're holding - */ - spin_unlock_irqrestore(&s->lock, flags); + /* + * Take the board out of reset ... + */ + val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); + sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x80); - dev_err(s->dev, "sscape: DMA upload has timed out\n"); - ret = -EAGAIN; - goto _release_dma; - } - } /* while */ + /* + * Upload the firmware to the SoundScape + * board through the DMA channel ... + */ + while (size != 0) { + unsigned long len; + + len = min(size, dma.bytes); + memcpy(dma.area, data, len); + data += len; + size -= len; + + snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE); + sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG); + if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) { + dev_err(s->dev, "sscape: DMA upload has timed out\n"); + ret = -EAGAIN; + goto _release_dma; + } + } /* while */ - set_host_mode_unsafe(s->io_base); - outb(0x0, s->io_base); + set_host_mode_unsafe(s->io_base); + outb(0x0, s->io_base); - /* - * Boot the board ... (I think) - */ - val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x40); - spin_unlock_irqrestore(&s->lock, flags); + /* + * Boot the board ... (I think) + */ + val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); + sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x40); + } /* * If all has gone well, then the board should acknowledge @@ -513,7 +502,6 @@ _release_dma: static int sscape_upload_bootblock(struct snd_card *card) { struct soundscape *sscape = get_card_soundscape(card); - unsigned long flags; const struct firmware *init_fw = NULL; int data = 0; int ret; @@ -527,15 +515,13 @@ static int sscape_upload_bootblock(struct snd_card *card) release_firmware(init_fw); - spin_lock_irqsave(&sscape->lock, flags); + guard(spinlock_irqsave)(&sscape->lock); if (ret == 0) data = host_read_ctrl_unsafe(sscape->io_base, 100); if (data & 0x10) sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2f); - spin_unlock_irqrestore(&sscape->lock, flags); - data &= 0xf; if (ret == 0 && data > 7) { dev_err(card->dev, @@ -593,11 +579,9 @@ static int sscape_midi_get(struct snd_kcontrol *kctl, struct snd_wss *chip = snd_kcontrol_chip(kctl); struct snd_card *card = chip->card; register struct soundscape *s = get_card_soundscape(card); - unsigned long flags; - spin_lock_irqsave(&s->lock, flags); + guard(spinlock_irqsave)(&s->lock); uctl->value.integer.value[0] = s->midi_vol; - spin_unlock_irqrestore(&s->lock, flags); return 0; } @@ -607,11 +591,10 @@ static int sscape_midi_put(struct snd_kcontrol *kctl, struct snd_wss *chip = snd_kcontrol_chip(kctl); struct snd_card *card = chip->card; struct soundscape *s = get_card_soundscape(card); - unsigned long flags; int change; unsigned char new_val; - spin_lock_irqsave(&s->lock, flags); + guard(spinlock_irqsave)(&s->lock); new_val = uctl->value.integer.value[0] & 127; /* @@ -642,7 +625,6 @@ __skip_change: */ set_midi_mode_unsafe(s->io_base); - spin_unlock_irqrestore(&s->lock, flags); return change; } @@ -852,8 +834,6 @@ static int create_ad1845(struct snd_card *card, unsigned port, err = snd_wss_create(card, port, -1, irq, dma1, dma2, codec_type, WSS_HWSHARE_DMA1, &chip); if (!err) { - unsigned long flags; - if (sscape->type != SSCAPE_VIVO) { /* * The input clock frequency on the SoundScape must @@ -861,9 +841,9 @@ static int create_ad1845(struct snd_card *card, unsigned port, * to get the playback to sound correct ... */ snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, AD1845_CLOCK, 0x20); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_wss_out(chip, AD1845_CLOCK, 0x20); + } snd_wss_mce_down(chip); } @@ -920,7 +900,6 @@ static int create_sscape(int dev, struct snd_card *card) unsigned mpu_irq_cfg; struct resource *io_res; struct resource *wss_res; - unsigned long flags; int err; int val; const char *name; @@ -1006,34 +985,34 @@ static int create_sscape(int dev, struct snd_card *card) * Tell the on-board devices where their resources are (I think - * I can't be sure without a datasheet ... So many magic values!) */ - spin_lock_irqsave(&sscape->lock, flags); + scoped_guard(spinlock_irqsave, &sscape->lock) { - sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e); - sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00); + sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e); + sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00); - /* - * Enable and configure the DMA channels ... - */ - sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50); - dma_cfg = (sscape->ic_type == IC_OPUS ? 0x40 : 0x70); - sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg); - sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20); - - mpu_irq_cfg |= mpu_irq_cfg << 2; - val = sscape_read_unsafe(sscape->io_base, GA_HMCTL_REG) & 0xF7; - if (joystick[dev]) - val |= 8; - sscape_write_unsafe(sscape->io_base, GA_HMCTL_REG, val | 0x10); - sscape_write_unsafe(sscape->io_base, GA_INTCFG_REG, 0xf0 | mpu_irq_cfg); - sscape_write_unsafe(sscape->io_base, - GA_CDCFG_REG, 0x09 | DMA_8BIT - | (dma[dev] << 4) | (irq_cfg << 1)); - /* - * Enable the master IRQ ... - */ - sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x80); + /* + * Enable and configure the DMA channels ... + */ + sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50); + dma_cfg = (sscape->ic_type == IC_OPUS ? 0x40 : 0x70); + sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg); + sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20); + + mpu_irq_cfg |= mpu_irq_cfg << 2; + val = sscape_read_unsafe(sscape->io_base, GA_HMCTL_REG) & 0xF7; + if (joystick[dev]) + val |= 8; + sscape_write_unsafe(sscape->io_base, GA_HMCTL_REG, val | 0x10); + sscape_write_unsafe(sscape->io_base, GA_INTCFG_REG, 0xf0 | mpu_irq_cfg); + sscape_write_unsafe(sscape->io_base, + GA_CDCFG_REG, 0x09 | DMA_8BIT + | (dma[dev] << 4) | (irq_cfg << 1)); + /* + * Enable the master IRQ ... + */ + sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x80); - spin_unlock_irqrestore(&sscape->lock, flags); + } /* * We have now enabled the codec chip, and so we should @@ -1073,7 +1052,7 @@ static int create_sscape(int dev, struct snd_card *card) /* * Initialize mixer */ - spin_lock_irqsave(&sscape->lock, flags); + guard(spinlock_irqsave)(&sscape->lock); sscape->midi_vol = 0; host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100); @@ -1090,7 +1069,6 @@ static int create_sscape(int dev, struct snd_card *card) host_write_ctrl_unsafe(sscape->io_base, CMD_ACK, 100); set_midi_mode_unsafe(sscape->io_base); - spin_unlock_irqrestore(&sscape->lock, flags); } } diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c index 494b21be665c..1250ecba659a 100644 --- a/sound/isa/wavefront/wavefront_midi.c +++ b/sound/isa/wavefront/wavefront_midi.c @@ -113,7 +113,6 @@ static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card) { snd_wavefront_midi_t *midi = &card->wavefront.midi; snd_wavefront_mpu_id mpu; - unsigned long flags; unsigned char midi_byte; int max = 256, mask = 1; int timeout; @@ -142,11 +141,9 @@ static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card) break; } - spin_lock_irqsave (&midi->virtual, flags); - if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) { - spin_unlock_irqrestore (&midi->virtual, flags); + guard(spinlock_irqsave)(&midi->virtual); + if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) goto __second; - } if (output_ready (midi)) { if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) { if (!midi->isvirtual || @@ -160,14 +157,11 @@ static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card) timer_delete(&midi->timer); } midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; - spin_unlock_irqrestore (&midi->virtual, flags); goto __second; } } else { - spin_unlock_irqrestore (&midi->virtual, flags); return; } - spin_unlock_irqrestore (&midi->virtual, flags); } __second: @@ -185,15 +179,13 @@ static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card) break; } - spin_lock_irqsave (&midi->virtual, flags); + guard(spinlock_irqsave)(&midi->virtual); if (!midi->isvirtual) mask = 0; mpu = midi->output_mpu ^ mask; mask = 0; /* don't invert the value from now */ - if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) { - spin_unlock_irqrestore (&midi->virtual, flags); + if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) return; - } if (snd_rawmidi_transmit_empty(midi->substream_output[mpu])) goto __timer; if (output_ready (midi)) { @@ -215,20 +207,16 @@ static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card) timer_delete(&midi->timer); } midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; - spin_unlock_irqrestore (&midi->virtual, flags); return; } } else { - spin_unlock_irqrestore (&midi->virtual, flags); return; } - spin_unlock_irqrestore (&midi->virtual, flags); } } static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream) { - unsigned long flags; snd_wavefront_midi_t *midi; snd_wavefront_mpu_id mpu; @@ -243,17 +231,15 @@ static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream if (!midi) return -EIO; - spin_lock_irqsave (&midi->open, flags); + guard(spinlock_irqsave)(&midi->open); midi->mode[mpu] |= MPU401_MODE_INPUT; midi->substream_input[mpu] = substream; - spin_unlock_irqrestore (&midi->open, flags); return 0; } static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substream) { - unsigned long flags; snd_wavefront_midi_t *midi; snd_wavefront_mpu_id mpu; @@ -268,17 +254,15 @@ static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substrea if (!midi) return -EIO; - spin_lock_irqsave (&midi->open, flags); + guard(spinlock_irqsave)(&midi->open); midi->mode[mpu] |= MPU401_MODE_OUTPUT; midi->substream_output[mpu] = substream; - spin_unlock_irqrestore (&midi->open, flags); return 0; } static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream) { - unsigned long flags; snd_wavefront_midi_t *midi; snd_wavefront_mpu_id mpu; @@ -293,16 +277,14 @@ static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substrea if (!midi) return -EIO; - spin_lock_irqsave (&midi->open, flags); + guard(spinlock_irqsave)(&midi->open); midi->mode[mpu] &= ~MPU401_MODE_INPUT; - spin_unlock_irqrestore (&midi->open, flags); return 0; } static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substream) { - unsigned long flags; snd_wavefront_midi_t *midi; snd_wavefront_mpu_id mpu; @@ -317,15 +299,13 @@ static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substre if (!midi) return -EIO; - spin_lock_irqsave (&midi->open, flags); + guard(spinlock_irqsave)(&midi->open); midi->mode[mpu] &= ~MPU401_MODE_OUTPUT; - spin_unlock_irqrestore (&midi->open, flags); return 0; } static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; snd_wavefront_midi_t *midi; snd_wavefront_mpu_id mpu; @@ -341,30 +321,27 @@ static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *subst if (!midi) return; - spin_lock_irqsave (&midi->virtual, flags); + guard(spinlock_irqsave)(&midi->virtual); if (up) { midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER; } else { midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER; } - spin_unlock_irqrestore (&midi->virtual, flags); } static void snd_wavefront_midi_output_timer(struct timer_list *t) { snd_wavefront_midi_t *midi = timer_container_of(midi, t, timer); snd_wavefront_card_t *card = midi->timer_card; - unsigned long flags; - spin_lock_irqsave (&midi->virtual, flags); - mod_timer(&midi->timer, 1 + jiffies); - spin_unlock_irqrestore (&midi->virtual, flags); + scoped_guard(spinlock_irqsave, &midi->virtual) { + mod_timer(&midi->timer, 1 + jiffies); + } snd_wavefront_midi_output_write(card); } static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; snd_wavefront_midi_t *midi; snd_wavefront_mpu_id mpu; @@ -380,22 +357,22 @@ static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *subs if (!midi) return; - spin_lock_irqsave (&midi->virtual, flags); - if (up) { - if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) { - if (!midi->istimer) { - timer_setup(&midi->timer, - snd_wavefront_midi_output_timer, - 0); - mod_timer(&midi->timer, 1 + jiffies); + scoped_guard(spinlock_irqsave, &midi->virtual) { + if (up) { + if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) { + if (!midi->istimer) { + timer_setup(&midi->timer, + snd_wavefront_midi_output_timer, + 0); + mod_timer(&midi->timer, 1 + jiffies); + } + midi->istimer++; + midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER; } - midi->istimer++; - midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER; + } else { + midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; } - } else { - midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; } - spin_unlock_irqrestore (&midi->virtual, flags); if (up) snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data); @@ -405,7 +382,6 @@ void snd_wavefront_midi_interrupt (snd_wavefront_card_t *card) { - unsigned long flags; snd_wavefront_midi_t *midi; static struct snd_rawmidi_substream *substream = NULL; static int mpu = external_mpu; @@ -419,37 +395,37 @@ snd_wavefront_midi_interrupt (snd_wavefront_card_t *card) return; } - spin_lock_irqsave (&midi->virtual, flags); - while (--max) { - - if (input_avail (midi)) { - byte = read_data (midi); - - if (midi->isvirtual) { - if (byte == WF_EXTERNAL_SWITCH) { - substream = midi->substream_input[external_mpu]; - mpu = external_mpu; - } else if (byte == WF_INTERNAL_SWITCH) { - substream = midi->substream_output[internal_mpu]; + scoped_guard(spinlock_irqsave, &midi->virtual) { + while (--max) { + + if (input_avail(midi)) { + byte = read_data(midi); + + if (midi->isvirtual) { + if (byte == WF_EXTERNAL_SWITCH) { + substream = midi->substream_input[external_mpu]; + mpu = external_mpu; + } else if (byte == WF_INTERNAL_SWITCH) { + substream = midi->substream_output[internal_mpu]; + mpu = internal_mpu; + } /* else just leave it as it is */ + } else { + substream = midi->substream_input[internal_mpu]; mpu = internal_mpu; - } /* else just leave it as it is */ - } else { - substream = midi->substream_input[internal_mpu]; - mpu = internal_mpu; - } + } - if (substream == NULL) { - continue; - } + if (substream == NULL) { + continue; + } - if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) { - snd_rawmidi_receive(substream, &byte, 1); + if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) { + snd_rawmidi_receive(substream, &byte, 1); + } + } else { + break; } - } else { - break; } - } - spin_unlock_irqrestore (&midi->virtual, flags); + } snd_wavefront_midi_output_write(card); } @@ -471,13 +447,10 @@ void snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card) { - unsigned long flags; - - spin_lock_irqsave (&card->wavefront.midi.virtual, flags); + guard(spinlock_irqsave)(&card->wavefront.midi.virtual); // snd_wavefront_midi_input_close (card->ics2115_external_rmidi); // snd_wavefront_midi_output_close (card->ics2115_external_rmidi); card->wavefront.midi.isvirtual = 0; - spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags); } int diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index bd679e2da154..cd5c177943aa 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -1741,10 +1741,10 @@ snd_wavefront_internal_interrupt (snd_wavefront_card_t *card) return; } - spin_lock(&dev->irq_lock); - dev->irq_ok = 1; - dev->irq_cnt++; - spin_unlock(&dev->irq_lock); + scoped_guard(spinlock, &dev->irq_lock) { + dev->irq_ok = 1; + dev->irq_cnt++; + } wake_up(&dev->interrupt_sleeper); } @@ -1796,11 +1796,11 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev, wait_queue_entry_t wait; init_waitqueue_entry(&wait, current); - spin_lock_irq(&dev->irq_lock); - add_wait_queue(&dev->interrupt_sleeper, &wait); - dev->irq_ok = 0; - outb (val,port); - spin_unlock_irq(&dev->irq_lock); + scoped_guard(spinlock_irq, &dev->irq_lock) { + add_wait_queue(&dev->interrupt_sleeper, &wait); + dev->irq_ok = 0; + outb(val, port); + } while (!dev->irq_ok && time_before(jiffies, timeout)) { schedule_timeout_uninterruptible(1); barrier(); diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 1b6a80021d18..6cf88625bbc3 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -360,7 +360,6 @@ static void snd_wss_busy_wait(struct snd_wss *chip) void snd_wss_mce_up(struct snd_wss *chip) { - unsigned long flags; int timeout; snd_wss_wait(chip); @@ -369,7 +368,7 @@ void snd_wss_mce_up(struct snd_wss *chip) dev_dbg(chip->card->dev, "mce_up - auto calibration time out (0)\n"); #endif - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); chip->mce_bit |= CS4231_MCE; timeout = wss_inb(chip, CS4231P(REGSEL)); if (timeout == 0x80) @@ -379,13 +378,11 @@ void snd_wss_mce_up(struct snd_wss *chip) if (!(timeout & CS4231_MCE)) wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); - spin_unlock_irqrestore(&chip->reg_lock, flags); } EXPORT_SYMBOL(snd_wss_mce_up); void snd_wss_mce_down(struct snd_wss *chip) { - unsigned long flags; unsigned long end_time; int timeout; int hw_mask = WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK | WSS_HW_AD1848; @@ -398,11 +395,11 @@ void snd_wss_mce_down(struct snd_wss *chip) "mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL)); #endif - spin_lock_irqsave(&chip->reg_lock, flags); - chip->mce_bit &= ~CS4231_MCE; - timeout = wss_inb(chip, CS4231P(REGSEL)); - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + chip->mce_bit &= ~CS4231_MCE; + timeout = wss_inb(chip, CS4231P(REGSEL)); + wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); + } if (timeout == 0x80) dev_dbg(chip->card->dev, "mce_down [0x%lx]: serious init problem - codec still busy\n", @@ -496,7 +493,7 @@ static int snd_wss_trigger(struct snd_pcm_substream *substream, snd_pcm_trigger_done(s, substream); } } - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); if (do_start) { chip->image[CS4231_IFACE_CTRL] |= what; if (chip->trigger) @@ -507,7 +504,6 @@ static int snd_wss_trigger(struct snd_pcm_substream *substream, chip->trigger(chip, what, 0); } snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); - spin_unlock(&chip->reg_lock); #if 0 snd_wss_debug(chip); #endif @@ -553,14 +549,11 @@ static unsigned char snd_wss_get_format(struct snd_wss *chip, static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute) { - unsigned long flags; mute = mute ? 0x80 : 0; - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->calibrate_mute == mute) { - spin_unlock_irqrestore(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); + if (chip->calibrate_mute == mute) return; - } if (!mute) { snd_wss_dout(chip, CS4231_LEFT_INPUT, chip->image[CS4231_LEFT_INPUT]); @@ -608,20 +601,18 @@ static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute) mute | chip->image[CS4231_LINE_RIGHT_OUTPUT]); } chip->calibrate_mute = mute; - spin_unlock_irqrestore(&chip->reg_lock, flags); } static void snd_wss_playback_format(struct snd_wss *chip, struct snd_pcm_hw_params *params, unsigned char pdfr) { - unsigned long flags; int full_calib = 1; - mutex_lock(&chip->mce_mutex); + guard(mutex)(&chip->mce_mutex); if (chip->hardware == WSS_HW_CS4231A || (chip->hardware & WSS_HW_CS4232_MASK)) { - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (pdfr & 0x0f)) { /* rate is same? */ snd_wss_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x10); @@ -633,7 +624,6 @@ static void snd_wss_playback_format(struct snd_wss *chip, udelay(100); /* Fixes audible clicks at least on GUS MAX */ full_calib = 0; } - spin_unlock_irqrestore(&chip->reg_lock, flags); } else if (chip->hardware == WSS_HW_AD1845) { unsigned rate = params_rate(params); @@ -646,30 +636,28 @@ static void snd_wss_playback_format(struct snd_wss *chip, * NOTE: We seem to need to write to the MSB before the LSB * to get the correct sample frequency. */ - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (pdfr & 0xf0)); snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); full_calib = 0; - spin_unlock_irqrestore(&chip->reg_lock, flags); } if (full_calib) { snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->hardware != WSS_HW_INTERWAVE && !chip->single_dma) { - if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) - pdfr = (pdfr & 0xf0) | - (chip->image[CS4231_REC_FORMAT] & 0x0f); - } else { - chip->image[CS4231_PLAYBK_FORMAT] = pdfr; + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + if (chip->hardware != WSS_HW_INTERWAVE && !chip->single_dma) { + if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) + pdfr = (pdfr & 0xf0) | + (chip->image[CS4231_REC_FORMAT] & 0x0f); + } else { + chip->image[CS4231_PLAYBK_FORMAT] = pdfr; + } + snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr); } - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr); - spin_unlock_irqrestore(&chip->reg_lock, flags); if (chip->hardware == WSS_HW_OPL3SA2) udelay(100); /* this seems to help */ snd_wss_mce_down(chip); } - mutex_unlock(&chip->mce_mutex); } static void snd_wss_capture_format(struct snd_wss *chip, @@ -679,10 +667,10 @@ static void snd_wss_capture_format(struct snd_wss *chip, unsigned long flags; int full_calib = 1; - mutex_lock(&chip->mce_mutex); + guard(mutex)(&chip->mce_mutex); if (chip->hardware == WSS_HW_CS4231A || (chip->hardware & WSS_HW_CS4232_MASK)) { - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (cdfr & 0x0f) || /* rate is same? */ (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) { snd_wss_out(chip, CS4231_ALT_FEATURE_1, @@ -693,7 +681,6 @@ static void snd_wss_capture_format(struct snd_wss *chip, chip->image[CS4231_ALT_FEATURE_1] &= ~0x20); full_calib = 0; } - spin_unlock_irqrestore(&chip->reg_lock, flags); } else if (chip->hardware == WSS_HW_AD1845) { unsigned rate = params_rate(params); @@ -706,12 +693,11 @@ static void snd_wss_capture_format(struct snd_wss *chip, * NOTE: We seem to need to write to the MSB before the LSB * to get the correct sample frequency. */ - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); snd_wss_out(chip, CS4231_REC_FORMAT, (cdfr & 0xf0)); snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); full_calib = 0; - spin_unlock_irqrestore(&chip->reg_lock, flags); } if (full_calib) { snd_wss_mce_up(chip); @@ -736,7 +722,6 @@ static void snd_wss_capture_format(struct snd_wss *chip, spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); } - mutex_unlock(&chip->mce_mutex); } /* @@ -754,10 +739,10 @@ static unsigned long snd_wss_timer_resolution(struct snd_timer *timer) static int snd_wss_timer_start(struct snd_timer *timer) { - unsigned long flags; unsigned int ticks; struct snd_wss *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->reg_lock, flags); + + guard(spinlock_irqsave)(&chip->reg_lock); ticks = timer->sticks; if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 || (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] || @@ -772,26 +757,22 @@ static int snd_wss_timer_start(struct snd_timer *timer) chip->image[CS4231_ALT_FEATURE_1] | CS4231_TIMER_ENABLE); } - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } static int snd_wss_timer_stop(struct snd_timer *timer) { - unsigned long flags; struct snd_wss *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->reg_lock, flags); + + guard(spinlock_irqsave)(&chip->reg_lock); chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE; snd_wss_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } static void snd_wss_init(struct snd_wss *chip) { - unsigned long flags; - snd_wss_calibrate_mute(chip, 1); snd_wss_mce_down(chip); @@ -799,15 +780,15 @@ static void snd_wss_init(struct snd_wss *chip) dev_dbg(chip->card->dev, "init: (1)\n"); #endif snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | - CS4231_PLAYBACK_PIO | - CS4231_RECORD_ENABLE | - CS4231_RECORD_PIO | - CS4231_CALIB_MODE); - chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB; - snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | + CS4231_PLAYBACK_PIO | + CS4231_RECORD_ENABLE | + CS4231_RECORD_PIO | + CS4231_CALIB_MODE); + chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB; + snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); + } snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE @@ -815,12 +796,12 @@ static void snd_wss_init(struct snd_wss *chip) #endif snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[CS4231_IFACE_CTRL] &= ~CS4231_AUTOCALIB; - snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); - snd_wss_out(chip, - CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + chip->image[CS4231_IFACE_CTRL] &= ~CS4231_AUTOCALIB; + snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); + snd_wss_out(chip, + CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); + } snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE @@ -828,16 +809,16 @@ static void snd_wss_init(struct snd_wss *chip) chip->image[CS4231_ALT_FEATURE_1]); #endif - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_ALT_FEATURE_2, - chip->image[CS4231_ALT_FEATURE_2]); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_wss_out(chip, CS4231_ALT_FEATURE_2, + chip->image[CS4231_ALT_FEATURE_2]); + } snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, - chip->image[CS4231_PLAYBK_FORMAT]); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_wss_out(chip, CS4231_PLAYBK_FORMAT, + chip->image[CS4231_PLAYBK_FORMAT]); + } snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE @@ -845,11 +826,11 @@ static void snd_wss_init(struct snd_wss *chip) #endif snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - if (!(chip->hardware & WSS_HW_AD1848_MASK)) - snd_wss_out(chip, CS4231_REC_FORMAT, - chip->image[CS4231_REC_FORMAT]); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + if (!(chip->hardware & WSS_HW_AD1848_MASK)) + snd_wss_out(chip, CS4231_REC_FORMAT, + chip->image[CS4231_REC_FORMAT]); + } snd_wss_mce_down(chip); snd_wss_calibrate_mute(chip, 0); @@ -860,21 +841,16 @@ static void snd_wss_init(struct snd_wss *chip) static int snd_wss_open(struct snd_wss *chip, unsigned int mode) { - unsigned long flags; - - mutex_lock(&chip->open_mutex); + guard(mutex)(&chip->open_mutex); if ((chip->mode & mode) || - ((chip->mode & WSS_MODE_OPEN) && chip->single_dma)) { - mutex_unlock(&chip->open_mutex); + ((chip->mode & WSS_MODE_OPEN) && chip->single_dma)) return -EAGAIN; - } if (chip->mode & WSS_MODE_OPEN) { chip->mode |= mode; - mutex_unlock(&chip->open_mutex); return 0; } /* ok. now enable and ack CODEC IRQ */ - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (!(chip->hardware & WSS_HW_AD1848_MASK)) { snd_wss_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ | @@ -893,10 +869,8 @@ static int snd_wss_open(struct snd_wss *chip, unsigned int mode) CS4231_TIMER_IRQ); snd_wss_out(chip, CS4231_IRQ_STATUS, 0); } - spin_unlock_irqrestore(&chip->reg_lock, flags); chip->mode = mode; - mutex_unlock(&chip->open_mutex); return 0; } @@ -904,12 +878,10 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) { unsigned long flags; - mutex_lock(&chip->open_mutex); + guard(mutex)(&chip->open_mutex); chip->mode &= ~mode; - if (chip->mode & WSS_MODE_OPEN) { - mutex_unlock(&chip->open_mutex); + if (chip->mode & WSS_MODE_OPEN) return; - } /* disable IRQ */ spin_lock_irqsave(&chip->reg_lock, flags); if (!(chip->hardware & WSS_HW_AD1848_MASK)) @@ -943,7 +915,6 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) spin_unlock_irqrestore(&chip->reg_lock, flags); chip->mode = 0; - mutex_unlock(&chip->open_mutex); } /* @@ -997,18 +968,16 @@ static int snd_wss_playback_prepare(struct snd_pcm_substream *substream) { struct snd_wss *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; unsigned int size = snd_pcm_lib_buffer_bytes(substream); unsigned int count = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); chip->p_dma_size = size; chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO); snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT], count) - 1; snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count); snd_wss_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8)); - spin_unlock_irqrestore(&chip->reg_lock, flags); #if 0 snd_wss_debug(chip); #endif @@ -1032,11 +1001,10 @@ static int snd_wss_capture_prepare(struct snd_pcm_substream *substream) { struct snd_wss *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; unsigned int size = snd_pcm_lib_buffer_bytes(substream); unsigned int count = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); chip->c_dma_size = size; chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); @@ -1056,18 +1024,16 @@ static int snd_wss_capture_prepare(struct snd_pcm_substream *substream) snd_wss_out(chip, CS4231_REC_UPR_CNT, (unsigned char) (count >> 8)); } - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } void snd_wss_overrange(struct snd_wss *chip) { - unsigned long flags; unsigned char res; - spin_lock_irqsave(&chip->reg_lock, flags); - res = snd_wss_in(chip, CS4231_TEST_INIT); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + res = snd_wss_in(chip, CS4231_TEST_INIT); + } if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */ chip->capture_substream->runtime->overrange++; } @@ -1113,13 +1079,12 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id) } } - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); status = ~CS4231_ALL_IRQS | ~status; if (chip->hardware & WSS_HW_AD1848_MASK) wss_outb(chip, CS4231P(STATUS), 0); else snd_wss_out(chip, CS4231_IRQ_STATUS, status); - spin_unlock(&chip->reg_lock); return IRQ_HANDLED; } EXPORT_SYMBOL(snd_wss_interrupt); @@ -1153,10 +1118,8 @@ static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *subst static int snd_ad1848_probe(struct snd_wss *chip) { unsigned long timeout = jiffies + msecs_to_jiffies(1000); - unsigned long flags; unsigned char r; unsigned short hardware = 0; - int err = 0; int i; while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { @@ -1164,7 +1127,7 @@ static int snd_ad1848_probe(struct snd_wss *chip) return -ENODEV; cond_resched(); } - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); /* set CS423x MODE 1 */ snd_wss_dout(chip, CS4231_MISC_INFO, 0); @@ -1173,19 +1136,15 @@ static int snd_ad1848_probe(struct snd_wss *chip) r = snd_wss_in(chip, CS4231_RIGHT_INPUT); if (r != 0x45) { /* RMGE always high on AD1847 */ - if ((r & ~CS4231_ENABLE_MIC_GAIN) != 0x45) { - err = -ENODEV; - goto out; - } + if ((r & ~CS4231_ENABLE_MIC_GAIN) != 0x45) + return -ENODEV; hardware = WSS_HW_AD1847; } else { snd_wss_dout(chip, CS4231_LEFT_INPUT, 0xaa); r = snd_wss_in(chip, CS4231_LEFT_INPUT); /* L/RMGE always low on AT2320 */ - if ((r | CS4231_ENABLE_MIC_GAIN) != 0xaa) { - err = -ENODEV; - goto out; - } + if ((r | CS4231_ENABLE_MIC_GAIN) != 0xaa) + return -ENODEV; } /* clear pending IRQ */ @@ -1194,11 +1153,11 @@ static int snd_ad1848_probe(struct snd_wss *chip) mb(); if ((chip->hardware & WSS_HW_TYPE_MASK) != WSS_HW_DETECT) - goto out; + return 0; if (hardware) { chip->hardware = hardware; - goto out; + return 0; } r = snd_wss_in(chip, CS4231_MISC_INFO); @@ -1227,14 +1186,11 @@ static int snd_ad1848_probe(struct snd_wss *chip) chip->hardware = WSS_HW_AD1848; out_mode: snd_wss_dout(chip, CS4231_MISC_INFO, 0); -out: - spin_unlock_irqrestore(&chip->reg_lock, flags); - return err; + return 0; } static int snd_wss_probe(struct snd_wss *chip) { - unsigned long flags; int i, id, rev, regnum; unsigned char *ptr; unsigned int hw; @@ -1250,11 +1206,10 @@ static int snd_wss_probe(struct snd_wss *chip) if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) msleep(2); else { - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2); id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f; - spin_unlock_irqrestore(&chip->reg_lock, flags); if (id == 0x0a) break; /* this is valid value */ } @@ -1289,11 +1244,11 @@ static int snd_wss_probe(struct snd_wss *chip) return -ENODEV; /* unknown CS4231 chip? */ } } - spin_lock_irqsave(&chip->reg_lock, flags); - wss_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */ - wss_outb(chip, CS4231P(STATUS), 0); - mb(); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + wss_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */ + wss_outb(chip, CS4231P(STATUS), 0); + mb(); + } if (!(chip->hardware & WSS_HW_AD1848_MASK)) chip->image[CS4231_MISC_INFO] = CS4231_MODE2; @@ -1328,10 +1283,10 @@ static int snd_wss_probe(struct snd_wss *chip) ptr = (unsigned char *) &chip->image; regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32; snd_wss_mce_down(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - for (i = 0; i < regnum; i++) /* ok.. fill all registers */ - snd_wss_out(chip, i, *ptr++); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + for (i = 0; i < regnum; i++) /* ok.. fill all registers */ + snd_wss_out(chip, i, *ptr++); + } snd_wss_mce_up(chip); snd_wss_mce_down(chip); @@ -1596,12 +1551,11 @@ static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on) static void snd_wss_suspend(struct snd_wss *chip) { int reg; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); - for (reg = 0; reg < 32; reg++) - chip->image[reg] = snd_wss_in(chip, reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + for (reg = 0; reg < 32; reg++) + chip->image[reg] = snd_wss_in(chip, reg); + } if (chip->thinkpad_flag) snd_wss_thinkpad_twiddle(chip, 0); } @@ -1610,27 +1564,26 @@ static void snd_wss_suspend(struct snd_wss *chip) static void snd_wss_resume(struct snd_wss *chip) { int reg; - unsigned long flags; /* int timeout; */ if (chip->thinkpad_flag) snd_wss_thinkpad_twiddle(chip, 1); snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - for (reg = 0; reg < 32; reg++) { - switch (reg) { - case CS4231_VERSION: - break; - default: - snd_wss_out(chip, reg, chip->image[reg]); - break; + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + for (reg = 0; reg < 32; reg++) { + switch (reg) { + case CS4231_VERSION: + break; + default: + snd_wss_out(chip, reg, chip->image[reg]); + break; + } } + /* Yamaha needs this to resume properly */ + if (chip->hardware == WSS_HW_OPL3SA2) + snd_wss_out(chip, CS4231_PLAYBK_FORMAT, + chip->image[CS4231_PLAYBK_FORMAT]); } - /* Yamaha needs this to resume properly */ - if (chip->hardware == WSS_HW_OPL3SA2) - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, - chip->image[CS4231_PLAYBK_FORMAT]); - spin_unlock_irqrestore(&chip->reg_lock, flags); #if 1 snd_wss_mce_down(chip); #else @@ -1639,11 +1592,11 @@ static void snd_wss_resume(struct snd_wss *chip) include rescheduling. -- iwai */ snd_wss_busy_wait(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->mce_bit &= ~CS4231_MCE; - timeout = wss_inb(chip, CS4231P(REGSEL)); - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + chip->mce_bit &= ~CS4231_MCE; + timeout = wss_inb(chip, CS4231P(REGSEL)); + wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); + } if (timeout == 0x80) dev_err(chip->card->dev "down [0x%lx]: serious init problem - codec still busy\n", @@ -1944,12 +1897,10 @@ static int snd_wss_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6; ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6; - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } @@ -1957,7 +1908,6 @@ static int snd_wss_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; unsigned short left, right; int change; @@ -1966,14 +1916,13 @@ static int snd_wss_put_mux(struct snd_kcontrol *kcontrol, return -EINVAL; left = ucontrol->value.enumerated.item[0] << 6; right = ucontrol->value.enumerated.item[1] << 6; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left; right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right; change = left != chip->image[CS4231_LEFT_INPUT] || right != chip->image[CS4231_RIGHT_INPUT]; snd_wss_out(chip, CS4231_LEFT_INPUT, left); snd_wss_out(chip, CS4231_RIGHT_INPUT, right); - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } @@ -1994,15 +1943,13 @@ int snd_wss_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); if (invert) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; return 0; @@ -2013,7 +1960,6 @@ int snd_wss_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; @@ -2025,11 +1971,10 @@ int snd_wss_put_single(struct snd_kcontrol *kcontrol, if (invert) val = mask - val; val <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); val = (chip->image[reg] & ~(mask << shift)) | val; change = val != chip->image[reg]; snd_wss_out(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } EXPORT_SYMBOL(snd_wss_put_single); @@ -2051,7 +1996,6 @@ int snd_wss_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int shift_left = (kcontrol->private_value >> 16) & 0x07; @@ -2059,10 +2003,9 @@ int snd_wss_get_double(struct snd_kcontrol *kcontrol, int mask = (kcontrol->private_value >> 24) & 0xff; int invert = (kcontrol->private_value >> 22) & 1; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask; ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); if (invert) { ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; @@ -2075,7 +2018,6 @@ int snd_wss_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int shift_left = (kcontrol->private_value >> 16) & 0x07; @@ -2093,7 +2035,7 @@ int snd_wss_put_double(struct snd_kcontrol *kcontrol, } val1 <<= shift_left; val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (left_reg != right_reg) { val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; @@ -2107,7 +2049,6 @@ int snd_wss_put_double(struct snd_kcontrol *kcontrol, change = val1 != chip->image[left_reg]; snd_wss_out(chip, left_reg, val1); } - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } EXPORT_SYMBOL(snd_wss_put_double); diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index 1af177f25c68..077fdf2181c1 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -103,9 +103,8 @@ static int read_ad1843_reg(void *priv, int reg) { struct snd_sgio2audio *chip = priv; int val; - unsigned long flags; - spin_lock_irqsave(&chip->ad1843_lock, flags); + guard(spinlock_irqsave)(&chip->ad1843_lock); writeq((reg << CODEC_CONTROL_ADDRESS_SHIFT) | CODEC_CONTROL_READ, &mace->perif.audio.codec_control); @@ -115,7 +114,6 @@ static int read_ad1843_reg(void *priv, int reg) val = readq(&mace->perif.audio.codec_read); - spin_unlock_irqrestore(&chip->ad1843_lock, flags); return val; } @@ -126,9 +124,8 @@ static int write_ad1843_reg(void *priv, int reg, int word) { struct snd_sgio2audio *chip = priv; int val; - unsigned long flags; - spin_lock_irqsave(&chip->ad1843_lock, flags); + guard(spinlock_irqsave)(&chip->ad1843_lock); writeq((reg << CODEC_CONTROL_ADDRESS_SHIFT) | (word << CODEC_CONTROL_WORD_SHIFT), @@ -137,7 +134,6 @@ static int write_ad1843_reg(void *priv, int reg, int word) val = readq(&mace->perif.audio.codec_control); /* flush bus */ udelay(200); - spin_unlock_irqrestore(&chip->ad1843_lock, flags); return 0; } @@ -351,10 +347,9 @@ static int snd_sgio2audio_dma_pull_frag(struct snd_sgio2audio *chip, u64 *src; s16 *dst; u64 x; - unsigned long flags; struct snd_pcm_runtime *runtime = chip->channel[ch].substream->runtime; - spin_lock_irqsave(&chip->channel[ch].lock, flags); + guard(spinlock_irqsave)(&chip->channel[ch].lock); src_base = (unsigned long) chip->ring_base | (ch << CHANNEL_RING_SHIFT); src_pos = readq(&mace->perif.audio.chan[ch].read_ptr); @@ -383,7 +378,6 @@ static int snd_sgio2audio_dma_pull_frag(struct snd_sgio2audio *chip, writeq(src_pos, &mace->perif.audio.chan[ch].read_ptr); /* in bytes */ chip->channel[ch].pos = dst_pos; - spin_unlock_irqrestore(&chip->channel[ch].lock, flags); return ret; } @@ -399,10 +393,9 @@ static int snd_sgio2audio_dma_push_frag(struct snd_sgio2audio *chip, int src_pos; u64 *dst; s16 *src; - unsigned long flags; struct snd_pcm_runtime *runtime = chip->channel[ch].substream->runtime; - spin_lock_irqsave(&chip->channel[ch].lock, flags); + guard(spinlock_irqsave)(&chip->channel[ch].lock); dst_base = (unsigned long)chip->ring_base | (ch << CHANNEL_RING_SHIFT); dst_pos = readq(&mace->perif.audio.chan[ch].write_ptr); @@ -433,7 +426,6 @@ static int snd_sgio2audio_dma_push_frag(struct snd_sgio2audio *chip, writeq(dst_pos, &mace->perif.audio.chan[ch].write_ptr); /* in bytes */ chip->channel[ch].pos = src_pos; - spin_unlock_irqrestore(&chip->channel[ch].lock, flags); return ret; } @@ -584,9 +576,8 @@ static int snd_sgio2audio_pcm_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct snd_sgio2audio_chan *chan = substream->runtime->private_data; int ch = chan->idx; - unsigned long flags; - spin_lock_irqsave(&chip->channel[ch].lock, flags); + guard(spinlock_irqsave)(&chip->channel[ch].lock); /* Setup the pseudo-dma transfer pointers. */ chip->channel[ch].pos = 0; @@ -610,7 +601,6 @@ static int snd_sgio2audio_pcm_prepare(struct snd_pcm_substream *substream) runtime->channels); break; } - spin_unlock_irqrestore(&chip->channel[ch].lock, flags); return 0; } diff --git a/sound/mips/snd-n64.c b/sound/mips/snd-n64.c index e1b2ff65d850..f17e63f2ff5a 100644 --- a/sound/mips/snd-n64.c +++ b/sound/mips/snd-n64.c @@ -81,10 +81,9 @@ static u32 n64mi_read_reg(struct n64audio *priv, const u8 reg) static void n64audio_push(struct n64audio *priv) { struct snd_pcm_runtime *runtime = priv->chan.substream->runtime; - unsigned long flags; u32 count; - spin_lock_irqsave(&priv->chan.lock, flags); + guard(spinlock_irqsave)(&priv->chan.lock); count = priv->chan.writesize; @@ -104,15 +103,12 @@ static void n64audio_push(struct n64audio *priv) priv->chan.nextpos %= priv->chan.bufsize; runtime->delay = runtime->period_size; - - spin_unlock_irqrestore(&priv->chan.lock, flags); } static irqreturn_t n64audio_isr(int irq, void *dev_id) { struct n64audio *priv = dev_id; const u32 intrs = n64mi_read_reg(priv, MI_INTR_REG); - unsigned long flags; // Check it's ours if (!(intrs & MI_INTR_AI)) @@ -121,11 +117,9 @@ static irqreturn_t n64audio_isr(int irq, void *dev_id) n64audio_write_reg(priv, AI_STATUS_REG, 1); if (priv->chan.substream && snd_pcm_running(priv->chan.substream)) { - spin_lock_irqsave(&priv->chan.lock, flags); - - priv->chan.pos = priv->chan.nextpos; - - spin_unlock_irqrestore(&priv->chan.lock, flags); + scoped_guard(spinlock_irqsave, &priv->chan.lock) { + priv->chan.pos = priv->chan.nextpos; + } snd_pcm_period_elapsed(priv->chan.substream); if (priv->chan.substream && snd_pcm_running(priv->chan.substream)) @@ -221,7 +215,7 @@ static int n64audio_pcm_prepare(struct snd_pcm_substream *substream) rate = 16; n64audio_write_reg(priv, AI_BITCLOCK_REG, rate - 1); - spin_lock_irq(&priv->chan.lock); + guard(spinlock_irq)(&priv->chan.lock); /* Setup the pseudo-dma transfer pointers. */ priv->chan.pos = 0; @@ -230,7 +224,6 @@ static int n64audio_pcm_prepare(struct snd_pcm_substream *substream) priv->chan.writesize = snd_pcm_lib_period_bytes(substream); priv->chan.bufsize = snd_pcm_lib_buffer_bytes(substream); - spin_unlock_irq(&priv->chan.lock); return 0; } diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 76dd2210f9ea..4b5a54da25fb 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c @@ -140,32 +140,25 @@ harmony_enable_interrupts(struct snd_harmony *h) static void harmony_mute(struct snd_harmony *h) { - unsigned long flags; - - spin_lock_irqsave(&h->mixer_lock, flags); + guard(spinlock_irqsave)(&h->mixer_lock); harmony_wait_for_control(h); harmony_write(h, HARMONY_GAINCTL, HARMONY_GAIN_SILENCE); - spin_unlock_irqrestore(&h->mixer_lock, flags); } static void harmony_unmute(struct snd_harmony *h) { - unsigned long flags; - - spin_lock_irqsave(&h->mixer_lock, flags); + guard(spinlock_irqsave)(&h->mixer_lock); harmony_wait_for_control(h); harmony_write(h, HARMONY_GAINCTL, h->st.gain); - spin_unlock_irqrestore(&h->mixer_lock, flags); } static void harmony_set_control(struct snd_harmony *h) { u32 ctrl; - unsigned long flags; - spin_lock_irqsave(&h->lock, flags); + guard(spinlock_irqsave)(&h->lock); ctrl = (HARMONY_CNTL_C | (h->st.format << 6) | @@ -174,8 +167,6 @@ harmony_set_control(struct snd_harmony *h) harmony_wait_for_control(h); harmony_write(h, HARMONY_CNTL, ctrl); - - spin_unlock_irqrestore(&h->lock, flags); } static irqreturn_t @@ -184,53 +175,53 @@ snd_harmony_interrupt(int irq, void *dev) u32 dstatus; struct snd_harmony *h = dev; - spin_lock(&h->lock); - harmony_disable_interrupts(h); - harmony_wait_for_control(h); - dstatus = harmony_read(h, HARMONY_DSTATUS); - spin_unlock(&h->lock); + scoped_guard(spinlock, &h->lock) { + harmony_disable_interrupts(h); + harmony_wait_for_control(h); + dstatus = harmony_read(h, HARMONY_DSTATUS); + } if (dstatus & HARMONY_DSTATUS_PN) { if (h->psubs && h->st.playing) { - spin_lock(&h->lock); - h->pbuf.buf += h->pbuf.count; /* PAGE_SIZE */ - h->pbuf.buf %= h->pbuf.size; /* MAX_BUFS*PAGE_SIZE */ - - harmony_write(h, HARMONY_PNXTADD, - h->pbuf.addr + h->pbuf.buf); - h->stats.play_intr++; - spin_unlock(&h->lock); + scoped_guard(spinlock, &h->lock) { + h->pbuf.buf += h->pbuf.count; /* PAGE_SIZE */ + h->pbuf.buf %= h->pbuf.size; /* MAX_BUFS*PAGE_SIZE */ + + harmony_write(h, HARMONY_PNXTADD, + h->pbuf.addr + h->pbuf.buf); + h->stats.play_intr++; + } snd_pcm_period_elapsed(h->psubs); } else { - spin_lock(&h->lock); - harmony_write(h, HARMONY_PNXTADD, h->sdma.addr); - h->stats.silence_intr++; - spin_unlock(&h->lock); + scoped_guard(spinlock, &h->lock) { + harmony_write(h, HARMONY_PNXTADD, h->sdma.addr); + h->stats.silence_intr++; + } } } if (dstatus & HARMONY_DSTATUS_RN) { if (h->csubs && h->st.capturing) { - spin_lock(&h->lock); - h->cbuf.buf += h->cbuf.count; - h->cbuf.buf %= h->cbuf.size; - - harmony_write(h, HARMONY_RNXTADD, - h->cbuf.addr + h->cbuf.buf); - h->stats.rec_intr++; - spin_unlock(&h->lock); + scoped_guard(spinlock, &h->lock) { + h->cbuf.buf += h->cbuf.count; + h->cbuf.buf %= h->cbuf.size; + + harmony_write(h, HARMONY_RNXTADD, + h->cbuf.addr + h->cbuf.buf); + h->stats.rec_intr++; + } snd_pcm_period_elapsed(h->csubs); } else { - spin_lock(&h->lock); - harmony_write(h, HARMONY_RNXTADD, h->gdma.addr); - h->stats.graveyard_intr++; - spin_unlock(&h->lock); + scoped_guard(spinlock, &h->lock) { + harmony_write(h, HARMONY_RNXTADD, h->gdma.addr); + h->stats.graveyard_intr++; + } } } - spin_lock(&h->lock); - harmony_enable_interrupts(h); - spin_unlock(&h->lock); + scoped_guard(spinlock, &h->lock) { + harmony_enable_interrupts(h); + } return IRQ_HANDLED; } @@ -297,7 +288,7 @@ snd_harmony_playback_trigger(struct snd_pcm_substream *ss, int cmd) if (h->st.capturing) return -EBUSY; - spin_lock(&h->lock); + guard(spinlock)(&h->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: h->st.playing = 1; @@ -316,11 +307,9 @@ snd_harmony_playback_trigger(struct snd_pcm_substream *ss, int cmd) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_SUSPEND: default: - spin_unlock(&h->lock); snd_BUG(); return -EINVAL; } - spin_unlock(&h->lock); return 0; } @@ -333,7 +322,7 @@ snd_harmony_capture_trigger(struct snd_pcm_substream *ss, int cmd) if (h->st.playing) return -EBUSY; - spin_lock(&h->lock); + guard(spinlock)(&h->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: h->st.capturing = 1; @@ -352,11 +341,9 @@ snd_harmony_capture_trigger(struct snd_pcm_substream *ss, int cmd) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_SUSPEND: default: - spin_unlock(&h->lock); snd_BUG(); return -EINVAL; } - spin_unlock(&h->lock); return 0; } @@ -674,7 +661,7 @@ snd_harmony_volume_get(struct snd_kcontrol *kc, int invert = (kc->private_value >> 24) & 0xff; int left, right; - spin_lock_irq(&h->mixer_lock); + guard(spinlock_irq)(&h->mixer_lock); left = (h->st.gain >> shift_left) & mask; right = (h->st.gain >> shift_right) & mask; @@ -687,8 +674,6 @@ snd_harmony_volume_get(struct snd_kcontrol *kc, if (shift_left != shift_right) ucontrol->value.integer.value[1] = right; - spin_unlock_irq(&h->mixer_lock); - return 0; } @@ -704,7 +689,7 @@ snd_harmony_volume_put(struct snd_kcontrol *kc, int left, right; int old_gain = h->st.gain; - spin_lock_irq(&h->mixer_lock); + guard(spinlock_irq)(&h->mixer_lock); left = ucontrol->value.integer.value[0] & mask; if (invert) @@ -722,8 +707,6 @@ snd_harmony_volume_put(struct snd_kcontrol *kc, snd_harmony_set_new_gain(h); - spin_unlock_irq(&h->mixer_lock); - return h->st.gain != old_gain; } @@ -743,13 +726,11 @@ snd_harmony_captureroute_get(struct snd_kcontrol *kc, struct snd_harmony *h = snd_kcontrol_chip(kc); int value; - spin_lock_irq(&h->mixer_lock); + guard(spinlock_irq)(&h->mixer_lock); value = (h->st.gain >> HARMONY_GAIN_IS_SHIFT) & 1; ucontrol->value.enumerated.item[0] = value; - spin_unlock_irq(&h->mixer_lock); - return 0; } @@ -761,7 +742,7 @@ snd_harmony_captureroute_put(struct snd_kcontrol *kc, int value; int old_gain = h->st.gain; - spin_lock_irq(&h->mixer_lock); + guard(spinlock_irq)(&h->mixer_lock); value = ucontrol->value.enumerated.item[0] & 1; h->st.gain &= ~HARMONY_GAIN_IS_MASK; @@ -769,8 +750,6 @@ snd_harmony_captureroute_put(struct snd_kcontrol *kc, snd_harmony_set_new_gain(h); - spin_unlock_irq(&h->mixer_lock); - return h->st.gain != old_gain; } diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index cd60c856a92e..c54bdefa5afe 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -326,11 +326,10 @@ void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned sh { if (!snd_ac97_valid_reg(ac97, reg)) return; - mutex_lock(&ac97->reg_mutex); + guard(mutex)(&ac97->reg_mutex); ac97->regs[reg] = value; ac97->bus->ops->write(ac97, reg, value); set_bit(reg, ac97->reg_accessed); - mutex_unlock(&ac97->reg_mutex); } EXPORT_SYMBOL(snd_ac97_write_cache); @@ -353,14 +352,13 @@ int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short va if (!snd_ac97_valid_reg(ac97, reg)) return -EINVAL; - mutex_lock(&ac97->reg_mutex); + guard(mutex)(&ac97->reg_mutex); change = ac97->regs[reg] != value; if (change) { ac97->regs[reg] = value; ac97->bus->ops->write(ac97, reg, value); } set_bit(reg, ac97->reg_accessed); - mutex_unlock(&ac97->reg_mutex); return change; } @@ -381,14 +379,10 @@ EXPORT_SYMBOL(snd_ac97_update); */ int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value) { - int change; - if (!snd_ac97_valid_reg(ac97, reg)) return -EINVAL; - mutex_lock(&ac97->reg_mutex); - change = snd_ac97_update_bits_nolock(ac97, reg, mask, value); - mutex_unlock(&ac97->reg_mutex); - return change; + guard(mutex)(&ac97->reg_mutex); + return snd_ac97_update_bits_nolock(ac97, reg, mask, value); } EXPORT_SYMBOL(snd_ac97_update_bits); @@ -416,12 +410,12 @@ static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, uns int change; unsigned short old, new, cfg; - mutex_lock(&ac97->page_mutex); + guard(mutex)(&ac97->page_mutex); old = ac97->spec.ad18xx.pcmreg[codec]; new = (old & ~mask) | (value & mask); change = old != new; if (change) { - mutex_lock(&ac97->reg_mutex); + guard(mutex)(&ac97->reg_mutex); cfg = snd_ac97_read_cache(ac97, AC97_AD_SERIAL_CFG); ac97->spec.ad18xx.pcmreg[codec] = new; /* select single codec */ @@ -433,9 +427,7 @@ static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, uns /* select all codecs */ ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG, cfg | 0x7000); - mutex_unlock(&ac97->reg_mutex); } - mutex_unlock(&ac97->page_mutex); return change; } @@ -716,12 +708,11 @@ static int snd_ac97_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ { struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - mutex_lock(&ac97->reg_mutex); + guard(mutex)(&ac97->reg_mutex); ucontrol->value.iec958.status[0] = ac97->spdif_status & 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[3] = (ac97->spdif_status >> 24) & 0xff; - mutex_unlock(&ac97->reg_mutex); return 0; } @@ -760,7 +751,7 @@ static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ } } - mutex_lock(&ac97->reg_mutex); + guard(mutex)(&ac97->reg_mutex); change = ac97->spdif_status != new; ac97->spdif_status = new; @@ -794,7 +785,6 @@ static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ } } - mutex_unlock(&ac97->reg_mutex); return change; } @@ -811,7 +801,7 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ value = (ucontrol->value.integer.value[0] & mask); - mutex_lock(&ac97->reg_mutex); + guard(mutex)(&ac97->reg_mutex); mask <<= shift; value <<= shift; old = snd_ac97_read_cache(ac97, reg); @@ -825,7 +815,6 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ if (extst & AC97_EA_SPDIF) snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ } - mutex_unlock(&ac97->reg_mutex); return change; } @@ -936,10 +925,9 @@ static int snd_ac97_ad18xx_pcm_get_volume(struct snd_kcontrol *kcontrol, struct struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); int codec = kcontrol->private_value & 3; - mutex_lock(&ac97->page_mutex); + guard(mutex)(&ac97->page_mutex); ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31); ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31); - mutex_unlock(&ac97->page_mutex); return 0; } diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 3002be9d88f3..64cc39dd2008 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -54,12 +54,11 @@ static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsi unsigned short page_save; int ret; - mutex_lock(&ac97->page_mutex); + guard(mutex)(&ac97->page_mutex); page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); ret = snd_ac97_update_bits(ac97, reg, mask, value); snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); - mutex_unlock(&ac97->page_mutex); /* unlock paging */ return ret; } @@ -976,12 +975,11 @@ static int snd_ac97_stac9708_put_bias(struct snd_kcontrol *kcontrol, struct snd_ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); int err; - mutex_lock(&ac97->page_mutex); + guard(mutex)(&ac97->page_mutex); snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba); err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010, (ucontrol->value.integer.value[0] & 1) << 4); snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0); - mutex_unlock(&ac97->page_mutex); return err; } @@ -3699,7 +3697,7 @@ static int snd_ac97_vt1618_UAJ_get(struct snd_kcontrol *kcontrol, unsigned short datpag, uaj; struct snd_ac97 *pac97 = snd_kcontrol_chip(kcontrol); - mutex_lock(&pac97->page_mutex); + guard(mutex)(&pac97->page_mutex); datpag = snd_ac97_read(pac97, AC97_INT_PAGING) & AC97_PAGE_MASK; snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, 0); @@ -3708,7 +3706,6 @@ static int snd_ac97_vt1618_UAJ_get(struct snd_kcontrol *kcontrol, vt1618_uaj[kcontrol->private_value].mask; snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, datpag); - mutex_unlock(&pac97->page_mutex); ucontrol->value.enumerated.item[0] = uaj >> vt1618_uaj[kcontrol->private_value].shift; diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c index 5fee8e89790f..4715d88ff8f4 100644 --- a/sound/pci/ac97/ac97_pcm.c +++ b/sound/pci/ac97/ac97_pcm.c @@ -192,7 +192,7 @@ static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate) mask = AC97_SC_SPSR_MASK; } - mutex_lock(&ac97->reg_mutex); + guard(mutex)(&ac97->reg_mutex); old = snd_ac97_read(ac97, reg) & mask; if (old != bits) { snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); @@ -217,7 +217,6 @@ static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate) ac97->spdif_status = sbits; } snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); - mutex_unlock(&ac97->reg_mutex); return 0; } @@ -571,33 +570,31 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate, return err; } } - spin_lock_irq(&pcm->bus->bus_lock); - for (i = 3; i < 12; i++) { - if (!(slots & (1 << i))) - continue; - ok_flag = 0; - for (cidx = 0; cidx < 4; cidx++) { - if (bus->used_slots[pcm->stream][cidx] & (1 << i)) { - spin_unlock_irq(&pcm->bus->bus_lock); - err = -EBUSY; - goto error; + scoped_guard(spinlock_irq, &pcm->bus->bus_lock) { + for (i = 3; i < 12; i++) { + if (!(slots & (1 << i))) + continue; + ok_flag = 0; + for (cidx = 0; cidx < 4; cidx++) { + if (bus->used_slots[pcm->stream][cidx] & (1 << i)) { + err = -EBUSY; + goto error; + } + if (pcm->r[r].rslots[cidx] & (1 << i)) { + bus->used_slots[pcm->stream][cidx] |= (1 << i); + ok_flag++; + } } - if (pcm->r[r].rslots[cidx] & (1 << i)) { - bus->used_slots[pcm->stream][cidx] |= (1 << i); - ok_flag++; + if (!ok_flag) { + dev_err(bus->card->dev, + "cannot find configuration for AC97 slot %i\n", + i); + err = -EAGAIN; + goto error; } } - if (!ok_flag) { - spin_unlock_irq(&pcm->bus->bus_lock); - dev_err(bus->card->dev, - "cannot find configuration for AC97 slot %i\n", - i); - err = -EAGAIN; - goto error; - } + pcm->cur_dbl = r; } - pcm->cur_dbl = r; - spin_unlock_irq(&pcm->bus->bus_lock); for (i = 3; i < 12; i++) { if (!(slots & (1 << i))) continue; @@ -665,7 +662,7 @@ int snd_ac97_pcm_close(struct ac97_pcm *pcm) #endif bus = pcm->bus; - spin_lock_irq(&pcm->bus->bus_lock); + guard(spinlock_irq)(&pcm->bus->bus_lock); for (i = 3; i < 12; i++) { if (!(slots & (1 << i))) continue; @@ -674,7 +671,6 @@ int snd_ac97_pcm_close(struct ac97_pcm *pcm) } pcm->aslots = 0; pcm->cur_dbl = 0; - spin_unlock_irq(&pcm->bus->bus_lock); return 0; } diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c index 2df3ba9a08dc..1c9d76994b3a 100644 --- a/sound/pci/ac97/ac97_proc.c +++ b/sound/pci/ac97/ac97_proc.c @@ -329,7 +329,7 @@ static void snd_ac97_proc_read(struct snd_info_entry *entry, struct snd_info_buf { struct snd_ac97 *ac97 = entry->private_data; - mutex_lock(&ac97->page_mutex); + guard(mutex)(&ac97->page_mutex); if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 int idx; for (idx = 0; idx < 3; idx++) @@ -355,7 +355,6 @@ static void snd_ac97_proc_read(struct snd_info_entry *entry, struct snd_info_buf } else { snd_ac97_proc_read_main(ac97, buffer, 0); } - mutex_unlock(&ac97->page_mutex); } #ifdef CONFIG_SND_DEBUG @@ -365,7 +364,8 @@ static void snd_ac97_proc_regs_write(struct snd_info_entry *entry, struct snd_in struct snd_ac97 *ac97 = entry->private_data; char line[64]; unsigned int reg, val; - mutex_lock(&ac97->page_mutex); + + guard(mutex)(&ac97->page_mutex); while (!snd_info_get_line(buffer, line, sizeof(line))) { if (sscanf(line, "%x %x", ®, &val) != 2) continue; @@ -373,7 +373,6 @@ static void snd_ac97_proc_regs_write(struct snd_info_entry *entry, struct snd_in if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff) snd_ac97_write_cache(ac97, reg, val); } - mutex_unlock(&ac97->page_mutex); } #endif @@ -392,7 +391,7 @@ static void snd_ac97_proc_regs_read(struct snd_info_entry *entry, { struct snd_ac97 *ac97 = entry->private_data; - mutex_lock(&ac97->page_mutex); + guard(mutex)(&ac97->page_mutex); if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 int idx; @@ -408,7 +407,6 @@ static void snd_ac97_proc_regs_read(struct snd_info_entry *entry, } else { snd_ac97_proc_regs_read_main(ac97, buffer, 0); } - mutex_unlock(&ac97->page_mutex); } void snd_ac97_proc_init(struct snd_ac97 * ac97) diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index 020cbb467e7e..f4ec404c0d15 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -353,7 +353,7 @@ snd_ad1889_playback_prepare(struct snd_pcm_substream *ss) reg |= AD_DS_WSMC_WAST; /* let's make sure we don't clobber ourselves */ - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); chip->wave.size = size; chip->wave.reg = reg; @@ -372,8 +372,6 @@ snd_ad1889_playback_prepare(struct snd_pcm_substream *ss) /* writes flush */ ad1889_readw(chip, AD_DS_WSMC); - spin_unlock_irq(&chip->lock); - dev_dbg(chip->card->dev, "prepare playback: addr = 0x%x, count = %u, size = %u, reg = 0x%x, rate = %u\n", chip->wave.addr, count, size, reg, rt->rate); @@ -403,7 +401,7 @@ snd_ad1889_capture_prepare(struct snd_pcm_substream *ss) reg |= AD_DS_RAMC_ADST; /* let's make sure we don't clobber ourselves */ - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); chip->ramc.size = size; chip->ramc.reg = reg; @@ -419,8 +417,6 @@ snd_ad1889_capture_prepare(struct snd_pcm_substream *ss) /* writes flush */ ad1889_readw(chip, AD_DS_RAMC); - spin_unlock_irq(&chip->lock); - dev_dbg(chip->card->dev, "prepare capture: addr = 0x%x, count = %u, size = %u, reg = 0x%x, rate = %u\n", chip->ramc.addr, count, size, reg, rt->rate); @@ -775,7 +771,7 @@ snd_ad1889_free(struct snd_card *card) { struct snd_ad1889 *chip = card->private_data; - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); ad1889_mute(chip); @@ -785,8 +781,6 @@ snd_ad1889_free(struct snd_card *card) /* clear DISR. If we don't, we'd better jump off the Eiffel Tower */ ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PTAI | AD_DMA_DISR_PMAI); ad1889_readl(chip, AD_DMA_DISR); /* flush, dammit! */ - - spin_unlock_irq(&chip->lock); } static int diff --git a/sound/pci/ak4531_codec.c b/sound/pci/ak4531_codec.c index e54812bfb2c6..cdad47e4098d 100644 --- a/sound/pci/ak4531_codec.c +++ b/sound/pci/ak4531_codec.c @@ -77,9 +77,8 @@ static int snd_ak4531_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e int invert = (kcontrol->private_value >> 22) & 1; int val; - mutex_lock(&ak4531->reg_mutex); + guard(mutex)(&ak4531->reg_mutex); val = (ak4531->regs[reg] >> shift) & mask; - mutex_unlock(&ak4531->reg_mutex); if (invert) { val = mask - val; } @@ -102,11 +101,10 @@ static int snd_ak4531_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e val = mask - val; } val <<= shift; - mutex_lock(&ak4531->reg_mutex); + guard(mutex)(&ak4531->reg_mutex); val = (ak4531->regs[reg] & ~(mask << shift)) | val; change = val != ak4531->regs[reg]; ak4531->write(ak4531, reg, ak4531->regs[reg] = val); - mutex_unlock(&ak4531->reg_mutex); return change; } @@ -146,10 +144,9 @@ static int snd_ak4531_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e int invert = (kcontrol->private_value >> 22) & 1; int left, right; - mutex_lock(&ak4531->reg_mutex); + guard(mutex)(&ak4531->reg_mutex); left = (ak4531->regs[left_reg] >> left_shift) & mask; right = (ak4531->regs[right_reg] >> right_shift) & mask; - mutex_unlock(&ak4531->reg_mutex); if (invert) { left = mask - left; right = mask - right; @@ -179,7 +176,7 @@ static int snd_ak4531_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e } left <<= left_shift; right <<= right_shift; - mutex_lock(&ak4531->reg_mutex); + guard(mutex)(&ak4531->reg_mutex); if (left_reg == right_reg) { left = (ak4531->regs[left_reg] & ~((mask << left_shift) | (mask << right_shift))) | left | right; change = left != ak4531->regs[left_reg]; @@ -191,7 +188,6 @@ static int snd_ak4531_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left); ak4531->write(ak4531, right_reg, ak4531->regs[right_reg] = right); } - mutex_unlock(&ak4531->reg_mutex); return change; } @@ -218,12 +214,11 @@ static int snd_ak4531_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl int left_shift = (kcontrol->private_value >> 16) & 0x0f; int right_shift = (kcontrol->private_value >> 24) & 0x0f; - mutex_lock(&ak4531->reg_mutex); + guard(mutex)(&ak4531->reg_mutex); 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[2] = (ak4531->regs[reg1] >> right_shift) & 1; ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1; - mutex_unlock(&ak4531->reg_mutex); return 0; } @@ -237,7 +232,7 @@ static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl int change; int val1, val2; - mutex_lock(&ak4531->reg_mutex); + guard(mutex)(&ak4531->reg_mutex); val1 = ak4531->regs[reg1] & ~((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; @@ -247,7 +242,6 @@ static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl change = val1 != ak4531->regs[reg1] || val2 != ak4531->regs[reg2]; ak4531->write(ak4531, reg1, ak4531->regs[reg1] = val1); ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2); - mutex_unlock(&ak4531->reg_mutex); return change; } diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index a6e499e0ceda..571d89a6a8da 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -911,13 +911,12 @@ static struct snd_ali_voice *snd_ali_alloc_voice(struct snd_ali * codec, dev_dbg(codec->card->dev, "alloc_voice: type=%d rec=%d\n", type, rec); - spin_lock_irq(&codec->voice_alloc); + guard(spinlock_irq)(&codec->voice_alloc); if (type == SNDRV_ALI_VOICE_TYPE_PCM) { idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) : snd_ali_find_free_channel(codec,rec); if (idx < 0) { dev_err(codec->card->dev, "ali_alloc_voice: err.\n"); - spin_unlock_irq(&codec->voice_alloc); return NULL; } pvoice = &(codec->synth.voices[idx]); @@ -925,10 +924,8 @@ static struct snd_ali_voice *snd_ali_alloc_voice(struct snd_ali * codec, pvoice->use = 1; pvoice->pcm = 1; pvoice->mode = rec; - spin_unlock_irq(&codec->voice_alloc); return pvoice; } - spin_unlock_irq(&codec->voice_alloc); return NULL; } @@ -943,16 +940,16 @@ static void snd_ali_free_voice(struct snd_ali * codec, if (!pvoice->use) return; snd_ali_clear_voices(codec, pvoice->number, pvoice->number); - spin_lock_irq(&codec->voice_alloc); - private_free = pvoice->private_free; - private_data = pvoice->private_data; - pvoice->private_free = NULL; - pvoice->private_data = NULL; - if (pvoice->pcm) - snd_ali_free_channel_pcm(codec, pvoice->number); - pvoice->use = pvoice->pcm = pvoice->synth = 0; - pvoice->substream = NULL; - spin_unlock_irq(&codec->voice_alloc); + scoped_guard(spinlock_irq, &codec->voice_alloc) { + private_free = pvoice->private_free; + private_data = pvoice->private_data; + pvoice->private_free = NULL; + pvoice->private_data = NULL; + if (pvoice->pcm) + snd_ali_free_channel_pcm(codec, pvoice->number); + pvoice->use = pvoice->pcm = pvoice->synth = 0; + pvoice->substream = NULL; + } if (private_free) private_free(private_data); } @@ -1109,7 +1106,7 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream, snd_pcm_trigger_done(s, substream); } } - spin_lock(&codec->reg_lock); + guard(spinlock)(&codec->reg_lock); if (!do_start) outl(what, ALI_REG(codec, ALI_STOP)); val = inl(ALI_REG(codec, ALI_AINTEN)); @@ -1121,7 +1118,6 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream, if (do_start) outl(what, ALI_REG(codec, ALI_START)); dev_dbg(codec->card->dev, "trigger: what=%xh whati=%xh\n", what, whati); - spin_unlock(&codec->reg_lock); return 0; } @@ -1189,8 +1185,8 @@ static int snd_ali_playback_prepare(struct snd_pcm_substream *substream) dev_dbg(codec->card->dev, "playback_prepare ...\n"); - spin_lock_irq(&codec->reg_lock); - + guard(spinlock_irq)(&codec->reg_lock); + /* set Delta (rate) value */ Delta = snd_ali_convert_rate(runtime->rate, 0); @@ -1259,7 +1255,6 @@ static int snd_ali_playback_prepare(struct snd_pcm_substream *substream) CTRL, EC); } - spin_unlock_irq(&codec->reg_lock); return 0; } @@ -1360,14 +1355,11 @@ snd_ali_playback_pointer(struct snd_pcm_substream *substream) struct snd_ali_voice *pvoice = runtime->private_data; unsigned int cso; - spin_lock(&codec->reg_lock); - if (!pvoice->running) { - spin_unlock(&codec->reg_lock); + guard(spinlock)(&codec->reg_lock); + if (!pvoice->running) return 0; - } outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR)); cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2)); - spin_unlock(&codec->reg_lock); dev_dbg(codec->card->dev, "playback pointer returned cso=%xh.\n", cso); cso %= runtime->buffer_size; @@ -1382,14 +1374,11 @@ static snd_pcm_uframes_t snd_ali_pointer(struct snd_pcm_substream *substream) struct snd_ali_voice *pvoice = runtime->private_data; unsigned int cso; - spin_lock(&codec->reg_lock); - if (!pvoice->running) { - spin_unlock(&codec->reg_lock); + guard(spinlock)(&codec->reg_lock); + if (!pvoice->running) return 0; - } outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR)); cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2)); - spin_unlock(&codec->reg_lock); cso %= runtime->buffer_size; return cso; @@ -1693,7 +1682,7 @@ static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0; - spin_lock_irq(&codec->reg_lock); + guard(spinlock_irq)(&codec->reg_lock); switch (kcontrol->private_value) { case 0: spdif_enable = (codec->spdif_mask & 0x02) ? 1 : 0; @@ -1709,7 +1698,6 @@ static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, break; } ucontrol->value.integer.value[0] = spdif_enable; - spin_unlock_irq(&codec->reg_lock); return 0; } @@ -1721,7 +1709,7 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol, spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0; - spin_lock_irq(&codec->reg_lock); + guard(spinlock_irq)(&codec->reg_lock); switch (kcontrol->private_value) { case 0: change = (codec->spdif_mask & 0x02) ? 1 : 0; @@ -1766,7 +1754,6 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol, default: break; } - spin_unlock_irq(&codec->reg_lock); return change; } @@ -1833,7 +1820,7 @@ static int ali_suspend(struct device *dev) for (i = 0; i < chip->num_of_codecs; i++) snd_ac97_suspend(chip->ac97[i]); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); im->regs[ALI_MISCINT >> 2] = inl(ALI_REG(chip, ALI_MISCINT)); /* im->regs[ALI_START >> 2] = inl(ALI_REG(chip, ALI_START)); */ @@ -1857,7 +1844,6 @@ static int ali_suspend(struct device *dev) /* stop all HW channel */ outl(0xffffffff, ALI_REG(chip, ALI_STOP)); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1868,27 +1854,25 @@ static int ali_resume(struct device *dev) struct snd_ali_image *im = &chip->image; int i, j; - spin_lock_irq(&chip->reg_lock); - - for (i = 0; i < ALI_CHANNELS; i++) { - outb(i, ALI_REG(chip, ALI_GC_CIR)); - for (j = 0; j < ALI_CHANNEL_REGS; j++) - outl(im->channel_regs[i][j], ALI_REG(chip, j*4 + 0xe0)); - } + scoped_guard(spinlock_irq, &chip->reg_lock) { + for (i = 0; i < ALI_CHANNELS; i++) { + outb(i, ALI_REG(chip, ALI_GC_CIR)); + for (j = 0; j < ALI_CHANNEL_REGS; j++) + outl(im->channel_regs[i][j], ALI_REG(chip, j*4 + 0xe0)); + } - for (i = 0; i < ALI_GLOBAL_REGS; i++) { - if ((i*4 == ALI_MISCINT) || (i*4 == ALI_STOP) || - (i*4 == ALI_START)) - continue; - outl(im->regs[i], ALI_REG(chip, i*4)); + for (i = 0; i < ALI_GLOBAL_REGS; i++) { + if ((i*4 == ALI_MISCINT) || (i*4 == ALI_STOP) || + (i*4 == ALI_START)) + continue; + outl(im->regs[i], ALI_REG(chip, i*4)); + } + + /* start HW channel */ + outl(im->regs[ALI_START >> 2], ALI_REG(chip, ALI_START)); + /* restore IRQ enable bits */ + outl(im->regs[ALI_MISCINT >> 2], ALI_REG(chip, ALI_MISCINT)); } - - /* start HW channel */ - outl(im->regs[ALI_START >> 2], ALI_REG(chip, ALI_START)); - /* restore IRQ enable bits */ - outl(im->regs[ALI_MISCINT >> 2], ALI_REG(chip, ALI_MISCINT)); - - spin_unlock_irq(&chip->reg_lock); for (i = 0 ; i < chip->num_of_codecs; i++) snd_ac97_resume(chip->ac97[i]); diff --git a/sound/pci/als300.c b/sound/pci/als300.c index f9e8424dc77f..733e84def5a7 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -402,7 +402,7 @@ static int snd_als300_playback_prepare(struct snd_pcm_substream *substream) unsigned short period_bytes = snd_pcm_lib_period_bytes(substream); unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); tmp = snd_als300_gcr_read(chip->port, PLAYBACK_CONTROL); tmp &= ~TRANSFER_START; @@ -419,7 +419,6 @@ static int snd_als300_playback_prepare(struct snd_pcm_substream *substream) runtime->dma_addr); snd_als300_gcr_write(chip->port, PLAYBACK_END, runtime->dma_addr + buffer_bytes - 1); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -431,7 +430,7 @@ static int snd_als300_capture_prepare(struct snd_pcm_substream *substream) unsigned short period_bytes = snd_pcm_lib_period_bytes(substream); unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); tmp = snd_als300_gcr_read(chip->port, RECORD_CONTROL); tmp &= ~TRANSFER_START; @@ -448,7 +447,6 @@ static int snd_als300_capture_prepare(struct snd_pcm_substream *substream) runtime->dma_addr); snd_als300_gcr_write(chip->port, RECORD_END, runtime->dma_addr + buffer_bytes - 1); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -463,7 +461,7 @@ static int snd_als300_trigger(struct snd_pcm_substream *substream, int cmd) data = substream->runtime->private_data; reg = data->control_register; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -492,7 +490,6 @@ static int snd_als300_trigger(struct snd_pcm_substream *substream, int cmd) snd_als300_dbgplay("TRIGGER INVALID\n"); ret = -EINVAL; } - spin_unlock(&chip->reg_lock); return ret; } @@ -506,10 +503,10 @@ static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream) data = substream->runtime->private_data; period_bytes = snd_pcm_lib_period_bytes(substream); - spin_lock(&chip->reg_lock); - current_ptr = (u16) snd_als300_gcr_read(chip->port, - data->block_counter_register) + 4; - spin_unlock(&chip->reg_lock); + scoped_guard(spinlock, &chip->reg_lock) { + current_ptr = (u16) snd_als300_gcr_read(chip->port, + data->block_counter_register) + 4; + } if (current_ptr > period_bytes) current_ptr = 0; else @@ -563,10 +560,9 @@ static int snd_als300_new_pcm(struct snd_als300 *chip) static void snd_als300_init(struct snd_als300 *chip) { - unsigned long flags; u32 tmp; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); chip->revision = (snd_als300_gcr_read(chip->port, MISC_CONTROL) >> 16) & 0x0000000F; /* Setup DRAM */ @@ -591,7 +587,6 @@ static void snd_als300_init(struct snd_als300 *chip) tmp = snd_als300_gcr_read(chip->port, PLAYBACK_CONTROL); snd_als300_gcr_write(chip->port, PLAYBACK_CONTROL, tmp & ~TRANSFER_START); - spin_unlock_irqrestore(&chip->reg_lock, flags); } static int snd_als300_create(struct snd_card *card, diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index eb159497c905..33034e07b3d6 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -369,14 +369,14 @@ static int snd_als4000_capture_prepare(struct snd_pcm_substream *substream) count >>= 1; count--; - spin_lock_irq(&chip->reg_lock); - snd_als4000_set_rate(chip, runtime->rate); - snd_als4000_set_capture_dma(chip, runtime->dma_addr, size); - spin_unlock_irq(&chip->reg_lock); - spin_lock_irq(&chip->mixer_lock); - snd_als4_cr_write(chip, ALS4K_CR1C_FIFO2_BLOCK_LENGTH_LO, count & 0xff); - snd_als4_cr_write(chip, ALS4K_CR1D_FIFO2_BLOCK_LENGTH_HI, count >> 8); - spin_unlock_irq(&chip->mixer_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + snd_als4000_set_rate(chip, runtime->rate); + snd_als4000_set_capture_dma(chip, runtime->dma_addr, size); + } + scoped_guard(spinlock_irq, &chip->mixer_lock) { + snd_als4_cr_write(chip, ALS4K_CR1C_FIFO2_BLOCK_LENGTH_LO, count & 0xff); + snd_als4_cr_write(chip, ALS4K_CR1D_FIFO2_BLOCK_LENGTH_HI, count >> 8); + } return 0; } @@ -402,7 +402,7 @@ static int snd_als4000_playback_prepare(struct snd_pcm_substream *substream) * reordering, ...). Something seems to get enabled on playback * that I haven't found out how to disable again, which then causes * the switching pops to reach the speakers the next time here. */ - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); snd_als4000_set_rate(chip, runtime->rate); snd_als4000_set_playback_dma(chip, runtime->dma_addr, size); @@ -413,7 +413,6 @@ static int snd_als4000_playback_prepare(struct snd_pcm_substream *substream) snd_sbdsp_command(chip, count & 0xff); snd_sbdsp_command(chip, count >> 8); snd_sbdsp_command(chip, playback_cmd(chip).dma_off); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -429,7 +428,7 @@ static int snd_als4000_capture_trigger(struct snd_pcm_substream *substream, int Probably need to take reg_lock as outer (or inner??) lock, too. (or serialize both lock operations? probably not, though... - racy?) */ - spin_lock(&chip->mixer_lock); + guard(spinlock)(&chip->mixer_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -447,7 +446,6 @@ static int snd_als4000_capture_trigger(struct snd_pcm_substream *substream, int result = -EINVAL; break; } - spin_unlock(&chip->mixer_lock); return result; } @@ -456,7 +454,7 @@ static int snd_als4000_playback_trigger(struct snd_pcm_substream *substream, int struct snd_sb *chip = snd_pcm_substream_chip(substream); int result = 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -472,7 +470,6 @@ static int snd_als4000_playback_trigger(struct snd_pcm_substream *substream, int result = -EINVAL; break; } - spin_unlock(&chip->reg_lock); return result; } @@ -481,9 +478,9 @@ static snd_pcm_uframes_t snd_als4000_capture_pointer(struct snd_pcm_substream *s struct snd_sb *chip = snd_pcm_substream_chip(substream); unsigned int result; - spin_lock(&chip->reg_lock); - result = snd_als4k_gcr_read(chip, ALS4K_GCRA4_FIFO2_CURRENT_ADDR); - spin_unlock(&chip->reg_lock); + scoped_guard(spinlock, &chip->reg_lock) { + result = snd_als4k_gcr_read(chip, ALS4K_GCRA4_FIFO2_CURRENT_ADDR); + } result &= 0xffff; return bytes_to_frames( substream->runtime, result ); } @@ -493,9 +490,9 @@ static snd_pcm_uframes_t snd_als4000_playback_pointer(struct snd_pcm_substream * struct snd_sb *chip = snd_pcm_substream_chip(substream); unsigned result; - spin_lock(&chip->reg_lock); - result = snd_als4k_gcr_read(chip, ALS4K_GCRA0_FIFO1_CURRENT_ADDR); - spin_unlock(&chip->reg_lock); + scoped_guard(spinlock, &chip->reg_lock) { + result = snd_als4k_gcr_read(chip, ALS4K_GCRA0_FIFO1_CURRENT_ADDR); + } result &= 0xffff; return bytes_to_frames( substream->runtime, result ); } @@ -536,10 +533,10 @@ static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id) snd_als4k_iobase_writeb(chip->alt_port, ALS4K_IOB_0E_IRQTYPE_SB_CR1E_MPU, pci_irqstatus); - spin_lock(&chip->mixer_lock); - /* SPECS_PAGE: 20 */ - sb_irqstatus = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS); - spin_unlock(&chip->mixer_lock); + scoped_guard(spinlock, &chip->mixer_lock) { + /* SPECS_PAGE: 20 */ + sb_irqstatus = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS); + } if (sb_irqstatus & SB_IRQTYPE_8BIT) snd_sb_ack_8bit(chip); @@ -709,18 +706,18 @@ static void snd_als4000_configure(struct snd_sb *chip) int i; /* do some more configuration */ - spin_lock_irq(&chip->mixer_lock); - tmp = snd_als4_cr_read(chip, ALS4K_CR0_SB_CONFIG); - snd_als4_cr_write(chip, ALS4K_CR0_SB_CONFIG, - tmp|ALS4K_CR0_MX80_81_REG_WRITE_ENABLE); - /* always select DMA channel 0, since we do not actually use DMA - * SPECS_PAGE: 19/20 */ - snd_sbmixer_write(chip, SB_DSP4_DMASETUP, SB_DMASETUP_DMA0); - snd_als4_cr_write(chip, ALS4K_CR0_SB_CONFIG, - tmp & ~ALS4K_CR0_MX80_81_REG_WRITE_ENABLE); - spin_unlock_irq(&chip->mixer_lock); + scoped_guard(spinlock_irq, &chip->mixer_lock) { + tmp = snd_als4_cr_read(chip, ALS4K_CR0_SB_CONFIG); + snd_als4_cr_write(chip, ALS4K_CR0_SB_CONFIG, + tmp|ALS4K_CR0_MX80_81_REG_WRITE_ENABLE); + /* always select DMA channel 0, since we do not actually use DMA + * SPECS_PAGE: 19/20 */ + snd_sbmixer_write(chip, SB_DSP4_DMASETUP, SB_DMASETUP_DMA0); + snd_als4_cr_write(chip, ALS4K_CR0_SB_CONFIG, + tmp & ~ALS4K_CR0_MX80_81_REG_WRITE_ENABLE); + } - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); /* enable interrupts */ snd_als4k_gcr_write(chip, ALS4K_GCR8C_MISC_CTRL, ALS4K_GCR8C_IRQ_MASK_CTRL_ENABLE); @@ -731,7 +728,6 @@ static void snd_als4000_configure(struct snd_sb *chip) /* enable burst mode to prevent dropouts during high PCI bus usage */ snd_als4k_gcr_write(chip, ALS4K_GCR99_DMA_EMULATION_CTRL, (snd_als4k_gcr_read(chip, ALS4K_GCR99_DMA_EMULATION_CTRL) & ~0x07) | 0x04); - spin_unlock_irq(&chip->reg_lock); } #ifdef SUPPORT_JOYSTICK diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 8419f2b6e589..fd0a67b772d1 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -982,12 +982,12 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) err = hpi_outstream_open(card->hpi->adapter->index, substream->number, &dpcm->h_stream); hpi_handle_error(err); - if (err) + if (err) { kfree(dpcm); - if (err == HPI_ERROR_OBJ_ALREADY_OPEN) - return -EBUSY; - if (err) + if (err == HPI_ERROR_OBJ_ALREADY_OPEN) + return -EBUSY; return -EIO; + } /*? also check ASI5000 samplerate source If external, only support external rate. @@ -1156,12 +1156,12 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream) err = hpi_handle_error( hpi_instream_open(card->hpi->adapter->index, substream->number, &dpcm->h_stream)); - if (err) + if (err) { kfree(dpcm); - if (err == HPI_ERROR_OBJ_ALREADY_OPEN) - return -EBUSY; - if (err) + if (err == HPI_ERROR_OBJ_ALREADY_OPEN) + return -EBUSY; return -EIO; + } timer_setup(&dpcm->timer, snd_card_asihpi_timer_function, 0); dpcm->substream = substream; diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 4f544950ee7b..2a0c59d5afa5 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -345,7 +345,6 @@ static int atiixp_build_dma_packets(struct atiixp *chip, struct atiixp_dma *dma, { unsigned int i; u32 addr, desc_addr; - unsigned long flags; if (periods > ATI_MAX_DESCRIPTORS) return -ENOMEM; @@ -363,11 +362,11 @@ static int atiixp_build_dma_packets(struct atiixp *chip, struct atiixp_dma *dma, return 0; /* reset DMA before changing the descriptor table */ - spin_lock_irqsave(&chip->reg_lock, flags); - writel(0, chip->remap_addr + dma->ops->llp_offset); - dma->ops->enable_dma(chip, 0); - dma->ops->enable_dma(chip, 1); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + writel(0, chip->remap_addr + dma->ops->llp_offset); + dma->ops->enable_dma(chip, 0); + dma->ops->enable_dma(chip, 1); + } /* fill the entries */ addr = (u32)substream->runtime->dma_addr; @@ -711,7 +710,7 @@ static int snd_atiixp_pcm_trigger(struct snd_pcm_substream *substream, int cmd) !dma->ops->flush_dma)) return -EINVAL; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: @@ -745,7 +744,6 @@ static int snd_atiixp_pcm_trigger(struct snd_pcm_substream *substream, int cmd) snd_atiixp_check_bus_busy(chip); } } - spin_unlock(&chip->reg_lock); return err; } @@ -859,7 +857,7 @@ static int snd_atiixp_spdif_prepare(struct snd_pcm_substream *substream) { struct atiixp *chip = snd_pcm_substream_chip(substream); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); if (chip->spdif_over_aclink) { unsigned int data; /* enable slots 10/11 */ @@ -877,7 +875,6 @@ static int snd_atiixp_spdif_prepare(struct snd_pcm_substream *substream) atiixp_update(chip, CMD, ATI_REG_CMD_SPDF_CONFIG_MASK, 0); atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_SPDF, 0); } - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -887,7 +884,7 @@ static int snd_atiixp_playback_prepare(struct snd_pcm_substream *substream) struct atiixp *chip = snd_pcm_substream_chip(substream); unsigned int data; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); data = atiixp_read(chip, OUT_DMA_SLOT) & ~ATI_REG_OUT_DMA_SLOT_MASK; switch (substream->runtime->channels) { case 8: @@ -922,7 +919,6 @@ static int snd_atiixp_playback_prepare(struct snd_pcm_substream *substream) atiixp_update(chip, 6CH_REORDER, ATI_REG_6CH_REORDER_EN, substream->runtime->channels >= 6 ? ATI_REG_6CH_REORDER_EN: 0); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -931,11 +927,10 @@ static int snd_atiixp_capture_prepare(struct snd_pcm_substream *substream) { struct atiixp *chip = snd_pcm_substream_chip(substream); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_IN, substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE ? ATI_REG_CMD_INTERLEAVE_IN : 0); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1043,9 +1038,9 @@ static int snd_atiixp_pcm_open(struct snd_pcm_substream *substream, runtime->private_data = dma; /* enable DMA bits */ - spin_lock_irq(&chip->reg_lock); - dma->ops->enable_dma(chip, 1); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + dma->ops->enable_dma(chip, 1); + } dma->opened = 1; return 0; @@ -1058,9 +1053,9 @@ static int snd_atiixp_pcm_close(struct snd_pcm_substream *substream, /* disable DMA bits */ if (snd_BUG_ON(!dma->ops || !dma->ops->enable_dma)) return -EINVAL; - spin_lock_irq(&chip->reg_lock); - dma->ops->enable_dma(chip, 0); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + dma->ops->enable_dma(chip, 0); + } dma->substream = NULL; dma->opened = 0; return 0; @@ -1073,9 +1068,8 @@ static int snd_atiixp_playback_open(struct snd_pcm_substream *substream) struct atiixp *chip = snd_pcm_substream_chip(substream); int err; - mutex_lock(&chip->open_mutex); + guard(mutex)(&chip->open_mutex); err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0); - mutex_unlock(&chip->open_mutex); if (err < 0) return err; substream->runtime->hw.channels_max = chip->max_channels; @@ -1089,11 +1083,9 @@ static int snd_atiixp_playback_open(struct snd_pcm_substream *substream) static int snd_atiixp_playback_close(struct snd_pcm_substream *substream) { struct atiixp *chip = snd_pcm_substream_chip(substream); - int err; - mutex_lock(&chip->open_mutex); - err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); - mutex_unlock(&chip->open_mutex); - return err; + + guard(mutex)(&chip->open_mutex); + return snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); } static int snd_atiixp_capture_open(struct snd_pcm_substream *substream) @@ -1111,27 +1103,23 @@ static int snd_atiixp_capture_close(struct snd_pcm_substream *substream) static int snd_atiixp_spdif_open(struct snd_pcm_substream *substream) { struct atiixp *chip = snd_pcm_substream_chip(substream); - int err; - mutex_lock(&chip->open_mutex); + + guard(mutex)(&chip->open_mutex); if (chip->spdif_over_aclink) /* share DMA_PLAYBACK */ - err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 2); + return snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 2); else - err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_SPDIF], -1); - mutex_unlock(&chip->open_mutex); - return err; + return snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_SPDIF], -1); } static int snd_atiixp_spdif_close(struct snd_pcm_substream *substream) { struct atiixp *chip = snd_pcm_substream_chip(substream); - int err; - mutex_lock(&chip->open_mutex); + + guard(mutex)(&chip->open_mutex); if (chip->spdif_over_aclink) - err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); + return snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); else - err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_SPDIF]); - mutex_unlock(&chip->open_mutex); - return err; + return snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_SPDIF]); } /* AC97 playback */ @@ -1355,10 +1343,9 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id) if (status & CODEC_CHECK_BITS) { unsigned int detected; detected = status & CODEC_CHECK_BITS; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); chip->codec_not_ready_bits |= detected; atiixp_update(chip, IER, detected, 0); /* disable the detected irqs */ - spin_unlock(&chip->reg_lock); } /* ack */ diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index f7417c2bb477..91f31e2ad3d3 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -314,7 +314,6 @@ static int atiixp_build_dma_packets(struct atiixp_modem *chip, { unsigned int i; u32 addr, desc_addr; - unsigned long flags; if (periods > ATI_MAX_DESCRIPTORS) return -ENOMEM; @@ -330,11 +329,11 @@ static int atiixp_build_dma_packets(struct atiixp_modem *chip, return 0; /* reset DMA before changing the descriptor table */ - spin_lock_irqsave(&chip->reg_lock, flags); - writel(0, chip->remap_addr + dma->ops->llp_offset); - dma->ops->enable_dma(chip, 0); - dma->ops->enable_dma(chip, 1); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + writel(0, chip->remap_addr + dma->ops->llp_offset); + dma->ops->enable_dma(chip, 0); + dma->ops->enable_dma(chip, 1); + } /* fill the entries */ addr = (u32)substream->runtime->dma_addr; @@ -661,7 +660,7 @@ static int snd_atiixp_pcm_trigger(struct snd_pcm_substream *substream, int cmd) !dma->ops->flush_dma)) return -EINVAL; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch(cmd) { case SNDRV_PCM_TRIGGER_START: dma->ops->enable_transfer(chip, 1); @@ -682,7 +681,6 @@ static int snd_atiixp_pcm_trigger(struct snd_pcm_substream *substream, int cmd) snd_atiixp_check_bus_busy(chip); } } - spin_unlock(&chip->reg_lock); return err; } @@ -753,13 +751,12 @@ static int snd_atiixp_playback_prepare(struct snd_pcm_substream *substream) struct atiixp_modem *chip = snd_pcm_substream_chip(substream); unsigned int data; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); /* set output threshold */ data = atiixp_read(chip, MODEM_OUT_FIFO); data &= ~ATI_REG_MODEM_OUT1_DMA_THRESHOLD_MASK; data |= 0x04 << ATI_REG_MODEM_OUT1_DMA_THRESHOLD_SHIFT; atiixp_write(chip, MODEM_OUT_FIFO, data); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -864,9 +861,9 @@ static int snd_atiixp_pcm_open(struct snd_pcm_substream *substream, runtime->private_data = dma; /* enable DMA bits */ - spin_lock_irq(&chip->reg_lock); - dma->ops->enable_dma(chip, 1); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + dma->ops->enable_dma(chip, 1); + } dma->opened = 1; return 0; @@ -879,9 +876,9 @@ static int snd_atiixp_pcm_close(struct snd_pcm_substream *substream, /* disable DMA bits */ if (snd_BUG_ON(!dma->ops || !dma->ops->enable_dma)) return -EINVAL; - spin_lock_irq(&chip->reg_lock); - dma->ops->enable_dma(chip, 0); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + dma->ops->enable_dma(chip, 0); + } dma->substream = NULL; dma->opened = 0; return 0; @@ -892,24 +889,17 @@ static int snd_atiixp_pcm_close(struct snd_pcm_substream *substream, static int snd_atiixp_playback_open(struct snd_pcm_substream *substream) { struct atiixp_modem *chip = snd_pcm_substream_chip(substream); - int err; - mutex_lock(&chip->open_mutex); - err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0); - mutex_unlock(&chip->open_mutex); - if (err < 0) - return err; - return 0; + guard(mutex)(&chip->open_mutex); + return snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0); } static int snd_atiixp_playback_close(struct snd_pcm_substream *substream) { struct atiixp_modem *chip = snd_pcm_substream_chip(substream); - int err; - mutex_lock(&chip->open_mutex); - err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); - mutex_unlock(&chip->open_mutex); - return err; + + guard(mutex)(&chip->open_mutex); + return snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); } static int snd_atiixp_capture_open(struct snd_pcm_substream *substream) @@ -1020,10 +1010,9 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id) if (status & CODEC_CHECK_BITS) { unsigned int detected; detected = status & CODEC_CHECK_BITS; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); chip->codec_not_ready_bits |= detected; atiixp_update(chip, IER, detected, 0); /* disable the detected irqs */ - spin_unlock(&chip->reg_lock); } /* ack */ diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index 1d7aab14579e..e2c501f4394c 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c @@ -347,7 +347,7 @@ static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; unsigned long period_size, buffer_size; - mutex_lock(&chip->mtx); + guard(mutex)(&chip->mtx); period_size = snd_pcm_lib_period_bytes(substream); buffer_size = snd_pcm_lib_buffer_bytes(substream); @@ -363,8 +363,6 @@ static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream) snd_pcm_period_elapsed, (void *)substream); - mutex_unlock(&chip->mtx); - return 0; } @@ -376,7 +374,7 @@ static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; unsigned long period_size, buffer_size; - mutex_lock(&chip->mtx); + guard(mutex)(&chip->mtx); period_size = snd_pcm_lib_period_bytes(substream); buffer_size = snd_pcm_lib_buffer_bytes(substream); @@ -392,8 +390,6 @@ static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream) snd_pcm_period_elapsed, (void *)substream); - mutex_unlock(&chip->mtx); - return 0; } @@ -401,10 +397,10 @@ static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream) static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream, int cmd) { - int status = 0; struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream); struct aw2 *chip = pcm_device->chip; - spin_lock(&chip->reg_lock); + + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: snd_aw2_saa7146_pcm_trigger_start_playback(&chip->saa7146, @@ -417,20 +413,19 @@ static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream, stream_number); break; default: - status = -EINVAL; + return -EINVAL; } - spin_unlock(&chip->reg_lock); - return status; + return 0; } /* capture trigger callback */ static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream, int cmd) { - int status = 0; struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream); struct aw2 *chip = pcm_device->chip; - spin_lock(&chip->reg_lock); + + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: snd_aw2_saa7146_pcm_trigger_start_capture(&chip->saa7146, @@ -443,10 +438,9 @@ static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream, stream_number); break; default: - status = -EINVAL; + return -EINVAL; } - spin_unlock(&chip->reg_lock); - return status; + return 0; } /* playback pointer callback */ diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index b33344f65b8c..6cdf76e2b7d2 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -1201,7 +1201,6 @@ snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec, unsigned int channels ) { - unsigned long flags; u16 val = 0xff00; u8 freq = 0; @@ -1244,7 +1243,7 @@ snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec, if (format_width == 16) val |= SOUNDFORMAT_FLAG_16BIT; - spin_lock_irqsave(codec->lock, flags); + guard(spinlock_irqsave)(codec->lock); /* set bitrate/format */ snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val); @@ -1266,8 +1265,6 @@ snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec, DMA_EPILOGUE_SOMETHING | DMA_SOMETHING_ELSE ); - - spin_unlock_irqrestore(codec->lock, flags); } static inline void @@ -1373,8 +1370,6 @@ snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip, if (!codec->running) { /* AZF3328 uses a two buffer pointer DMA transfer approach */ - unsigned long flags; - /* width 32bit (prevent overflow): */ u32 area_length; struct codec_setup_io { @@ -1405,11 +1400,10 @@ snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip, /* build combined I/O buffer length word */ setup_io.dma_lengths = (area_length << 16) | (area_length); - spin_lock_irqsave(codec->lock, flags); + guard(spinlock_irqsave)(codec->lock); snd_azf3328_codec_outl_multi( codec, IDX_IO_CODEC_DMA_START_1, &setup_io, 3 ); - spin_unlock_irqrestore(codec->lock, flags); } } @@ -1464,48 +1458,48 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) snd_pcm_format_width(runtime->format), runtime->channels); - spin_lock(codec->lock); - /* first, remember current value: */ - flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); + scoped_guard(spinlock, codec->lock) { + /* first, remember current value: */ + flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); - /* stop transfer */ - flags1 &= ~DMA_RESUME; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); + /* stop transfer */ + flags1 &= ~DMA_RESUME; + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); - /* FIXME: clear interrupts or what??? */ - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff); - spin_unlock(codec->lock); + /* FIXME: clear interrupts or what??? */ + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff); + } snd_azf3328_codec_setdmaa(chip, codec, runtime->dma_addr, snd_pcm_lib_period_bytes(substream), snd_pcm_lib_buffer_bytes(substream) ); - spin_lock(codec->lock); + scoped_guard(spinlock, codec->lock) { #ifdef WIN9X - /* FIXME: enable playback/recording??? */ - flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); - - /* start transfer again */ - /* FIXME: what is this value (0x0010)??? */ - flags1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); + /* FIXME: enable playback/recording??? */ + flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2; + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); + + /* start transfer again */ + /* FIXME: what is this value (0x0010)??? */ + flags1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); #else /* NT4 */ - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - 0x0000); - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - DMA_RUN_SOMETHING1); - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - DMA_RUN_SOMETHING1 | - DMA_RUN_SOMETHING2); - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - DMA_RESUME | - SOMETHING_ALMOST_ALWAYS_SET | - DMA_EPILOGUE_SOMETHING | - DMA_SOMETHING_ELSE); + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, + 0x0000); + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, + DMA_RUN_SOMETHING1); + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, + DMA_RUN_SOMETHING1 | + DMA_RUN_SOMETHING2); + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, + DMA_RESUME | + SOMETHING_ALMOST_ALWAYS_SET | + DMA_EPILOGUE_SOMETHING | + DMA_SOMETHING_ELSE); #endif - spin_unlock(codec->lock); + } snd_azf3328_ctrl_codec_activity(chip, codec->type, 1); if (is_main_mixer_playback_codec) { @@ -1521,14 +1515,14 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_RESUME: dev_dbg(chip->card->dev, "PCM RESUME %s\n", codec->name); /* resume codec if we were active */ - spin_lock(codec->lock); - if (codec->running) - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - snd_azf3328_codec_inw( - codec, IDX_IO_CODEC_DMA_FLAGS - ) | DMA_RESUME - ); - spin_unlock(codec->lock); + scoped_guard(spinlock, codec->lock) { + if (codec->running) + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, + snd_azf3328_codec_inw( + codec, IDX_IO_CODEC_DMA_FLAGS + ) | DMA_RESUME + ); + } break; case SNDRV_PCM_TRIGGER_STOP: dev_dbg(chip->card->dev, "PCM STOP %s\n", codec->name); @@ -1541,22 +1535,22 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ); } - spin_lock(codec->lock); - /* first, remember current value: */ - flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); + scoped_guard(spinlock, codec->lock) { + /* first, remember current value: */ + flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); - /* stop transfer */ - flags1 &= ~DMA_RESUME; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); + /* stop transfer */ + flags1 &= ~DMA_RESUME; + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); - /* hmm, is this really required? we're resetting the same bit - * immediately thereafter... */ - flags1 |= DMA_RUN_SOMETHING1; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); + /* hmm, is this really required? we're resetting the same bit + * immediately thereafter... */ + flags1 |= DMA_RUN_SOMETHING1; + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); - flags1 &= ~DMA_RUN_SOMETHING1; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); - spin_unlock(codec->lock); + flags1 &= ~DMA_RUN_SOMETHING1; + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); + } snd_azf3328_ctrl_codec_activity(chip, codec->type, 0); if (is_main_mixer_playback_codec) { @@ -1724,12 +1718,11 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport, struct snd_azf3328 *chip = gameport_get_port_data(gameport); int i; u8 val; - unsigned long flags; if (snd_BUG_ON(!chip)) return 0; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); val = snd_azf3328_game_inb(chip, IDX_GAME_LEGACY_COMPATIBLE); *buttons = (~(val) >> 4) & 0xf; @@ -1766,7 +1759,6 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport, snd_azf3328_game_outb(chip, IDX_GAME_AXES_CONFIG, val); snd_azf3328_game_outw(chip, IDX_GAME_AXIS_VALUE, 0xffff); - spin_unlock_irqrestore(&chip->reg_lock, flags); for (i = 0; i < ARRAY_SIZE(chip->axes); i++) { axes[i] = chip->axes[i]; @@ -1863,11 +1855,11 @@ snd_azf3328_pcm_interrupt(struct snd_azf3328 *chip, if (!(status & (1 << codec_type))) continue; - spin_lock(codec->lock); - which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE); - /* ack all IRQ types immediately */ - snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which); - spin_unlock(codec->lock); + scoped_guard(spinlock, codec->lock) { + which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE); + /* ack all IRQ types immediately */ + snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which); + } if (codec->substream) { snd_pcm_period_elapsed(codec->substream); @@ -1912,9 +1904,9 @@ snd_azf3328_interrupt(int irq, void *dev_id) if (chip->timer) snd_timer_interrupt(chip->timer, chip->timer->sticks); /* ACK timer */ - spin_lock(&chip->reg_lock); - snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07); - spin_unlock(&chip->reg_lock); + scoped_guard(spinlock, &chip->reg_lock) { + snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07); + } dev_dbg(chip->card->dev, "timer IRQ\n"); } @@ -2137,7 +2129,6 @@ static int snd_azf3328_timer_start(struct snd_timer *timer) { struct snd_azf3328 *chip; - unsigned long flags; unsigned int delay; chip = snd_timer_chip(timer); @@ -2152,9 +2143,8 @@ snd_azf3328_timer_start(struct snd_timer *timer) } dev_dbg(chip->card->dev, "setting timer countdown value %d\n", delay); delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); snd_azf3328_ctrl_outl(chip, IDX_IO_TIMER_VALUE, delay); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } @@ -2162,10 +2152,9 @@ static int snd_azf3328_timer_stop(struct snd_timer *timer) { struct snd_azf3328 *chip; - unsigned long flags; chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); /* disable timer countdown and interrupt */ /* Hmm, should we write TIMER_IRQ_ACK here? YES indeed, otherwise a rogue timer operation - which prompts @@ -2174,7 +2163,6 @@ snd_azf3328_timer_stop(struct snd_timer *timer) Simply manually poking 0x04 _once_ immediately successfully stops the hardware/ALSA interrupt activity. */ snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x04); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } @@ -2406,10 +2394,9 @@ snd_azf3328_create(struct snd_card *card, codec->running = true; snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); - spin_lock_irq(codec->lock); + guard(spinlock_irq)(codec->lock); snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS, dma_init); - spin_unlock_irq(codec->lock); } return 0; diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index b70f6f4ffe67..383def1f2af7 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -431,10 +431,10 @@ static int snd_bt87x_close(struct snd_pcm_substream *substream) { struct snd_bt87x *chip = snd_pcm_substream_chip(substream); - spin_lock_irq(&chip->reg_lock); - chip->reg_control |= CTL_A_PWRDN; - snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + chip->reg_control |= CTL_A_PWRDN; + snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); + } chip->substream = NULL; clear_bit(0, &chip->opened); @@ -466,20 +466,19 @@ static int snd_bt87x_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int decimation; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->reg_control &= ~(CTL_DA_SDR_MASK | CTL_DA_SBR); decimation = (ANALOG_CLOCK + runtime->rate / 4) / runtime->rate; chip->reg_control |= decimation << CTL_DA_SDR_SHIFT; if (runtime->format == SNDRV_PCM_FORMAT_S8) chip->reg_control |= CTL_DA_SBR; snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); - spin_unlock_irq(&chip->reg_lock); return 0; } static int snd_bt87x_start(struct snd_bt87x *chip) { - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); chip->current_line = 0; chip->reg_control |= CTL_FIFO_ENABLE | CTL_RISC_ENABLE | CTL_ACAP_EN; snd_bt87x_writel(chip, REG_RISC_STRT_ADD, chip->dma_risc.addr); @@ -487,18 +486,16 @@ static int snd_bt87x_start(struct snd_bt87x *chip) chip->line_bytes | (chip->lines << 16)); snd_bt87x_writel(chip, REG_INT_MASK, chip->interrupt_mask); snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); - spin_unlock(&chip->reg_lock); return 0; } static int snd_bt87x_stop(struct snd_bt87x *chip) { - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); chip->reg_control &= ~(CTL_FIFO_ENABLE | CTL_RISC_ENABLE | CTL_ACAP_EN); snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); snd_bt87x_writel(chip, REG_INT_MASK, 0); snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); - spin_unlock(&chip->reg_lock); return 0; } @@ -560,13 +557,12 @@ static int snd_bt87x_capture_volume_put(struct snd_kcontrol *kcontrol, u32 old_control; int changed; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); old_control = chip->reg_control; chip->reg_control = (chip->reg_control & ~CTL_A_GAIN_MASK) | (value->value.integer.value[0] << CTL_A_GAIN_SHIFT); snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); changed = old_control != chip->reg_control; - spin_unlock_irq(&chip->reg_lock); return changed; } @@ -596,13 +592,12 @@ static int snd_bt87x_capture_boost_put(struct snd_kcontrol *kcontrol, u32 old_control; int changed; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); old_control = chip->reg_control; chip->reg_control = (chip->reg_control & ~CTL_A_G2X) | (value->value.integer.value[0] ? CTL_A_G2X : 0); snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); changed = chip->reg_control != old_control; - spin_unlock_irq(&chip->reg_lock); return changed; } @@ -638,13 +633,12 @@ static int snd_bt87x_capture_source_put(struct snd_kcontrol *kcontrol, u32 old_control; int changed; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); old_control = chip->reg_control; chip->reg_control = (chip->reg_control & ~CTL_A_SEL_MASK) | (value->value.enumerated.item[0] << CTL_A_SEL_SHIFT); snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); changed = chip->reg_control != old_control; - spin_unlock_irq(&chip->reg_lock); return changed; } diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 242618793181..41774e2ef53f 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -332,16 +332,13 @@ unsigned int snd_ca0106_ptr_read(struct snd_ca0106 * emu, unsigned int reg, unsigned int chn) { - unsigned long flags; - unsigned int regptr, val; + unsigned int regptr; regptr = (reg << 16) | chn; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outl(regptr, emu->port + CA0106_PTR); - val = inl(emu->port + CA0106_DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; + return inl(emu->port + CA0106_DATA); } void snd_ca0106_ptr_write(struct snd_ca0106 *emu, @@ -350,14 +347,12 @@ void snd_ca0106_ptr_write(struct snd_ca0106 *emu, unsigned int data) { unsigned int regptr; - unsigned long flags; regptr = (reg << 16) | chn; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outl(regptr, emu->port + CA0106_PTR); outl(data, emu->port + CA0106_DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } int snd_ca0106_spi_write(struct snd_ca0106 * emu, @@ -451,24 +446,20 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb) { - unsigned long flags; unsigned int intr_enable; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); intr_enable = inl(emu->port + CA0106_INTE) | intrenb; outl(intr_enable, emu->port + CA0106_INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); } static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb) { - unsigned long flags; unsigned int intr_enable; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); intr_enable = inl(emu->port + CA0106_INTE) & ~intrenb; outl(intr_enable, emu->port + CA0106_INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); } @@ -1138,26 +1129,20 @@ static unsigned short snd_ca0106_ac97_read(struct snd_ac97 *ac97, unsigned short reg) { struct snd_ca0106 *emu = ac97->private_data; - unsigned long flags; - unsigned short val; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outb(reg, emu->port + CA0106_AC97ADDRESS); - val = inw(emu->port + CA0106_AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; + return inw(emu->port + CA0106_AC97DATA); } static void snd_ca0106_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) { struct snd_ca0106 *emu = ac97->private_data; - unsigned long flags; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outb(reg, emu->port + CA0106_AC97ADDRESS); outw(val, emu->port + CA0106_AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } static int snd_ca0106_ac97(struct snd_ca0106 *chip) diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c index c99603e137e5..c181e4954579 100644 --- a/sound/pci/ca0106/ca0106_proc.c +++ b/sound/pci/ca0106/ca0106_proc.c @@ -281,16 +281,14 @@ static void snd_ca0106_proc_reg_write32(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_ca0106 *emu = entry->private_data; - unsigned long flags; char line[64]; u32 reg, val; while (!snd_info_get_line(buffer, line, sizeof(line))) { if (sscanf(line, "%x %x", ®, &val) != 2) continue; if (reg < 0x40 && val <= 0xffffffff) { - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outl(val, emu->port + (reg & 0xfffffffc)); - spin_unlock_irqrestore(&emu->emu_lock, flags); } } } @@ -300,13 +298,13 @@ static void snd_ca0106_proc_reg_read32(struct snd_info_entry *entry, { struct snd_ca0106 *emu = entry->private_data; unsigned long value; - unsigned long flags; int i; + snd_iprintf(buffer, "Registers:\n\n"); for(i = 0; i < 0x20; i+=4) { - spin_lock_irqsave(&emu->emu_lock, flags); - value = inl(emu->port + i); - spin_unlock_irqrestore(&emu->emu_lock, flags); + scoped_guard(spinlock_irqsave, &emu->emu_lock) { + value = inl(emu->port + i); + } snd_iprintf(buffer, "Register %02X: %08lX\n", i, value); } } @@ -316,13 +314,13 @@ static void snd_ca0106_proc_reg_read16(struct snd_info_entry *entry, { struct snd_ca0106 *emu = entry->private_data; unsigned int value; - unsigned long flags; int i; + snd_iprintf(buffer, "Registers:\n\n"); for(i = 0; i < 0x20; i+=2) { - spin_lock_irqsave(&emu->emu_lock, flags); - value = inw(emu->port + i); - spin_unlock_irqrestore(&emu->emu_lock, flags); + scoped_guard(spinlock_irqsave, &emu->emu_lock) { + value = inw(emu->port + i); + } snd_iprintf(buffer, "Register %02X: %04X\n", i, value); } } @@ -332,13 +330,13 @@ static void snd_ca0106_proc_reg_read8(struct snd_info_entry *entry, { struct snd_ca0106 *emu = entry->private_data; unsigned int value; - unsigned long flags; int i; + snd_iprintf(buffer, "Registers:\n\n"); for(i = 0; i < 0x20; i+=1) { - spin_lock_irqsave(&emu->emu_lock, flags); - value = inb(emu->port + i); - spin_unlock_irqrestore(&emu->emu_lock, flags); + scoped_guard(spinlock_irqsave, &emu->emu_lock) { + value = inb(emu->port + i); + } snd_iprintf(buffer, "Register %02X: %02X\n", i, value); } } diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c index f9cec67f31ac..6efd93abddb5 100644 --- a/sound/pci/ca0106/ca_midi.c +++ b/sound/pci/ca0106/ca_midi.c @@ -45,58 +45,54 @@ static void ca_midi_interrupt(struct snd_ca_midi *midi, unsigned int status) return; } - spin_lock(&midi->input_lock); - if ((status & midi->ipr_rx) && ca_midi_input_avail(midi)) { - if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { - ca_midi_clear_rx(midi); - } else { - byte = ca_midi_read_data(midi); - if(midi->substream_input) - snd_rawmidi_receive(midi->substream_input, &byte, 1); - - + scoped_guard(spinlock, &midi->input_lock) { + if ((status & midi->ipr_rx) && ca_midi_input_avail(midi)) { + if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { + ca_midi_clear_rx(midi); + } else { + byte = ca_midi_read_data(midi); + if (midi->substream_input) + snd_rawmidi_receive(midi->substream_input, &byte, 1); + } } } - spin_unlock(&midi->input_lock); - spin_lock(&midi->output_lock); - if ((status & midi->ipr_tx) && ca_midi_output_ready(midi)) { - if (midi->substream_output && - snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { - ca_midi_write_data(midi, byte); - } else { - midi->interrupt_disable(midi,midi->tx_enable); + scoped_guard(spinlock, &midi->output_lock) { + if ((status & midi->ipr_tx) && ca_midi_output_ready(midi)) { + if (midi->substream_output && + snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { + ca_midi_write_data(midi, byte); + } else { + midi->interrupt_disable(midi, midi->tx_enable); + } } } - spin_unlock(&midi->output_lock); - } static void ca_midi_cmd(struct snd_ca_midi *midi, unsigned char cmd, int ack) { - unsigned long flags; int timeout, ok; - spin_lock_irqsave(&midi->input_lock, flags); - ca_midi_write_data(midi, 0x00); - /* ca_midi_clear_rx(midi); */ - - ca_midi_write_cmd(midi, cmd); - if (ack) { - ok = 0; - timeout = 10000; - while (!ok && timeout-- > 0) { - if (ca_midi_input_avail(midi)) { - if (ca_midi_read_data(midi) == midi->ack) - ok = 1; + scoped_guard(spinlock_irqsave, &midi->input_lock) { + ca_midi_write_data(midi, 0x00); + /* ca_midi_clear_rx(midi); */ + + ca_midi_write_cmd(midi, cmd); + if (ack) { + ok = 0; + timeout = 10000; + while (!ok && timeout-- > 0) { + if (ca_midi_input_avail(midi)) { + if (ca_midi_read_data(midi) == midi->ack) + ok = 1; + } } - } - if (!ok && ca_midi_read_data(midi) == midi->ack) + if (!ok && ca_midi_read_data(midi) == midi->ack) + ok = 1; + } else { ok = 1; - } else { - ok = 1; + } } - spin_unlock_irqrestore(&midi->input_lock, flags); if (!ok) pr_err("ca_midi_cmd: 0x%x failed at 0x%x (status = 0x%x, data = 0x%x)!!!\n", cmd, @@ -108,83 +104,69 @@ static void ca_midi_cmd(struct snd_ca_midi *midi, unsigned char cmd, int ack) static int ca_midi_input_open(struct snd_rawmidi_substream *substream) { struct snd_ca_midi *midi = substream->rmidi->private_data; - unsigned long flags; if (snd_BUG_ON(!midi->dev_id)) return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= CA_MIDI_MODE_INPUT; - midi->substream_input = substream; - if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - ca_midi_cmd(midi, midi->reset, 1); - ca_midi_cmd(midi, midi->enter_uart, 1); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); + scoped_guard(spinlock_irqsave, &midi->open_lock) { + midi->midi_mode |= CA_MIDI_MODE_INPUT; + midi->substream_input = substream; + if (midi->midi_mode & CA_MIDI_MODE_OUTPUT) + return 0; } + ca_midi_cmd(midi, midi->reset, 1); + ca_midi_cmd(midi, midi->enter_uart, 1); return 0; } static int ca_midi_output_open(struct snd_rawmidi_substream *substream) { struct snd_ca_midi *midi = substream->rmidi->private_data; - unsigned long flags; if (snd_BUG_ON(!midi->dev_id)) return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= CA_MIDI_MODE_OUTPUT; - midi->substream_output = substream; - if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - ca_midi_cmd(midi, midi->reset, 1); - ca_midi_cmd(midi, midi->enter_uart, 1); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); + scoped_guard(spinlock_irqsave, &midi->open_lock) { + midi->midi_mode |= CA_MIDI_MODE_OUTPUT; + midi->substream_output = substream; + if (midi->midi_mode & CA_MIDI_MODE_INPUT) + return 0; } + ca_midi_cmd(midi, midi->reset, 1); + ca_midi_cmd(midi, midi->enter_uart, 1); return 0; } static int ca_midi_input_close(struct snd_rawmidi_substream *substream) { struct snd_ca_midi *midi = substream->rmidi->private_data; - unsigned long flags; if (snd_BUG_ON(!midi->dev_id)) return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->interrupt_disable(midi,midi->rx_enable); - midi->midi_mode &= ~CA_MIDI_MODE_INPUT; - midi->substream_input = NULL; - if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - ca_midi_cmd(midi, midi->reset, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); + scoped_guard(spinlock_irqsave, &midi->open_lock) { + midi->interrupt_disable(midi, midi->rx_enable); + midi->midi_mode &= ~CA_MIDI_MODE_INPUT; + midi->substream_input = NULL; + if (midi->midi_mode & CA_MIDI_MODE_OUTPUT) + return 0; } + ca_midi_cmd(midi, midi->reset, 0); return 0; } static int ca_midi_output_close(struct snd_rawmidi_substream *substream) { struct snd_ca_midi *midi = substream->rmidi->private_data; - unsigned long flags; if (snd_BUG_ON(!midi->dev_id)) return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - - midi->interrupt_disable(midi,midi->tx_enable); - midi->midi_mode &= ~CA_MIDI_MODE_OUTPUT; - midi->substream_output = NULL; - - if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - ca_midi_cmd(midi, midi->reset, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); + scoped_guard(spinlock_irqsave, &midi->open_lock) { + midi->interrupt_disable(midi, midi->tx_enable); + midi->midi_mode &= ~CA_MIDI_MODE_OUTPUT; + midi->substream_output = NULL; + if (midi->midi_mode & CA_MIDI_MODE_INPUT) + return 0; } + ca_midi_cmd(midi, midi->reset, 0); return 0; } @@ -205,7 +187,6 @@ static void ca_midi_input_trigger(struct snd_rawmidi_substream *substream, int u static void ca_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { struct snd_ca_midi *midi = substream->rmidi->private_data; - unsigned long flags; if (snd_BUG_ON(!midi->dev_id)) return; @@ -214,25 +195,23 @@ static void ca_midi_output_trigger(struct snd_rawmidi_substream *substream, int int max = 4; unsigned char byte; - spin_lock_irqsave(&midi->output_lock, flags); + scoped_guard(spinlock_irqsave, &midi->output_lock) { - /* try to send some amount of bytes here before interrupts */ - while (max > 0) { - if (ca_midi_output_ready(midi)) { - if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT) || - snd_rawmidi_transmit(substream, &byte, 1) != 1) { - /* no more data */ - spin_unlock_irqrestore(&midi->output_lock, flags); - return; + /* try to send some amount of bytes here before interrupts */ + while (max > 0) { + if (ca_midi_output_ready(midi)) { + if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT) || + snd_rawmidi_transmit(substream, &byte, 1) != 1) { + /* no more data */ + return; + } + ca_midi_write_data(midi, byte); + max--; + } else { + break; } - ca_midi_write_data(midi, byte); - max--; - } else { - break; } } - - spin_unlock_irqrestore(&midi->output_lock, flags); midi->interrupt_enable(midi,midi->tx_enable); } else { diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index c4ee550d7c96..0666be543474 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -664,14 +664,11 @@ static int snd_cmipci_playback2_hw_params(struct snd_pcm_substream *substream, { struct cmipci *cm = snd_pcm_substream_chip(substream); if (params_channels(hw_params) > 2) { - mutex_lock(&cm->open_mutex); - if (cm->opened[CM_CH_PLAY]) { - mutex_unlock(&cm->open_mutex); + guard(mutex)(&cm->open_mutex); + if (cm->opened[CM_CH_PLAY]) return -EBUSY; - } /* reserve the channel A */ cm->opened[CM_CH_PLAY] = CM_OPEN_PLAYBACK_MULTI; - mutex_unlock(&cm->open_mutex); } return 0; } @@ -715,7 +712,7 @@ static int set_dac_channels(struct cmipci *cm, struct cmipci_pcm *rec, int chann } if (cm->can_multi_ch) { - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); if (channels > 2) { snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); @@ -738,7 +735,6 @@ static int set_dac_channels(struct cmipci *cm, struct cmipci_pcm *rec, int chann snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); else snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); - spin_unlock_irq(&cm->reg_lock); } return 0; } @@ -779,7 +775,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, period_size = (period_size * runtime->channels) / 2; } - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); /* set buffer address */ reg = rec->ch ? CM_REG_CH1_FRAME1 : CM_REG_CH0_FRAME1; @@ -845,7 +841,6 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, } rec->running = 0; - spin_unlock_irq(&cm->reg_lock); return 0; } @@ -857,14 +852,13 @@ static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec, int cmd) { unsigned int inthld, chen, reset, pause; - int result = 0; inthld = CM_CH0_INT_EN << rec->ch; chen = CM_CHEN0 << rec->ch; reset = CM_RST_CH0 << rec->ch; pause = CM_PAUSE0 << rec->ch; - spin_lock(&cm->reg_lock); + guard(spinlock)(&cm->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: rec->running = 1; @@ -896,11 +890,9 @@ static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec, snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); break; default: - result = -EINVAL; - break; + return -EINVAL; } - spin_unlock(&cm->reg_lock); - return result; + return 0; } /* @@ -990,10 +982,9 @@ static int snd_cmipci_spdif_default_get(struct snd_kcontrol *kcontrol, struct cmipci *chip = snd_kcontrol_chip(kcontrol); int i; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); for (i = 0; i < 4; i++) ucontrol->value.iec958.status[i] = (chip->dig_status >> (i * 8)) & 0xff; - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1005,12 +996,11 @@ static int snd_cmipci_spdif_default_put(struct snd_kcontrol *kcontrol, unsigned int val; val = 0; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); for (i = 0; i < 4; i++) val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8); change = val != chip->dig_status; chip->dig_status = val; - spin_unlock_irq(&chip->reg_lock); return change; } @@ -1064,10 +1054,9 @@ static int snd_cmipci_spdif_stream_get(struct snd_kcontrol *kcontrol, struct cmipci *chip = snd_kcontrol_chip(kcontrol); int i; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); for (i = 0; i < 4; i++) ucontrol->value.iec958.status[i] = (chip->dig_pcm_status >> (i * 8)) & 0xff; - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1079,12 +1068,11 @@ static int snd_cmipci_spdif_stream_put(struct snd_kcontrol *kcontrol, unsigned int val; val = 0; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); for (i = 0; i < 4; i++) val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8); change = val != chip->dig_pcm_status; chip->dig_pcm_status = val; - spin_unlock_irq(&chip->reg_lock); return change; } @@ -1228,7 +1216,7 @@ static int setup_spdif_playback(struct cmipci *cm, struct snd_pcm_substream *sub return err; } - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); cm->spdif_playback_avail = up; if (up) { /* they are controlled via "IEC958 Output Switch" */ @@ -1254,7 +1242,6 @@ static int setup_spdif_playback(struct cmipci *cm, struct snd_pcm_substream *sub snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); setup_ac3(cm, subs, 0, 0); } - spin_unlock_irq(&cm->reg_lock); return 0; } @@ -1320,32 +1307,32 @@ static void snd_cmipci_silence_hack(struct cmipci *cm, struct cmipci_pcm *rec) /* configure for 16 bits, 2 channels, 8 kHz */ if (runtime->channels > 2) set_dac_channels(cm, rec, 2); - spin_lock_irq(&cm->reg_lock); - val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); - val &= ~(CM_ASFC_MASK << (rec->ch * 3)); - val |= (4 << CM_ASFC_SHIFT) << (rec->ch * 3); - snd_cmipci_write(cm, CM_REG_FUNCTRL1, val); - val = snd_cmipci_read(cm, CM_REG_CHFORMAT); - val &= ~(CM_CH0FMT_MASK << (rec->ch * 2)); - val |= (3 << CM_CH0FMT_SHIFT) << (rec->ch * 2); - if (cm->can_96k) - val &= ~(CM_CH0_SRATE_MASK << (rec->ch * 2)); - snd_cmipci_write(cm, CM_REG_CHFORMAT, val); + scoped_guard(spinlock_irq, &cm->reg_lock) { + val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); + val &= ~(CM_ASFC_MASK << (rec->ch * 3)); + val |= (4 << CM_ASFC_SHIFT) << (rec->ch * 3); + snd_cmipci_write(cm, CM_REG_FUNCTRL1, val); + val = snd_cmipci_read(cm, CM_REG_CHFORMAT); + val &= ~(CM_CH0FMT_MASK << (rec->ch * 2)); + val |= (3 << CM_CH0FMT_SHIFT) << (rec->ch * 2); + if (cm->can_96k) + val &= ~(CM_CH0_SRATE_MASK << (rec->ch * 2)); + snd_cmipci_write(cm, CM_REG_CHFORMAT, val); - /* start stream (we don't need interrupts) */ - cm->ctrl |= CM_CHEN0 << rec->ch; - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); - spin_unlock_irq(&cm->reg_lock); + /* start stream (we don't need interrupts) */ + cm->ctrl |= CM_CHEN0 << rec->ch; + snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); + } msleep(1); /* stop and reset stream */ - spin_lock_irq(&cm->reg_lock); - cm->ctrl &= ~(CM_CHEN0 << rec->ch); - val = CM_RST_CH0 << rec->ch; - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | val); - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~val); - spin_unlock_irq(&cm->reg_lock); + scoped_guard(spinlock_irq, &cm->reg_lock) { + cm->ctrl &= ~(CM_CHEN0 << rec->ch); + val = CM_RST_CH0 << rec->ch; + snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | val); + snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~val); + } rec->needs_silencing = 0; } @@ -1379,20 +1366,19 @@ static int snd_cmipci_capture_spdif_prepare(struct snd_pcm_substream *substream) { struct cmipci *cm = snd_pcm_substream_chip(substream); - spin_lock_irq(&cm->reg_lock); - snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF); - if (cm->can_96k) { - if (substream->runtime->rate > 48000) - snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); + scoped_guard(spinlock_irq, &cm->reg_lock) { + snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF); + if (cm->can_96k) { + if (substream->runtime->rate > 48000) + snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); + else + snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); + } + if (snd_pcm_format_width(substream->runtime->format) > 16) + snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); else - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); + snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); } - if (snd_pcm_format_width(substream->runtime->format) > 16) - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); - else - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); - - spin_unlock_irq(&cm->reg_lock); return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_CAPT], substream); } @@ -1401,10 +1387,9 @@ static int snd_cmipci_capture_spdif_hw_free(struct snd_pcm_substream *subs) { struct cmipci *cm = snd_pcm_substream_chip(subs); - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF); snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); - spin_unlock_irq(&cm->reg_lock); return 0; } @@ -1424,14 +1409,14 @@ static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id) return IRQ_NONE; /* acknowledge interrupt */ - spin_lock(&cm->reg_lock); - if (status & CM_CHINT0) - mask |= CM_CH0_INT_EN; - if (status & CM_CHINT1) - mask |= CM_CH1_INT_EN; - snd_cmipci_clear_bit(cm, CM_REG_INT_HLDCLR, mask); - snd_cmipci_set_bit(cm, CM_REG_INT_HLDCLR, mask); - spin_unlock(&cm->reg_lock); + scoped_guard(spinlock, &cm->reg_lock) { + if (status & CM_CHINT0) + mask |= CM_CH0_INT_EN; + if (status & CM_CHINT1) + mask |= CM_CH1_INT_EN; + snd_cmipci_clear_bit(cm, CM_REG_INT_HLDCLR, mask); + snd_cmipci_set_bit(cm, CM_REG_INT_HLDCLR, mask); + } if (cm->rmidi && (status & CM_UARTINT)) snd_mpu401_uart_interrupt(irq, cm->rmidi->private_data); @@ -1582,21 +1567,17 @@ static int open_device_check(struct cmipci *cm, int mode, struct snd_pcm_substre * pcm framework doesn't pass file pointer before actually opened, * we can't know whether blocking mode or not in open callback.. */ - mutex_lock(&cm->open_mutex); - if (cm->opened[ch]) { - mutex_unlock(&cm->open_mutex); + guard(mutex)(&cm->open_mutex); + if (cm->opened[ch]) return -EBUSY; - } cm->opened[ch] = mode; cm->channel[ch].substream = subs; if (! (mode & CM_OPEN_DAC)) { /* disable dual DAC mode */ cm->channel[ch].is_dac = 0; - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENDBDAC); - spin_unlock_irq(&cm->reg_lock); } - mutex_unlock(&cm->open_mutex); return 0; } @@ -1604,7 +1585,7 @@ static void close_device_check(struct cmipci *cm, int mode) { int ch = mode & CM_OPEN_CH_MASK; - mutex_lock(&cm->open_mutex); + guard(mutex)(&cm->open_mutex); if (cm->opened[ch] == mode) { if (cm->channel[ch].substream) { snd_cmipci_ch_reset(cm, ch); @@ -1615,12 +1596,10 @@ static void close_device_check(struct cmipci *cm, int mode) if (! cm->channel[ch].is_dac) { /* enable dual DAC mode again */ cm->channel[ch].is_dac = 1; - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_ENDBDAC); - spin_unlock_irq(&cm->reg_lock); } } - mutex_unlock(&cm->open_mutex); } /* @@ -1685,7 +1664,7 @@ static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream) if (err < 0) return err; runtime->hw = snd_cmipci_playback2; - mutex_lock(&cm->open_mutex); + guard(mutex)(&cm->open_mutex); if (! cm->opened[CM_CH_PLAY]) { if (cm->can_multi_ch) { runtime->hw.channels_max = cm->max_channels; @@ -1697,7 +1676,6 @@ static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream) snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_8); } } - mutex_unlock(&cm->open_mutex); if (cm->chip_version == 68) { runtime->hw.rates |= SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000; @@ -2010,7 +1988,7 @@ static int snd_cmipci_get_volume(struct snd_kcontrol *kcontrol, int val; cmipci_sb_reg_decode(®, kcontrol->private_value); - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); val = (snd_cmipci_mixer_read(cm, reg.left_reg) >> reg.left_shift) & reg.mask; if (reg.invert) val = reg.mask - val; @@ -2021,7 +1999,6 @@ static int snd_cmipci_get_volume(struct snd_kcontrol *kcontrol, val = reg.mask - val; ucontrol->value.integer.value[1] = val; } - spin_unlock_irq(&cm->reg_lock); return 0; } @@ -2045,7 +2022,7 @@ static int snd_cmipci_put_volume(struct snd_kcontrol *kcontrol, right <<= reg.right_shift; } else right = 0; - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); oleft = snd_cmipci_mixer_read(cm, reg.left_reg); left |= oleft & ~(reg.mask << reg.left_shift); change = left != oleft; @@ -2060,7 +2037,6 @@ static int snd_cmipci_put_volume(struct snd_kcontrol *kcontrol, snd_cmipci_mixer_write(cm, reg.right_reg, right); } else snd_cmipci_mixer_write(cm, reg.left_reg, left); - spin_unlock_irq(&cm->reg_lock); return change; } @@ -2092,10 +2068,9 @@ static int snd_cmipci_get_input_sw(struct snd_kcontrol *kcontrol, int val1, val2; cmipci_sb_reg_decode(®, kcontrol->private_value); - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); val1 = snd_cmipci_mixer_read(cm, reg.left_reg); val2 = snd_cmipci_mixer_read(cm, reg.right_reg); - spin_unlock_irq(&cm->reg_lock); ucontrol->value.integer.value[0] = (val1 >> reg.left_shift) & 1; ucontrol->value.integer.value[1] = (val2 >> reg.left_shift) & 1; ucontrol->value.integer.value[2] = (val1 >> reg.right_shift) & 1; @@ -2112,7 +2087,7 @@ static int snd_cmipci_put_input_sw(struct snd_kcontrol *kcontrol, int val1, val2, oval1, oval2; cmipci_sb_reg_decode(®, kcontrol->private_value); - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); oval1 = snd_cmipci_mixer_read(cm, reg.left_reg); oval2 = snd_cmipci_mixer_read(cm, reg.right_reg); val1 = oval1 & ~((1 << reg.left_shift) | (1 << reg.right_shift)); @@ -2124,7 +2099,6 @@ static int snd_cmipci_put_input_sw(struct snd_kcontrol *kcontrol, change = val1 != oval1 || val2 != oval2; snd_cmipci_mixer_write(cm, reg.left_reg, val1); snd_cmipci_mixer_write(cm, reg.right_reg, val2); - spin_unlock_irq(&cm->reg_lock); return change; } @@ -2182,7 +2156,7 @@ static int snd_cmipci_get_native_mixer(struct snd_kcontrol *kcontrol, unsigned char oreg, val; cmipci_sb_reg_decode(®, kcontrol->private_value); - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); oreg = inb(cm->iobase + reg.left_reg); val = (oreg >> reg.left_shift) & reg.mask; if (reg.invert) @@ -2194,7 +2168,6 @@ static int snd_cmipci_get_native_mixer(struct snd_kcontrol *kcontrol, val = reg.mask - val; ucontrol->value.integer.value[1] = val; } - spin_unlock_irq(&cm->reg_lock); return 0; } @@ -2206,7 +2179,7 @@ static int snd_cmipci_put_native_mixer(struct snd_kcontrol *kcontrol, unsigned char oreg, nreg, val; cmipci_sb_reg_decode(®, kcontrol->private_value); - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); oreg = inb(cm->iobase + reg.left_reg); val = ucontrol->value.integer.value[0] & reg.mask; if (reg.invert) @@ -2221,7 +2194,6 @@ static int snd_cmipci_put_native_mixer(struct snd_kcontrol *kcontrol, nreg |= (val << reg.right_shift); } outb(nreg, cm->iobase + reg.left_reg); - spin_unlock_irq(&cm->reg_lock); return (nreg != oreg); } @@ -2308,10 +2280,9 @@ static int _snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol, unsigned int val; struct cmipci *cm = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); if (args->ac3_sensitive && cm->mixer_insensitive) { ucontrol->value.integer.value[0] = 0; - spin_unlock_irq(&cm->reg_lock); return 0; } if (args->is_byte) @@ -2319,7 +2290,6 @@ static int _snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol, else val = snd_cmipci_read(cm, args->reg); ucontrol->value.integer.value[0] = ((val & args->mask) == args->mask_on) ? 1 : 0; - spin_unlock_irq(&cm->reg_lock); return 0; } @@ -2341,10 +2311,9 @@ static int _snd_cmipci_uswitch_put(struct snd_kcontrol *kcontrol, int change; struct cmipci *cm = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); if (args->ac3_sensitive && cm->mixer_insensitive) { /* ignored */ - spin_unlock_irq(&cm->reg_lock); return 0; } if (args->is_byte) @@ -2364,7 +2333,6 @@ static int _snd_cmipci_uswitch_put(struct snd_kcontrol *kcontrol, else snd_cmipci_write(cm, args->reg, val); } - spin_unlock_irq(&cm->reg_lock); return change; } @@ -2497,9 +2465,8 @@ static int snd_cmipci_line_in_mode_get(struct snd_kcontrol *kcontrol, { struct cmipci *cm = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); ucontrol->value.enumerated.item[0] = get_line_in_mode(cm); - spin_unlock_irq(&cm->reg_lock); return 0; } @@ -2509,7 +2476,7 @@ static int snd_cmipci_line_in_mode_put(struct snd_kcontrol *kcontrol, struct cmipci *cm = snd_kcontrol_chip(kcontrol); int change; - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); if (ucontrol->value.enumerated.item[0] == 2) change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CENTR2LIN | CM_BASE2LIN); else @@ -2518,7 +2485,6 @@ static int snd_cmipci_line_in_mode_put(struct snd_kcontrol *kcontrol, change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_REAR2LIN); else change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_REAR2LIN); - spin_unlock_irq(&cm->reg_lock); return change; } @@ -2534,11 +2500,11 @@ static int snd_cmipci_mic_in_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct cmipci *cm = snd_kcontrol_chip(kcontrol); + /* same bit as spdi_phase */ - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); ucontrol->value.enumerated.item[0] = (snd_cmipci_read_b(cm, CM_REG_MISC) & CM_SPDIF_INVERSE) ? 1 : 0; - spin_unlock_irq(&cm->reg_lock); return 0; } @@ -2548,12 +2514,11 @@ static int snd_cmipci_mic_in_mode_put(struct snd_kcontrol *kcontrol, struct cmipci *cm = snd_kcontrol_chip(kcontrol); int change; - spin_lock_irq(&cm->reg_lock); + guard(spinlock_irq)(&cm->reg_lock); if (ucontrol->value.enumerated.item[0]) change = snd_cmipci_set_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE); else change = snd_cmipci_clear_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE); - spin_unlock_irq(&cm->reg_lock); return change; } @@ -2635,9 +2600,9 @@ static int snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device) strscpy(card->mixername, "CMedia PCI"); - spin_lock_irq(&cm->reg_lock); - snd_cmipci_mixer_write(cm, 0x00, 0x00); /* mixer reset */ - spin_unlock_irq(&cm->reg_lock); + scoped_guard(spinlock_irq, &cm->reg_lock) { + snd_cmipci_mixer_write(cm, 0x00, 0x00); /* mixer reset */ + } for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_mixers); idx++) { if (cm->chip_version == 68) { // 8768 has no PCM volume diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 31cb9cbe2f03..d00b2c9fb1e3 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -651,7 +651,7 @@ static int snd_cs4281_trigger(struct snd_pcm_substream *substream, int cmd) struct cs4281_dma *dma = substream->runtime->private_data; struct cs4281 *chip = snd_pcm_substream_chip(substream); - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_PAUSE_PUSH: dma->valDCR |= BA0_DCR_MSK; @@ -678,13 +678,11 @@ static int snd_cs4281_trigger(struct snd_pcm_substream *substream, int cmd) dma->valFCR &= ~BA0_FCR_FEN; break; default: - spin_unlock(&chip->reg_lock); return -EINVAL; } snd_cs4281_pokeBA0(chip, dma->regDMR, dma->valDMR); snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR); snd_cs4281_pokeBA0(chip, dma->regDCR, dma->valDCR); - spin_unlock(&chip->reg_lock); return 0; } @@ -782,9 +780,8 @@ static int snd_cs4281_playback_prepare(struct snd_pcm_substream *substream) struct cs4281_dma *dma = runtime->private_data; struct cs4281 *chip = snd_pcm_substream_chip(substream); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); snd_cs4281_mode(chip, dma, runtime, 0, 1); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -794,9 +791,8 @@ static int snd_cs4281_capture_prepare(struct snd_pcm_substream *substream) struct cs4281_dma *dma = runtime->private_data; struct cs4281 *chip = snd_pcm_substream_chip(substream); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); snd_cs4281_mode(chip, dma, runtime, 1, 1); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1580,7 +1576,7 @@ static int snd_cs4281_midi_input_open(struct snd_rawmidi_substream *substream) { struct cs4281 *chip = substream->rmidi->private_data; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->midcr |= BA0_MIDCR_RXE; chip->midi_input = substream; if (!(chip->uartm & CS4281_MODE_OUTPUT)) { @@ -1588,7 +1584,6 @@ static int snd_cs4281_midi_input_open(struct snd_rawmidi_substream *substream) } else { snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); } - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1596,7 +1591,7 @@ static int snd_cs4281_midi_input_close(struct snd_rawmidi_substream *substream) { struct cs4281 *chip = substream->rmidi->private_data; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->midcr &= ~(BA0_MIDCR_RXE | BA0_MIDCR_RIE); chip->midi_input = NULL; if (!(chip->uartm & CS4281_MODE_OUTPUT)) { @@ -1605,7 +1600,6 @@ static int snd_cs4281_midi_input_close(struct snd_rawmidi_substream *substream) snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); } chip->uartm &= ~CS4281_MODE_INPUT; - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1613,7 +1607,7 @@ static int snd_cs4281_midi_output_open(struct snd_rawmidi_substream *substream) { struct cs4281 *chip = substream->rmidi->private_data; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->uartm |= CS4281_MODE_OUTPUT; chip->midcr |= BA0_MIDCR_TXE; chip->midi_output = substream; @@ -1622,7 +1616,6 @@ static int snd_cs4281_midi_output_open(struct snd_rawmidi_substream *substream) } else { snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); } - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1630,7 +1623,7 @@ static int snd_cs4281_midi_output_close(struct snd_rawmidi_substream *substream) { struct cs4281 *chip = substream->rmidi->private_data; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->midcr &= ~(BA0_MIDCR_TXE | BA0_MIDCR_TIE); chip->midi_output = NULL; if (!(chip->uartm & CS4281_MODE_INPUT)) { @@ -1639,16 +1632,14 @@ static int snd_cs4281_midi_output_close(struct snd_rawmidi_substream *substream) snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); } chip->uartm &= ~CS4281_MODE_OUTPUT; - spin_unlock_irq(&chip->reg_lock); return 0; } static void snd_cs4281_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct cs4281 *chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (up) { if ((chip->midcr & BA0_MIDCR_RIE) == 0) { chip->midcr |= BA0_MIDCR_RIE; @@ -1660,16 +1651,14 @@ static void snd_cs4281_midi_input_trigger(struct snd_rawmidi_substream *substrea snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); } } - spin_unlock_irqrestore(&chip->reg_lock, flags); } static void snd_cs4281_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct cs4281 *chip = substream->rmidi->private_data; unsigned char byte; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (up) { if ((chip->midcr & BA0_MIDCR_TIE) == 0) { chip->midcr |= BA0_MIDCR_TIE; @@ -1690,7 +1679,6 @@ static void snd_cs4281_midi_output_trigger(struct snd_rawmidi_substream *substre snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); } } - spin_unlock_irqrestore(&chip->reg_lock, flags); } static const struct snd_rawmidi_ops snd_cs4281_midi_output = @@ -1743,10 +1731,12 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id) } if (status & (BA0_HISR_DMA(0)|BA0_HISR_DMA(1)|BA0_HISR_DMA(2)|BA0_HISR_DMA(3))) { - for (dma = 0; dma < 4; dma++) + for (dma = 0; dma < 4; dma++) { + bool period_elapsed = false; + cdma = &chip->dma[dma]; + if (status & BA0_HISR_DMA(dma)) { - cdma = &chip->dma[dma]; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); /* ack DMA IRQ */ val = snd_cs4281_peekBA0(chip, cdma->regHDSR); /* workaround, sometimes CS4281 acknowledges */ @@ -1755,24 +1745,24 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id) if ((val & BA0_HDSR_DHTC) && !(cdma->frag & 1)) { cdma->frag--; chip->spurious_dhtc_irq++; - spin_unlock(&chip->reg_lock); continue; } if ((val & BA0_HDSR_DTC) && (cdma->frag & 1)) { cdma->frag--; chip->spurious_dtc_irq++; - spin_unlock(&chip->reg_lock); continue; } - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(cdma->substream); + period_elapsed = true; } + if (period_elapsed) + snd_pcm_period_elapsed(cdma->substream); + } } if ((status & BA0_HISR_MIDI) && chip->rmidi) { unsigned char c; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_RBE) == 0) { c = snd_cs4281_peekBA0(chip, BA0_MIDRP); if ((chip->midcr & BA0_MIDCR_RIE) == 0) @@ -1789,7 +1779,6 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id) } snd_cs4281_pokeBA0(chip, BA0_MIDWP, c); } - spin_unlock(&chip->reg_lock); } /* EOI to the PCI part... reenables interrupts */ @@ -1805,7 +1794,6 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id) static void snd_cs4281_opl3_command(struct snd_opl3 *opl3, unsigned short cmd, unsigned char val) { - unsigned long flags; struct cs4281 *chip = opl3->private_data; void __iomem *port; @@ -1814,15 +1802,13 @@ static void snd_cs4281_opl3_command(struct snd_opl3 *opl3, unsigned short cmd, else port = chip->ba0 + BA0_B0AP; /* left port */ - spin_lock_irqsave(&opl3->reg_lock, flags); + guard(spinlock_irqsave)(&opl3->reg_lock); writel((unsigned int)cmd, port); udelay(10); writel((unsigned int)val, port + 4); udelay(30); - - spin_unlock_irqrestore(&opl3->reg_lock, flags); } static int __snd_cs4281_probe(struct pci_dev *pci, diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 85a7988cf822..b96ab7fd464c 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -707,7 +707,6 @@ static void snd_cs46xx_proc_stop(struct snd_cs46xx *chip) static void snd_cs46xx_set_play_sample_rate(struct snd_cs46xx *chip, unsigned int rate) { - unsigned long flags; unsigned int tmp1, tmp2; unsigned int phiIncr; unsigned int correctionPerGOF, correctionPerSec; @@ -744,16 +743,14 @@ static void snd_cs46xx_set_play_sample_rate(struct snd_cs46xx *chip, unsigned in /* * Fill in the SampleRateConverter control block. */ - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); snd_cs46xx_poke(chip, BA1_PSRC, ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF)); snd_cs46xx_poke(chip, BA1_PPI, phiIncr); - spin_unlock_irqrestore(&chip->reg_lock, flags); } static void snd_cs46xx_set_capture_sample_rate(struct snd_cs46xx *chip, unsigned int rate) { - unsigned long flags; unsigned int phiIncr, coeffIncr, tmp1, tmp2; unsigned int correctionPerGOF, correctionPerSec, initialDelay; unsigned int frameGroupLength, cnt; @@ -818,14 +815,14 @@ static void snd_cs46xx_set_capture_sample_rate(struct snd_cs46xx *chip, unsigned /* * Fill in the VariDecimate control block. */ - spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs46xx_poke(chip, BA1_CSRC, - ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF)); - snd_cs46xx_poke(chip, BA1_CCI, coeffIncr); - snd_cs46xx_poke(chip, BA1_CD, - (((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80); - snd_cs46xx_poke(chip, BA1_CPI, phiIncr); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_cs46xx_poke(chip, BA1_CSRC, + ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF)); + snd_cs46xx_poke(chip, BA1_CCI, coeffIncr); + snd_cs46xx_poke(chip, BA1_CD, + (((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80); + snd_cs46xx_poke(chip, BA1_CPI, phiIncr); + } /* * Figure out the frame group length for the write back task. Basically, @@ -848,13 +845,12 @@ static void snd_cs46xx_set_capture_sample_rate(struct snd_cs46xx *chip, unsigned /* * Fill in the WriteBack control block. */ - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); snd_cs46xx_poke(chip, BA1_CFG1, frameGroupLength); snd_cs46xx_poke(chip, BA1_CFG2, (0x00800000 | frameGroupLength)); snd_cs46xx_poke(chip, BA1_CCST, 0x0000FFFF); snd_cs46xx_poke(chip, BA1_CSPB, ((65536 * rate) / 24000)); snd_cs46xx_poke(chip, (BA1_CSPB + 4), 0x0000FFFF); - spin_unlock_irqrestore(&chip->reg_lock, flags); } /* @@ -969,15 +965,14 @@ static int snd_cs46xx_playback_trigger(struct snd_pcm_substream *substream, if (substream->runtime->periods != CS46XX_FRAGS) snd_cs46xx_playback_transfer(substream); #else - spin_lock(&chip->reg_lock); - if (substream->runtime->periods != CS46XX_FRAGS) - snd_cs46xx_playback_transfer(substream); - { unsigned int tmp; - tmp = snd_cs46xx_peek(chip, BA1_PCTL); - tmp &= 0x0000ffff; - snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp); + scoped_guard(spinlock, &chip->reg_lock) { + unsigned int tmp; + if (substream->runtime->periods != CS46XX_FRAGS) + snd_cs46xx_playback_transfer(substream); + tmp = snd_cs46xx_peek(chip, BA1_PCTL); + tmp &= 0x0000ffff; + snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp); } - spin_unlock(&chip->reg_lock); #endif break; case SNDRV_PCM_TRIGGER_STOP: @@ -990,13 +985,12 @@ static int snd_cs46xx_playback_trigger(struct snd_pcm_substream *substream, if (!cpcm->pcm_channel->unlinked) cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel); #else - spin_lock(&chip->reg_lock); - { unsigned int tmp; - tmp = snd_cs46xx_peek(chip, BA1_PCTL); - tmp &= 0x0000ffff; - snd_cs46xx_poke(chip, BA1_PCTL, tmp); + scoped_guard(spinlock, &chip->reg_lock) { + unsigned int tmp; + tmp = snd_cs46xx_peek(chip, BA1_PCTL); + tmp &= 0x0000ffff; + snd_cs46xx_poke(chip, BA1_PCTL, tmp); } - spin_unlock(&chip->reg_lock); #endif break; default: @@ -1012,9 +1006,8 @@ static int snd_cs46xx_capture_trigger(struct snd_pcm_substream *substream, { struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); unsigned int tmp; - int result = 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -1029,12 +1022,9 @@ static int snd_cs46xx_capture_trigger(struct snd_pcm_substream *substream, snd_cs46xx_poke(chip, BA1_CCTL, tmp); break; default: - result = -EINVAL; - break; + return -EINVAL; } - spin_unlock(&chip->reg_lock); - - return result; + return 0; } #ifdef CONFIG_SND_CS46XX_NEW_DSP @@ -1093,24 +1083,17 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, if (snd_BUG_ON(!sample_rate)) return -ENXIO; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); - if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) { - mutex_unlock(&chip->spos_mutex); + if (_cs46xx_adjust_sample_rate(chip, cpcm, sample_rate)) return -ENXIO; - } snd_BUG_ON(!cpcm->pcm_channel); - if (!cpcm->pcm_channel) { - mutex_unlock(&chip->spos_mutex); + if (!cpcm->pcm_channel) return -ENXIO; - } - - if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size)) { - mutex_unlock(&chip->spos_mutex); + if (cs46xx_dsp_pcm_channel_set_period(chip, cpcm->pcm_channel, period_size)) return -EINVAL; - } dev_dbg(chip->card->dev, "period_size (%d), periods (%d) buffer_size(%d)\n", @@ -1144,12 +1127,8 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, if (runtime->dma_area == cpcm->hw_buf.area) snd_pcm_set_runtime_buffer(substream, NULL); err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (err < 0) { -#ifdef CONFIG_SND_CS46XX_NEW_DSP - mutex_unlock(&chip->spos_mutex); -#endif + if (err < 0) return err; - } #ifdef CONFIG_SND_CS46XX_NEW_DSP if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) { @@ -1169,10 +1148,6 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, } -#ifdef CONFIG_SND_CS46XX_NEW_DSP - mutex_unlock(&chip->spos_mutex); -#endif - return 0; } @@ -1386,7 +1361,7 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id) if ((status1 & HISR_MIDI) && chip->rmidi) { unsigned char c; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_RBE) == 0) { c = snd_cs46xx_peekBA0(chip, BA0_MIDRP); if ((chip->midcr & MIDCR_RIE) == 0) @@ -1403,7 +1378,6 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id) } snd_cs46xx_pokeBA0(chip, BA0_MIDWP, c); } - spin_unlock(&chip->reg_lock); } /* * EOI to the PCI part....reenables interrupts @@ -1495,16 +1469,14 @@ static int _cs46xx_playback_open_channel (struct snd_pcm_substream *substream,in cpcm->substream = substream; #ifdef CONFIG_SND_CS46XX_NEW_DSP - mutex_lock(&chip->spos_mutex); - cpcm->pcm_channel = NULL; - cpcm->pcm_channel_id = pcm_channel_id; - + scoped_guard(mutex, &chip->spos_mutex) { + cpcm->pcm_channel = NULL; + cpcm->pcm_channel_id = pcm_channel_id; + } snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_sizes); - - mutex_unlock(&chip->spos_mutex); #else chip->playback_pcm = cpcm; /* HACK */ #endif @@ -1541,9 +1513,9 @@ static int snd_cs46xx_playback_open_iec958(struct snd_pcm_substream *substream) dev_dbg(chip->card->dev, "open raw iec958 channel\n"); - mutex_lock(&chip->spos_mutex); - cs46xx_iec958_pre_open (chip); - mutex_unlock(&chip->spos_mutex); + scoped_guard(mutex, &chip->spos_mutex) { + cs46xx_iec958_pre_open(chip); + } return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL); } @@ -1559,9 +1531,9 @@ static int snd_cs46xx_playback_close_iec958(struct snd_pcm_substream *substream) err = snd_cs46xx_playback_close(substream); - mutex_lock(&chip->spos_mutex); - cs46xx_iec958_post_close (chip); - mutex_unlock(&chip->spos_mutex); + scoped_guard(mutex, &chip->spos_mutex) { + cs46xx_iec958_post_close(chip); + } return err; } @@ -1602,12 +1574,12 @@ static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream) if (!cpcm) return -ENXIO; #ifdef CONFIG_SND_CS46XX_NEW_DSP - mutex_lock(&chip->spos_mutex); - if (cpcm->pcm_channel) { - cs46xx_dsp_destroy_pcm_channel(chip,cpcm->pcm_channel); - cpcm->pcm_channel = NULL; + scoped_guard(mutex, &chip->spos_mutex) { + if (cpcm->pcm_channel) { + cs46xx_dsp_destroy_pcm_channel(chip, cpcm->pcm_channel); + cpcm->pcm_channel = NULL; + } } - mutex_unlock(&chip->spos_mutex); #else chip->playback_pcm = NULL; #endif @@ -1982,15 +1954,15 @@ static int snd_cs46xx_iec958_put(struct snd_kcontrol *kcontrol, switch (kcontrol->private_value) { case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT: - mutex_lock(&chip->spos_mutex); - change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED); - if (ucontrol->value.integer.value[0] && !change) - cs46xx_dsp_enable_spdif_out(chip); - else if (change && !ucontrol->value.integer.value[0]) - cs46xx_dsp_disable_spdif_out(chip); - - res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED)); - mutex_unlock(&chip->spos_mutex); + scoped_guard(mutex, &chip->spos_mutex) { + change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED); + if (ucontrol->value.integer.value[0] && !change) + cs46xx_dsp_enable_spdif_out(chip); + else if (change && !ucontrol->value.integer.value[0]) + cs46xx_dsp_disable_spdif_out(chip); + + res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED)); + } break; case CS46XX_MIXER_SPDIF_INPUT_ELEMENT: change = chip->dsp_spos_instance->spdif_status_in; @@ -2131,12 +2103,11 @@ static int snd_cs46xx_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); struct dsp_spos_instance * ins = chip->dsp_spos_instance; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff); ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff); ucontrol->value.iec958.status[2] = 0; ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff); - mutex_unlock(&chip->spos_mutex); return 0; } @@ -2149,7 +2120,7 @@ static int snd_cs46xx_spdif_default_put(struct snd_kcontrol *kcontrol, unsigned int val; int change; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | @@ -2163,8 +2134,6 @@ static int snd_cs46xx_spdif_default_put(struct snd_kcontrol *kcontrol, if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) ) cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); - mutex_unlock(&chip->spos_mutex); - return change; } @@ -2184,12 +2153,11 @@ static int snd_cs46xx_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); struct dsp_spos_instance * ins = chip->dsp_spos_instance; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff); ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff); ucontrol->value.iec958.status[2] = 0; ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff); - mutex_unlock(&chip->spos_mutex); return 0; } @@ -2202,7 +2170,7 @@ static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol, unsigned int val; int change; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | @@ -2216,8 +2184,6 @@ static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol, if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN ) cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); - mutex_unlock(&chip->spos_mutex); - return change; } @@ -2532,7 +2498,7 @@ static int snd_cs46xx_midi_input_open(struct snd_rawmidi_substream *substream) struct snd_cs46xx *chip = substream->rmidi->private_data; chip->active_ctrl(chip, 1); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->uartm |= CS46XX_MODE_INPUT; chip->midcr |= MIDCR_RXE; chip->midi_input = substream; @@ -2541,7 +2507,6 @@ static int snd_cs46xx_midi_input_open(struct snd_rawmidi_substream *substream) } else { snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); } - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -2549,16 +2514,16 @@ static int snd_cs46xx_midi_input_close(struct snd_rawmidi_substream *substream) { struct snd_cs46xx *chip = substream->rmidi->private_data; - spin_lock_irq(&chip->reg_lock); - chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE); - chip->midi_input = NULL; - if (!(chip->uartm & CS46XX_MODE_OUTPUT)) { - snd_cs46xx_midi_reset(chip); - } else { - snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); + scoped_guard(spinlock_irq, &chip->reg_lock) { + chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE); + chip->midi_input = NULL; + if (!(chip->uartm & CS46XX_MODE_OUTPUT)) { + snd_cs46xx_midi_reset(chip); + } else { + snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); + } + chip->uartm &= ~CS46XX_MODE_INPUT; } - chip->uartm &= ~CS46XX_MODE_INPUT; - spin_unlock_irq(&chip->reg_lock); chip->active_ctrl(chip, -1); return 0; } @@ -2569,7 +2534,7 @@ static int snd_cs46xx_midi_output_open(struct snd_rawmidi_substream *substream) chip->active_ctrl(chip, 1); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->uartm |= CS46XX_MODE_OUTPUT; chip->midcr |= MIDCR_TXE; chip->midi_output = substream; @@ -2578,7 +2543,6 @@ static int snd_cs46xx_midi_output_open(struct snd_rawmidi_substream *substream) } else { snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); } - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -2586,26 +2550,25 @@ static int snd_cs46xx_midi_output_close(struct snd_rawmidi_substream *substream) { struct snd_cs46xx *chip = substream->rmidi->private_data; - spin_lock_irq(&chip->reg_lock); - chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE); - chip->midi_output = NULL; - if (!(chip->uartm & CS46XX_MODE_INPUT)) { - snd_cs46xx_midi_reset(chip); - } else { - snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); + scoped_guard(spinlock_irq, &chip->reg_lock) { + chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE); + chip->midi_output = NULL; + if (!(chip->uartm & CS46XX_MODE_INPUT)) { + snd_cs46xx_midi_reset(chip); + } else { + snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); + } + chip->uartm &= ~CS46XX_MODE_OUTPUT; } - chip->uartm &= ~CS46XX_MODE_OUTPUT; - spin_unlock_irq(&chip->reg_lock); chip->active_ctrl(chip, -1); return 0; } static void snd_cs46xx_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct snd_cs46xx *chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (up) { if ((chip->midcr & MIDCR_RIE) == 0) { chip->midcr |= MIDCR_RIE; @@ -2617,16 +2580,14 @@ static void snd_cs46xx_midi_input_trigger(struct snd_rawmidi_substream *substrea snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); } } - spin_unlock_irqrestore(&chip->reg_lock, flags); } static void snd_cs46xx_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct snd_cs46xx *chip = substream->rmidi->private_data; unsigned char byte; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (up) { if ((chip->midcr & MIDCR_TIE) == 0) { chip->midcr |= MIDCR_TIE; @@ -2647,7 +2608,6 @@ static void snd_cs46xx_midi_output_trigger(struct snd_rawmidi_substream *substre snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); } } - spin_unlock_irqrestore(&chip->reg_lock, flags); } static const struct snd_rawmidi_ops snd_cs46xx_midi_output = diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index e07f85322f1c..3d34575a0e8f 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c @@ -283,7 +283,7 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) if (snd_BUG_ON(!ins)) return; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); for (i = 0; i < ins->nscb; ++i) { if (ins->scbs[i].deleted) continue; @@ -297,7 +297,6 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) vfree(ins->symbol_table.symbols); kfree(ins->modules); kfree(ins); - mutex_unlock(&chip->spos_mutex); } static int dsp_load_parameter(struct snd_cs46xx *chip, @@ -525,7 +524,7 @@ static void cs46xx_dsp_proc_modules_read (struct snd_info_entry *entry, struct dsp_spos_instance * ins = chip->dsp_spos_instance; int i,j; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); snd_iprintf(buffer, "MODULES:\n"); for ( i = 0; i < ins->nmodules; ++i ) { snd_iprintf(buffer, "\n%s:\n", ins->modules[i].module_name); @@ -538,7 +537,6 @@ static void cs46xx_dsp_proc_modules_read (struct snd_info_entry *entry, desc->segment_type,desc->offset, desc->size); } } - mutex_unlock(&chip->spos_mutex); } static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry, @@ -549,7 +547,7 @@ static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry, int i, j, col; void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); snd_iprintf(buffer, "TASK TREES:\n"); for ( i = 0; i < ins->ntask; ++i) { snd_iprintf(buffer,"\n%04x %s:\n",ins->tasks[i].address,ins->tasks[i].task_name); @@ -566,7 +564,6 @@ static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry, } snd_iprintf(buffer,"\n"); - mutex_unlock(&chip->spos_mutex); } static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry, @@ -576,7 +573,7 @@ static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry, struct dsp_spos_instance * ins = chip->dsp_spos_instance; int i; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); snd_iprintf(buffer, "SCB's:\n"); for ( i = 0; i < ins->nscb; ++i) { if (ins->scbs[i].deleted) @@ -599,7 +596,6 @@ static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry, } snd_iprintf(buffer,"\n"); - mutex_unlock(&chip->spos_mutex); } static void cs46xx_dsp_proc_parameter_dump_read (struct snd_info_entry *entry, @@ -831,14 +827,13 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) snd_info_set_text_ops(entry, chip, cs46xx_dsp_proc_scb_read); - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); /* register/update SCB's entries on proc */ for (i = 0; i < ins->nscb; ++i) { if (ins->scbs[i].deleted) continue; cs46xx_dsp_proc_register_scb_desc (chip, (ins->scbs + i)); } - mutex_unlock(&chip->spos_mutex); return 0; } @@ -851,12 +846,13 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip) if (!ins) return 0; - mutex_lock(&chip->spos_mutex); - for (i = 0; i < ins->nscb; ++i) { - if (ins->scbs[i].deleted) continue; - cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); + scoped_guard(mutex, &chip->spos_mutex) { + for (i = 0; i < ins->nscb; ++i) { + if (ins->scbs[i].deleted) + continue; + cs46xx_dsp_proc_free_scb_desc((ins->scbs + i)); + } } - mutex_unlock(&chip->spos_mutex); snd_info_free_entry(ins->proc_dsp_dir); ins->proc_dsp_dir = NULL; @@ -1677,7 +1673,7 @@ int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip) if (snd_BUG_ON(!ins->spdif_in_src)) return -EINVAL; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED) ) { /* time countdown enable */ @@ -1700,7 +1696,7 @@ int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip) ins->spdif_in_src, SCB_ON_PARENT_SUBLIST_SCB); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); /* reset SPDIF input sample buffer pointer */ /*snd_cs46xx_poke (chip, (SPDIFI_SCB_INST + 0x0c) << 2, @@ -1713,15 +1709,12 @@ int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip) /* unmute SRC volume */ cs46xx_dsp_scb_set_volume (chip,ins->spdif_in_src,0x7fff,0x7fff); - spin_unlock_irq(&chip->reg_lock); - /* set SPDIF input sample rate and unmute NOTE: only 48khz support for SPDIF input this time */ /* cs46xx_dsp_set_src_sample_rate(chip,ins->spdif_in_src,48000); */ /* monitor state */ ins->spdif_status_in = 1; - mutex_unlock(&chip->spos_mutex); return 0; } @@ -1735,17 +1728,16 @@ int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip) if (snd_BUG_ON(!ins->spdif_in_src)) return -EINVAL; - mutex_lock(&chip->spos_mutex); + scoped_guard(mutex, &chip->spos_mutex) { + /* Remove the asynchronous receiver SCB */ + cs46xx_dsp_remove_scb(chip, ins->asynch_rx_scb); + ins->asynch_rx_scb = NULL; - /* Remove the asynchronous receiver SCB */ - cs46xx_dsp_remove_scb (chip,ins->asynch_rx_scb); - ins->asynch_rx_scb = NULL; + cs46xx_src_unlink(chip, ins->spdif_in_src); - cs46xx_src_unlink(chip,ins->spdif_in_src); - - /* monitor state */ - ins->spdif_status_in = 0; - mutex_unlock(&chip->spos_mutex); + /* monitor state */ + ins->spdif_status_in = 0; + } /* restore amplifier */ chip->active_ctrl(chip, -1); @@ -1763,10 +1755,9 @@ int cs46xx_dsp_enable_pcm_capture (struct snd_cs46xx *chip) if (snd_BUG_ON(!ins->ref_snoop_scb)) return -EINVAL; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); ins->pcm_input = cs46xx_add_record_source(chip,ins->ref_snoop_scb,PCMSERIALIN_PCM_SCB_ADDR, "PCMSerialInput_Wave"); - mutex_unlock(&chip->spos_mutex); return 0; } @@ -1778,10 +1769,9 @@ int cs46xx_dsp_disable_pcm_capture (struct snd_cs46xx *chip) if (snd_BUG_ON(!ins->pcm_input)) return -EINVAL; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); cs46xx_dsp_remove_scb (chip,ins->pcm_input); ins->pcm_input = NULL; - mutex_unlock(&chip->spos_mutex); return 0; } @@ -1795,10 +1785,9 @@ int cs46xx_dsp_enable_adc_capture (struct snd_cs46xx *chip) if (snd_BUG_ON(!ins->codec_in_scb)) return -EINVAL; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); ins->adc_input = cs46xx_add_record_source(chip,ins->codec_in_scb,PCMSERIALIN_SCB_ADDR, "PCMSerialInput_ADC"); - mutex_unlock(&chip->spos_mutex); return 0; } @@ -1810,10 +1799,9 @@ int cs46xx_dsp_disable_adc_capture (struct snd_cs46xx *chip) if (snd_BUG_ON(!ins->adc_input)) return -EINVAL; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); cs46xx_dsp_remove_scb (chip,ins->adc_input); ins->adc_input = NULL; - mutex_unlock(&chip->spos_mutex); return 0; } @@ -1861,7 +1849,7 @@ int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right) struct dsp_spos_instance * ins = chip->dsp_spos_instance; struct dsp_scb_descriptor * scb; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); /* main output */ scb = ins->master_mix_scb->sub_list_ptr; @@ -1880,8 +1868,6 @@ int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right) ins->dac_volume_left = left; ins->dac_volume_right = right; - mutex_unlock(&chip->spos_mutex); - return 0; } @@ -1889,7 +1875,7 @@ int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right) { struct dsp_spos_instance * ins = chip->dsp_spos_instance; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); if (ins->asynch_rx_scb != NULL) cs46xx_dsp_scb_set_volume (chip,ins->asynch_rx_scb, @@ -1898,8 +1884,6 @@ int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right) ins->spdif_input_volume_left = left; ins->spdif_input_volume_right = right; - mutex_unlock(&chip->spos_mutex); - return 0; } diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 28faca268196..32ed415bf427 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c @@ -63,7 +63,7 @@ static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry, int j,col; void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; - mutex_lock(&chip->spos_mutex); + guard(mutex)(&chip->spos_mutex); snd_iprintf(buffer,"%04x %s:\n",scb->address,scb->scb_name); for (col = 0,j = 0;j < 0x10; j++,col++) { @@ -91,7 +91,6 @@ static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry, scb->task_entry->address); snd_iprintf(buffer,"index [%d] ref_count [%d]\n",scb->index,scb->ref_count); - mutex_unlock(&chip->spos_mutex); } #endif @@ -160,7 +159,6 @@ static void _dsp_clear_sample_buffer (struct snd_cs46xx *chip, u32 sample_buffer void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb) { struct dsp_spos_instance * ins = chip->dsp_spos_instance; - unsigned long flags; /* check integrety */ if (snd_BUG_ON(scb->index < 0 || @@ -176,9 +174,9 @@ void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * goto _end; #endif - spin_lock_irqsave(&chip->reg_lock, flags); - _dsp_unlink_scb (chip,scb); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + _dsp_unlink_scb(chip, scb); + } cs46xx_dsp_proc_free_scb_desc(scb); if (snd_BUG_ON(!scb->scb_symbol)) @@ -263,8 +261,6 @@ _dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u struct dsp_spos_instance * ins = chip->dsp_spos_instance; struct dsp_scb_descriptor * scb; - unsigned long flags; - if (snd_BUG_ON(!ins->the_null_scb)) return NULL; @@ -318,12 +314,10 @@ _dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u snd_BUG(); } - spin_lock_irqsave(&chip->reg_lock, flags); - - /* update entry in DSP RAM */ - cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr); - - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + /* update entry in DSP RAM */ + cs46xx_dsp_spos_update_scb(chip, scb->parent_scb_ptr); + } } @@ -1220,7 +1214,6 @@ cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, /* struct dsp_scb_descriptor * pcm_parent_scb; */ char scb_name[DSP_MAX_SCB_NAME]; int i, pcm_index = -1, insert_point, src_index = -1, pass_through = 0; - unsigned long flags; switch (pcm_channel_id) { case DSP_PCM_MAIN_CHANNEL: @@ -1357,7 +1350,7 @@ cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, return NULL; } - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); ins->pcm_channels[pcm_index].sample_rate = sample_rate; ins->pcm_channels[pcm_index].pcm_reader_scb = pcm_scb; ins->pcm_channels[pcm_index].src_scb = src_scb; @@ -1368,7 +1361,6 @@ cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, ins->pcm_channels[pcm_index].pcm_slot = pcm_index; ins->pcm_channels[pcm_index].mixer_scb = mixer_scb; ins->npcm_channels ++; - spin_unlock_irqrestore(&chip->reg_lock, flags); return (ins->pcm_channels + pcm_index); } @@ -1456,20 +1448,19 @@ void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip, struct dsp_pcm_channel_descriptor * pcm_channel) { struct dsp_spos_instance * ins = chip->dsp_spos_instance; - unsigned long flags; if (snd_BUG_ON(!pcm_channel->active || ins->npcm_channels <= 0 || pcm_channel->src_scb->ref_count <= 0)) return; - spin_lock_irqsave(&chip->reg_lock, flags); - pcm_channel->unlinked = 1; - pcm_channel->active = 0; - pcm_channel->private_data = NULL; - pcm_channel->src_scb->ref_count --; - ins->npcm_channels --; - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + pcm_channel->unlinked = 1; + pcm_channel->active = 0; + pcm_channel->private_data = NULL; + pcm_channel->src_scb->ref_count--; + ins->npcm_channels--; + } cs46xx_dsp_remove_scb(chip,pcm_channel->pcm_reader_scb); @@ -1488,22 +1479,17 @@ void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip, int cs46xx_dsp_pcm_unlink (struct snd_cs46xx * chip, struct dsp_pcm_channel_descriptor * pcm_channel) { - unsigned long flags; - if (snd_BUG_ON(!pcm_channel->active || chip->dsp_spos_instance->npcm_channels <= 0)) return -EIO; - spin_lock_irqsave(&chip->reg_lock, flags); - if (pcm_channel->unlinked) { - spin_unlock_irqrestore(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); + if (pcm_channel->unlinked) return -EIO; - } pcm_channel->unlinked = 1; _dsp_unlink_scb (chip,pcm_channel->pcm_reader_scb); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } @@ -1514,14 +1500,11 @@ int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip, struct dsp_spos_instance * ins = chip->dsp_spos_instance; struct dsp_scb_descriptor * parent_scb; struct dsp_scb_descriptor * src_scb = pcm_channel->src_scb; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); - if (pcm_channel->unlinked == 0) { - spin_unlock_irqrestore(&chip->reg_lock, flags); + if (pcm_channel->unlinked == 0) return -EIO; - } parent_scb = src_scb; @@ -1542,7 +1525,6 @@ int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip, cs46xx_dsp_spos_update_scb(chip,parent_scb); pcm_channel->unlinked = 0; - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } @@ -1575,17 +1557,14 @@ cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * s int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src) { - unsigned long flags; - if (snd_BUG_ON(!src->parent_scb_ptr)) return -EINVAL; /* mute SCB */ cs46xx_dsp_scb_set_volume (chip,src,0,0); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); _dsp_unlink_scb (chip,src); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 76566e7baea0..0ebf6c02b1ef 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -176,9 +176,10 @@ static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au) static void process_bm0_irq(struct cs5535audio *cs5535au) { u8 bm_stat; - spin_lock(&cs5535au->reg_lock); - bm_stat = cs_readb(cs5535au, ACC_BM0_STATUS); - spin_unlock(&cs5535au->reg_lock); + + scoped_guard(spinlock, &cs5535au->reg_lock) { + bm_stat = cs_readb(cs5535au, ACC_BM0_STATUS); + } if (bm_stat & EOP) { snd_pcm_period_elapsed(cs5535au->playback_substream); } else { @@ -191,9 +192,10 @@ static void process_bm0_irq(struct cs5535audio *cs5535au) static void process_bm1_irq(struct cs5535audio *cs5535au) { u8 bm_stat; - spin_lock(&cs5535au->reg_lock); - bm_stat = cs_readb(cs5535au, ACC_BM1_STATUS); - spin_unlock(&cs5535au->reg_lock); + + scoped_guard(spinlock, &cs5535au->reg_lock) { + bm_stat = cs_readb(cs5535au, ACC_BM1_STATUS); + } if (bm_stat & EOP) snd_pcm_period_elapsed(cs5535au->capture_substream); } diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index f296b2c63026..48b99a07e3bc 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c @@ -150,10 +150,9 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au, dma->substream = substream; dma->period_bytes = period_bytes; dma->periods = periods; - spin_lock_irq(&cs5535au->reg_lock); + guard(spinlock_irq)(&cs5535au->reg_lock); dma->ops->disable_dma(cs5535au); dma->ops->setup_prd(cs5535au, jmpprd_addr); - spin_unlock_irq(&cs5535au->reg_lock); return 0; } @@ -276,9 +275,8 @@ static int snd_cs5535audio_trigger(struct snd_pcm_substream *substream, int cmd) { struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream); struct cs5535audio_dma *dma = substream->runtime->private_data; - int err = 0; - spin_lock(&cs5535au->reg_lock); + guard(spinlock)(&cs5535au->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_PAUSE_PUSH: dma->ops->pause_dma(cs5535au); @@ -300,11 +298,9 @@ static int snd_cs5535audio_trigger(struct snd_pcm_substream *substream, int cmd) break; default: dev_err(cs5535au->card->dev, "unhandled trigger\n"); - err = -EINVAL; - break; + return -EINVAL; } - spin_unlock(&cs5535au->reg_lock); - return err; + return 0; } static snd_pcm_uframes_t snd_cs5535audio_pcm_pointer(struct snd_pcm_substream diff --git a/sound/pci/ctxfi/ctamixer.c b/sound/pci/ctxfi/ctamixer.c index 397900929aa6..bb4658592636 100644 --- a/sound/pci/ctxfi/ctamixer.c +++ b/sound/pci/ctxfi/ctamixer.c @@ -231,7 +231,6 @@ static int get_amixer_rsc(struct amixer_mgr *mgr, int err, i; unsigned int idx; struct amixer *amixer; - unsigned long flags; *ramixer = NULL; @@ -243,15 +242,15 @@ static int get_amixer_rsc(struct amixer_mgr *mgr, /* Check whether there are sufficient * amixer resources to meet request. */ err = 0; - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i = 0; i < desc->msr; i++) { - err = mgr_get_resource(&mgr->mgr, 1, &idx); - if (err) - break; + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + for (i = 0; i < desc->msr; i++) { + err = mgr_get_resource(&mgr->mgr, 1, &idx); + if (err) + break; - amixer->idx[i] = idx; + amixer->idx[i] = idx; + } } - spin_unlock_irqrestore(&mgr->mgr_lock, flags); if (err) { dev_err(mgr->card->dev, "Can't meet AMIXER resource request!\n"); @@ -267,25 +266,23 @@ static int get_amixer_rsc(struct amixer_mgr *mgr, return 0; error: - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i--; i >= 0; i--) - mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + for (i--; i >= 0; i--) + mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]); + } - spin_unlock_irqrestore(&mgr->mgr_lock, flags); kfree(amixer); return err; } static int put_amixer_rsc(struct amixer_mgr *mgr, struct amixer *amixer) { - unsigned long flags; int i; - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i = 0; i < amixer->rsc.msr; i++) - mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + for (i = 0; i < amixer->rsc.msr; i++) + mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]); + } amixer_rsc_uninit(amixer); kfree(amixer); @@ -387,7 +384,6 @@ static int get_sum_rsc(struct sum_mgr *mgr, int err, i; unsigned int idx; struct sum *sum; - unsigned long flags; *rsum = NULL; @@ -398,15 +394,15 @@ static int get_sum_rsc(struct sum_mgr *mgr, /* Check whether there are sufficient sum resources to meet request. */ err = 0; - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i = 0; i < desc->msr; i++) { - err = mgr_get_resource(&mgr->mgr, 1, &idx); - if (err) - break; + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + for (i = 0; i < desc->msr; i++) { + err = mgr_get_resource(&mgr->mgr, 1, &idx); + if (err) + break; - sum->idx[i] = idx; + sum->idx[i] = idx; + } } - spin_unlock_irqrestore(&mgr->mgr_lock, flags); if (err) { dev_err(mgr->card->dev, "Can't meet SUM resource request!\n"); @@ -422,25 +418,22 @@ static int get_sum_rsc(struct sum_mgr *mgr, return 0; error: - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i--; i >= 0; i--) - mgr_put_resource(&mgr->mgr, 1, sum->idx[i]); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + for (i--; i >= 0; i--) + mgr_put_resource(&mgr->mgr, 1, sum->idx[i]); + } kfree(sum); return err; } static int put_sum_rsc(struct sum_mgr *mgr, struct sum *sum) { - unsigned long flags; int i; - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i = 0; i < sum->rsc.msr; i++) - mgr_put_resource(&mgr->mgr, 1, sum->idx[i]); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + for (i = 0; i < sum->rsc.msr; i++) + mgr_put_resource(&mgr->mgr, 1, sum->idx[i]); + } sum_rsc_uninit(sum); kfree(sum); diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 2a3e9d8ba7db..14779b383d9e 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -295,10 +295,10 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) src = apcm->src; for (i = 0; i < n_amixer; i++) { amixer = apcm->amixers[i]; - mutex_lock(&atc->atc_mutex); - amixer->ops->setup(amixer, &src->rsc, - INIT_VOL, atc->pcm[i+device*2]); - mutex_unlock(&atc->atc_mutex); + scoped_guard(mutex, &atc->atc_mutex) { + amixer->ops->setup(amixer, &src->rsc, + INIT_VOL, atc->pcm[i+device*2]); + } src = src->ops->next_interleave(src); if (!src) src = apcm->src; @@ -874,7 +874,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) return -ENOENT; } - mutex_lock(&atc->atc_mutex); + guard(mutex)(&atc->atc_mutex); dao->ops->get_spos(dao, &status); if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) { status &= ~(IEC958_AES3_CON_FS << 24); @@ -884,7 +884,6 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) } if ((rate != atc->pll_rate) && (32000 != rate)) err = atc_pll_init(atc, rate); - mutex_unlock(&atc->atc_mutex); return err; } @@ -921,13 +920,13 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) src = apcm->src; } /* Connect to SPDIFOO */ - mutex_lock(&atc->atc_mutex); - dao = container_of(atc->daios[SPDIFOO], struct dao, daio); - amixer = apcm->amixers[0]; - dao->ops->set_left_input(dao, &amixer->rsc); - amixer = apcm->amixers[1]; - dao->ops->set_right_input(dao, &amixer->rsc); - mutex_unlock(&atc->atc_mutex); + scoped_guard(mutex, &atc->atc_mutex) { + dao = container_of(atc->daios[SPDIFOO], struct dao, daio); + amixer = apcm->amixers[0]; + dao->ops->set_left_input(dao, &amixer->rsc); + amixer = apcm->amixers[1]; + dao->ops->set_right_input(dao, &amixer->rsc); + } ct_timer_prepare(apcm->timer); @@ -1115,7 +1114,7 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) struct rsc *rscs[2] = {NULL}; unsigned int spos = 0; - mutex_lock(&atc->atc_mutex); + guard(mutex)(&atc->atc_mutex); dao = container_of(atc->daios[SPDIFOO], struct dao, daio); da_dsc.msr = state ? 1 : atc->msr; da_dsc.passthru = state ? 1 : 0; @@ -1133,7 +1132,6 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) } dao->ops->set_spos(dao, spos); dao->ops->commit_write(dao); - mutex_unlock(&atc->atc_mutex); return err; } diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c index 806c4d754387..c0c3f8ab8467 100644 --- a/sound/pci/ctxfi/ctdaio.c +++ b/sound/pci/ctxfi/ctdaio.c @@ -503,14 +503,13 @@ static int get_daio_rsc(struct daio_mgr *mgr, struct daio **rdaio) { int err; - unsigned long flags; *rdaio = NULL; /* Check whether there are sufficient daio resources to meet request. */ - spin_lock_irqsave(&mgr->mgr_lock, flags); - err = daio_mgr_get_rsc(&mgr->mgr, desc->type); - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + err = daio_mgr_get_rsc(&mgr->mgr, desc->type); + } if (err) { dev_err(mgr->card->dev, "Can't meet DAIO resource request!\n"); @@ -551,22 +550,20 @@ static int get_daio_rsc(struct daio_mgr *mgr, return 0; error: - spin_lock_irqsave(&mgr->mgr_lock, flags); - daio_mgr_put_rsc(&mgr->mgr, desc->type); - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + daio_mgr_put_rsc(&mgr->mgr, desc->type); + } return err; } static int put_daio_rsc(struct daio_mgr *mgr, struct daio *daio) { - unsigned long flags; - mgr->daio_disable(mgr, daio); mgr->commit_write(mgr); - spin_lock_irqsave(&mgr->mgr_lock, flags); - daio_mgr_put_rsc(&mgr->mgr, daio->type); - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + daio_mgr_put_rsc(&mgr->mgr, daio->type); + } if (daio->type <= DAIO_OUT_MAX) { dao_rsc_uninit(container_of(daio, struct dao, daio)); @@ -622,34 +619,26 @@ static int daio_map_op(void *data, struct imapper *entry) static int daio_imap_add(struct daio_mgr *mgr, struct imapper *entry) { - unsigned long flags; - int err; - - spin_lock_irqsave(&mgr->imap_lock, flags); + guard(spinlock_irqsave)(&mgr->imap_lock); if (!entry->addr && mgr->init_imap_added) { input_mapper_delete(&mgr->imappers, mgr->init_imap, daio_map_op, mgr); mgr->init_imap_added = 0; } - err = input_mapper_add(&mgr->imappers, entry, daio_map_op, mgr); - spin_unlock_irqrestore(&mgr->imap_lock, flags); - - return err; + return input_mapper_add(&mgr->imappers, entry, daio_map_op, mgr); } static int daio_imap_delete(struct daio_mgr *mgr, struct imapper *entry) { - unsigned long flags; int err; - spin_lock_irqsave(&mgr->imap_lock, flags); + guard(spinlock_irqsave)(&mgr->imap_lock); err = input_mapper_delete(&mgr->imappers, entry, daio_map_op, mgr); if (list_empty(&mgr->imappers)) { input_mapper_add(&mgr->imappers, mgr->init_imap, daio_map_op, mgr); mgr->init_imap_added = 1; } - spin_unlock_irqrestore(&mgr->imap_lock, flags); return err; } @@ -719,12 +708,11 @@ error1: int daio_mgr_destroy(void *ptr) { struct daio_mgr *daio_mgr = ptr; - unsigned long flags; /* free daio input mapper list */ - spin_lock_irqsave(&daio_mgr->imap_lock, flags); - free_input_mapper_list(&daio_mgr->imappers); - spin_unlock_irqrestore(&daio_mgr->imap_lock, flags); + scoped_guard(spinlock_irqsave, &daio_mgr->imap_lock) { + free_input_mapper_list(&daio_mgr->imappers); + } rsc_mgr_uninit(&daio_mgr->mgr); kfree(daio_mgr); diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index 9edbf5d8c3c7..42b90c9b2ee9 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c @@ -2091,57 +2091,30 @@ static int hw_resume(struct hw *hw, struct card_conf *info) static u32 hw_read_20kx(struct hw *hw, u32 reg) { - u32 value; - unsigned long flags; - - spin_lock_irqsave( - &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); + guard(spinlock_irqsave)(&container_of(hw, struct hw20k1, hw)->reg_20k1_lock); outl(reg, hw->io_base + 0x0); - value = inl(hw->io_base + 0x4); - spin_unlock_irqrestore( - &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); - - return value; + return inl(hw->io_base + 0x4); } static void hw_write_20kx(struct hw *hw, u32 reg, u32 data) { - unsigned long flags; - - spin_lock_irqsave( - &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); + guard(spinlock_irqsave)(&container_of(hw, struct hw20k1, hw)->reg_20k1_lock); outl(reg, hw->io_base + 0x0); outl(data, hw->io_base + 0x4); - spin_unlock_irqrestore( - &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); - } static u32 hw_read_pci(struct hw *hw, u32 reg) { - u32 value; - unsigned long flags; - - spin_lock_irqsave( - &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); + guard(spinlock_irqsave)(&container_of(hw, struct hw20k1, hw)->reg_pci_lock); outl(reg, hw->io_base + 0x10); - value = inl(hw->io_base + 0x14); - spin_unlock_irqrestore( - &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); - - return value; + return inl(hw->io_base + 0x14); } static void hw_write_pci(struct hw *hw, u32 reg, u32 data) { - unsigned long flags; - - spin_lock_irqsave( - &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); + guard(spinlock_irqsave)(&container_of(hw, struct hw20k1, hw)->reg_pci_lock); outl(reg, hw->io_base + 0x10); outl(data, hw->io_base + 0x14); - spin_unlock_irqrestore( - &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); } static const struct hw ct20k1_preset = { diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c index 159bd4008069..46afc9604c08 100644 --- a/sound/pci/ctxfi/ctsrc.c +++ b/sound/pci/ctxfi/ctsrc.c @@ -414,18 +414,16 @@ get_src_rsc(struct src_mgr *mgr, const struct src_desc *desc, struct src **rsrc) unsigned int idx = SRC_RESOURCE_NUM; int err; struct src *src; - unsigned long flags; *rsrc = NULL; /* Check whether there are sufficient src resources to meet request. */ - spin_lock_irqsave(&mgr->mgr_lock, flags); - if (MEMRD == desc->mode) - err = mgr_get_resource(&mgr->mgr, desc->multi, &idx); - else - err = mgr_get_resource(&mgr->mgr, 1, &idx); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + if (MEMRD == desc->mode) + err = mgr_get_resource(&mgr->mgr, desc->multi, &idx); + else + err = mgr_get_resource(&mgr->mgr, 1, &idx); + } if (err) { dev_err(mgr->card->dev, "Can't meet SRC resource request!\n"); @@ -454,29 +452,25 @@ get_src_rsc(struct src_mgr *mgr, const struct src_desc *desc, struct src **rsrc) error2: kfree(src); error1: - spin_lock_irqsave(&mgr->mgr_lock, flags); - if (MEMRD == desc->mode) - mgr_put_resource(&mgr->mgr, desc->multi, idx); - else - mgr_put_resource(&mgr->mgr, 1, idx); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + if (MEMRD == desc->mode) + mgr_put_resource(&mgr->mgr, desc->multi, idx); + else + mgr_put_resource(&mgr->mgr, 1, idx); + } return err; } static int put_src_rsc(struct src_mgr *mgr, struct src *src) { - unsigned long flags; - - spin_lock_irqsave(&mgr->mgr_lock, flags); - src->rsc.ops->master(&src->rsc); - if (MEMRD == src->mode) - mgr_put_resource(&mgr->mgr, src->multi, - src->rsc.ops->index(&src->rsc)); - else - mgr_put_resource(&mgr->mgr, 1, src->rsc.ops->index(&src->rsc)); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + src->rsc.ops->master(&src->rsc); + if (MEMRD == src->mode) + mgr_put_resource(&mgr->mgr, src->multi, + src->rsc.ops->index(&src->rsc)); + else + mgr_put_resource(&mgr->mgr, 1, src->rsc.ops->index(&src->rsc)); + } src_rsc_uninit(src, mgr); kfree(src); @@ -714,7 +708,6 @@ static int get_srcimp_rsc(struct srcimp_mgr *mgr, int err, i; unsigned int idx; struct srcimp *srcimp; - unsigned long flags; *rsrcimp = NULL; @@ -725,15 +718,15 @@ static int get_srcimp_rsc(struct srcimp_mgr *mgr, /* Check whether there are sufficient SRCIMP resources. */ err = 0; - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i = 0; i < desc->msr; i++) { - err = mgr_get_resource(&mgr->mgr, 1, &idx); - if (err) - break; + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + for (i = 0; i < desc->msr; i++) { + err = mgr_get_resource(&mgr->mgr, 1, &idx); + if (err) + break; - srcimp->idx[i] = idx; + srcimp->idx[i] = idx; + } } - spin_unlock_irqrestore(&mgr->mgr_lock, flags); if (err) { dev_err(mgr->card->dev, "Can't meet SRCIMP resource request!\n"); @@ -749,25 +742,22 @@ static int get_srcimp_rsc(struct srcimp_mgr *mgr, return 0; error1: - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i--; i >= 0; i--) - mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + for (i--; i >= 0; i--) + mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]); + } kfree(srcimp); return err; } static int put_srcimp_rsc(struct srcimp_mgr *mgr, struct srcimp *srcimp) { - unsigned long flags; int i; - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i = 0; i < srcimp->rsc.msr; i++) - mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + for (i = 0; i < srcimp->rsc.msr; i++) + mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]); + } srcimp_rsc_uninit(srcimp); kfree(srcimp); @@ -790,34 +780,26 @@ static int srcimp_map_op(void *data, struct imapper *entry) static int srcimp_imap_add(struct srcimp_mgr *mgr, struct imapper *entry) { - unsigned long flags; - int err; - - spin_lock_irqsave(&mgr->imap_lock, flags); + guard(spinlock_irqsave)(&mgr->imap_lock); if ((0 == entry->addr) && (mgr->init_imap_added)) { input_mapper_delete(&mgr->imappers, mgr->init_imap, srcimp_map_op, mgr); mgr->init_imap_added = 0; } - err = input_mapper_add(&mgr->imappers, entry, srcimp_map_op, mgr); - spin_unlock_irqrestore(&mgr->imap_lock, flags); - - return err; + return input_mapper_add(&mgr->imappers, entry, srcimp_map_op, mgr); } static int srcimp_imap_delete(struct srcimp_mgr *mgr, struct imapper *entry) { - unsigned long flags; int err; - spin_lock_irqsave(&mgr->imap_lock, flags); + guard(spinlock_irqsave)(&mgr->imap_lock); err = input_mapper_delete(&mgr->imappers, entry, srcimp_map_op, mgr); if (list_empty(&mgr->imappers)) { input_mapper_add(&mgr->imappers, mgr->init_imap, srcimp_map_op, mgr); mgr->init_imap_added = 1; } - spin_unlock_irqrestore(&mgr->imap_lock, flags); return err; } @@ -870,12 +852,11 @@ error1: int srcimp_mgr_destroy(void *ptr) { struct srcimp_mgr *srcimp_mgr = ptr; - unsigned long flags; /* free src input mapper list */ - spin_lock_irqsave(&srcimp_mgr->imap_lock, flags); - free_input_mapper_list(&srcimp_mgr->imappers); - spin_unlock_irqrestore(&srcimp_mgr->imap_lock, flags); + scoped_guard(spinlock_irqsave, &srcimp_mgr->imap_lock) { + free_input_mapper_list(&srcimp_mgr->imappers); + } rsc_mgr_uninit(&srcimp_mgr->mgr); kfree(srcimp_mgr); diff --git a/sound/pci/ctxfi/cttimer.c b/sound/pci/ctxfi/cttimer.c index fa6867adb42b..609b10320ff7 100644 --- a/sound/pci/ctxfi/cttimer.c +++ b/sound/pci/ctxfi/cttimer.c @@ -68,7 +68,6 @@ static void ct_systimer_callback(struct timer_list *t) struct ct_atc_pcm *apcm = ti->apcm; unsigned int period_size = runtime->period_size; unsigned int buffer_size = runtime->buffer_size; - unsigned long flags; unsigned int position, dist, interval; position = substream->ops->pointer(substream); @@ -82,10 +81,9 @@ static void ct_systimer_callback(struct timer_list *t) * at 8kHz in 8-bit format or at 88kHz in 24-bit format. */ interval = ((period_size - (position % period_size)) * HZ + (runtime->rate - 1)) / runtime->rate + HZ * 5 / 1000; - spin_lock_irqsave(&ti->lock, flags); + guard(spinlock_irqsave)(&ti->lock); if (ti->running) mod_timer(&ti->timer, jiffies + interval); - spin_unlock_irqrestore(&ti->lock, flags); } static void ct_systimer_init(struct ct_timer_instance *ti) @@ -96,24 +94,19 @@ static void ct_systimer_init(struct ct_timer_instance *ti) static void ct_systimer_start(struct ct_timer_instance *ti) { struct snd_pcm_runtime *runtime = ti->substream->runtime; - unsigned long flags; - spin_lock_irqsave(&ti->lock, flags); + guard(spinlock_irqsave)(&ti->lock); ti->running = 1; mod_timer(&ti->timer, jiffies + (runtime->period_size * HZ + (runtime->rate - 1)) / runtime->rate); - spin_unlock_irqrestore(&ti->lock, flags); } static void ct_systimer_stop(struct ct_timer_instance *ti) { - unsigned long flags; - - spin_lock_irqsave(&ti->lock, flags); + guard(spinlock_irqsave)(&ti->lock); ti->running = 0; timer_delete(&ti->timer); - spin_unlock_irqrestore(&ti->lock, flags); } static void ct_systimer_prepare(struct ct_timer_instance *ti) @@ -229,25 +222,22 @@ static int ct_xfitimer_reprogram(struct ct_timer *atimer, int can_update) static void ct_xfitimer_check_period(struct ct_timer *atimer) { struct ct_timer_instance *ti; - unsigned long flags; - spin_lock_irqsave(&atimer->list_lock, flags); + guard(spinlock_irqsave)(&atimer->list_lock); list_for_each_entry(ti, &atimer->instance_head, instance_list) { if (ti->running && ti->need_update) { ti->need_update = 0; ti->apcm->interrupt(ti->apcm); } } - spin_unlock_irqrestore(&atimer->list_lock, flags); } /* Handle timer-interrupt */ static void ct_xfitimer_callback(struct ct_timer *atimer) { int update; - unsigned long flags; - spin_lock_irqsave(&atimer->lock, flags); + guard(spinlock_irqsave)(&atimer->lock); atimer->irq_handling = 1; do { update = ct_xfitimer_reprogram(atimer, 1); @@ -257,7 +247,6 @@ static void ct_xfitimer_callback(struct ct_timer *atimer) spin_lock(&atimer->lock); } while (atimer->reprogram); atimer->irq_handling = 0; - spin_unlock_irqrestore(&atimer->lock, flags); } static void ct_xfitimer_prepare(struct ct_timer_instance *ti) @@ -271,45 +260,39 @@ static void ct_xfitimer_prepare(struct ct_timer_instance *ti) /* start/stop the timer */ static void ct_xfitimer_update(struct ct_timer *atimer) { - unsigned long flags; - - spin_lock_irqsave(&atimer->lock, flags); + guard(spinlock_irqsave)(&atimer->lock); if (atimer->irq_handling) { /* reached from IRQ handler; let it handle later */ atimer->reprogram = 1; - spin_unlock_irqrestore(&atimer->lock, flags); return; } ct_xfitimer_irq_stop(atimer); ct_xfitimer_reprogram(atimer, 0); - spin_unlock_irqrestore(&atimer->lock, flags); } static void ct_xfitimer_start(struct ct_timer_instance *ti) { struct ct_timer *atimer = ti->timer_base; - unsigned long flags; - spin_lock_irqsave(&atimer->lock, flags); - if (list_empty(&ti->running_list)) - atimer->wc = ct_xfitimer_get_wc(atimer); - ti->running = 1; - ti->need_update = 0; - list_add(&ti->running_list, &atimer->running_head); - spin_unlock_irqrestore(&atimer->lock, flags); + scoped_guard(spinlock_irqsave, &atimer->lock) { + if (list_empty(&ti->running_list)) + atimer->wc = ct_xfitimer_get_wc(atimer); + ti->running = 1; + ti->need_update = 0; + list_add(&ti->running_list, &atimer->running_head); + } ct_xfitimer_update(atimer); } static void ct_xfitimer_stop(struct ct_timer_instance *ti) { struct ct_timer *atimer = ti->timer_base; - unsigned long flags; - spin_lock_irqsave(&atimer->lock, flags); - list_del_init(&ti->running_list); - ti->running = 0; - spin_unlock_irqrestore(&atimer->lock, flags); + scoped_guard(spinlock_irqsave, &atimer->lock) { + list_del_init(&ti->running_list); + ti->running = 0; + } ct_xfitimer_update(atimer); } @@ -347,9 +330,9 @@ ct_timer_instance_new(struct ct_timer *atimer, struct ct_atc_pcm *apcm) if (atimer->ops->init) atimer->ops->init(ti); - spin_lock_irq(&atimer->list_lock); - list_add(&ti->instance_list, &atimer->instance_head); - spin_unlock_irq(&atimer->list_lock); + scoped_guard(spinlock_irq, &atimer->list_lock) { + list_add(&ti->instance_list, &atimer->instance_head); + } return ti; } @@ -382,9 +365,9 @@ void ct_timer_instance_free(struct ct_timer_instance *ti) if (atimer->ops->free_instance) atimer->ops->free_instance(ti); - spin_lock_irq(&atimer->list_lock); - list_del(&ti->instance_list); - spin_unlock_irq(&atimer->list_lock); + scoped_guard(spinlock_irq, &atimer->list_lock) { + list_del(&ti->instance_list); + } kfree(ti); } diff --git a/sound/pci/ctxfi/ctvmem.c b/sound/pci/ctxfi/ctvmem.c index 7a805c4a58e1..823d6e240a07 100644 --- a/sound/pci/ctxfi/ctvmem.c +++ b/sound/pci/ctxfi/ctvmem.c @@ -29,7 +29,7 @@ static struct ct_vm_block * get_vm_block(struct ct_vm *vm, unsigned int size, struct ct_atc *atc) { - struct ct_vm_block *block = NULL, *entry; + struct ct_vm_block *block, *entry; struct list_head *pos; size = CT_PAGE_ALIGN(size); @@ -39,26 +39,25 @@ get_vm_block(struct ct_vm *vm, unsigned int size, struct ct_atc *atc) return NULL; } - mutex_lock(&vm->lock); + guard(mutex)(&vm->lock); list_for_each(pos, &vm->unused) { entry = list_entry(pos, struct ct_vm_block, list); if (entry->size >= size) break; /* found a block that is big enough */ } if (pos == &vm->unused) - goto out; + return NULL; if (entry->size == size) { /* Move the vm node from unused list to used list directly */ list_move(&entry->list, &vm->used); vm->size -= size; - block = entry; - goto out; + return entry; } block = kzalloc(sizeof(*block), GFP_KERNEL); if (!block) - goto out; + return NULL; block->addr = entry->addr; block->size = size; @@ -67,8 +66,6 @@ get_vm_block(struct ct_vm *vm, unsigned int size, struct ct_atc *atc) entry->size -= size; vm->size -= size; - out: - mutex_unlock(&vm->lock); return block; } @@ -79,7 +76,7 @@ static void put_vm_block(struct ct_vm *vm, struct ct_vm_block *block) block->size = CT_PAGE_ALIGN(block->size); - mutex_lock(&vm->lock); + guard(mutex)(&vm->lock); list_del(&block->list); vm->size += block->size; @@ -116,7 +113,6 @@ static void put_vm_block(struct ct_vm *vm, struct ct_vm_block *block) pos = pre; pre = pos->prev; } - mutex_unlock(&vm->lock); } /* Map host addr (kmalloced/vmalloced) to device logical addr. */ diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 2b33ef588ac3..f2c8602a1ad7 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -237,7 +237,7 @@ static int hw_rule_sample_rate(struct snd_pcm_hw_params *params, struct snd_interval fixed; int err; - mutex_lock(&chip->mode_mutex); + guard(mutex)(&chip->mode_mutex); if (chip->can_set_rate) { err = 0; @@ -247,7 +247,6 @@ static int hw_rule_sample_rate(struct snd_pcm_hw_params *params, err = snd_interval_refine(rate, &fixed); } - mutex_unlock(&chip->mode_mutex); return err; } @@ -415,7 +414,7 @@ static int pcm_digital_in_open(struct snd_pcm_substream *substream) int err, max_channels; max_channels = num_digital_busses_in(chip) - substream->number; - mutex_lock(&chip->mode_mutex); + guard(mutex)(&chip->mode_mutex); if (chip->digital_mode == DIGITAL_MODE_ADAT) err = pcm_open(substream, max_channels); else /* If the card has ADAT, subtract the 6 channels @@ -424,24 +423,22 @@ static int pcm_digital_in_open(struct snd_pcm_substream *substream) err = pcm_open(substream, max_channels - ECHOCARD_HAS_ADAT); if (err < 0) - goto din_exit; + return err; err = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, hw_rule_capture_channels_by_format, NULL, SNDRV_PCM_HW_PARAM_FORMAT, -1); if (err < 0) - goto din_exit; + return err; err = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, hw_rule_capture_format_by_channels, NULL, SNDRV_PCM_HW_PARAM_CHANNELS, -1); if (err < 0) - goto din_exit; + return err; -din_exit: - mutex_unlock(&chip->mode_mutex); - return err; + return 0; } @@ -454,7 +451,7 @@ static int pcm_digital_out_open(struct snd_pcm_substream *substream) int err, max_channels; max_channels = num_digital_busses_out(chip) - substream->number; - mutex_lock(&chip->mode_mutex); + guard(mutex)(&chip->mode_mutex); if (chip->digital_mode == DIGITAL_MODE_ADAT) err = pcm_open(substream, max_channels); else /* If the card has ADAT, subtract the 6 channels @@ -463,7 +460,7 @@ static int pcm_digital_out_open(struct snd_pcm_substream *substream) err = pcm_open(substream, max_channels - ECHOCARD_HAS_ADAT); if (err < 0) - goto dout_exit; + return err; err = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, @@ -471,18 +468,16 @@ static int pcm_digital_out_open(struct snd_pcm_substream *substream) NULL, SNDRV_PCM_HW_PARAM_FORMAT, -1); if (err < 0) - goto dout_exit; + return err; err = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, hw_rule_playback_format_by_channels, NULL, SNDRV_PCM_HW_PARAM_CHANNELS, -1); if (err < 0) - goto dout_exit; + return err; -dout_exit: - mutex_unlock(&chip->mode_mutex); - return err; + return 0; } #endif /* !ECHOCARD_HAS_VMIXER */ @@ -499,7 +494,7 @@ static int pcm_close(struct snd_pcm_substream *substream) * freed by its callback */ - mutex_lock(&chip->mode_mutex); + guard(mutex)(&chip->mode_mutex); dev_dbg(chip->card->dev, "pcm_open opencount=%d can_set_rate=%d, rate_set=%d", chip->opencount, chip->can_set_rate, chip->rate_set); @@ -516,7 +511,6 @@ static int pcm_close(struct snd_pcm_substream *substream) break; } - mutex_unlock(&chip->mode_mutex); return 0; } @@ -537,22 +531,21 @@ static int init_engine(struct snd_pcm_substream *substream, /* Sets up che hardware. If it's already initialized, reset and * redo with the new parameters */ - spin_lock_irq(&chip->lock); - if (pipe->index >= 0) { - dev_dbg(chip->card->dev, "hwp_ie free(%d)\n", pipe->index); - err = free_pipes(chip, pipe); - snd_BUG_ON(err); - chip->substream[pipe->index] = NULL; - } + scoped_guard(spinlock_irq, &chip->lock) { + if (pipe->index >= 0) { + dev_dbg(chip->card->dev, "hwp_ie free(%d)\n", pipe->index); + err = free_pipes(chip, pipe); + snd_BUG_ON(err); + chip->substream[pipe->index] = NULL; + } - err = allocate_pipes(chip, pipe, pipe_index, interleave); - if (err < 0) { - spin_unlock_irq(&chip->lock); - dev_err(chip->card->dev, "allocate_pipes(%d) err=%d\n", - pipe_index, err); - return err; + err = allocate_pipes(chip, pipe, pipe_index, interleave); + if (err < 0) { + dev_err(chip->card->dev, "allocate_pipes(%d) err=%d\n", + pipe_index, err); + return err; + } } - spin_unlock_irq(&chip->lock); dev_dbg(chip->card->dev, "allocate_pipes()=%d\n", pipe_index); dev_dbg(chip->card->dev, @@ -600,9 +593,8 @@ static int init_engine(struct snd_pcm_substream *substream, smp_wmb(); chip->substream[pipe_index] = substream; chip->rate_set = 1; - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); set_sample_rate(chip, hw_params->rate_num / hw_params->rate_den); - spin_unlock_irq(&chip->lock); return 0; } @@ -664,14 +656,13 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) chip = snd_pcm_substream_chip(substream); pipe = (struct audiopipe *) substream->runtime->private_data; - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); if (pipe->index >= 0) { dev_dbg(chip->card->dev, "pcm_hw_free(%d)\n", pipe->index); free_pipes(chip, pipe); chip->substream[pipe->index] = NULL; pipe->index = -1; } - spin_unlock_irq(&chip->lock); return 0; } @@ -721,15 +712,12 @@ static int pcm_prepare(struct snd_pcm_substream *substream) * exclusive control */ - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); - if (snd_BUG_ON(!is_pipe_allocated(chip, pipe_index))) { - spin_unlock_irq(&chip->lock); + if (snd_BUG_ON(!is_pipe_allocated(chip, pipe_index))) return -EINVAL; - } set_audio_format(chip, pipe_index, &format); - spin_unlock_irq(&chip->lock); return 0; } @@ -753,7 +741,7 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) } } - spin_lock(&chip->lock); + guard(spinlock)(&chip->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_START: @@ -801,7 +789,6 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) default: err = -EINVAL; } - spin_unlock(&chip->lock); return err; } @@ -1018,7 +1005,7 @@ static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol, changed = 0; chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); for (c = 0; c < num_busses_out(chip); c++) { gain = ucontrol->value.integer.value[c]; /* Ignore out of range values */ @@ -1031,7 +1018,6 @@ static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol, } if (changed) update_output_line_level(chip); - spin_unlock_irq(&chip->lock); return changed; } @@ -1099,7 +1085,7 @@ static int snd_echo_input_gain_put(struct snd_kcontrol *kcontrol, changed = 0; chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); for (c = 0; c < num_analog_busses_in(chip); c++) { gain = ucontrol->value.integer.value[c]; /* Ignore out of range values */ @@ -1112,7 +1098,6 @@ static int snd_echo_input_gain_put(struct snd_kcontrol *kcontrol, } if (changed) update_input_line_level(chip); - spin_unlock_irq(&chip->lock); return changed; } @@ -1168,7 +1153,7 @@ static int snd_echo_output_nominal_put(struct snd_kcontrol *kcontrol, changed = 0; chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); for (c = 0; c < num_analog_busses_out(chip); c++) { if (chip->nominal_level[c] != ucontrol->value.integer.value[c]) { set_nominal_level(chip, c, @@ -1178,7 +1163,6 @@ static int snd_echo_output_nominal_put(struct snd_kcontrol *kcontrol, } if (changed) update_output_line_level(chip); - spin_unlock_irq(&chip->lock); return changed; } @@ -1231,7 +1215,7 @@ static int snd_echo_input_nominal_put(struct snd_kcontrol *kcontrol, changed = 0; chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); for (c = 0; c < num_analog_busses_in(chip); c++) { if (chip->nominal_level[bx_analog_in(chip) + c] != ucontrol->value.integer.value[c]) { @@ -1244,7 +1228,6 @@ static int snd_echo_input_nominal_put(struct snd_kcontrol *kcontrol, update_output_line_level(chip); /* "Output" is not a mistake * here. */ - spin_unlock_irq(&chip->lock); return changed; } @@ -1304,10 +1287,9 @@ static int snd_echo_mixer_put(struct snd_kcontrol *kcontrol, if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT) return -EINVAL; if (chip->monitor_gain[out][in] != gain) { - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); set_monitor_gain(chip, out, in, gain); update_output_line_level(chip); - spin_unlock_irq(&chip->lock); changed = 1; } return changed; @@ -1367,10 +1349,9 @@ static int snd_echo_vmixer_put(struct snd_kcontrol *kcontrol, if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT) return -EINVAL; if (chip->vmixer_gain[out][vch] != ucontrol->value.integer.value[0]) { - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); set_vmixer_gain(chip, out, vch, ucontrol->value.integer.value[0]); update_vmixer_level(chip); - spin_unlock_irq(&chip->lock); changed = 1; } return changed; @@ -1440,7 +1421,7 @@ static int snd_echo_digital_mode_put(struct snd_kcontrol *kcontrol, if (dmode != chip->digital_mode) { /* mode_mutex is required to make this operation atomic wrt pcm_digital_*_open() and set_input_clock() functions. */ - mutex_lock(&chip->mode_mutex); + guard(mutex)(&chip->mode_mutex); /* Do not allow the user to change the digital mode when a pcm device is open because it also changes the number of channels @@ -1460,7 +1441,6 @@ static int snd_echo_digital_mode_put(struct snd_kcontrol *kcontrol, if (changed >= 0) changed = 1; /* No errors */ } - mutex_unlock(&chip->mode_mutex); } return changed; } @@ -1507,9 +1487,8 @@ static int snd_echo_spdif_mode_put(struct snd_kcontrol *kcontrol, chip = snd_kcontrol_chip(kcontrol); mode = !!ucontrol->value.enumerated.item[0]; if (mode != chip->professional_spdif) { - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); set_professional_spdif(chip, mode); - spin_unlock_irq(&chip->lock); return 1; } return 0; @@ -1573,13 +1552,11 @@ static int snd_echo_clock_source_put(struct snd_kcontrol *kcontrol, return -EINVAL; dclock = chip->clock_source_list[eclock]; if (chip->input_clock != dclock) { - mutex_lock(&chip->mode_mutex); - spin_lock_irq(&chip->lock); + guard(mutex)(&chip->mode_mutex); + guard(spinlock_irq)(&chip->lock); changed = set_input_clock(chip, dclock); if (!changed) changed = 1; /* no errors */ - spin_unlock_irq(&chip->lock); - mutex_unlock(&chip->mode_mutex); } if (changed < 0) @@ -1623,9 +1600,8 @@ static int snd_echo_phantom_power_put(struct snd_kcontrol *kcontrol, power = !!ucontrol->value.integer.value[0]; if (chip->phantom_power != power) { - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); changed = set_phantom_power(chip, power); - spin_unlock_irq(&chip->lock); if (changed == 0) changed = 1; /* no errors */ } @@ -1666,9 +1642,8 @@ static int snd_echo_automute_put(struct snd_kcontrol *kcontrol, automute = !!ucontrol->value.integer.value[0]; if (chip->digital_in_automute != automute) { - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); changed = set_input_auto_mute(chip, automute); - spin_unlock_irq(&chip->lock); if (changed == 0) changed = 1; /* no errors */ } @@ -1696,9 +1671,8 @@ static int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol, struct echoaudio *chip; chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); set_meters_on(chip, ucontrol->value.integer.value[0]); - spin_unlock_irq(&chip->lock); return 1; } @@ -2143,17 +2117,13 @@ static int snd_echo_suspend(struct device *dev) if (chip->midi_out) snd_echo_midi_output_trigger(chip->midi_out, 0); #endif - spin_lock_irq(&chip->lock); - if (wait_handshake(chip)) { - spin_unlock_irq(&chip->lock); - return -EIO; - } - clear_handshake(chip); - if (send_vector(chip, DSP_VC_GO_COMATOSE) < 0) { - spin_unlock_irq(&chip->lock); - return -EIO; + scoped_guard(spinlock_irq, &chip->lock) { + if (wait_handshake(chip)) + return -EIO; + clear_handshake(chip); + if (send_vector(chip, DSP_VC_GO_COMATOSE) < 0) + return -EIO; } - spin_unlock_irq(&chip->lock); chip->dsp_code = NULL; free_irq(chip->irq, chip); diff --git a/sound/pci/echoaudio/echoaudio_3g.c b/sound/pci/echoaudio/echoaudio_3g.c index 18b4d4b4d38d..c9ee98ea3c71 100644 --- a/sound/pci/echoaudio/echoaudio_3g.c +++ b/sound/pci/echoaudio/echoaudio_3g.c @@ -119,7 +119,7 @@ static int set_digital_mode(struct echoaudio *chip, u8 mode) * updated by the DSP comm object. */ if (err >= 0 && previous_mode != mode && (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) { - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); for (o = 0; o < num_busses_out(chip); o++) for (i = 0; i < num_busses_in(chip); i++) set_monitor_gain(chip, o, i, @@ -134,7 +134,6 @@ static int set_digital_mode(struct echoaudio *chip, u8 mode) for (o = 0; o < num_busses_out(chip); o++) set_output_gain(chip, o, chip->output_gain[o]); update_output_line_level(chip); - spin_unlock_irq(&chip->lock); } return err; @@ -396,7 +395,7 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) return -EINVAL; } - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); if (incompatible_clock) { chip->sample_rate = 48000; @@ -422,7 +421,6 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) } err = write_control_reg(chip, control_reg, get_frq_reg(chip), 1); - spin_unlock_irq(&chip->lock); if (err < 0) return err; chip->digital_mode = mode; diff --git a/sound/pci/echoaudio/gina24_dsp.c b/sound/pci/echoaudio/gina24_dsp.c index 56e9d1b9b330..78fbac9f3eac 100644 --- a/sound/pci/echoaudio/gina24_dsp.c +++ b/sound/pci/echoaudio/gina24_dsp.c @@ -305,7 +305,7 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) return -EINVAL; } - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); if (incompatible_clock) { /* Switch to 48KHz, internal */ chip->sample_rate = 48000; @@ -336,7 +336,6 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) } err = write_control_reg(chip, control_reg, true); - spin_unlock_irq(&chip->lock); if (err < 0) return err; chip->digital_mode = mode; diff --git a/sound/pci/echoaudio/layla24_dsp.c b/sound/pci/echoaudio/layla24_dsp.c index ef27805d63f6..decfccb1e803 100644 --- a/sound/pci/echoaudio/layla24_dsp.c +++ b/sound/pci/echoaudio/layla24_dsp.c @@ -358,16 +358,15 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) if (incompatible_clock) { /* Switch to 48KHz, internal */ chip->sample_rate = 48000; - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); set_input_clock(chip, ECHO_CLOCK_INTERNAL); - spin_unlock_irq(&chip->lock); } /* switch_asic() can sleep */ if (switch_asic(chip, asic) < 0) return -EIO; - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); /* Tweak the control register */ control_reg = le32_to_cpu(chip->comm_page->control_register); @@ -387,7 +386,6 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) } err = write_control_reg(chip, control_reg, true); - spin_unlock_irq(&chip->lock); if (err < 0) return err; chip->digital_mode = mode; diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c index 4ee230794b4e..dd5212644844 100644 --- a/sound/pci/echoaudio/midi.c +++ b/sound/pci/echoaudio/midi.c @@ -167,9 +167,8 @@ static void snd_echo_midi_input_trigger(struct snd_rawmidi_substream *substream, struct echoaudio *chip = substream->rmidi->private_data; if (up != chip->midi_input_enabled) { - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); enable_midi_input(chip, up); - spin_unlock_irq(&chip->lock); chip->midi_input_enabled = up; } } @@ -201,14 +200,13 @@ static int snd_echo_midi_output_open(struct snd_rawmidi_substream *substream) static void snd_echo_midi_output_write(struct timer_list *t) { struct echoaudio *chip = timer_container_of(chip, t, timer); - unsigned long flags; int bytes, sent, time; unsigned char buf[MIDI_OUT_BUFFER_SIZE - 1]; /* No interrupts are involved: we have to check at regular intervals if the card's output buffer has room for new data. */ sent = 0; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); chip->midi_full = 0; if (!snd_rawmidi_transmit_empty(chip->midi_out)) { bytes = snd_rawmidi_transmit_peek(chip->midi_out, buf, @@ -242,7 +240,6 @@ static void snd_echo_midi_output_write(struct timer_list *t) dev_dbg(chip->card->dev, "Timer armed(%d)\n", ((time * HZ + 999) / 1000)); } - spin_unlock_irqrestore(&chip->lock, flags); } @@ -251,25 +248,29 @@ static void snd_echo_midi_output_trigger(struct snd_rawmidi_substream *substream int up) { struct echoaudio *chip = substream->rmidi->private_data; + bool remove_timer = false; dev_dbg(chip->card->dev, "snd_echo_midi_output_trigger(%d)\n", up); - spin_lock_irq(&chip->lock); - if (up) { - if (!chip->tinuse) { - timer_setup(&chip->timer, snd_echo_midi_output_write, - 0); - chip->tinuse = 1; - } - } else { - if (chip->tinuse) { - chip->tinuse = 0; - spin_unlock_irq(&chip->lock); - timer_delete_sync(&chip->timer); - dev_dbg(chip->card->dev, "Timer removed\n"); - return; + scoped_guard(spinlock_irq, &chip->lock) { + if (up) { + if (!chip->tinuse) { + timer_setup(&chip->timer, snd_echo_midi_output_write, + 0); + chip->tinuse = 1; + } + } else { + if (chip->tinuse) { + chip->tinuse = 0; + remove_timer = true; + } } } - spin_unlock_irq(&chip->lock); + + if (remove_timer) { + timer_delete_sync(&chip->timer); + dev_dbg(chip->card->dev, "Timer removed\n"); + return; + } if (up && !chip->midi_full) snd_echo_midi_output_write(&chip->timer); diff --git a/sound/pci/echoaudio/mona_dsp.c b/sound/pci/echoaudio/mona_dsp.c index f8e7bb6ce040..9bb6a174745c 100644 --- a/sound/pci/echoaudio/mona_dsp.c +++ b/sound/pci/echoaudio/mona_dsp.c @@ -381,7 +381,7 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) return -EINVAL; } - spin_lock_irq(&chip->lock); + guard(spinlock_irq)(&chip->lock); if (incompatible_clock) { /* Switch to 48KHz, internal */ chip->sample_rate = 48000; @@ -413,7 +413,6 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) } err = write_control_reg(chip, control_reg, false); - spin_unlock_irq(&chip->lock); if (err < 0) return err; chip->digital_mode = mode; diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index bbe252b8916c..b2fe2d164ba8 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -745,12 +745,12 @@ static void emu1010_clock_event(struct snd_emu10k1 *emu) { struct snd_ctl_elem_id id; - spin_lock_irq(&emu->reg_lock); - // This is the only thing that can actually happen. - emu->emu1010.clock_source = emu->emu1010.clock_fallback; - emu->emu1010.wclock = 1 - emu->emu1010.clock_source; - snd_emu1010_update_clock(emu); - spin_unlock_irq(&emu->reg_lock); + scoped_guard(spinlock_irq, &emu->reg_lock) { + // This is the only thing that can actually happen. + emu->emu1010.clock_source = emu->emu1010.clock_fallback; + emu->emu1010.wclock = 1 - emu->emu1010.clock_source; + snd_emu1010_update_clock(emu); + } snd_ctl_build_ioff(&id, emu->ctl_clock_source, 0); snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE, &id); } @@ -768,7 +768,7 @@ static void emu1010_work(struct work_struct *work) return; #endif - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &sts); @@ -779,8 +779,6 @@ static void emu1010_work(struct work_struct *work) if (sts & EMU_HANA_IRQ_WCLK_CHANGED) emu1010_clock_event(emu); - - snd_emu1010_fpga_unlock(emu); } static void emu1010_interrupt(struct snd_emu10k1 *emu) @@ -814,13 +812,13 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) * Proper init follows in snd_emu10k1_init(). */ outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); dev_info(emu->card->dev, "emu1010: Loading Hana Firmware\n"); err = snd_emu1010_load_firmware(emu, 0, &emu->firmware); if (err < 0) { dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n"); - goto fail; + return err; } /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ @@ -830,8 +828,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) dev_info(emu->card->dev, "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n", reg); - err = -ENODEV; - goto fail; + return -ENODEV; } dev_info(emu->card->dev, "emu1010: Hana Firmware loaded\n"); @@ -891,9 +888,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) // so it is safe to simply enable the outputs. snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); -fail: - snd_emu1010_fpga_unlock(emu); - return err; + return 0; } /* * Create the EMU10K1 instance diff --git a/sound/pci/emu10k1/emu10k1_synth.c b/sound/pci/emu10k1/emu10k1_synth.c index 68dfcb24b889..662d20eb9689 100644 --- a/sound/pci/emu10k1/emu10k1_synth.c +++ b/sound/pci/emu10k1/emu10k1_synth.c @@ -55,10 +55,9 @@ static int snd_emu10k1_synth_probe(struct device *_dev) return -ENOMEM; } - spin_lock_irq(&hw->voice_lock); + guard(spinlock_irq)(&hw->voice_lock); hw->synth = emux; hw->get_synth_voice = snd_emu10k1_synth_get_voice; - spin_unlock_irq(&hw->voice_lock); dev->driver_data = emux; @@ -77,10 +76,10 @@ static int snd_emu10k1_synth_remove(struct device *_dev) emux = dev->driver_data; hw = emux->hw; - spin_lock_irq(&hw->voice_lock); - hw->synth = NULL; - hw->get_synth_voice = NULL; - spin_unlock_irq(&hw->voice_lock); + scoped_guard(spinlock_irq, &hw->voice_lock) { + hw->synth = NULL; + hw->get_synth_voice = NULL; + } snd_emux_free(emux); return 0; diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 8c18ad987223..9607a0f7174b 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -281,16 +281,13 @@ static unsigned int snd_emu10k1x_ptr_read(struct emu10k1x * emu, unsigned int reg, unsigned int chn) { - unsigned long flags; - unsigned int regptr, val; + unsigned int regptr; regptr = (reg << 16) | chn; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outl(regptr, emu->port + PTR); - val = inl(emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; + return inl(emu->port + DATA); } static void snd_emu10k1x_ptr_write(struct emu10k1x *emu, @@ -299,45 +296,36 @@ static void snd_emu10k1x_ptr_write(struct emu10k1x *emu, unsigned int data) { unsigned int regptr; - unsigned long flags; regptr = (reg << 16) | chn; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outl(regptr, emu->port + PTR); outl(data, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } static void snd_emu10k1x_intr_enable(struct emu10k1x *emu, unsigned int intrenb) { - unsigned long flags; unsigned int intr_enable; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); intr_enable = inl(emu->port + INTE) | intrenb; outl(intr_enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); } static void snd_emu10k1x_intr_disable(struct emu10k1x *emu, unsigned int intrenb) { - unsigned long flags; unsigned int intr_enable; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); intr_enable = inl(emu->port + INTE) & ~intrenb; outl(intr_enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); } static void snd_emu10k1x_gpio_write(struct emu10k1x *emu, unsigned int value) { - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outl(value, emu->port + GPIO); - spin_unlock_irqrestore(&emu->emu_lock, flags); } static void snd_emu10k1x_pcm_free_substream(struct snd_pcm_runtime *runtime) @@ -694,26 +682,20 @@ static unsigned short snd_emu10k1x_ac97_read(struct snd_ac97 *ac97, unsigned short reg) { struct emu10k1x *emu = ac97->private_data; - unsigned long flags; - unsigned short val; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outb(reg, emu->port + AC97ADDRESS); - val = inw(emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; + return inw(emu->port + AC97DATA); } static void snd_emu10k1x_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) { struct emu10k1x *emu = ac97->private_data; - unsigned long flags; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outb(reg, emu->port + AC97ADDRESS); outw(val, emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } static int snd_emu10k1x_ac97(struct emu10k1x *chip) @@ -966,14 +948,12 @@ static void snd_emu10k1x_proc_reg_read(struct snd_info_entry *entry, { struct emu10k1x *emu = entry->private_data; unsigned long value,value1,value2; - unsigned long flags; int i; snd_iprintf(buffer, "Registers:\n\n"); for(i = 0; i < 0x20; i+=4) { - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); value = inl(emu->port + i); - spin_unlock_irqrestore(&emu->emu_lock, flags); snd_iprintf(buffer, "Register %02X: %08lX\n", i, value); } snd_iprintf(buffer, "\nRegisters\n\n"); @@ -1206,28 +1186,28 @@ static void do_emu10k1x_midi_interrupt(struct emu10k1x *emu, return; } - spin_lock(&midi->input_lock); - if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) { - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_INPUT)) { - mpu401_clear_rx(emu, midi); - } else { - byte = mpu401_read_data(emu, midi); - if (midi->substream_input) - snd_rawmidi_receive(midi->substream_input, &byte, 1); + scoped_guard(spinlock, &midi->input_lock) { + if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) { + if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_INPUT)) { + mpu401_clear_rx(emu, midi); + } else { + byte = mpu401_read_data(emu, midi); + if (midi->substream_input) + snd_rawmidi_receive(midi->substream_input, &byte, 1); + } } } - spin_unlock(&midi->input_lock); - spin_lock(&midi->output_lock); - if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) { - if (midi->substream_output && - snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { - mpu401_write_data(emu, midi, byte); - } else { - snd_emu10k1x_intr_disable(emu, midi->tx_enable); + scoped_guard(spinlock, &midi->output_lock) { + if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) { + if (midi->substream_output && + snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { + mpu401_write_data(emu, midi, byte); + } else { + snd_emu10k1x_intr_disable(emu, midi->tx_enable); + } } } - spin_unlock(&midi->output_lock); } static void snd_emu10k1x_midi_interrupt(struct emu10k1x *emu, unsigned int status) @@ -1238,29 +1218,28 @@ static void snd_emu10k1x_midi_interrupt(struct emu10k1x *emu, unsigned int statu static int snd_emu10k1x_midi_cmd(struct emu10k1x * emu, struct emu10k1x_midi *midi, unsigned char cmd, int ack) { - unsigned long flags; int timeout, ok; - spin_lock_irqsave(&midi->input_lock, flags); - mpu401_write_data(emu, midi, 0x00); - /* mpu401_clear_rx(emu, midi); */ - - mpu401_write_cmd(emu, midi, cmd); - if (ack) { - ok = 0; - timeout = 10000; - while (!ok && timeout-- > 0) { - if (mpu401_input_avail(emu, midi)) { - if (mpu401_read_data(emu, midi) == MPU401_ACK) - ok = 1; + scoped_guard(spinlock_irqsave, &midi->input_lock) { + mpu401_write_data(emu, midi, 0x00); + /* mpu401_clear_rx(emu, midi); */ + + mpu401_write_cmd(emu, midi, cmd); + if (ack) { + ok = 0; + timeout = 10000; + while (!ok && timeout-- > 0) { + if (mpu401_input_avail(emu, midi)) { + if (mpu401_read_data(emu, midi) == MPU401_ACK) + ok = 1; + } } - } - if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK) + if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK) + ok = 1; + } else { ok = 1; - } else { - ok = 1; + } } - spin_unlock_irqrestore(&midi->input_lock, flags); if (!ok) { dev_err(emu->card->dev, "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", @@ -1276,100 +1255,78 @@ static int snd_emu10k1x_midi_input_open(struct snd_rawmidi_substream *substream) { struct emu10k1x *emu; struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; emu = midi->emu; if (snd_BUG_ON(!emu)) return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= EMU10K1X_MIDI_MODE_INPUT; - midi->substream_input = substream; - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 1)) - goto error_out; - if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) - goto error_out; - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); + scoped_guard(spinlock_irqsave, &midi->open_lock) { + midi->midi_mode |= EMU10K1X_MIDI_MODE_INPUT; + midi->substream_input = substream; + if (midi->midi_mode & EMU10K1X_MIDI_MODE_OUTPUT) + return 0; } + if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 1)) + return -EIO; + if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) + return -EIO; return 0; - -error_out: - return -EIO; } static int snd_emu10k1x_midi_output_open(struct snd_rawmidi_substream *substream) { struct emu10k1x *emu; struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; emu = midi->emu; if (snd_BUG_ON(!emu)) return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= EMU10K1X_MIDI_MODE_OUTPUT; - midi->substream_output = substream; - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 1)) - goto error_out; - if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) - goto error_out; - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); + scoped_guard(spinlock_irqsave, &midi->open_lock) { + midi->midi_mode |= EMU10K1X_MIDI_MODE_OUTPUT; + midi->substream_output = substream; + if (midi->midi_mode & EMU10K1X_MIDI_MODE_INPUT) + return 0; } + if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 1)) + return -EIO; + if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) + return -EIO; return 0; - -error_out: - return -EIO; } static int snd_emu10k1x_midi_input_close(struct snd_rawmidi_substream *substream) { struct emu10k1x *emu; struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; - int err = 0; emu = midi->emu; if (snd_BUG_ON(!emu)) return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - snd_emu10k1x_intr_disable(emu, midi->rx_enable); - midi->midi_mode &= ~EMU10K1X_MIDI_MODE_INPUT; - midi->substream_input = NULL; - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - err = snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); + scoped_guard(spinlock_irqsave, &midi->open_lock) { + snd_emu10k1x_intr_disable(emu, midi->rx_enable); + midi->midi_mode &= ~EMU10K1X_MIDI_MODE_INPUT; + midi->substream_input = NULL; + if (midi->midi_mode & EMU10K1X_MIDI_MODE_OUTPUT) + return 0; } - return err; + return snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 0); } static int snd_emu10k1x_midi_output_close(struct snd_rawmidi_substream *substream) { struct emu10k1x *emu; struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; - int err = 0; emu = midi->emu; if (snd_BUG_ON(!emu)) return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - snd_emu10k1x_intr_disable(emu, midi->tx_enable); - midi->midi_mode &= ~EMU10K1X_MIDI_MODE_OUTPUT; - midi->substream_output = NULL; - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - err = snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); + scoped_guard(spinlock_irqsave, &midi->open_lock) { + snd_emu10k1x_intr_disable(emu, midi->tx_enable); + midi->midi_mode &= ~EMU10K1X_MIDI_MODE_OUTPUT; + midi->substream_output = NULL; + if (midi->midi_mode & EMU10K1X_MIDI_MODE_INPUT) + return 0; } - return err; + return snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 0); } static void snd_emu10k1x_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) @@ -1390,7 +1347,6 @@ static void snd_emu10k1x_midi_output_trigger(struct snd_rawmidi_substream *subst { struct emu10k1x *emu; struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; emu = midi->emu; if (snd_BUG_ON(!emu)) @@ -1401,22 +1357,21 @@ static void snd_emu10k1x_midi_output_trigger(struct snd_rawmidi_substream *subst unsigned char byte; /* try to send some amount of bytes here before interrupts */ - spin_lock_irqsave(&midi->output_lock, flags); - while (max > 0) { - if (mpu401_output_ready(emu, midi)) { - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_OUTPUT) || - snd_rawmidi_transmit(substream, &byte, 1) != 1) { - /* no more data */ - spin_unlock_irqrestore(&midi->output_lock, flags); - return; + scoped_guard(spinlock_irqsave, &midi->output_lock) { + while (max > 0) { + if (mpu401_output_ready(emu, midi)) { + if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_OUTPUT) || + snd_rawmidi_transmit(substream, &byte, 1) != 1) { + /* no more data */ + return; + } + mpu401_write_data(emu, midi, byte); + max--; + } else { + break; } - mpu401_write_data(emu, midi, byte); - max--; - } else { - break; } } - spin_unlock_irqrestore(&midi->output_lock, flags); snd_emu10k1x_intr_enable(emu, midi->tx_enable); } else { snd_emu10k1x_intr_disable(emu, midi->tx_enable); diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 7db0660e6b61..37af7bf76347 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -440,13 +440,11 @@ int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu, void *private_data, struct snd_emu10k1_fx8010_irq *irq) { - unsigned long flags; - irq->handler = handler; irq->gpr_running = gpr_running; irq->private_data = private_data; irq->next = NULL; - spin_lock_irqsave(&emu->fx8010.irq_lock, flags); + guard(spinlock_irqsave)(&emu->fx8010.irq_lock); if (emu->fx8010.irq_handlers == NULL) { emu->fx8010.irq_handlers = irq; emu->dsp_interrupt = snd_emu10k1_fx8010_interrupt; @@ -455,7 +453,6 @@ int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu, irq->next = emu->fx8010.irq_handlers; emu->fx8010.irq_handlers = irq; } - spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags); return 0; } @@ -463,9 +460,8 @@ int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu, struct snd_emu10k1_fx8010_irq *irq) { struct snd_emu10k1_fx8010_irq *tmp; - unsigned long flags; - spin_lock_irqsave(&emu->fx8010.irq_lock, flags); + guard(spinlock_irqsave)(&emu->fx8010.irq_lock); tmp = emu->fx8010.irq_handlers; if (tmp == irq) { emu->fx8010.irq_handlers = tmp->next; @@ -479,7 +475,6 @@ int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu, if (tmp) tmp->next = tmp->next->next; } - spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags); return 0; } @@ -1026,12 +1021,12 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, struct snd_emu10k1_fx8010_code *icode, bool in_kernel) { - int err = 0; + int err; - mutex_lock(&emu->fx8010.lock); + guard(mutex)(&emu->fx8010.lock); err = snd_emu10k1_verify_controls(emu, icode, in_kernel); if (err < 0) - goto __error; + return err; strscpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name)); /* stop FX processor - this may be dangerous, but it's better to miss some samples than generate wrong ones - [jk] */ @@ -1042,27 +1037,25 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, /* ok, do the main job */ err = snd_emu10k1_del_controls(emu, icode, in_kernel); if (err < 0) - goto __error; + return err; err = snd_emu10k1_gpr_poke(emu, icode, in_kernel); if (err < 0) - goto __error; + return err; err = snd_emu10k1_tram_poke(emu, icode, in_kernel); if (err < 0) - goto __error; + return err; err = snd_emu10k1_code_poke(emu, icode, in_kernel); if (err < 0) - goto __error; + return err; err = snd_emu10k1_add_controls(emu, icode, in_kernel); if (err < 0) - goto __error; + return err; /* start FX processor when the DSP code is updated */ if (emu->audigy) snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg); else snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg); - __error: - mutex_unlock(&emu->fx8010.lock); - return err; + return 0; } static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu, @@ -1070,7 +1063,7 @@ static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu, { int err; - mutex_lock(&emu->fx8010.lock); + guard(mutex)(&emu->fx8010.lock); strscpy(icode->name, emu->fx8010.name, sizeof(icode->name)); /* ok, do the main job */ err = snd_emu10k1_gpr_peek(emu, icode); @@ -1080,7 +1073,6 @@ static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu, err = snd_emu10k1_code_peek(emu, icode); if (err >= 0) err = snd_emu10k1_list_controls(emu, icode); - mutex_unlock(&emu->fx8010.lock); return err; } @@ -1088,7 +1080,6 @@ static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu, struct snd_emu10k1_fx8010_pcm_rec *ipcm) { unsigned int i; - int err = 0; struct snd_emu10k1_fx8010_pcm *pcm; if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT) @@ -1098,20 +1089,16 @@ static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu, if (ipcm->channels > 32) return -EINVAL; pcm = &emu->fx8010.pcm[ipcm->substream]; - mutex_lock(&emu->fx8010.lock); - spin_lock_irq(&emu->reg_lock); - if (pcm->opened) { - err = -EBUSY; - goto __error; - } + guard(mutex)(&emu->fx8010.lock); + guard(spinlock_irq)(&emu->reg_lock); + if (pcm->opened) + return -EBUSY; if (ipcm->channels == 0) { /* remove */ pcm->valid = 0; } else { /* FIXME: we need to add universal code to the PCM transfer routine */ - if (ipcm->channels != 2) { - err = -EINVAL; - goto __error; - } + if (ipcm->channels != 2) + return -EINVAL; pcm->valid = 1; pcm->opened = 0; pcm->channels = ipcm->channels; @@ -1126,17 +1113,13 @@ static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu, for (i = 0; i < pcm->channels; i++) pcm->etram[i] = ipcm->etram[i]; } - __error: - spin_unlock_irq(&emu->reg_lock); - mutex_unlock(&emu->fx8010.lock); - return err; + return 0; } static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu, struct snd_emu10k1_fx8010_pcm_rec *ipcm) { unsigned int i; - int err = 0; struct snd_emu10k1_fx8010_pcm *pcm; if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT) @@ -1144,8 +1127,8 @@ static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu, ipcm->substream = array_index_nospec(ipcm->substream, EMU10K1_FX8010_PCM_COUNT); pcm = &emu->fx8010.pcm[ipcm->substream]; - mutex_lock(&emu->fx8010.lock); - spin_lock_irq(&emu->reg_lock); + guard(mutex)(&emu->fx8010.lock); + guard(spinlock_irq)(&emu->reg_lock); ipcm->channels = pcm->channels; ipcm->tram_start = pcm->tram_start; ipcm->buffer_size = pcm->buffer_size; @@ -1159,9 +1142,7 @@ static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu, ipcm->etram[i] = pcm->etram[i]; ipcm->res1 = ipcm->res2 = 0; ipcm->pad = 0; - spin_unlock_irq(&emu->reg_lock); - mutex_unlock(&emu->fx8010.lock); - return err; + return 0; } #define SND_EMU10K1_GPR_CONTROLS 44 @@ -2415,9 +2396,9 @@ int snd_emu10k1_fx8010_tram_setup(struct snd_emu10k1 *emu, u32 size) } if ((emu->fx8010.etram_pages.bytes / 2) == size) return 0; - spin_lock_irq(&emu->emu_lock); - outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG); - spin_unlock_irq(&emu->emu_lock); + scoped_guard(spinlock_irq, &emu->emu_lock) { + outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG); + } snd_emu10k1_ptr_write(emu, TCB, 0, 0); snd_emu10k1_ptr_write(emu, TCBS, 0, TCBS_BUFFSIZE_16K); if (emu->fx8010.etram_pages.area != NULL) { @@ -2433,9 +2414,9 @@ int snd_emu10k1_fx8010_tram_setup(struct snd_emu10k1 *emu, u32 size) memset(emu->fx8010.etram_pages.area, 0, size * 2); snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr); snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg); - spin_lock_irq(&emu->emu_lock); - outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); - spin_unlock_irq(&emu->emu_lock); + scoped_guard(spinlock_irq, &emu->emu_lock) { + outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); + } } return 0; @@ -2547,9 +2528,9 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un return -EPERM; if (get_user(addr, (unsigned int __user *)argp)) return -EFAULT; - mutex_lock(&emu->fx8010.lock); - res = snd_emu10k1_fx8010_tram_setup(emu, addr); - mutex_unlock(&emu->fx8010.lock); + scoped_guard(mutex, &emu->fx8010.lock) { + res = snd_emu10k1_fx8010_tram_setup(emu, addr); + } return res; case SNDRV_EMU10K1_IOCTL_STOP: if (!capable(CAP_SYS_ADMIN)) diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index d665d5d1ad7c..f4906ab30c02 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -662,9 +662,8 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol, change = (emu->emu1010.output_source[channel] != val); if (change) { emu->emu1010.output_source[channel] = val; - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); snd_emu1010_output_source_apply(emu, channel, val); - snd_emu1010_fpga_unlock(emu); } return change; } @@ -708,9 +707,8 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol, change = (emu->emu1010.input_source[channel] != val); if (change) { emu->emu1010.input_source[channel] = val; - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); snd_emu1010_input_source_apply(emu, channel, val); - snd_emu1010_fpga_unlock(emu); } return change; } @@ -980,30 +978,25 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol, const struct snd_emu1010_clock_info *emu_ci = &emu1010_clock_info[emu1010_idx(emu)]; unsigned int val; - int change = 0; val = ucontrol->value.enumerated.item[0] ; if (val >= emu_ci->num) return -EINVAL; - snd_emu1010_fpga_lock(emu); - spin_lock_irq(&emu->reg_lock); - change = (emu->emu1010.clock_source != val); - if (change) { + guard(snd_emu1010_fpga_lock)(emu); + scoped_guard(spinlock_irq, &emu->reg_lock) { + if (emu->emu1010.clock_source == val) + return 0; emu->emu1010.clock_source = val; emu->emu1010.wclock = emu_ci->vals[val]; snd_emu1010_update_clock(emu); snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE); snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, emu->emu1010.wclock); - spin_unlock_irq(&emu->reg_lock); - - msleep(10); // Allow DLL to settle - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); - } else { - spin_unlock_irq(&emu->reg_lock); } - snd_emu1010_fpga_unlock(emu); - return change; + + msleep(10); // Allow DLL to settle + snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); + return 1; } static const struct snd_kcontrol_new snd_emu1010_clock_source = @@ -1211,13 +1204,13 @@ static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, change = (emu->i2c_capture_source != source_id); if (change) { snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */ - spin_lock_irq(&emu->emu_lock); - gpio = inw(emu->port + A_IOCFG); - if (source_id==0) - outw(gpio | 0x4, emu->port + A_IOCFG); - else - outw(gpio & ~0x4, emu->port + A_IOCFG); - spin_unlock_irq(&emu->emu_lock); + scoped_guard(spinlock_irq, &emu->emu_lock) { + gpio = inw(emu->port + A_IOCFG); + if (source_id == 0) + outw(gpio | 0x4, emu->port + A_IOCFG); + else + outw(gpio & ~0x4, emu->port + A_IOCFG); + } ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ @@ -1378,14 +1371,13 @@ static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol, } - spin_lock_irq(&emu->reg_lock); + guard(spinlock_irq)(&emu->reg_lock); reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); tmp = reg & ~A_SPDIF_RATE_MASK; tmp |= val; change = (tmp != reg); if (change) snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); - spin_unlock_irq(&emu->reg_lock); return change; } @@ -1509,7 +1501,7 @@ static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol, int num_efx = emu->audigy ? 8 : 4; int mask = emu->audigy ? 0x3f : 0x0f; - spin_lock_irq(&emu->reg_lock); + guard(spinlock_irq)(&emu->reg_lock); for (voice = 0; voice < 3; voice++) for (idx = 0; idx < num_efx; idx++) { val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask; @@ -1529,7 +1521,6 @@ static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol, &mix->send_routing[0][0]); } } - spin_unlock_irq(&emu->reg_lock); return change; } @@ -1577,7 +1568,7 @@ static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol, int change = 0, idx, val; int num_efx = emu->audigy ? 8 : 4; - spin_lock_irq(&emu->reg_lock); + guard(spinlock_irq)(&emu->reg_lock); for (idx = 0; idx < 3*num_efx; idx++) { val = ucontrol->value.integer.value[idx] & 255; if (mix->send_volume[idx/num_efx][idx%num_efx] != val) { @@ -1596,7 +1587,6 @@ static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol, &mix->send_volume[0][0]); } } - spin_unlock_irq(&emu->reg_lock); return change; } @@ -1641,7 +1631,7 @@ static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol, &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int change = 0, idx, val; - spin_lock_irq(&emu->reg_lock); + guard(spinlock_irq)(&emu->reg_lock); for (idx = 0; idx < 3; idx++) { unsigned uval = ucontrol->value.integer.value[idx] & 0x1ffff; val = uval * 0x8000U / 0xffffU; @@ -1658,7 +1648,6 @@ static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol, snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]); } } - spin_unlock_irq(&emu->reg_lock); return change; } @@ -1711,7 +1700,7 @@ static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol, int num_efx = emu->audigy ? 8 : 4; int mask = emu->audigy ? 0x3f : 0x0f; - spin_lock_irq(&emu->reg_lock); + guard(spinlock_irq)(&emu->reg_lock); for (idx = 0; idx < num_efx; idx++) { val = ucontrol->value.integer.value[idx] & mask; if (mix->send_routing[0][idx] != val) { @@ -1726,7 +1715,6 @@ static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol, &mix->send_routing[0][0]); } } - spin_unlock_irq(&emu->reg_lock); return change; } @@ -1774,7 +1762,7 @@ static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol, int change = 0, idx, val; int num_efx = emu->audigy ? 8 : 4; - spin_lock_irq(&emu->reg_lock); + guard(spinlock_irq)(&emu->reg_lock); for (idx = 0; idx < num_efx; idx++) { val = ucontrol->value.integer.value[idx] & 255; if (mix->send_volume[0][idx] != val) { @@ -1788,7 +1776,6 @@ static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol, &mix->send_volume[0][0]); } } - spin_unlock_irq(&emu->reg_lock); return change; } @@ -1833,7 +1820,7 @@ static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol, int change = 0, val; unsigned uval; - spin_lock_irq(&emu->reg_lock); + guard(spinlock_irq)(&emu->reg_lock); uval = ucontrol->value.integer.value[0] & 0x1ffff; val = uval * 0x8000U / 0xffffU; if (mix->attn[0] != val) { @@ -1845,7 +1832,6 @@ static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol, snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]); } } - spin_unlock_irq(&emu->reg_lock); return change; } @@ -1888,7 +1874,7 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol, sw = ucontrol->value.integer.value[0]; if (emu->card_capabilities->invert_shared_spdif) sw = !sw; - spin_lock_irq(&emu->emu_lock); + guard(spinlock_irq)(&emu->emu_lock); if ( emu->card_capabilities->i2c_adc) { /* Do nothing for Audigy 2 ZS Notebook */ } else if (emu->audigy) { @@ -1909,7 +1895,6 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol, reg |= val; outl(reg | val, emu->port + HCFG); } - spin_unlock_irq(&emu->emu_lock); return change; } @@ -2330,9 +2315,9 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, for (i = 0; i < emu_ri->n_outs; i++) emu->emu1010.output_source[i] = emu1010_map_source(emu_ri, emu_ri->out_dflts[i]); - snd_emu1010_fpga_lock(emu); - snd_emu1010_apply_sources(emu); - snd_emu1010_fpga_unlock(emu); + scoped_guard(snd_emu1010_fpga_lock, emu) { + snd_emu1010_apply_sources(emu); + } kctl = emu->ctl_clock_source = snd_ctl_new1(&snd_emu1010_clock_source, emu); err = snd_ctl_add(card, kctl); diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c index efff19bbc0e9..c102a3599225 100644 --- a/sound/pci/emu10k1/emumpu401.c +++ b/sound/pci/emu10k1/emumpu401.c @@ -68,28 +68,28 @@ static void do_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, struct snd_emu10k return; } - spin_lock(&midi->input_lock); - if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) { - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { - mpu401_clear_rx(emu, midi); - } else { - byte = mpu401_read_data(emu, midi); - if (midi->substream_input) - snd_rawmidi_receive(midi->substream_input, &byte, 1); + scoped_guard(spinlock, &midi->input_lock) { + if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) { + if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { + mpu401_clear_rx(emu, midi); + } else { + byte = mpu401_read_data(emu, midi); + if (midi->substream_input) + snd_rawmidi_receive(midi->substream_input, &byte, 1); + } } } - spin_unlock(&midi->input_lock); - spin_lock(&midi->output_lock); - if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) { - if (midi->substream_output && - snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { - mpu401_write_data(emu, midi, byte); - } else { - snd_emu10k1_intr_disable(emu, midi->tx_enable); + scoped_guard(spinlock, &midi->output_lock) { + if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) { + if (midi->substream_output && + snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { + mpu401_write_data(emu, midi, byte); + } else { + snd_emu10k1_intr_disable(emu, midi->tx_enable); + } } } - spin_unlock(&midi->output_lock); } static void snd_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, unsigned int status) @@ -106,26 +106,26 @@ static int snd_emu10k1_midi_cmd(struct snd_emu10k1 * emu, struct snd_emu10k1_mid { int timeout, ok; - spin_lock_irq(&midi->input_lock); - mpu401_write_data(emu, midi, 0x00); - /* mpu401_clear_rx(emu, midi); */ - - mpu401_write_cmd(emu, midi, cmd); - if (ack) { - ok = 0; - timeout = 10000; - while (!ok && timeout-- > 0) { - if (mpu401_input_avail(emu, midi)) { - if (mpu401_read_data(emu, midi) == MPU401_ACK) - ok = 1; + scoped_guard(spinlock_irq, &midi->input_lock) { + mpu401_write_data(emu, midi, 0x00); + /* mpu401_clear_rx(emu, midi); */ + + mpu401_write_cmd(emu, midi, cmd); + if (ack) { + ok = 0; + timeout = 10000; + while (!ok && timeout-- > 0) { + if (mpu401_input_avail(emu, midi)) { + if (mpu401_read_data(emu, midi) == MPU401_ACK) + ok = 1; + } } - } - if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK) + if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK) + ok = 1; + } else { ok = 1; - } else { - ok = 1; + } } - spin_unlock_irq(&midi->input_lock); if (!ok) { dev_err(emu->card->dev, "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", @@ -145,22 +145,17 @@ static int snd_emu10k1_midi_input_open(struct snd_rawmidi_substream *substream) emu = midi->emu; if (snd_BUG_ON(!emu)) return -ENXIO; - spin_lock_irq(&midi->open_lock); - midi->midi_mode |= EMU10K1_MIDI_MODE_INPUT; - midi->substream_input = substream; - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) { - spin_unlock_irq(&midi->open_lock); - if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) - goto error_out; - if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) - goto error_out; - } else { - spin_unlock_irq(&midi->open_lock); + scoped_guard(spinlock_irq, &midi->open_lock) { + midi->midi_mode |= EMU10K1_MIDI_MODE_INPUT; + midi->substream_input = substream; + if (midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) + return 0; } + if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) + return -EIO; + if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) + return -EIO; return 0; - -error_out: - return -EIO; } static int snd_emu10k1_midi_output_open(struct snd_rawmidi_substream *substream) @@ -171,66 +166,53 @@ static int snd_emu10k1_midi_output_open(struct snd_rawmidi_substream *substream) emu = midi->emu; if (snd_BUG_ON(!emu)) return -ENXIO; - spin_lock_irq(&midi->open_lock); - midi->midi_mode |= EMU10K1_MIDI_MODE_OUTPUT; - midi->substream_output = substream; - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { - spin_unlock_irq(&midi->open_lock); - if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) - goto error_out; - if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) - goto error_out; - } else { - spin_unlock_irq(&midi->open_lock); + scoped_guard(spinlock_irq, &midi->open_lock) { + midi->midi_mode |= EMU10K1_MIDI_MODE_OUTPUT; + midi->substream_output = substream; + if (midi->midi_mode & EMU10K1_MIDI_MODE_INPUT) + return 0; } + if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) + return -EIO; + if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) + return -EIO; return 0; - -error_out: - return -EIO; } static int snd_emu10k1_midi_input_close(struct snd_rawmidi_substream *substream) { struct snd_emu10k1 *emu; struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - int err = 0; emu = midi->emu; if (snd_BUG_ON(!emu)) return -ENXIO; - spin_lock_irq(&midi->open_lock); - snd_emu10k1_intr_disable(emu, midi->rx_enable); - midi->midi_mode &= ~EMU10K1_MIDI_MODE_INPUT; - midi->substream_input = NULL; - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) { - spin_unlock_irq(&midi->open_lock); - err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); - } else { - spin_unlock_irq(&midi->open_lock); + scoped_guard(spinlock_irq, &midi->open_lock) { + snd_emu10k1_intr_disable(emu, midi->rx_enable); + midi->midi_mode &= ~EMU10K1_MIDI_MODE_INPUT; + midi->substream_input = NULL; + if (midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) + return 0; } - return err; + return snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); } static int snd_emu10k1_midi_output_close(struct snd_rawmidi_substream *substream) { struct snd_emu10k1 *emu; struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - int err = 0; emu = midi->emu; if (snd_BUG_ON(!emu)) return -ENXIO; - spin_lock_irq(&midi->open_lock); - snd_emu10k1_intr_disable(emu, midi->tx_enable); - midi->midi_mode &= ~EMU10K1_MIDI_MODE_OUTPUT; - midi->substream_output = NULL; - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { - spin_unlock_irq(&midi->open_lock); - err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); - } else { - spin_unlock_irq(&midi->open_lock); + scoped_guard(spinlock_irq, &midi->open_lock) { + snd_emu10k1_intr_disable(emu, midi->tx_enable); + midi->midi_mode &= ~EMU10K1_MIDI_MODE_OUTPUT; + midi->substream_output = NULL; + if (midi->midi_mode & EMU10K1_MIDI_MODE_INPUT) + return 0; } - return err; + return snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); } static void snd_emu10k1_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) @@ -261,22 +243,21 @@ static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substr unsigned char byte; /* try to send some amount of bytes here before interrupts */ - spin_lock_irq(&midi->output_lock); - while (max > 0) { - if (mpu401_output_ready(emu, midi)) { - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) || - snd_rawmidi_transmit(substream, &byte, 1) != 1) { - /* no more data */ - spin_unlock_irq(&midi->output_lock); - return; + scoped_guard(spinlock_irq, &midi->output_lock) { + while (max > 0) { + if (mpu401_output_ready(emu, midi)) { + if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) || + snd_rawmidi_transmit(substream, &byte, 1) != 1) { + /* no more data */ + return; + } + mpu401_write_data(emu, midi, byte); + max--; + } else { + break; } - mpu401_write_data(emu, midi, byte); - max--; - } else { - break; } } - spin_unlock_irq(&midi->output_lock); snd_emu10k1_intr_enable(emu, midi->tx_enable); } else { snd_emu10k1_intr_disable(emu, midi->tx_enable); diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 5414148057ea..071c75ba81fd 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -319,7 +319,7 @@ static void snd_emu10k1_pcm_init_voices(struct snd_emu10k1 *emu, unsigned int end_addr, struct snd_emu10k1_pcm_mixer *mix) { - spin_lock_irq(&emu->reg_lock); + guard(spinlock_irq)(&emu->reg_lock); snd_emu10k1_pcm_init_voice(emu, evoice, w_16, stereo, start_addr, end_addr, &mix->send_routing[stereo][0], @@ -329,7 +329,6 @@ static void snd_emu10k1_pcm_init_voices(struct snd_emu10k1 *emu, start_addr, end_addr, &mix->send_routing[2][0], &mix->send_volume[2][0]); - spin_unlock_irq(&emu->reg_lock); } static void snd_emu10k1_pcm_init_extra_voice(struct snd_emu10k1 *emu, @@ -726,14 +725,13 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, struct snd_emu10k1_pcm_mixer *mix; bool w_16 = snd_pcm_format_width(runtime->format) == 16; bool stereo = runtime->channels == 2; - int result = 0; /* dev_dbg(emu->card->dev, "trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream)) */ - spin_lock(&emu->reg_lock); + guard(spinlock)(&emu->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: snd_emu10k1_playback_prepare_voices(emu, epcm, w_16, stereo, 1); @@ -755,11 +753,9 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, snd_emu10k1_playback_mute_voices(emu, epcm->voices[0], stereo); break; default: - result = -EINVAL; - break; + return -EINVAL; } - spin_unlock(&emu->reg_lock); - return result; + return 0; } static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream, @@ -768,9 +764,8 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream, struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_emu10k1_pcm *epcm = runtime->private_data; - int result = 0; - spin_lock(&emu->reg_lock); + guard(spinlock)(&emu->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -829,10 +824,9 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream, } break; default: - result = -EINVAL; + return -EINVAL; } - spin_unlock(&emu->reg_lock); - return result; + return 0; } static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream *substream) @@ -923,7 +917,7 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream, u64 mask; int result = 0; - spin_lock(&emu->reg_lock); + guard(spinlock)(&emu->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: @@ -950,7 +944,7 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream, if (result == 0) { // The extra voice is allowed to lag a bit snd_emu10k1_playback_trigger_voice(emu, epcm->extra); - goto leave; + return 0; } snd_emu10k1_efx_playback_stop_voices( @@ -972,11 +966,8 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream, epcm->resume_pos = snd_emu10k1_playback_pointer(substream); break; default: - result = -EINVAL; - break; + return -EINVAL; } -leave: - spin_unlock(&emu->reg_lock); return result; } @@ -1345,7 +1336,7 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) #endif runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE; } else { - spin_lock_irq(&emu->reg_lock); + guard(spinlock_irq)(&emu->reg_lock); runtime->hw.channels_min = runtime->hw.channels_max = 0; for (idx = 0; idx < nefx; idx++) { if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) { @@ -1355,7 +1346,6 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) } epcm->capture_cr_val = emu->efx_voices_mask[0]; epcm->capture_cr_val2 = emu->efx_voices_mask[1]; - spin_unlock_irq(&emu->reg_lock); } err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_efx_capture_channels); @@ -1539,12 +1529,11 @@ static int snd_emu10k1_pcm_efx_voices_mask_put(struct snd_kcontrol *kcontrol, st if (bits == 9 || bits == 11 || bits == 13 || bits == 15 || bits > 16) return -EINVAL; - spin_lock_irq(&emu->reg_lock); + guard(spinlock_irq)(&emu->reg_lock); change = (nval[0] != emu->efx_voices_mask[0]) || (nval[1] != emu->efx_voices_mask[1]); emu->efx_voices_mask[0] = nval[0]; emu->efx_voices_mask[1] = nval[1]; - spin_unlock_irq(&emu->reg_lock); return change; } @@ -1685,9 +1674,9 @@ static int snd_emu10k1_fx8010_playback_trigger(struct snd_pcm_substream *substre { struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - int result = 0; + int result; - spin_lock(&emu->reg_lock); + guard(spinlock)(&emu->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: /* follow thru */ @@ -1707,7 +1696,7 @@ static int snd_emu10k1_fx8010_playback_trigger(struct snd_pcm_substream *substre #endif result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq); if (result < 0) - goto __err; + return result; snd_emu10k1_fx8010_playback_transfer(substream); /* roll the ball */ snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1); break; @@ -1720,12 +1709,9 @@ static int snd_emu10k1_fx8010_playback_trigger(struct snd_pcm_substream *substre pcm->tram_shift = 0; break; default: - result = -EINVAL; - break; + return -EINVAL; } - __err: - spin_unlock(&emu->reg_lock); - return result; + return 0; } static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(struct snd_pcm_substream *substream) @@ -1769,13 +1755,10 @@ static int snd_emu10k1_fx8010_playback_open(struct snd_pcm_substream *substream) runtime->hw = snd_emu10k1_fx8010_playback; runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels; runtime->hw.period_bytes_max = (pcm->buffer_size * 2) / 2; - spin_lock_irq(&emu->reg_lock); - if (pcm->valid == 0) { - spin_unlock_irq(&emu->reg_lock); + guard(spinlock_irq)(&emu->reg_lock); + if (pcm->valid == 0) return -ENODEV; - } pcm->opened = 1; - spin_unlock_irq(&emu->reg_lock); return 0; } @@ -1784,9 +1767,8 @@ static int snd_emu10k1_fx8010_playback_close(struct snd_pcm_substream *substream struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - spin_lock_irq(&emu->reg_lock); + guard(spinlock_irq)(&emu->reg_lock); pcm->opened = 0; - spin_unlock_irq(&emu->reg_lock); return 0; } diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index bd4734dc04cd..f6186b5be049 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c @@ -166,7 +166,7 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, u32 value2; if (emu->card_capabilities->emu_model) { - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); // This represents the S/PDIF lock status on 0404b, which is // kinda weird and unhelpful, because monitoring it via IRQ is @@ -200,8 +200,6 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, snd_iprintf(buffer, "\nS/PDIF mode: %s%s\n", value & EMU_HANA_SPDIF_MODE_RX_PRO ? "professional" : "consumer", value & EMU_HANA_SPDIF_MODE_RX_NOCOPY ? ", no copy" : ""); - - snd_emu1010_fpga_unlock(emu); } else { snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS); snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS); @@ -464,7 +462,7 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry, u32 value; int i; - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); snd_iprintf(buffer, "EMU1010 Registers:\n\n"); @@ -504,8 +502,6 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry, snd_emu_proc_emu1010_link_read(emu, buffer, 0x701); } } - - snd_emu1010_fpga_unlock(emu); } static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry, @@ -541,15 +537,13 @@ static unsigned int snd_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn) { - unsigned int regptr, val; + unsigned int regptr; regptr = (reg << 16) | chn; - spin_lock_irq(&emu->emu_lock); + guard(spinlock_irq)(&emu->emu_lock); outl(regptr, emu->port + iobase + PTR); - val = inl(emu->port + iobase + DATA); - spin_unlock_irq(&emu->emu_lock); - return val; + return inl(emu->port + iobase + DATA); } static void snd_ptr_write(struct snd_emu10k1 *emu, @@ -562,10 +556,9 @@ static void snd_ptr_write(struct snd_emu10k1 *emu, regptr = (reg << 16) | chn; - spin_lock_irq(&emu->emu_lock); + guard(spinlock_irq)(&emu->emu_lock); outl(regptr, emu->port + iobase + PTR); outl(data, emu->port + iobase + DATA); - spin_unlock_irq(&emu->emu_lock); } diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index b60ab5671e00..9c897c3e8c28 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c @@ -30,7 +30,6 @@ static inline bool check_ptr_reg(struct snd_emu10k1 *emu, unsigned int reg) unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn) { - unsigned long flags; unsigned int regptr, val; unsigned int mask; @@ -38,10 +37,10 @@ unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, un if (!check_ptr_reg(emu, regptr)) return 0; - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - val = inl(emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); + scoped_guard(spinlock_irqsave, &emu->emu_lock) { + outl(regptr, emu->port + PTR); + val = inl(emu->port + DATA); + } if (reg & 0xff000000) { unsigned char size, offset; @@ -61,13 +60,13 @@ EXPORT_SYMBOL(snd_emu10k1_ptr_read); void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data) { unsigned int regptr; - unsigned long flags; unsigned int mask; regptr = (reg << 16) | chn; if (!check_ptr_reg(emu, regptr)) return; + guard(spinlock_irqsave)(&emu->emu_lock); if (reg & 0xff000000) { unsigned char size, offset; @@ -79,15 +78,12 @@ void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned i mask <<= offset; data <<= offset; - spin_lock_irqsave(&emu->emu_lock, flags); outl(regptr, emu->port + PTR); data |= inl(emu->port + DATA) & ~mask; } else { - spin_lock_irqsave(&emu->emu_lock, flags); outl(regptr, emu->port + PTR); } outl(data, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } EXPORT_SYMBOL(snd_emu10k1_ptr_write); @@ -96,7 +92,6 @@ void snd_emu10k1_ptr_write_multiple(struct snd_emu10k1 *emu, unsigned int chn, . { va_list va; u32 addr_mask; - unsigned long flags; if (snd_BUG_ON(!emu)) return; @@ -105,7 +100,7 @@ void snd_emu10k1_ptr_write_multiple(struct snd_emu10k1 *emu, unsigned int chn, . addr_mask = ~((emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK) >> 16); va_start(va, chn); - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); for (;;) { u32 data; u32 reg = va_arg(va, u32); @@ -117,7 +112,6 @@ void snd_emu10k1_ptr_write_multiple(struct snd_emu10k1 *emu, unsigned int chn, . outl((reg << 16) | chn, emu->port + PTR); outl(data, emu->port + DATA); } - spin_unlock_irqrestore(&emu->emu_lock, flags); va_end(va); } @@ -127,16 +121,13 @@ unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn) { - unsigned long flags; - unsigned int regptr, val; + unsigned int regptr; regptr = (reg << 16) | chn; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outl(regptr, emu->port + PTR2); - val = inl(emu->port + DATA2); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; + return inl(emu->port + DATA2); } void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, @@ -145,14 +136,12 @@ void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int data) { unsigned int regptr; - unsigned long flags; regptr = (reg << 16) | chn; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outl(regptr, emu->port + PTR2); outl(data, emu->port + DATA2); - spin_unlock_irqrestore(&emu->emu_lock, flags); } int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, @@ -161,22 +150,19 @@ int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int reset, set; unsigned int reg, tmp; int n, result; - int err = 0; /* This function is not re-entrant, so protect against it. */ - spin_lock(&emu->spi_lock); + guard(spinlock)(&emu->spi_lock); if (emu->card_capabilities->ca0108_chip) reg = P17V_SPI; else { /* For other chip types the SPI register * is currently unknown. */ - err = 1; - goto spi_write_exit; + return 1; } if (data > 0xffff) { /* Only 16bit values allowed */ - err = 1; - goto spi_write_exit; + return 1; } tmp = snd_emu10k1_ptr20_read(emu, reg, 0); @@ -197,15 +183,11 @@ int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, } if (result) { /* Timed out */ - err = 1; - goto spi_write_exit; + return 1; } snd_emu10k1_ptr20_write(emu, reg, 0, reset | data); tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */ - err = 0; -spi_write_exit: - spin_unlock(&emu->spi_lock); - return err; + return 0; } /* The ADC does not support i2c read, so only write is implemented */ @@ -217,7 +199,6 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, int timeout = 0; int status; int retry; - int err = 0; if ((reg > 0x7f) || (value > 0x1ff)) { dev_err(emu->card->dev, "i2c_write: invalid values.\n"); @@ -225,7 +206,7 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, } /* This function is not re-entrant, so protect against it. */ - spin_lock(&emu->i2c_lock); + guard(spinlock)(&emu->i2c_lock); tmp = reg << 25 | value << 16; @@ -264,11 +245,10 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, dev_err(emu->card->dev, "status=0x%x, reg=%d, value=%d\n", status, reg, value); /* dump_stack(); */ - err = -EINVAL; + return -EINVAL; } - spin_unlock(&emu->i2c_lock); - return err; + return 0; } static void snd_emu1010_fpga_write_locked(struct snd_emu10k1 *emu, u32 reg, u32 value) @@ -297,9 +277,8 @@ void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value) void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value) { - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); snd_emu1010_fpga_write_locked(emu, reg, value); - snd_emu1010_fpga_unlock(emu); } void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value) @@ -477,32 +456,27 @@ void snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, int dock, void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb) { - unsigned long flags; unsigned int enable; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); enable = inl(emu->port + INTE) | intrenb; outl(enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); } void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb) { - unsigned long flags; unsigned int enable; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); enable = inl(emu->port + INTE) & ~intrenb; outl(enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); } void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum) { - unsigned long flags; unsigned int val; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); if (voicenum >= 32) { outl(CLIEH << 16, emu->port + PTR); val = inl(emu->port + DATA); @@ -513,15 +487,13 @@ void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenu val |= 1 << voicenum; } outl(val, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum) { - unsigned long flags; unsigned int val; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); if (voicenum >= 32) { outl(CLIEH << 16, emu->port + PTR); val = inl(emu->port + DATA); @@ -532,14 +504,11 @@ void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicen val &= ~(1 << voicenum); } outl(val, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum) { - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); if (voicenum >= 32) { outl(CLIPH << 16, emu->port + PTR); voicenum = 1 << (voicenum - 32); @@ -548,15 +517,13 @@ void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum) voicenum = 1 << voicenum; } outl(voicenum, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum) { - unsigned long flags; unsigned int val; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); if (voicenum >= 32) { outl(HLIEH << 16, emu->port + PTR); val = inl(emu->port + DATA); @@ -567,15 +534,13 @@ void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned i val |= 1 << voicenum; } outl(val, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum) { - unsigned long flags; unsigned int val; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); if (voicenum >= 32) { outl(HLIEH << 16, emu->port + PTR); val = inl(emu->port + DATA); @@ -586,14 +551,11 @@ void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned val &= ~(1 << voicenum); } outl(val, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum) { - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); if (voicenum >= 32) { outl(HLIPH << 16, emu->port + PTR); voicenum = 1 << (voicenum - 32); @@ -602,16 +564,14 @@ void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum = 1 << voicenum; } outl(voicenum, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } #if 0 void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum) { - unsigned long flags; unsigned int sol; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); if (voicenum >= 32) { outl(SOLEH << 16, emu->port + PTR); sol = inl(emu->port + DATA); @@ -622,15 +582,13 @@ void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voice sol |= 1 << voicenum; } outl(sol, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum) { - unsigned long flags; unsigned int sol; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); if (voicenum >= 32) { outl(SOLEH << 16, emu->port + PTR); sol = inl(emu->port + DATA); @@ -641,32 +599,25 @@ void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voi sol &= ~(1 << voicenum); } outl(sol, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } #endif void snd_emu10k1_voice_set_loop_stop_multiple(struct snd_emu10k1 *emu, u64 voices) { - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outl(SOLEL << 16, emu->port + PTR); outl(inl(emu->port + DATA) | (u32)voices, emu->port + DATA); outl(SOLEH << 16, emu->port + PTR); outl(inl(emu->port + DATA) | (u32)(voices >> 32), emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } void snd_emu10k1_voice_clear_loop_stop_multiple(struct snd_emu10k1 *emu, u64 voices) { - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outl(SOLEL << 16, emu->port + PTR); outl(inl(emu->port + DATA) & (u32)~voices, emu->port + DATA); outl(SOLEH << 16, emu->port + PTR); outl(inl(emu->port + DATA) & (u32)(~voices >> 32), emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } int snd_emu10k1_voice_clear_loop_stop_multiple_atomic(struct snd_emu10k1 *emu, u64 voices) @@ -749,23 +700,17 @@ void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait) unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg) { struct snd_emu10k1 *emu = ac97->private_data; - unsigned long flags; - unsigned short val; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outb(reg, emu->port + AC97ADDRESS); - val = inw(emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; + return inw(emu->port + AC97DATA); } void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data) { struct snd_emu10k1 *emu = ac97->private_data; - unsigned long flags; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); outb(reg, emu->port + AC97ADDRESS); outw(data, emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); } diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index f6982bc6ff0d..be889a4ccf9a 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -261,14 +261,12 @@ int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *b int size; struct list_head *p, *nextp; struct snd_emu10k1_memblk *deleted; - unsigned long flags; - spin_lock_irqsave(&emu->memblk_lock, flags); + guard(spinlock_irqsave)(&emu->memblk_lock); if (blk->mapped_page >= 0) { /* update order link */ list_move_tail(&blk->mapped_order_link, &emu->mapped_order_link_head); - spin_unlock_irqrestore(&emu->memblk_lock, flags); return 0; } err = map_memblk(emu, blk); @@ -289,7 +287,6 @@ int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *b } } } - spin_unlock_irqrestore(&emu->memblk_lock, flags); return err; } @@ -315,12 +312,10 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst if (snd_BUG_ON(!hdr)) return NULL; - mutex_lock(&hdr->block_mutex); + guard(mutex)(&hdr->block_mutex); blk = search_empty(emu, runtime->dma_bytes); - if (blk == NULL) { - mutex_unlock(&hdr->block_mutex); + if (blk == NULL) return NULL; - } /* fill buffer addresses but pointers are not stored so that * snd_free_pci_page() is not called in synth_free() */ @@ -335,7 +330,6 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst if (! is_valid_page(emu, addr)) { dev_err_ratelimited(emu->card->dev, "emu: failure page = %d\n", idx); - mutex_unlock(&hdr->block_mutex); return NULL; } emu->page_addr_table[page] = addr; @@ -347,10 +341,8 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst err = snd_emu10k1_memblk_map(emu, blk); if (err < 0) { __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk); - mutex_unlock(&hdr->block_mutex); return NULL; } - mutex_unlock(&hdr->block_mutex); return (struct snd_util_memblk *)blk; } @@ -407,19 +399,15 @@ snd_emu10k1_synth_alloc(struct snd_emu10k1 *hw, unsigned int size) struct snd_emu10k1_memblk *blk; struct snd_util_memhdr *hdr = hw->memhdr; - mutex_lock(&hdr->block_mutex); + guard(mutex)(&hdr->block_mutex); blk = (struct snd_emu10k1_memblk *)__snd_util_mem_alloc(hdr, size); - if (blk == NULL) { - mutex_unlock(&hdr->block_mutex); + if (blk == NULL) return NULL; - } if (synth_alloc_pages(hw, blk)) { __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk); - mutex_unlock(&hdr->block_mutex); return NULL; } snd_emu10k1_memblk_map(hw, blk); - mutex_unlock(&hdr->block_mutex); return (struct snd_util_memblk *)blk; } @@ -433,16 +421,14 @@ snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *memblk) { struct snd_util_memhdr *hdr = emu->memhdr; struct snd_emu10k1_memblk *blk = (struct snd_emu10k1_memblk *)memblk; - unsigned long flags; - mutex_lock(&hdr->block_mutex); - spin_lock_irqsave(&emu->memblk_lock, flags); - if (blk->mapped_page >= 0) - unmap_memblk(emu, blk); - spin_unlock_irqrestore(&emu->memblk_lock, flags); + guard(mutex)(&hdr->block_mutex); + scoped_guard(spinlock_irqsave, &emu->memblk_lock) { + if (blk->mapped_page >= 0) + unmap_memblk(emu, blk); + } synth_free_pages(emu, blk); __snd_util_mem_free(hdr, memblk); - mutex_unlock(&hdr->block_mutex); return 0; } diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index e774174d10de..b74128e61254 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -342,24 +342,20 @@ static int snd_p16v_pcm_prepare_capture(struct snd_pcm_substream *substream) static void snd_p16v_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb) { - unsigned long flags; unsigned int enable; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); enable = inl(emu->port + INTE2) | intrenb; outl(enable, emu->port + INTE2); - spin_unlock_irqrestore(&emu->emu_lock, flags); } static void snd_p16v_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb) { - unsigned long flags; unsigned int disable; - spin_lock_irqsave(&emu->emu_lock, flags); + guard(spinlock_irqsave)(&emu->emu_lock); disable = inl(emu->port + INTE2) & (~intrenb); outl(disable, emu->port + INTE2); - spin_unlock_irqrestore(&emu->emu_lock, flags); } static void snd_p16v_interrupt(struct snd_emu10k1 *emu) diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c index 77fb5427aaed..7fe1d1727768 100644 --- a/sound/pci/emu10k1/voice.c +++ b/sound/pci/emu10k1/voice.c @@ -77,7 +77,6 @@ static void voice_free(struct snd_emu10k1 *emu, int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int count, int channels, struct snd_emu10k1_pcm *epcm, struct snd_emu10k1_voice **rvoice) { - unsigned long flags; int result; if (snd_BUG_ON(!rvoice)) @@ -87,7 +86,7 @@ int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int count, int ch if (snd_BUG_ON(!channels)) return -EINVAL; - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); for (int got = 0; got < channels; ) { result = voice_alloc(emu, type, count, epcm, &rvoice[got]); if (result == 0) { @@ -113,7 +112,6 @@ int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int count, int ch } break; } - spin_unlock_irqrestore(&emu->voice_lock, flags); return result; } @@ -123,17 +121,15 @@ EXPORT_SYMBOL(snd_emu10k1_voice_alloc); int snd_emu10k1_voice_free(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *pvoice) { - unsigned long flags; int last; if (snd_BUG_ON(!pvoice)) return -EINVAL; - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); do { last = pvoice->last; voice_free(emu, pvoice++); } while (!last); - spin_unlock_irqrestore(&emu->voice_lock, flags); return 0; } diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 82e10ecb9196..657056a59175 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -596,7 +596,7 @@ static void snd_es1371_codec_write(struct snd_ac97 *ac97, unsigned int t, x, flag; flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0; - mutex_lock(&ensoniq->src_mutex); + guard(mutex)(&ensoniq->src_mutex); for (t = 0; t < POLL_COUNT; t++) { if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { /* save the current state for latter */ @@ -622,11 +622,9 @@ static void snd_es1371_codec_write(struct snd_ac97 *ac97, /* restore SRC reg */ snd_es1371_wait_src_ready(ensoniq); outl(x, ES_REG(ensoniq, 1371_SMPRATE)); - mutex_unlock(&ensoniq->src_mutex); return; } } - mutex_unlock(&ensoniq->src_mutex); dev_err(ensoniq->card->dev, "codec write timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); } @@ -713,7 +711,7 @@ static void snd_es1371_adc_rate(struct ensoniq * ensoniq, unsigned int rate) { unsigned int n, truncm, freq; - mutex_lock(&ensoniq->src_mutex); + guard(mutex)(&ensoniq->src_mutex); n = rate / 3000; if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9))) n--; @@ -737,14 +735,13 @@ static void snd_es1371_adc_rate(struct ensoniq * ensoniq, unsigned int rate) snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, n << 8); snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, n << 8); - mutex_unlock(&ensoniq->src_mutex); } static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate) { unsigned int freq, r; - mutex_lock(&ensoniq->src_mutex); + guard(mutex)(&ensoniq->src_mutex); freq = DIV_ROUND_CLOSEST(rate << 15, 3000); r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P2 | ES_1371_DIS_R1)) | @@ -758,14 +755,13 @@ static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate) r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P2 | ES_1371_DIS_R1)); outl(r, ES_REG(ensoniq, 1371_SMPRATE)); - mutex_unlock(&ensoniq->src_mutex); } static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate) { unsigned int freq, r; - mutex_lock(&ensoniq->src_mutex); + guard(mutex)(&ensoniq->src_mutex); freq = DIV_ROUND_CLOSEST(rate << 15, 3000); r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | ES_1371_DIS_R1)) | @@ -780,7 +776,6 @@ static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate) r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | ES_1371_DIS_R1)); outl(r, ES_REG(ensoniq, 1371_SMPRATE)); - mutex_unlock(&ensoniq->src_mutex); } #endif /* CHIP1371 */ @@ -804,13 +799,13 @@ static int snd_ensoniq_trigger(struct snd_pcm_substream *substream, int cmd) } else if (s == ensoniq->capture_substream) return -EINVAL; } - spin_lock(&ensoniq->reg_lock); - if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) - ensoniq->sctrl |= what; - else - ensoniq->sctrl &= ~what; - outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); - spin_unlock(&ensoniq->reg_lock); + scoped_guard(spinlock, &ensoniq->reg_lock) { + if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) + ensoniq->sctrl |= what; + else + ensoniq->sctrl &= ~what; + outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); + } break; } case SNDRV_PCM_TRIGGER_START: @@ -830,13 +825,13 @@ static int snd_ensoniq_trigger(struct snd_pcm_substream *substream, int cmd) snd_pcm_trigger_done(s, substream); } } - spin_lock(&ensoniq->reg_lock); - if (cmd == SNDRV_PCM_TRIGGER_START) - ensoniq->ctrl |= what; - else - ensoniq->ctrl &= ~what; - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - spin_unlock(&ensoniq->reg_lock); + scoped_guard(spinlock, &ensoniq->reg_lock) { + if (cmd == SNDRV_PCM_TRIGGER_START) + ensoniq->ctrl |= what; + else + ensoniq->ctrl &= ~what; + outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); + } break; } default: @@ -861,36 +856,36 @@ static int snd_ensoniq_playback1_prepare(struct snd_pcm_substream *substream) mode |= 0x02; if (runtime->channels > 1) mode |= 0x01; - spin_lock_irq(&ensoniq->reg_lock); - ensoniq->ctrl &= ~ES_DAC1_EN; + scoped_guard(spinlock_irq, &ensoniq->reg_lock) { + ensoniq->ctrl &= ~ES_DAC1_EN; #ifdef CHIP1371 - /* 48k doesn't need SRC (it breaks AC3-passthru) */ - if (runtime->rate == 48000) - ensoniq->ctrl |= ES_1373_BYPASS_P1; - else - ensoniq->ctrl &= ~ES_1373_BYPASS_P1; + /* 48k doesn't need SRC (it breaks AC3-passthru) */ + if (runtime->rate == 48000) + ensoniq->ctrl |= ES_1373_BYPASS_P1; + else + ensoniq->ctrl &= ~ES_1373_BYPASS_P1; #endif - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE)); - outl(runtime->dma_addr, ES_REG(ensoniq, DAC1_FRAME)); - outl((ensoniq->p1_dma_size >> 2) - 1, ES_REG(ensoniq, DAC1_SIZE)); - ensoniq->sctrl &= ~(ES_P1_LOOP_SEL | ES_P1_PAUSE | ES_P1_SCT_RLD | ES_P1_MODEM); - ensoniq->sctrl |= ES_P1_INT_EN | ES_P1_MODEO(mode); - outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); - outl((ensoniq->p1_period_size >> snd_ensoniq_sample_shift[mode]) - 1, - ES_REG(ensoniq, DAC1_COUNT)); + outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); + outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE)); + outl(runtime->dma_addr, ES_REG(ensoniq, DAC1_FRAME)); + outl((ensoniq->p1_dma_size >> 2) - 1, ES_REG(ensoniq, DAC1_SIZE)); + ensoniq->sctrl &= ~(ES_P1_LOOP_SEL | ES_P1_PAUSE | ES_P1_SCT_RLD | ES_P1_MODEM); + ensoniq->sctrl |= ES_P1_INT_EN | ES_P1_MODEO(mode); + outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); + outl((ensoniq->p1_period_size >> snd_ensoniq_sample_shift[mode]) - 1, + ES_REG(ensoniq, DAC1_COUNT)); #ifdef CHIP1370 - ensoniq->ctrl &= ~ES_1370_WTSRSELM; - switch (runtime->rate) { - case 5512: ensoniq->ctrl |= ES_1370_WTSRSEL(0); break; - case 11025: ensoniq->ctrl |= ES_1370_WTSRSEL(1); break; - case 22050: ensoniq->ctrl |= ES_1370_WTSRSEL(2); break; - case 44100: ensoniq->ctrl |= ES_1370_WTSRSEL(3); break; - default: snd_BUG(); - } + ensoniq->ctrl &= ~ES_1370_WTSRSELM; + switch (runtime->rate) { + case 5512: ensoniq->ctrl |= ES_1370_WTSRSEL(0); break; + case 11025: ensoniq->ctrl |= ES_1370_WTSRSEL(1); break; + case 22050: ensoniq->ctrl |= ES_1370_WTSRSEL(2); break; + case 44100: ensoniq->ctrl |= ES_1370_WTSRSEL(3); break; + default: snd_BUG(); + } #endif - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - spin_unlock_irq(&ensoniq->reg_lock); + outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); + } #ifndef CHIP1370 snd_es1371_dac1_rate(ensoniq, runtime->rate); #endif @@ -909,28 +904,28 @@ static int snd_ensoniq_playback2_prepare(struct snd_pcm_substream *substream) mode |= 0x02; if (runtime->channels > 1) mode |= 0x01; - spin_lock_irq(&ensoniq->reg_lock); - ensoniq->ctrl &= ~ES_DAC2_EN; - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE)); - outl(runtime->dma_addr, ES_REG(ensoniq, DAC2_FRAME)); - outl((ensoniq->p2_dma_size >> 2) - 1, ES_REG(ensoniq, DAC2_SIZE)); - ensoniq->sctrl &= ~(ES_P2_LOOP_SEL | ES_P2_PAUSE | ES_P2_DAC_SEN | - ES_P2_END_INCM | ES_P2_ST_INCM | ES_P2_MODEM); - ensoniq->sctrl |= ES_P2_INT_EN | ES_P2_MODEO(mode) | - ES_P2_END_INCO(mode & 2 ? 2 : 1) | ES_P2_ST_INCO(0); - outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); - outl((ensoniq->p2_period_size >> snd_ensoniq_sample_shift[mode]) - 1, - ES_REG(ensoniq, DAC2_COUNT)); + scoped_guard(spinlock_irq, &ensoniq->reg_lock) { + ensoniq->ctrl &= ~ES_DAC2_EN; + outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); + outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE)); + outl(runtime->dma_addr, ES_REG(ensoniq, DAC2_FRAME)); + outl((ensoniq->p2_dma_size >> 2) - 1, ES_REG(ensoniq, DAC2_SIZE)); + ensoniq->sctrl &= ~(ES_P2_LOOP_SEL | ES_P2_PAUSE | ES_P2_DAC_SEN | + ES_P2_END_INCM | ES_P2_ST_INCM | ES_P2_MODEM); + ensoniq->sctrl |= ES_P2_INT_EN | ES_P2_MODEO(mode) | + ES_P2_END_INCO(mode & 2 ? 2 : 1) | ES_P2_ST_INCO(0); + outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); + outl((ensoniq->p2_period_size >> snd_ensoniq_sample_shift[mode]) - 1, + ES_REG(ensoniq, DAC2_COUNT)); #ifdef CHIP1370 - if (!(ensoniq->u.es1370.pclkdiv_lock & ES_MODE_CAPTURE)) { - ensoniq->ctrl &= ~ES_1370_PCLKDIVM; - ensoniq->ctrl |= ES_1370_PCLKDIVO(ES_1370_SRTODIV(runtime->rate)); - ensoniq->u.es1370.pclkdiv_lock |= ES_MODE_PLAY2; - } + if (!(ensoniq->u.es1370.pclkdiv_lock & ES_MODE_CAPTURE)) { + ensoniq->ctrl &= ~ES_1370_PCLKDIVM; + ensoniq->ctrl |= ES_1370_PCLKDIVO(ES_1370_SRTODIV(runtime->rate)); + ensoniq->u.es1370.pclkdiv_lock |= ES_MODE_PLAY2; + } #endif - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - spin_unlock_irq(&ensoniq->reg_lock); + outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); + } #ifndef CHIP1370 snd_es1371_dac2_rate(ensoniq, runtime->rate); #endif @@ -949,26 +944,26 @@ static int snd_ensoniq_capture_prepare(struct snd_pcm_substream *substream) mode |= 0x02; if (runtime->channels > 1) mode |= 0x01; - spin_lock_irq(&ensoniq->reg_lock); - ensoniq->ctrl &= ~ES_ADC_EN; - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE)); - outl(runtime->dma_addr, ES_REG(ensoniq, ADC_FRAME)); - outl((ensoniq->c_dma_size >> 2) - 1, ES_REG(ensoniq, ADC_SIZE)); - ensoniq->sctrl &= ~(ES_R1_LOOP_SEL | ES_R1_MODEM); - ensoniq->sctrl |= ES_R1_INT_EN | ES_R1_MODEO(mode); - outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); - outl((ensoniq->c_period_size >> snd_ensoniq_sample_shift[mode]) - 1, - ES_REG(ensoniq, ADC_COUNT)); + scoped_guard(spinlock_irq, &ensoniq->reg_lock) { + ensoniq->ctrl &= ~ES_ADC_EN; + outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); + outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE)); + outl(runtime->dma_addr, ES_REG(ensoniq, ADC_FRAME)); + outl((ensoniq->c_dma_size >> 2) - 1, ES_REG(ensoniq, ADC_SIZE)); + ensoniq->sctrl &= ~(ES_R1_LOOP_SEL | ES_R1_MODEM); + ensoniq->sctrl |= ES_R1_INT_EN | ES_R1_MODEO(mode); + outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); + outl((ensoniq->c_period_size >> snd_ensoniq_sample_shift[mode]) - 1, + ES_REG(ensoniq, ADC_COUNT)); #ifdef CHIP1370 - if (!(ensoniq->u.es1370.pclkdiv_lock & ES_MODE_PLAY2)) { - ensoniq->ctrl &= ~ES_1370_PCLKDIVM; - ensoniq->ctrl |= ES_1370_PCLKDIVO(ES_1370_SRTODIV(runtime->rate)); - ensoniq->u.es1370.pclkdiv_lock |= ES_MODE_CAPTURE; - } + if (!(ensoniq->u.es1370.pclkdiv_lock & ES_MODE_PLAY2)) { + ensoniq->ctrl &= ~ES_1370_PCLKDIVM; + ensoniq->ctrl |= ES_1370_PCLKDIVO(ES_1370_SRTODIV(runtime->rate)); + ensoniq->u.es1370.pclkdiv_lock |= ES_MODE_CAPTURE; + } #endif - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - spin_unlock_irq(&ensoniq->reg_lock); + outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); + } #ifndef CHIP1370 snd_es1371_adc_rate(ensoniq, runtime->rate); #endif @@ -980,16 +975,14 @@ static snd_pcm_uframes_t snd_ensoniq_playback1_pointer(struct snd_pcm_substream struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); size_t ptr; - spin_lock(&ensoniq->reg_lock); + guard(spinlock)(&ensoniq->reg_lock); if (inl(ES_REG(ensoniq, CONTROL)) & ES_DAC1_EN) { outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE)); ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, DAC1_SIZE))); - ptr = bytes_to_frames(substream->runtime, ptr); + return bytes_to_frames(substream->runtime, ptr); } else { - ptr = 0; + return 0; } - spin_unlock(&ensoniq->reg_lock); - return ptr; } static snd_pcm_uframes_t snd_ensoniq_playback2_pointer(struct snd_pcm_substream *substream) @@ -997,16 +990,14 @@ static snd_pcm_uframes_t snd_ensoniq_playback2_pointer(struct snd_pcm_substream struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); size_t ptr; - spin_lock(&ensoniq->reg_lock); + guard(spinlock)(&ensoniq->reg_lock); if (inl(ES_REG(ensoniq, CONTROL)) & ES_DAC2_EN) { outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE)); ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, DAC2_SIZE))); - ptr = bytes_to_frames(substream->runtime, ptr); + return bytes_to_frames(substream->runtime, ptr); } else { - ptr = 0; + return 0; } - spin_unlock(&ensoniq->reg_lock); - return ptr; } static snd_pcm_uframes_t snd_ensoniq_capture_pointer(struct snd_pcm_substream *substream) @@ -1014,16 +1005,14 @@ static snd_pcm_uframes_t snd_ensoniq_capture_pointer(struct snd_pcm_substream *s struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); size_t ptr; - spin_lock(&ensoniq->reg_lock); + guard(spinlock)(&ensoniq->reg_lock); if (inl(ES_REG(ensoniq, CONTROL)) & ES_ADC_EN) { outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE)); ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, ADC_SIZE))); - ptr = bytes_to_frames(substream->runtime, ptr); + return bytes_to_frames(substream->runtime, ptr); } else { - ptr = 0; + return 0; } - spin_unlock(&ensoniq->reg_lock); - return ptr; } static const struct snd_pcm_hardware snd_ensoniq_playback1 = @@ -1101,10 +1090,10 @@ static int snd_ensoniq_playback1_open(struct snd_pcm_substream *substream) ensoniq->playback1_substream = substream; runtime->hw = snd_ensoniq_playback1; snd_pcm_set_sync(substream); - spin_lock_irq(&ensoniq->reg_lock); - if (ensoniq->spdif && ensoniq->playback2_substream == NULL) - ensoniq->spdif_stream = ensoniq->spdif_default; - spin_unlock_irq(&ensoniq->reg_lock); + scoped_guard(spinlock_irq, &ensoniq->reg_lock) { + if (ensoniq->spdif && ensoniq->playback2_substream == NULL) + ensoniq->spdif_stream = ensoniq->spdif_default; + } #ifdef CHIP1370 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &snd_es1370_hw_constraints_rates); @@ -1124,10 +1113,10 @@ static int snd_ensoniq_playback2_open(struct snd_pcm_substream *substream) ensoniq->playback2_substream = substream; runtime->hw = snd_ensoniq_playback2; snd_pcm_set_sync(substream); - spin_lock_irq(&ensoniq->reg_lock); - if (ensoniq->spdif && ensoniq->playback1_substream == NULL) - ensoniq->spdif_stream = ensoniq->spdif_default; - spin_unlock_irq(&ensoniq->reg_lock); + scoped_guard(spinlock_irq, &ensoniq->reg_lock) { + if (ensoniq->spdif && ensoniq->playback1_substream == NULL) + ensoniq->spdif_stream = ensoniq->spdif_default; + } #ifdef CHIP1370 snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &snd_es1370_hw_constraints_clock); @@ -1171,12 +1160,11 @@ static int snd_ensoniq_playback2_close(struct snd_pcm_substream *substream) struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); ensoniq->playback2_substream = NULL; - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); #ifdef CHIP1370 ensoniq->u.es1370.pclkdiv_lock &= ~ES_MODE_PLAY2; #endif ensoniq->mode &= ~ES_MODE_PLAY2; - spin_unlock_irq(&ensoniq->reg_lock); return 0; } @@ -1185,12 +1173,11 @@ static int snd_ensoniq_capture_close(struct snd_pcm_substream *substream) struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); ensoniq->capture_substream = NULL; - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); #ifdef CHIP1370 ensoniq->u.es1370.pclkdiv_lock &= ~ES_MODE_CAPTURE; #endif ensoniq->mode &= ~ES_MODE_CAPTURE; - spin_unlock_irq(&ensoniq->reg_lock); return 0; } @@ -1312,12 +1299,12 @@ static int snd_ens1373_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&ensoniq->reg_lock); + + guard(spinlock_irq)(&ensoniq->reg_lock); ucontrol->value.iec958.status[0] = (ensoniq->spdif_default >> 0) & 0xff; ucontrol->value.iec958.status[1] = (ensoniq->spdif_default >> 8) & 0xff; ucontrol->value.iec958.status[2] = (ensoniq->spdif_default >> 16) & 0xff; ucontrol->value.iec958.status[3] = (ensoniq->spdif_default >> 24) & 0xff; - spin_unlock_irq(&ensoniq->reg_lock); return 0; } @@ -1332,13 +1319,12 @@ static int snd_ens1373_spdif_default_put(struct snd_kcontrol *kcontrol, ((u32)ucontrol->value.iec958.status[1] << 8) | ((u32)ucontrol->value.iec958.status[2] << 16) | ((u32)ucontrol->value.iec958.status[3] << 24); - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); change = ensoniq->spdif_default != val; ensoniq->spdif_default = val; if (change && ensoniq->playback1_substream == NULL && ensoniq->playback2_substream == NULL) outl(val, ES_REG(ensoniq, CHANNEL_STATUS)); - spin_unlock_irq(&ensoniq->reg_lock); return change; } @@ -1356,12 +1342,12 @@ static int snd_ens1373_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&ensoniq->reg_lock); + + guard(spinlock_irq)(&ensoniq->reg_lock); ucontrol->value.iec958.status[0] = (ensoniq->spdif_stream >> 0) & 0xff; ucontrol->value.iec958.status[1] = (ensoniq->spdif_stream >> 8) & 0xff; ucontrol->value.iec958.status[2] = (ensoniq->spdif_stream >> 16) & 0xff; ucontrol->value.iec958.status[3] = (ensoniq->spdif_stream >> 24) & 0xff; - spin_unlock_irq(&ensoniq->reg_lock); return 0; } @@ -1376,13 +1362,12 @@ static int snd_ens1373_spdif_stream_put(struct snd_kcontrol *kcontrol, ((u32)ucontrol->value.iec958.status[1] << 8) | ((u32)ucontrol->value.iec958.status[2] << 16) | ((u32)ucontrol->value.iec958.status[3] << 24); - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); change = ensoniq->spdif_stream != val; ensoniq->spdif_stream = val; if (change && (ensoniq->playback1_substream != NULL || ensoniq->playback2_substream != NULL)) outl(val, ES_REG(ensoniq, CHANNEL_STATUS)); - spin_unlock_irq(&ensoniq->reg_lock); return change; } @@ -1397,9 +1382,8 @@ static int snd_es1371_spdif_get(struct snd_kcontrol *kcontrol, { struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); ucontrol->value.integer.value[0] = ensoniq->ctrl & ES_1373_SPDIF_THRU ? 1 : 0; - spin_unlock_irq(&ensoniq->reg_lock); return 0; } @@ -1412,7 +1396,7 @@ static int snd_es1371_spdif_put(struct snd_kcontrol *kcontrol, nval1 = ucontrol->value.integer.value[0] ? ES_1373_SPDIF_THRU : 0; nval2 = ucontrol->value.integer.value[0] ? ES_1373_SPDIF_EN : 0; - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); change = (ensoniq->ctrl & ES_1373_SPDIF_THRU) != nval1; ensoniq->ctrl &= ~ES_1373_SPDIF_THRU; ensoniq->ctrl |= nval1; @@ -1420,7 +1404,6 @@ static int snd_es1371_spdif_put(struct snd_kcontrol *kcontrol, ensoniq->cssr |= nval2; outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); - spin_unlock_irq(&ensoniq->reg_lock); return change; } @@ -1460,12 +1443,11 @@ static int snd_es1373_rear_get(struct snd_kcontrol *kcontrol, struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); int val = 0; - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); if ((ensoniq->cssr & (ES_1373_REAR_BIT27|ES_1373_REAR_BIT26| ES_1373_REAR_BIT24)) == ES_1373_REAR_BIT26) val = 1; ucontrol->value.integer.value[0] = val; - spin_unlock_irq(&ensoniq->reg_lock); return 0; } @@ -1478,13 +1460,12 @@ static int snd_es1373_rear_put(struct snd_kcontrol *kcontrol, nval1 = ucontrol->value.integer.value[0] ? ES_1373_REAR_BIT26 : (ES_1373_REAR_BIT27|ES_1373_REAR_BIT24); - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); change = (ensoniq->cssr & (ES_1373_REAR_BIT27| ES_1373_REAR_BIT26|ES_1373_REAR_BIT24)) != nval1; ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT26|ES_1373_REAR_BIT24); ensoniq->cssr |= nval1; outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); - spin_unlock_irq(&ensoniq->reg_lock); return change; } @@ -1505,11 +1486,10 @@ static int snd_es1373_line_get(struct snd_kcontrol *kcontrol, struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); int val = 0; - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); if (ensoniq->ctrl & ES_1371_GPIO_OUT(4)) val = 1; ucontrol->value.integer.value[0] = val; - spin_unlock_irq(&ensoniq->reg_lock); return 0; } @@ -1520,7 +1500,7 @@ static int snd_es1373_line_put(struct snd_kcontrol *kcontrol, int changed; unsigned int ctrl; - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); ctrl = ensoniq->ctrl; if (ucontrol->value.integer.value[0]) ensoniq->ctrl |= ES_1371_GPIO_OUT(4); /* switch line-in -> rear out */ @@ -1529,7 +1509,6 @@ static int snd_es1373_line_put(struct snd_kcontrol *kcontrol, changed = (ctrl != ensoniq->ctrl); if (changed) outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - spin_unlock_irq(&ensoniq->reg_lock); return changed; } @@ -1665,9 +1644,8 @@ static int snd_ensoniq_control_get(struct snd_kcontrol *kcontrol, struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); int mask = kcontrol->private_value; - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); ucontrol->value.integer.value[0] = ensoniq->ctrl & mask ? 1 : 0; - spin_unlock_irq(&ensoniq->reg_lock); return 0; } @@ -1680,12 +1658,11 @@ static int snd_ensoniq_control_put(struct snd_kcontrol *kcontrol, int change; nval = ucontrol->value.integer.value[0] ? mask : 0; - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); change = (ensoniq->ctrl & mask) != nval; ensoniq->ctrl &= ~mask; ensoniq->ctrl |= nval; outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - spin_unlock_irq(&ensoniq->reg_lock); return change; } @@ -2079,19 +2056,19 @@ static void snd_ensoniq_midi_interrupt(struct ensoniq * ensoniq) if (rmidi == NULL) return; /* do Rx at first */ - spin_lock(&ensoniq->reg_lock); - mask = ensoniq->uartm & ES_MODE_INPUT ? ES_RXRDY : 0; - while (mask) { - status = inb(ES_REG(ensoniq, UART_STATUS)); - if ((status & mask) == 0) - break; - byte = inb(ES_REG(ensoniq, UART_DATA)); - snd_rawmidi_receive(ensoniq->midi_input, &byte, 1); + scoped_guard(spinlock, &ensoniq->reg_lock) { + mask = ensoniq->uartm & ES_MODE_INPUT ? ES_RXRDY : 0; + while (mask) { + status = inb(ES_REG(ensoniq, UART_STATUS)); + if ((status & mask) == 0) + break; + byte = inb(ES_REG(ensoniq, UART_DATA)); + snd_rawmidi_receive(ensoniq->midi_input, &byte, 1); + } } - spin_unlock(&ensoniq->reg_lock); /* do Tx at second */ - spin_lock(&ensoniq->reg_lock); + guard(spinlock)(&ensoniq->reg_lock); mask = ensoniq->uartm & ES_MODE_OUTPUT ? ES_TXRDY : 0; while (mask) { status = inb(ES_REG(ensoniq, UART_STATUS)); @@ -2105,14 +2082,13 @@ static void snd_ensoniq_midi_interrupt(struct ensoniq * ensoniq) outb(byte, ES_REG(ensoniq, UART_DATA)); } } - spin_unlock(&ensoniq->reg_lock); } static int snd_ensoniq_midi_input_open(struct snd_rawmidi_substream *substream) { struct ensoniq *ensoniq = substream->rmidi->private_data; - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); ensoniq->uartm |= ES_MODE_INPUT; ensoniq->midi_input = substream; if (!(ensoniq->uartm & ES_MODE_OUTPUT)) { @@ -2120,7 +2096,6 @@ static int snd_ensoniq_midi_input_open(struct snd_rawmidi_substream *substream) outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL)); outl(ensoniq->ctrl |= ES_UART_EN, ES_REG(ensoniq, CONTROL)); } - spin_unlock_irq(&ensoniq->reg_lock); return 0; } @@ -2128,7 +2103,7 @@ static int snd_ensoniq_midi_input_close(struct snd_rawmidi_substream *substream) { struct ensoniq *ensoniq = substream->rmidi->private_data; - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); if (!(ensoniq->uartm & ES_MODE_OUTPUT)) { outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL)); outl(ensoniq->ctrl &= ~ES_UART_EN, ES_REG(ensoniq, CONTROL)); @@ -2137,7 +2112,6 @@ static int snd_ensoniq_midi_input_close(struct snd_rawmidi_substream *substream) } ensoniq->midi_input = NULL; ensoniq->uartm &= ~ES_MODE_INPUT; - spin_unlock_irq(&ensoniq->reg_lock); return 0; } @@ -2145,7 +2119,7 @@ static int snd_ensoniq_midi_output_open(struct snd_rawmidi_substream *substream) { struct ensoniq *ensoniq = substream->rmidi->private_data; - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); ensoniq->uartm |= ES_MODE_OUTPUT; ensoniq->midi_output = substream; if (!(ensoniq->uartm & ES_MODE_INPUT)) { @@ -2153,7 +2127,6 @@ static int snd_ensoniq_midi_output_open(struct snd_rawmidi_substream *substream) outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL)); outl(ensoniq->ctrl |= ES_UART_EN, ES_REG(ensoniq, CONTROL)); } - spin_unlock_irq(&ensoniq->reg_lock); return 0; } @@ -2161,7 +2134,7 @@ static int snd_ensoniq_midi_output_close(struct snd_rawmidi_substream *substream { struct ensoniq *ensoniq = substream->rmidi->private_data; - spin_lock_irq(&ensoniq->reg_lock); + guard(spinlock_irq)(&ensoniq->reg_lock); if (!(ensoniq->uartm & ES_MODE_INPUT)) { outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL)); outl(ensoniq->ctrl &= ~ES_UART_EN, ES_REG(ensoniq, CONTROL)); @@ -2170,17 +2143,15 @@ static int snd_ensoniq_midi_output_close(struct snd_rawmidi_substream *substream } ensoniq->midi_output = NULL; ensoniq->uartm &= ~ES_MODE_OUTPUT; - spin_unlock_irq(&ensoniq->reg_lock); return 0; } static void snd_ensoniq_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct ensoniq *ensoniq = substream->rmidi->private_data; int idx; - spin_lock_irqsave(&ensoniq->reg_lock, flags); + guard(spinlock_irqsave)(&ensoniq->reg_lock); if (up) { if ((ensoniq->uartc & ES_RXINTEN) == 0) { /* empty input FIFO */ @@ -2195,16 +2166,14 @@ static void snd_ensoniq_midi_input_trigger(struct snd_rawmidi_substream *substre outb(ensoniq->uartc, ES_REG(ensoniq, UART_CONTROL)); } } - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); } static void snd_ensoniq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct ensoniq *ensoniq = substream->rmidi->private_data; unsigned char byte; - spin_lock_irqsave(&ensoniq->reg_lock, flags); + guard(spinlock_irqsave)(&ensoniq->reg_lock); if (up) { if (ES_TXINTENI(ensoniq->uartc) == 0) { ensoniq->uartc |= ES_TXINTENO(1); @@ -2225,7 +2194,6 @@ static void snd_ensoniq_midi_output_trigger(struct snd_rawmidi_substream *substr outb(ensoniq->uartc, ES_REG(ensoniq, UART_CONTROL)); } } - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); } static const struct snd_rawmidi_ops snd_ensoniq_midi_output = @@ -2276,17 +2244,17 @@ static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id) if (!(status & ES_INTR)) return IRQ_NONE; - spin_lock(&ensoniq->reg_lock); - sctrl = ensoniq->sctrl; - if (status & ES_DAC1) - sctrl &= ~ES_P1_INT_EN; - if (status & ES_DAC2) - sctrl &= ~ES_P2_INT_EN; - if (status & ES_ADC) - sctrl &= ~ES_R1_INT_EN; - outl(sctrl, ES_REG(ensoniq, SERIAL)); - outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); - spin_unlock(&ensoniq->reg_lock); + scoped_guard(spinlock, &ensoniq->reg_lock) { + sctrl = ensoniq->sctrl; + if (status & ES_DAC1) + sctrl &= ~ES_P1_INT_EN; + if (status & ES_DAC2) + sctrl &= ~ES_P2_INT_EN; + if (status & ES_ADC) + sctrl &= ~ES_R1_INT_EN; + outl(sctrl, ES_REG(ensoniq, SERIAL)); + outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); + } if (status & ES_UART) snd_ensoniq_midi_interrupt(ensoniq); diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 0ce7076206f9..280125eff362 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -237,11 +237,9 @@ MODULE_DEVICE_TABLE(pci, snd_es1938_ids); * -----------------------------------------------------------------*/ static void snd_es1938_mixer_write(struct es1938 *chip, unsigned char reg, unsigned char val) { - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); + guard(spinlock_irqsave)(&chip->mixer_lock); outb(reg, SLSB_REG(chip, MIXERADDR)); outb(val, SLSB_REG(chip, MIXERDATA)); - spin_unlock_irqrestore(&chip->mixer_lock, flags); dev_dbg(chip->card->dev, "Mixer reg %02x set to %02x\n", reg, val); } @@ -251,11 +249,10 @@ static void snd_es1938_mixer_write(struct es1938 *chip, unsigned char reg, unsig static int snd_es1938_mixer_read(struct es1938 *chip, unsigned char reg) { int data; - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); + + guard(spinlock_irqsave)(&chip->mixer_lock); outb(reg, SLSB_REG(chip, MIXERADDR)); data = inb(SLSB_REG(chip, MIXERDATA)); - spin_unlock_irqrestore(&chip->mixer_lock, flags); dev_dbg(chip->card->dev, "Mixer reg %02x now is %02x\n", reg, data); return data; } @@ -266,9 +263,9 @@ static int snd_es1938_mixer_read(struct es1938 *chip, unsigned char reg) static int snd_es1938_mixer_bits(struct es1938 *chip, unsigned char reg, unsigned char mask, unsigned char val) { - unsigned long flags; unsigned char old, new, oval; - spin_lock_irqsave(&chip->mixer_lock, flags); + + guard(spinlock_irqsave)(&chip->mixer_lock); outb(reg, SLSB_REG(chip, MIXERADDR)); old = inb(SLSB_REG(chip, MIXERDATA)); oval = old & mask; @@ -279,7 +276,6 @@ static int snd_es1938_mixer_bits(struct es1938 *chip, unsigned char reg, "Mixer reg %02x was %02x, set to %02x\n", reg, old, new); } - spin_unlock_irqrestore(&chip->mixer_lock, flags); return oval; } @@ -322,11 +318,9 @@ static int snd_es1938_get_byte(struct es1938 *chip) * -----------------------------------------------------------------*/ static void snd_es1938_write(struct es1938 *chip, unsigned char reg, unsigned char val) { - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); snd_es1938_write_cmd(chip, reg); snd_es1938_write_cmd(chip, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); dev_dbg(chip->card->dev, "Reg %02x set to %02x\n", reg, val); } @@ -336,12 +330,11 @@ static void snd_es1938_write(struct es1938 *chip, unsigned char reg, unsigned ch static unsigned char snd_es1938_read(struct es1938 *chip, unsigned char reg) { unsigned char val; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + + guard(spinlock_irqsave)(&chip->reg_lock); snd_es1938_write_cmd(chip, ESS_CMD_READREG); snd_es1938_write_cmd(chip, reg); val = snd_es1938_get_byte(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); dev_dbg(chip->card->dev, "Reg %02x now is %02x\n", reg, val); return val; } @@ -352,9 +345,9 @@ static unsigned char snd_es1938_read(struct es1938 *chip, unsigned char reg) static int snd_es1938_bits(struct es1938 *chip, unsigned char reg, unsigned char mask, unsigned char val) { - unsigned long flags; unsigned char old, new, oval; - spin_lock_irqsave(&chip->reg_lock, flags); + + guard(spinlock_irqsave)(&chip->reg_lock); snd_es1938_write_cmd(chip, ESS_CMD_READREG); snd_es1938_write_cmd(chip, reg); old = snd_es1938_get_byte(chip); @@ -366,7 +359,6 @@ static int snd_es1938_bits(struct es1938 *chip, unsigned char reg, unsigned char dev_dbg(chip->card->dev, "Reg %02x was %02x, set to %02x\n", reg, old, new); } - spin_unlock_irqrestore(&chip->reg_lock, flags); return oval; } diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 624ba7d47566..51aee2c4d461 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -574,10 +574,8 @@ static void __maestro_write(struct es1968 *chip, u16 reg, u16 data) static inline void maestro_write(struct es1968 *chip, u16 reg, u16 data) { - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); __maestro_write(chip, reg, data); - spin_unlock_irqrestore(&chip->reg_lock, flags); } /* no spinlock */ @@ -592,12 +590,8 @@ static u16 __maestro_read(struct es1968 *chip, u16 reg) static inline u16 maestro_read(struct es1968 *chip, u16 reg) { - unsigned long flags; - u16 result; - spin_lock_irqsave(&chip->reg_lock, flags); - result = __maestro_read(chip, reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return result; + guard(spinlock_irqsave)(&chip->reg_lock); + return __maestro_read(chip, reg); } /* Wait for the codec bus to be free */ @@ -693,10 +687,8 @@ static void __apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 dat static void apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data) { - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); __apu_set_register(chip, channel, reg, data); - spin_unlock_irqrestore(&chip->reg_lock, flags); } static u16 __apu_get_register(struct es1968 *chip, u16 channel, u8 reg) @@ -710,62 +702,40 @@ static u16 __apu_get_register(struct es1968 *chip, u16 channel, u8 reg) static u16 apu_get_register(struct es1968 *chip, u16 channel, u8 reg) { - unsigned long flags; - u16 v; - spin_lock_irqsave(&chip->reg_lock, flags); - v = __apu_get_register(chip, channel, reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return v; + guard(spinlock_irqsave)(&chip->reg_lock); + return __apu_get_register(chip, channel, reg); } #if 0 /* ASSP is not supported */ static void assp_set_register(struct es1968 *chip, u32 reg, u32 value) { - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave),(&chip->reg_lock); outl(reg, chip->io_port + ASSP_INDEX); outl(value, chip->io_port + ASSP_DATA); - spin_unlock_irqrestore(&chip->reg_lock, flags); } static u32 assp_get_register(struct es1968 *chip, u32 reg) { - unsigned long flags; - u32 value; - - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); outl(reg, chip->io_port + ASSP_INDEX); - value = inl(chip->io_port + ASSP_DATA); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - return value; + return inl(chip->io_port + ASSP_DATA); } #endif static void wave_set_register(struct es1968 *chip, u16 reg, u16 value) { - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); outw(reg, chip->io_port + WC_INDEX); outw(value, chip->io_port + WC_DATA); - spin_unlock_irqrestore(&chip->reg_lock, flags); } static u16 wave_get_register(struct es1968 *chip, u16 reg) { - unsigned long flags; - u16 value; - - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); outw(reg, chip->io_port + WC_INDEX); - value = inw(chip->io_port + WC_DATA); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - return value; + return inw(chip->io_port + WC_DATA); } /* ******************* @@ -924,7 +894,7 @@ static inline void snd_es1968_trigger_apu(struct es1968 *esm, int apu, int mode) static void snd_es1968_pcm_start(struct es1968 *chip, struct esschan *es) { - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); __apu_set_register(chip, es->apu[0], 5, es->base[0]); snd_es1968_trigger_apu(chip, es->apu[0], es->apu_mode[0]); if (es->mode == ESM_MODE_CAPTURE) { @@ -939,19 +909,17 @@ static void snd_es1968_pcm_start(struct es1968 *chip, struct esschan *es) snd_es1968_trigger_apu(chip, es->apu[3], es->apu_mode[3]); } } - spin_unlock(&chip->reg_lock); } static void snd_es1968_pcm_stop(struct es1968 *chip, struct esschan *es) { - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); snd_es1968_trigger_apu(chip, es->apu[0], 0); snd_es1968_trigger_apu(chip, es->apu[1], 0); if (es->mode == ESM_MODE_CAPTURE) { snd_es1968_trigger_apu(chip, es->apu[2], 0); snd_es1968_trigger_apu(chip, es->apu[3], 0); } - spin_unlock(&chip->reg_lock); } /* set the wavecache control reg */ @@ -981,7 +949,6 @@ static void snd_es1968_playback_setup(struct es1968 *chip, struct esschan *es, int high_apu = 0; int channel, apu; int i, size; - unsigned long flags; u32 freq; size = es->dma_size >> es->wav_shift; @@ -1051,12 +1018,12 @@ static void snd_es1968_playback_setup(struct es1968 *chip, struct esschan *es, apu_set_register(chip, apu, 10, 0x8F08); } - spin_lock_irqsave(&chip->reg_lock, flags); - /* clear WP interrupts */ - outw(1, chip->io_port + 0x04); - /* enable WP ints */ - outw(inw(chip->io_port + ESM_PORT_HOST_IRQ) | ESM_HIRQ_DSIE, chip->io_port + ESM_PORT_HOST_IRQ); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + /* clear WP interrupts */ + outw(1, chip->io_port + 0x04); + /* enable WP ints */ + outw(inw(chip->io_port + ESM_PORT_HOST_IRQ) | ESM_HIRQ_DSIE, chip->io_port + ESM_PORT_HOST_IRQ); + } freq = runtime->rate; /* set frequency */ @@ -1127,7 +1094,6 @@ static void snd_es1968_capture_setup(struct es1968 *chip, struct esschan *es, { int size; u32 freq; - unsigned long flags; size = es->dma_size >> es->wav_shift; @@ -1179,12 +1145,11 @@ static void snd_es1968_capture_setup(struct es1968 *chip, struct esschan *es, snd_es1968_apu_set_freq(chip, es->apu[2], freq); snd_es1968_apu_set_freq(chip, es->apu[3], freq); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); /* clear WP interrupts */ outw(1, chip->io_port + 0x04); /* enable WP ints */ outw(inw(chip->io_port + ESM_PORT_HOST_IRQ) | ESM_HIRQ_DSIE, chip->io_port + ESM_PORT_HOST_IRQ); - spin_unlock_irqrestore(&chip->reg_lock, flags); } /******************* @@ -1228,7 +1193,7 @@ static int snd_es1968_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct es1968 *chip = snd_pcm_substream_chip(substream); struct esschan *es = substream->runtime->private_data; - spin_lock(&chip->substream_lock); + guard(spinlock)(&chip->substream_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -1249,7 +1214,6 @@ static int snd_es1968_pcm_trigger(struct snd_pcm_substream *substream, int cmd) snd_es1968_bob_dec(chip); break; } - spin_unlock(&chip->substream_lock); return 0; } @@ -1318,12 +1282,11 @@ static int calc_available_memory_size(struct es1968 *chip) int max_size = 0; struct esm_memory *buf; - mutex_lock(&chip->memory_mutex); + guard(mutex)(&chip->memory_mutex); list_for_each_entry(buf, &chip->buf_list, list) { if (buf->empty && buf->buf.bytes > max_size) max_size = buf->buf.bytes; } - mutex_unlock(&chip->memory_mutex); if (max_size >= 128*1024) max_size = 127*1024; return max_size; @@ -1335,21 +1298,18 @@ static struct esm_memory *snd_es1968_new_memory(struct es1968 *chip, int size) struct esm_memory *buf; size = ALIGN(size, ESM_MEM_ALIGN); - mutex_lock(&chip->memory_mutex); + guard(mutex)(&chip->memory_mutex); list_for_each_entry(buf, &chip->buf_list, list) { if (buf->empty && buf->buf.bytes >= size) goto __found; } - mutex_unlock(&chip->memory_mutex); return NULL; __found: if (buf->buf.bytes > size) { struct esm_memory *chunk = kmalloc(sizeof(*chunk), GFP_KERNEL); - if (chunk == NULL) { - mutex_unlock(&chip->memory_mutex); + if (chunk == NULL) return NULL; - } chunk->buf = buf->buf; chunk->buf.bytes -= size; chunk->buf.area += size; @@ -1359,7 +1319,6 @@ __found: list_add(&chunk->list, &buf->list); } buf->empty = 0; - mutex_unlock(&chip->memory_mutex); return buf; } @@ -1368,7 +1327,7 @@ static void snd_es1968_free_memory(struct es1968 *chip, struct esm_memory *buf) { struct esm_memory *chunk; - mutex_lock(&chip->memory_mutex); + guard(mutex)(&chip->memory_mutex); buf->empty = 1; if (buf->list.prev != &chip->buf_list) { chunk = list_entry(buf->list.prev, struct esm_memory, list); @@ -1387,7 +1346,6 @@ static void snd_es1968_free_memory(struct es1968 *chip, struct esm_memory *buf) kfree(chunk); } } - mutex_unlock(&chip->memory_mutex); } static void snd_es1968_free_dmabuf(struct es1968 *chip) @@ -1549,9 +1507,8 @@ static int snd_es1968_playback_open(struct snd_pcm_substream *substream) runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max = calc_available_memory_size(chip); - spin_lock_irq(&chip->substream_lock); + guard(spinlock_irq)(&chip->substream_lock); list_add(&es->list, &chip->substream_list); - spin_unlock_irq(&chip->substream_lock); return 0; } @@ -1609,9 +1566,8 @@ static int snd_es1968_capture_open(struct snd_pcm_substream *substream) if (err < 0) return err; - spin_lock_irq(&chip->substream_lock); + guard(spinlock_irq)(&chip->substream_lock); list_add(&es->list, &chip->substream_list); - spin_unlock_irq(&chip->substream_lock); return 0; } @@ -1624,9 +1580,9 @@ static int snd_es1968_playback_close(struct snd_pcm_substream *substream) if (substream->runtime->private_data == NULL) return 0; es = substream->runtime->private_data; - spin_lock_irq(&chip->substream_lock); - list_del(&es->list); - spin_unlock_irq(&chip->substream_lock); + scoped_guard(spinlock_irq, &chip->substream_lock) { + list_del(&es->list); + } snd_es1968_free_apu_pair(chip, es->apu[0]); kfree(es); @@ -1641,9 +1597,9 @@ static int snd_es1968_capture_close(struct snd_pcm_substream *substream) if (substream->runtime->private_data == NULL) return 0; es = substream->runtime->private_data; - spin_lock_irq(&chip->substream_lock); - list_del(&es->list); - spin_unlock_irq(&chip->substream_lock); + scoped_guard(spinlock_irq, &chip->substream_lock) { + list_del(&es->list); + } snd_es1968_free_memory(chip, es->mixbuf); snd_es1968_free_apu_pair(chip, es->apu[0]); snd_es1968_free_apu_pair(chip, es->apu[2]); @@ -1724,29 +1680,29 @@ static void es1968_measure_clock(struct es1968 *chip) apu_set_register(chip, apu, 9, 0xD000); apu_set_register(chip, apu, 10, 0x8F08); apu_set_register(chip, apu, 11, 0x0000); - spin_lock_irq(&chip->reg_lock); - outw(1, chip->io_port + 0x04); /* clear WP interrupts */ - outw(inw(chip->io_port + ESM_PORT_HOST_IRQ) | ESM_HIRQ_DSIE, chip->io_port + ESM_PORT_HOST_IRQ); /* enable WP ints */ - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + outw(1, chip->io_port + 0x04); /* clear WP interrupts */ + outw(inw(chip->io_port + ESM_PORT_HOST_IRQ) | ESM_HIRQ_DSIE, chip->io_port + ESM_PORT_HOST_IRQ); /* enable WP ints */ + } snd_es1968_apu_set_freq(chip, apu, ((unsigned int)48000 << 16) / chip->clock); /* 48000 Hz */ chip->in_measurement = 1; chip->measure_apu = apu; - spin_lock_irq(&chip->reg_lock); - snd_es1968_bob_inc(chip, ESM_BOB_FREQ); - __apu_set_register(chip, apu, 5, pa & 0xffff); - snd_es1968_trigger_apu(chip, apu, ESM_APU_16BITLINEAR); - start_time = ktime_get(); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + snd_es1968_bob_inc(chip, ESM_BOB_FREQ); + __apu_set_register(chip, apu, 5, pa & 0xffff); + snd_es1968_trigger_apu(chip, apu, ESM_APU_16BITLINEAR); + start_time = ktime_get(); + } msleep(50); - spin_lock_irq(&chip->reg_lock); - offset = __apu_get_register(chip, apu, 5); - stop_time = ktime_get(); - snd_es1968_trigger_apu(chip, apu, 0); /* stop */ - snd_es1968_bob_dec(chip); - chip->in_measurement = 0; - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + offset = __apu_get_register(chip, apu, 5); + stop_time = ktime_get(); + snd_es1968_trigger_apu(chip, apu, 0); /* stop */ + snd_es1968_bob_dec(chip); + chip->in_measurement = 0; + } /* check the current position */ offset -= (pa & 0xffff); @@ -1970,15 +1926,15 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id) if (event & ESM_SOUND_IRQ) { struct esschan *es; - spin_lock(&chip->substream_lock); - list_for_each_entry(es, &chip->substream_list, list) { - if (es->running) { - snd_es1968_update_pcm(chip, es); - if (es->fmt & ESS_FMT_STEREO) - snd_es1968_suppress_jitter(chip, es); + scoped_guard(spinlock, &chip->substream_lock) { + list_for_each_entry(es, &chip->substream_list, list) { + if (es->running) { + snd_es1968_update_pcm(chip, es); + if (es->fmt & ESS_FMT_STEREO) + snd_es1968_suppress_jitter(chip, es); + } } } - spin_unlock(&chip->substream_lock); if (chip->in_measurement) { unsigned int curp = __apu_get_register(chip, chip->measure_apu, 5); if (curp < chip->measure_lastpos) diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index cf40bd06b734..4ca992449ea3 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -279,16 +279,14 @@ static int snd_fm801_update_bits(struct fm801 *chip, unsigned short reg, unsigned short mask, unsigned short value) { int change; - unsigned long flags; unsigned short old, new; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); old = fm801_ioread16(chip, reg); new = (old & ~mask) | value; change = old != new; if (change) fm801_iowrite16(chip, reg, new); - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } @@ -393,7 +391,7 @@ static int snd_fm801_playback_trigger(struct snd_pcm_substream *substream, { struct fm801 *chip = snd_pcm_substream_chip(substream); - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: chip->ply_ctrl &= ~(FM801_BUF1_LAST | @@ -414,12 +412,10 @@ static int snd_fm801_playback_trigger(struct snd_pcm_substream *substream, chip->ply_ctrl &= ~FM801_PAUSE; break; default: - spin_unlock(&chip->reg_lock); snd_BUG(); return -EINVAL; } fm801_writew(chip, PLY_CTRL, chip->ply_ctrl); - spin_unlock(&chip->reg_lock); return 0; } @@ -428,7 +424,7 @@ static int snd_fm801_capture_trigger(struct snd_pcm_substream *substream, { struct fm801 *chip = snd_pcm_substream_chip(substream); - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: chip->cap_ctrl &= ~(FM801_BUF1_LAST | @@ -449,12 +445,10 @@ static int snd_fm801_capture_trigger(struct snd_pcm_substream *substream, chip->cap_ctrl &= ~FM801_PAUSE; break; default: - spin_unlock(&chip->reg_lock); snd_BUG(); return -EINVAL; } fm801_writew(chip, CAP_CTRL, chip->cap_ctrl); - spin_unlock(&chip->reg_lock); return 0; } @@ -465,7 +459,7 @@ static int snd_fm801_playback_prepare(struct snd_pcm_substream *substream) chip->ply_size = snd_pcm_lib_buffer_bytes(substream); chip->ply_count = snd_pcm_lib_period_bytes(substream); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->ply_ctrl &= ~(FM801_START | FM801_16BIT | FM801_STEREO | FM801_RATE_MASK | FM801_CHANNELS_MASK); @@ -487,7 +481,6 @@ static int snd_fm801_playback_prepare(struct snd_pcm_substream *substream) fm801_writel(chip, PLY_BUF1, chip->ply_buffer); fm801_writel(chip, PLY_BUF2, chip->ply_buffer + (chip->ply_count % chip->ply_size)); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -498,7 +491,7 @@ static int snd_fm801_capture_prepare(struct snd_pcm_substream *substream) chip->cap_size = snd_pcm_lib_buffer_bytes(substream); chip->cap_count = snd_pcm_lib_period_bytes(substream); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->cap_ctrl &= ~(FM801_START | FM801_16BIT | FM801_STEREO | FM801_RATE_MASK); if (snd_pcm_format_width(runtime->format) == 16) @@ -514,7 +507,6 @@ static int snd_fm801_capture_prepare(struct snd_pcm_substream *substream) fm801_writel(chip, CAP_BUF1, chip->cap_buffer); fm801_writel(chip, CAP_BUF2, chip->cap_buffer + (chip->cap_count % chip->cap_size)); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -525,13 +517,12 @@ static snd_pcm_uframes_t snd_fm801_playback_pointer(struct snd_pcm_substream *su if (!(chip->ply_ctrl & FM801_START)) return 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); ptr = chip->ply_pos + (chip->ply_count - 1) - fm801_readw(chip, PLY_COUNT); if (fm801_readw(chip, IRQ_STATUS) & FM801_IRQ_PLAYBACK) { ptr += chip->ply_count; ptr %= chip->ply_size; } - spin_unlock(&chip->reg_lock); return bytes_to_frames(substream->runtime, ptr); } @@ -542,13 +533,12 @@ static snd_pcm_uframes_t snd_fm801_capture_pointer(struct snd_pcm_substream *sub if (!(chip->cap_ctrl & FM801_START)) return 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); ptr = chip->cap_pos + (chip->cap_count - 1) - fm801_readw(chip, CAP_COUNT); if (fm801_readw(chip, IRQ_STATUS) & FM801_IRQ_CAPTURE) { ptr += chip->cap_count; ptr %= chip->cap_size; } - spin_unlock(&chip->reg_lock); return bytes_to_frames(substream->runtime, ptr); } @@ -565,31 +555,31 @@ static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id) /* ack first */ fm801_writew(chip, IRQ_STATUS, status); if (chip->pcm && (status & FM801_IRQ_PLAYBACK) && chip->playback_substream) { - spin_lock(&chip->reg_lock); - chip->ply_buf++; - chip->ply_pos += chip->ply_count; - chip->ply_pos %= chip->ply_size; - tmp = chip->ply_pos + chip->ply_count; - tmp %= chip->ply_size; - if (chip->ply_buf & 1) - fm801_writel(chip, PLY_BUF1, chip->ply_buffer + tmp); - else - fm801_writel(chip, PLY_BUF2, chip->ply_buffer + tmp); - spin_unlock(&chip->reg_lock); + scoped_guard(spinlock, &chip->reg_lock) { + chip->ply_buf++; + chip->ply_pos += chip->ply_count; + chip->ply_pos %= chip->ply_size; + tmp = chip->ply_pos + chip->ply_count; + tmp %= chip->ply_size; + if (chip->ply_buf & 1) + fm801_writel(chip, PLY_BUF1, chip->ply_buffer + tmp); + else + fm801_writel(chip, PLY_BUF2, chip->ply_buffer + tmp); + } snd_pcm_period_elapsed(chip->playback_substream); } if (chip->pcm && (status & FM801_IRQ_CAPTURE) && chip->capture_substream) { - spin_lock(&chip->reg_lock); - chip->cap_buf++; - chip->cap_pos += chip->cap_count; - chip->cap_pos %= chip->cap_size; - tmp = chip->cap_pos + chip->cap_count; - tmp %= chip->cap_size; - if (chip->cap_buf & 1) - fm801_writel(chip, CAP_BUF1, chip->cap_buffer + tmp); - else - fm801_writel(chip, CAP_BUF2, chip->cap_buffer + tmp); - spin_unlock(&chip->reg_lock); + scoped_guard(spinlock, &chip->reg_lock) { + chip->cap_buf++; + chip->cap_pos += chip->cap_count; + chip->cap_pos %= chip->cap_size; + tmp = chip->cap_pos + chip->cap_count; + tmp %= chip->cap_size; + if (chip->cap_buf & 1) + fm801_writel(chip, CAP_BUF1, chip->cap_buffer + tmp); + else + fm801_writel(chip, CAP_BUF2, chip->cap_buffer + tmp); + } snd_pcm_period_elapsed(chip->capture_substream); } if (chip->rmidi && (status & FM801_IRQ_MPU)) @@ -924,10 +914,9 @@ static int snd_fm801_get_double(struct snd_kcontrol *kcontrol, int invert = (kcontrol->private_value >> 24) & 0xff; long *value = ucontrol->value.integer.value; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); value[0] = (fm801_ioread16(chip, reg) >> shift_left) & mask; value[1] = (fm801_ioread16(chip, reg) >> shift_right) & mask; - spin_unlock_irq(&chip->reg_lock); if (invert) { value[0] = mask - value[0]; value[1] = mask - value[1]; diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 027849329c1b..b4c9e7d11609 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c @@ -358,14 +358,13 @@ static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ele struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned short vol; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F); ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F); if (kcontrol->private_value & AUREON_AC97_STEREO) ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F); - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -401,12 +400,11 @@ static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_el { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -439,11 +437,10 @@ static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ct { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -642,11 +639,10 @@ static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -704,9 +700,8 @@ static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -944,11 +939,10 @@ static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned short val; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; val = val > PCM_MIN ? (val - PCM_MIN) : 0; ucontrol->value.integer.value[0] = val; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -984,12 +978,11 @@ static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va unsigned short val; int i; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (i = 0; i < 2; i++) { val = wm_get(ice, WM_ADC_GAIN + i); ucontrol->value.integer.value[i] = ~val>>5 & 0x1; } - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -1031,13 +1024,12 @@ static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val int i, idx; unsigned short vol; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (i = 0; i < 2; i++) { idx = WM_ADC_GAIN + i; vol = wm_get(ice, idx) & 0x1f; ucontrol->value.integer.value[i] = vol; } - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -1097,11 +1089,10 @@ static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned short val; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); val = wm_get(ice, WM_ADC_MUX); ucontrol->value.enumerated.item[0] = val & 7; ucontrol->value.enumerated.item[1] = (val >> 4) & 7; - mutex_unlock(&ice->gpio_mutex); return 0; } diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index 08adf4dd1303..e5a9585cba4c 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c @@ -126,13 +126,12 @@ static int ap_cs8427_sendbytes(struct snd_i2c_device *device, unsigned char *byt int res = count; unsigned char tmp; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); tmp = ap_cs8427_codec_select(ice); ap_cs8427_write_byte(ice, (device->addr << 1) | 0, tmp); /* address + write mode */ while (count-- > 0) ap_cs8427_write_byte(ice, *bytes++, tmp); ap_cs8427_codec_deassert(ice, tmp); - mutex_unlock(&ice->gpio_mutex); return res; } @@ -143,13 +142,12 @@ static int ap_cs8427_readbytes(struct snd_i2c_device *device, unsigned char *byt int res = count; unsigned char tmp; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); tmp = ap_cs8427_codec_select(ice); ap_cs8427_write_byte(ice, (device->addr << 1) | 1, tmp); /* address + read mode */ while (count-- > 0) *bytes++ = ap_cs8427_read_byte(ice, tmp); ap_cs8427_codec_deassert(ice, tmp); - mutex_unlock(&ice->gpio_mutex); return res; } @@ -176,7 +174,7 @@ static void snd_ice1712_delta_cs8403_spdif_write(struct snd_ice1712 *ice, unsign /* send byte to transmitter */ mask1 = ICE1712_DELTA_SPDIF_OUT_STAT_CLOCK; mask2 = ICE1712_DELTA_SPDIF_OUT_STAT_DATA; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); for (idx = 7; idx >= 0; idx--) { tmp &= ~(mask1 | mask2); @@ -190,7 +188,6 @@ static void snd_ice1712_delta_cs8403_spdif_write(struct snd_ice1712 *ice, unsign } tmp &= ~mask1; snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - mutex_unlock(&ice->gpio_mutex); } @@ -205,15 +202,13 @@ static int delta_spdif_default_put(struct snd_ice1712 *ice, struct snd_ctl_elem_ int change; val = snd_cs8403_encode_spdif_bits(&ucontrol->value.iec958); - spin_lock_irq(&ice->reg_lock); - change = ice->spdif.cs8403_bits != val; - ice->spdif.cs8403_bits = val; - if (change && ice->playback_pro_substream == NULL) { - spin_unlock_irq(&ice->reg_lock); - snd_ice1712_delta_cs8403_spdif_write(ice, val); - } else { - spin_unlock_irq(&ice->reg_lock); + scoped_guard(spinlock_irq, &ice->reg_lock) { + change = ice->spdif.cs8403_bits != val; + ice->spdif.cs8403_bits = val; + if (!change || ice->playback_pro_substream) + return change; } + snd_ice1712_delta_cs8403_spdif_write(ice, val); return change; } @@ -228,15 +223,13 @@ static int delta_spdif_stream_put(struct snd_ice1712 *ice, struct snd_ctl_elem_v int change; val = snd_cs8403_encode_spdif_bits(&ucontrol->value.iec958); - spin_lock_irq(&ice->reg_lock); - change = ice->spdif.cs8403_stream_bits != val; - ice->spdif.cs8403_stream_bits = val; - if (change && ice->playback_pro_substream != NULL) { - spin_unlock_irq(&ice->reg_lock); - snd_ice1712_delta_cs8403_spdif_write(ice, val); - } else { - spin_unlock_irq(&ice->reg_lock); + scoped_guard(spinlock_irq, &ice->reg_lock) { + change = ice->spdif.cs8403_stream_bits != val; + ice->spdif.cs8403_stream_bits = val; + if (!change || ice->playback_pro_substream) + return change; } + snd_ice1712_delta_cs8403_spdif_write(ice, val); return change; } @@ -306,14 +299,13 @@ static void delta_1010_set_rate_val(struct snd_ice1712 *ice, unsigned int rate) if (rate == 0) /* no hint - S/PDIF input is master, simply return */ return; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); tmp2 = tmp & ~ICE1712_DELTA_DFS; if (rate > 48000) tmp2 |= ICE1712_DELTA_DFS; if (tmp != tmp2) snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp2); - mutex_unlock(&ice->gpio_mutex); } /* @@ -328,9 +320,9 @@ static void delta_ak4524_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) return; /* check before reset ak4524 to avoid unnecessary clicks */ - mutex_lock(&ice->gpio_mutex); - tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); - mutex_unlock(&ice->gpio_mutex); + scoped_guard(mutex, &ice->gpio_mutex) { + tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); + } tmp2 = tmp & ~ICE1712_DELTA_DFS; if (rate > 48000) tmp2 |= ICE1712_DELTA_DFS; @@ -339,12 +331,12 @@ static void delta_ak4524_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) /* do it again */ snd_akm4xxx_reset(ak, 1); - mutex_lock(&ice->gpio_mutex); - tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ~ICE1712_DELTA_DFS; - if (rate > 48000) - tmp |= ICE1712_DELTA_DFS; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - mutex_unlock(&ice->gpio_mutex); + scoped_guard(mutex, &ice->gpio_mutex) { + tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ~ICE1712_DELTA_DFS; + if (rate > 48000) + tmp |= ICE1712_DELTA_DFS; + snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); + } snd_akm4xxx_reset(ak, 0); } @@ -379,23 +371,22 @@ static void delta_open_spdif(struct snd_ice1712 *ice, struct snd_pcm_substream * /* set up */ static void delta_setup_spdif(struct snd_ice1712 *ice, int rate) { - unsigned long flags; unsigned int tmp; int change; - spin_lock_irqsave(&ice->reg_lock, flags); - tmp = ice->spdif.cs8403_stream_bits; - if (tmp & 0x01) /* consumer */ - tmp &= (tmp & 0x01) ? ~0x06 : ~0x18; - switch (rate) { - case 32000: tmp |= (tmp & 0x01) ? 0x04 : 0x00; break; - case 44100: tmp |= (tmp & 0x01) ? 0x00 : 0x10; break; - case 48000: tmp |= (tmp & 0x01) ? 0x02 : 0x08; break; - default: tmp |= (tmp & 0x01) ? 0x00 : 0x18; break; + scoped_guard(spinlock_irqsave, &ice->reg_lock) { + tmp = ice->spdif.cs8403_stream_bits; + if (tmp & 0x01) /* consumer */ + tmp &= (tmp & 0x01) ? ~0x06 : ~0x18; + switch (rate) { + case 32000: tmp |= (tmp & 0x01) ? 0x04 : 0x00; break; + case 44100: tmp |= (tmp & 0x01) ? 0x00 : 0x10; break; + case 48000: tmp |= (tmp & 0x01) ? 0x02 : 0x08; break; + default: tmp |= (tmp & 0x01) ? 0x00 : 0x18; break; + } + change = ice->spdif.cs8403_stream_bits != tmp; + ice->spdif.cs8403_stream_bits = tmp; } - change = ice->spdif.cs8403_stream_bits != tmp; - ice->spdif.cs8403_stream_bits = tmp; - spin_unlock_irqrestore(&ice->reg_lock, flags); if (change) snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &ice->spdif.stream_ctl->id); snd_ice1712_delta_cs8403_spdif_write(ice, tmp); diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c index 8bb86b3c894e..1dffcb011deb 100644 --- a/sound/pci/ice1712/ews.c +++ b/sound/pci/ice1712/ews.c @@ -260,15 +260,13 @@ static int ews88_spdif_default_put(struct snd_ice1712 *ice, struct snd_ctl_elem_ int change; val = snd_cs8404_encode_spdif_bits(&ucontrol->value.iec958); - spin_lock_irq(&ice->reg_lock); - change = ice->spdif.cs8403_bits != val; - ice->spdif.cs8403_bits = val; - if (change && ice->playback_pro_substream == NULL) { - spin_unlock_irq(&ice->reg_lock); - snd_ice1712_ews_cs8404_spdif_write(ice, val); - } else { - spin_unlock_irq(&ice->reg_lock); + scoped_guard(spinlock_irq, &ice->reg_lock) { + change = ice->spdif.cs8403_bits != val; + ice->spdif.cs8403_bits = val; + if (!change || ice->playback_pro_substream) + return change; } + snd_ice1712_ews_cs8404_spdif_write(ice, val); return change; } @@ -283,15 +281,13 @@ static int ews88_spdif_stream_put(struct snd_ice1712 *ice, struct snd_ctl_elem_v int change; val = snd_cs8404_encode_spdif_bits(&ucontrol->value.iec958); - spin_lock_irq(&ice->reg_lock); - change = ice->spdif.cs8403_stream_bits != val; - ice->spdif.cs8403_stream_bits = val; - if (change && ice->playback_pro_substream != NULL) { - spin_unlock_irq(&ice->reg_lock); - snd_ice1712_ews_cs8404_spdif_write(ice, val); - } else { - spin_unlock_irq(&ice->reg_lock); + scoped_guard(spinlock_irq, &ice->reg_lock) { + change = ice->spdif.cs8403_stream_bits != val; + ice->spdif.cs8403_stream_bits = val; + if (!change || ice->playback_pro_substream) + return change; } + snd_ice1712_ews_cs8404_spdif_write(ice, val); return change; } @@ -305,23 +301,22 @@ static void ews88_open_spdif(struct snd_ice1712 *ice, struct snd_pcm_substream * /* set up SPDIF for EWS88MT / EWS88D */ static void ews88_setup_spdif(struct snd_ice1712 *ice, int rate) { - unsigned long flags; unsigned char tmp; int change; - spin_lock_irqsave(&ice->reg_lock, flags); - tmp = ice->spdif.cs8403_stream_bits; - if (tmp & 0x10) /* consumer */ - tmp &= (tmp & 0x01) ? ~0x06 : ~0x60; - switch (rate) { - case 32000: tmp |= (tmp & 0x01) ? 0x02 : 0x00; break; - case 44100: tmp |= (tmp & 0x01) ? 0x06 : 0x40; break; - case 48000: tmp |= (tmp & 0x01) ? 0x04 : 0x20; break; - default: tmp |= (tmp & 0x01) ? 0x06 : 0x40; break; + scoped_guard(spinlock_irqsave, &ice->reg_lock) { + tmp = ice->spdif.cs8403_stream_bits; + if (tmp & 0x10) /* consumer */ + tmp &= (tmp & 0x01) ? ~0x06 : ~0x60; + switch (rate) { + case 32000: tmp |= (tmp & 0x01) ? 0x02 : 0x00; break; + case 44100: tmp |= (tmp & 0x01) ? 0x06 : 0x40; break; + case 48000: tmp |= (tmp & 0x01) ? 0x04 : 0x20; break; + default: tmp |= (tmp & 0x01) ? 0x06 : 0x40; break; + } + change = ice->spdif.cs8403_stream_bits != tmp; + ice->spdif.cs8403_stream_bits = tmp; } - change = ice->spdif.cs8403_stream_bits != tmp; - ice->spdif.cs8403_stream_bits = tmp; - spin_unlock_irqrestore(&ice->reg_lock, flags); if (change) snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &ice->spdif.stream_ctl->id); snd_ice1712_ews_cs8404_spdif_write(ice, tmp); diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c index 46daeea8dc66..071f94dc7390 100644 --- a/sound/pci/ice1712/hoontech.c +++ b/sound/pci/ice1712/hoontech.c @@ -41,35 +41,35 @@ static void snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned cha static void snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate) { struct hoontech_spec *spec = ice->spec; - mutex_lock(&ice->gpio_mutex); + + guard(mutex)(&ice->gpio_mutex); ICE1712_STDSP24_0_DAREAR(spec->boxbits, activate); snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]); - mutex_unlock(&ice->gpio_mutex); } static void snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate) { struct hoontech_spec *spec = ice->spec; - mutex_lock(&ice->gpio_mutex); + + guard(mutex)(&ice->gpio_mutex); ICE1712_STDSP24_3_MUTE(spec->boxbits, activate); snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]); - mutex_unlock(&ice->gpio_mutex); } static void snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate) { struct hoontech_spec *spec = ice->spec; - mutex_lock(&ice->gpio_mutex); + + guard(mutex)(&ice->gpio_mutex); ICE1712_STDSP24_3_INSEL(spec->boxbits, activate); snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]); - mutex_unlock(&ice->gpio_mutex); } static void snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate) { struct hoontech_spec *spec = ice->spec; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); /* select box */ ICE1712_STDSP24_0_BOX(spec->boxbits, box); @@ -111,15 +111,13 @@ static void snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, in ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0); snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); - - mutex_unlock(&ice->gpio_mutex); } static void snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master) { struct hoontech_spec *spec = ice->spec; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); /* select box */ ICE1712_STDSP24_0_BOX(spec->boxbits, box); @@ -139,17 +137,15 @@ static void snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int m ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1); snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); - - mutex_unlock(&ice->gpio_mutex); } static void snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate) { struct hoontech_spec *spec = ice->spec; - mutex_lock(&ice->gpio_mutex); + + guard(mutex)(&ice->gpio_mutex); ICE1712_STDSP24_3_MIDI2(spec->boxbits, activate); snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]); - mutex_unlock(&ice->gpio_mutex); } static int hoontech_init(struct snd_ice1712 *ice, bool staudio) diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 1aefd46ebf6b..1e39b985bef2 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -249,13 +249,12 @@ static int snd_ice1712_digmix_route_ac97_put(struct snd_kcontrol *kcontrol, stru struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned char val, nval; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); val = inb(ICEMT(ice, MONITOR_ROUTECTRL)); nval = val & ~ICE1712_ROUTE_AC97; if (ucontrol->value.integer.value[0]) nval |= ICE1712_ROUTE_AC97; outb(nval, ICEMT(ice, MONITOR_ROUTECTRL)); - spin_unlock_irq(&ice->reg_lock); return val != nval; } @@ -484,7 +483,7 @@ static int snd_ice1712_playback_trigger(struct snd_pcm_substream *substream, int result = 0; u32 tmp; - spin_lock(&ice->reg_lock); + guard(spinlock)(&ice->reg_lock); tmp = snd_ice1712_read(ice, ICE1712_IREG_PBK_CTRL); if (cmd == SNDRV_PCM_TRIGGER_START) { tmp |= 1; @@ -498,7 +497,6 @@ static int snd_ice1712_playback_trigger(struct snd_pcm_substream *substream, result = -EINVAL; } snd_ice1712_write(ice, ICE1712_IREG_PBK_CTRL, tmp); - spin_unlock(&ice->reg_lock); return result; } @@ -509,7 +507,7 @@ static int snd_ice1712_playback_ds_trigger(struct snd_pcm_substream *substream, int result = 0; u32 tmp; - spin_lock(&ice->reg_lock); + guard(spinlock)(&ice->reg_lock); tmp = snd_ice1712_ds_read(ice, substream->number * 2, ICE1712_DSC_CONTROL); if (cmd == SNDRV_PCM_TRIGGER_START) { tmp |= 1; @@ -523,7 +521,6 @@ static int snd_ice1712_playback_ds_trigger(struct snd_pcm_substream *substream, result = -EINVAL; } snd_ice1712_ds_write(ice, substream->number * 2, ICE1712_DSC_CONTROL, tmp); - spin_unlock(&ice->reg_lock); return result; } @@ -534,7 +531,7 @@ static int snd_ice1712_capture_trigger(struct snd_pcm_substream *substream, int result = 0; u8 tmp; - spin_lock(&ice->reg_lock); + guard(spinlock)(&ice->reg_lock); tmp = snd_ice1712_read(ice, ICE1712_IREG_CAP_CTRL); if (cmd == SNDRV_PCM_TRIGGER_START) { tmp |= 1; @@ -544,7 +541,6 @@ static int snd_ice1712_capture_trigger(struct snd_pcm_substream *substream, result = -EINVAL; } snd_ice1712_write(ice, ICE1712_IREG_CAP_CTRL, tmp); - spin_unlock(&ice->reg_lock); return result; } @@ -564,7 +560,7 @@ static int snd_ice1712_playback_prepare(struct snd_pcm_substream *substream) rate = (runtime->rate * 8192) / 375; if (rate > 0x000fffff) rate = 0x000fffff; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); outb(0, ice->ddma_port + 15); outb(ICE1712_DMA_MODE_WRITE | ICE1712_DMA_AUTOINIT, ice->ddma_port + 0x0b); outl(runtime->dma_addr, ice->ddma_port + 0); @@ -577,7 +573,6 @@ static int snd_ice1712_playback_prepare(struct snd_pcm_substream *substream) snd_ice1712_write(ice, ICE1712_IREG_PBK_COUNT_HI, period_size >> 8); snd_ice1712_write(ice, ICE1712_IREG_PBK_LEFT, 0); snd_ice1712_write(ice, ICE1712_IREG_PBK_RIGHT, 0); - spin_unlock_irq(&ice->reg_lock); return 0; } @@ -599,7 +594,7 @@ static int snd_ice1712_playback_ds_prepare(struct snd_pcm_substream *substream) ice->playback_con_active_buf[substream->number] = 0; ice->playback_con_virt_addr[substream->number] = runtime->dma_addr; chn = substream->number * 2; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); snd_ice1712_ds_write(ice, chn, ICE1712_DSC_ADDR0, runtime->dma_addr); snd_ice1712_ds_write(ice, chn, ICE1712_DSC_COUNT0, period_size); snd_ice1712_ds_write(ice, chn, ICE1712_DSC_ADDR1, runtime->dma_addr + (runtime->periods > 1 ? period_size + 1 : 0)); @@ -611,7 +606,6 @@ static int snd_ice1712_playback_ds_prepare(struct snd_pcm_substream *substream) snd_ice1712_ds_write(ice, chn + 1, ICE1712_DSC_RATE, rate); snd_ice1712_ds_write(ice, chn + 1, ICE1712_DSC_VOLUME, 0); } - spin_unlock_irq(&ice->reg_lock); return 0; } @@ -629,13 +623,13 @@ static int snd_ice1712_capture_prepare(struct snd_pcm_substream *substream) tmp &= ~0x04; if (runtime->channels == 2) tmp &= ~0x02; - spin_lock_irq(&ice->reg_lock); - outl(ice->capture_con_virt_addr = runtime->dma_addr, ICEREG(ice, CONCAP_ADDR)); - outw(buf_size, ICEREG(ice, CONCAP_COUNT)); - snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_HI, period_size >> 8); - snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_LO, period_size & 0xff); - snd_ice1712_write(ice, ICE1712_IREG_CAP_CTRL, tmp); - spin_unlock_irq(&ice->reg_lock); + scoped_guard(spinlock_irq, &ice->reg_lock) { + outl(ice->capture_con_virt_addr = runtime->dma_addr, ICEREG(ice, CONCAP_ADDR)); + outw(buf_size, ICEREG(ice, CONCAP_COUNT)); + snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_HI, period_size >> 8); + snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_LO, period_size & 0xff); + snd_ice1712_write(ice, ICE1712_IREG_CAP_CTRL, tmp); + } snd_ac97_set_rate(ice->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); return 0; } @@ -763,10 +757,9 @@ static int snd_ice1712_playback_ds_open(struct snd_pcm_substream *substream) ice->playback_con_substream_ds[substream->number] = substream; runtime->hw = snd_ice1712_playback_ds; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); tmp = inw(ICEDS(ice, INTMASK)) & ~(1 << (substream->number * 2)); outw(tmp, ICEDS(ice, INTMASK)); - spin_unlock_irq(&ice->reg_lock); return 0; } @@ -796,10 +789,9 @@ static int snd_ice1712_playback_ds_close(struct snd_pcm_substream *substream) struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); u32 tmp; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); tmp = inw(ICEDS(ice, INTMASK)) | (3 << (substream->number * 2)); outw(tmp, ICEDS(ice, INTMASK)); - spin_unlock_irq(&ice->reg_lock); ice->playback_con_substream_ds[substream->number] = NULL; return 0; } @@ -911,14 +903,13 @@ static int snd_ice1712_pro_trigger(struct snd_pcm_substream *substream, return -EINVAL; what = ICE1712_PLAYBACK_PAUSE; snd_pcm_trigger_done(substream, substream); - spin_lock(&ice->reg_lock); + guard(spinlock)(&ice->reg_lock); old = inl(ICEMT(ice, PLAYBACK_CONTROL)); if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) old |= what; else old &= ~what; outl(old, ICEMT(ice, PLAYBACK_CONTROL)); - spin_unlock(&ice->reg_lock); break; } case SNDRV_PCM_TRIGGER_START: @@ -937,14 +928,13 @@ static int snd_ice1712_pro_trigger(struct snd_pcm_substream *substream, snd_pcm_trigger_done(s, substream); } } - spin_lock(&ice->reg_lock); + guard(spinlock)(&ice->reg_lock); old = inl(ICEMT(ice, PLAYBACK_CONTROL)); if (cmd == SNDRV_PCM_TRIGGER_START) old |= what; else old &= ~what; outl(old, ICEMT(ice, PLAYBACK_CONTROL)); - spin_unlock(&ice->reg_lock); break; } default: @@ -957,7 +947,6 @@ static int snd_ice1712_pro_trigger(struct snd_pcm_substream *substream, */ static void snd_ice1712_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, int force) { - unsigned long flags; unsigned char val, old; unsigned int i; @@ -982,24 +971,21 @@ static void snd_ice1712_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, break; } - spin_lock_irqsave(&ice->reg_lock, flags); - if (inb(ICEMT(ice, PLAYBACK_CONTROL)) & (ICE1712_CAPTURE_START_SHADOW| - ICE1712_PLAYBACK_PAUSE| - ICE1712_PLAYBACK_START)) { -__out: - spin_unlock_irqrestore(&ice->reg_lock, flags); - return; - } - if (!force && is_pro_rate_locked(ice)) - goto __out; + scoped_guard(spinlock_irqsave, &ice->reg_lock) { + if (inb(ICEMT(ice, PLAYBACK_CONTROL)) & (ICE1712_CAPTURE_START_SHADOW| + ICE1712_PLAYBACK_PAUSE| + ICE1712_PLAYBACK_START)) + return; + if (!force && is_pro_rate_locked(ice)) + return; - old = inb(ICEMT(ice, RATE)); - if (!force && old == val) - goto __out; + old = inb(ICEMT(ice, RATE)); + if (!force && old == val) + return; - ice->cur_rate = rate; - outb(val, ICEMT(ice, RATE)); - spin_unlock_irqrestore(&ice->reg_lock, flags); + ice->cur_rate = rate; + outb(val, ICEMT(ice, RATE)); + } if (ice->gpio.set_pro_rate) ice->gpio.set_pro_rate(ice, rate); @@ -1016,11 +1002,10 @@ static int snd_ice1712_playback_pro_prepare(struct snd_pcm_substream *substream) struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); ice->playback_pro_size = snd_pcm_lib_buffer_bytes(substream); - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); outl(substream->runtime->dma_addr, ICEMT(ice, PLAYBACK_ADDR)); outw((ice->playback_pro_size >> 2) - 1, ICEMT(ice, PLAYBACK_SIZE)); outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ICEMT(ice, PLAYBACK_COUNT)); - spin_unlock_irq(&ice->reg_lock); return 0; } @@ -1039,11 +1024,10 @@ static int snd_ice1712_capture_pro_prepare(struct snd_pcm_substream *substream) struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); ice->capture_pro_size = snd_pcm_lib_buffer_bytes(substream); - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); outl(substream->runtime->dma_addr, ICEMT(ice, CAPTURE_ADDR)); outw((ice->capture_pro_size >> 2) - 1, ICEMT(ice, CAPTURE_SIZE)); outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ICEMT(ice, CAPTURE_COUNT)); - spin_unlock_irq(&ice->reg_lock); return 0; } @@ -1258,12 +1242,11 @@ static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struc int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); ucontrol->value.integer.value[0] = !((ice->pro_volumes[priv_idx] >> 15) & 1); ucontrol->value.integer.value[1] = !((ice->pro_volumes[priv_idx] >> 31) & 1); - spin_unlock_irq(&ice->reg_lock); return 0; } @@ -1276,12 +1259,11 @@ static int snd_ice1712_pro_mixer_switch_put(struct snd_kcontrol *kcontrol, struc nval = (ucontrol->value.integer.value[0] ? 0 : 0x00008000) | (ucontrol->value.integer.value[1] ? 0 : 0x80000000); - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); nval |= ice->pro_volumes[priv_idx] & ~0x80008000; change = nval != ice->pro_volumes[priv_idx]; ice->pro_volumes[priv_idx] = nval; snd_ice1712_update_volume(ice, priv_idx); - spin_unlock_irq(&ice->reg_lock); return change; } @@ -1300,12 +1282,11 @@ static int snd_ice1712_pro_mixer_volume_get(struct snd_kcontrol *kcontrol, struc int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); ucontrol->value.integer.value[0] = (ice->pro_volumes[priv_idx] >> 0) & 127; ucontrol->value.integer.value[1] = (ice->pro_volumes[priv_idx] >> 16) & 127; - spin_unlock_irq(&ice->reg_lock); return 0; } @@ -1318,12 +1299,11 @@ static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struc nval = (ucontrol->value.integer.value[0] & 127) | ((ucontrol->value.integer.value[1] & 127) << 16); - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); nval |= ice->pro_volumes[priv_idx] & ~0x007f007f; change = nval != ice->pro_volumes[priv_idx]; ice->pro_volumes[priv_idx] = nval; snd_ice1712_update_volume(ice, priv_idx); - spin_unlock_irq(&ice->reg_lock); return change; } @@ -1781,7 +1761,7 @@ static int snd_ice1712_pro_internal_clock_get(struct snd_kcontrol *kcontrol, }; unsigned char val; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); if (is_spdif_master(ice)) { ucontrol->value.enumerated.item[0] = 13; } else { @@ -1792,7 +1772,6 @@ static int snd_ice1712_pro_internal_clock_get(struct snd_kcontrol *kcontrol, } ucontrol->value.enumerated.item[0] = val; } - spin_unlock_irq(&ice->reg_lock); return 0; } @@ -1916,10 +1895,9 @@ static int snd_ice1712_pro_rate_locking_put(struct snd_kcontrol *kcontrol, int change = 0, nval; nval = ucontrol->value.integer.value[0] ? 1 : 0; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); change = PRO_RATE_LOCKED != nval; PRO_RATE_LOCKED = nval; - spin_unlock_irq(&ice->reg_lock); return change; } @@ -1947,10 +1925,9 @@ static int snd_ice1712_pro_rate_reset_put(struct snd_kcontrol *kcontrol, int change = 0, nval; nval = ucontrol->value.integer.value[0] ? 1 : 0; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); change = PRO_RATE_RESET != nval; PRO_RATE_RESET = nval; - spin_unlock_irq(&ice->reg_lock); return change; } @@ -1986,10 +1963,10 @@ static int snd_ice1712_pro_route_analog_get(struct snd_kcontrol *kcontrol, int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); unsigned int val, cval; - spin_lock_irq(&ice->reg_lock); - val = inw(ICEMT(ice, ROUTE_PSDOUT03)); - cval = inl(ICEMT(ice, ROUTE_CAPTURE)); - spin_unlock_irq(&ice->reg_lock); + scoped_guard(spinlock_irq, &ice->reg_lock) { + val = inw(ICEMT(ice, ROUTE_PSDOUT03)); + cval = inl(ICEMT(ice, ROUTE_CAPTURE)); + } val >>= ((idx % 2) * 8) + ((idx / 2) * 2); val &= 3; @@ -2023,35 +2000,35 @@ static int snd_ice1712_pro_route_analog_put(struct snd_kcontrol *kcontrol, else nval = 0; /* pcm */ shift = ((idx % 2) * 8) + ((idx / 2) * 2); - spin_lock_irq(&ice->reg_lock); - val = old_val = inw(ICEMT(ice, ROUTE_PSDOUT03)); - val &= ~(0x03 << shift); - val |= nval << shift; - change = val != old_val; - if (change) - outw(val, ICEMT(ice, ROUTE_PSDOUT03)); - spin_unlock_irq(&ice->reg_lock); + scoped_guard(spinlock_irq, &ice->reg_lock) { + val = old_val = inw(ICEMT(ice, ROUTE_PSDOUT03)); + val &= ~(0x03 << shift); + val |= nval << shift; + change = val != old_val; + if (change) + outw(val, ICEMT(ice, ROUTE_PSDOUT03)); + } if (nval < 2) /* dig mixer of pcm */ return change; /* update CAPTURE */ - spin_lock_irq(&ice->reg_lock); - val = old_val = inl(ICEMT(ice, ROUTE_CAPTURE)); - shift = ((idx / 2) * 8) + ((idx % 2) * 4); - if (nval == 2) { /* analog in */ - nval = ucontrol->value.enumerated.item[0] - 1; - val &= ~(0x07 << shift); - val |= nval << shift; - } else { /* spdif in */ - nval = (ucontrol->value.enumerated.item[0] - 9) << 3; - val &= ~(0x08 << shift); - val |= nval << shift; - } - if (val != old_val) { - change = 1; - outl(val, ICEMT(ice, ROUTE_CAPTURE)); + scoped_guard(spinlock_irq, &ice->reg_lock) { + val = old_val = inl(ICEMT(ice, ROUTE_CAPTURE)); + shift = ((idx / 2) * 8) + ((idx % 2) * 4); + if (nval == 2) { /* analog in */ + nval = ucontrol->value.enumerated.item[0] - 1; + val &= ~(0x07 << shift); + val |= nval << shift; + } else { /* spdif in */ + nval = (ucontrol->value.enumerated.item[0] - 9) << 3; + val &= ~(0x08 << shift); + val |= nval << shift; + } + if (val != old_val) { + change = 1; + outl(val, ICEMT(ice, ROUTE_CAPTURE)); + } } - spin_unlock_irq(&ice->reg_lock); return change; } @@ -2084,7 +2061,7 @@ static int snd_ice1712_pro_route_spdif_put(struct snd_kcontrol *kcontrol, unsigned int val, old_val, nval; /* update SPDOUT */ - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); val = old_val = inw(ICEMT(ice, ROUTE_SPDOUT)); if (ucontrol->value.enumerated.item[0] >= 11) nval = 1; @@ -2110,7 +2087,6 @@ static int snd_ice1712_pro_route_spdif_put(struct snd_kcontrol *kcontrol, change = val != old_val; if (change) outw(val, ICEMT(ice, ROUTE_SPDOUT)); - spin_unlock_irq(&ice->reg_lock); return change; } @@ -2157,10 +2133,9 @@ static int snd_ice1712_pro_volume_rate_put(struct snd_kcontrol *kcontrol, struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int change; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); change = inb(ICEMT(ice, MONITOR_RATE)) != ucontrol->value.integer.value[0]; outb(ucontrol->value.integer.value[0], ICEMT(ice, MONITOR_RATE)); - spin_unlock_irq(&ice->reg_lock); return change; } @@ -2188,12 +2163,11 @@ static int snd_ice1712_pro_peak_get(struct snd_kcontrol *kcontrol, struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int idx; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); for (idx = 0; idx < 22; idx++) { outb(idx, ICEMT(ice, MONITOR_PEAKINDEX)); ucontrol->value.integer.value[idx] = inb(ICEMT(ice, MONITOR_PEAKDATA)); } - spin_unlock_irq(&ice->reg_lock); return 0; } @@ -2675,11 +2649,11 @@ static int snd_ice1712_suspend(struct device *dev) snd_ac97_suspend(ice->ac97); - spin_lock_irq(&ice->reg_lock); - ice->pm_saved_is_spdif_master = is_spdif_master(ice); - ice->pm_saved_spdif_ctrl = inw(ICEMT(ice, ROUTE_SPDOUT)); - ice->pm_saved_route = inw(ICEMT(ice, ROUTE_PSDOUT03)); - spin_unlock_irq(&ice->reg_lock); + scoped_guard(spinlock_irq, &ice->reg_lock) { + ice->pm_saved_is_spdif_master = is_spdif_master(ice); + ice->pm_saved_spdif_ctrl = inw(ICEMT(ice, ROUTE_SPDOUT)); + ice->pm_saved_route = inw(ICEMT(ice, ROUTE_PSDOUT03)); + } if (ice->pm_suspend) ice->pm_suspend(ice); @@ -2712,10 +2686,10 @@ static int snd_ice1712_resume(struct device *dev) if (ice->pm_saved_is_spdif_master) { /* switching to external clock via SPDIF */ - spin_lock_irq(&ice->reg_lock); - outb(inb(ICEMT(ice, RATE)) | ICE1712_SPDIF_MASTER, - ICEMT(ice, RATE)); - spin_unlock_irq(&ice->reg_lock); + scoped_guard(spinlock_irq, &ice->reg_lock) { + outb(inb(ICEMT(ice, RATE)) | ICE1712_SPDIF_MASTER, + ICEMT(ice, RATE)); + } snd_ice1712_set_input_clock_source(ice, 1); } else { /* internal on-card clock */ diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 0445d2e8e548..e2dbbbfbca9f 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -288,9 +288,8 @@ static void vt1724_enable_midi_irq(struct snd_rawmidi_substream *substream, { struct snd_ice1712 *ice = substream->rmidi->private_data; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); enable_midi_irq(ice, flag, enable); - spin_unlock_irq(&ice->reg_lock); } static int vt1724_midi_output_open(struct snd_rawmidi_substream *s) @@ -306,9 +305,8 @@ static int vt1724_midi_output_close(struct snd_rawmidi_substream *s) static void vt1724_midi_output_trigger(struct snd_rawmidi_substream *s, int up) { struct snd_ice1712 *ice = s->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&ice->reg_lock, flags); + guard(spinlock_irqsave)(&ice->reg_lock); if (up) { ice->midi_output = 1; vt1724_midi_write(ice); @@ -316,7 +314,6 @@ static void vt1724_midi_output_trigger(struct snd_rawmidi_substream *s, int up) ice->midi_output = 0; enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); } - spin_unlock_irqrestore(&ice->reg_lock, flags); } static void vt1724_midi_output_drain(struct snd_rawmidi_substream *s) @@ -357,16 +354,14 @@ static int vt1724_midi_input_close(struct snd_rawmidi_substream *s) static void vt1724_midi_input_trigger(struct snd_rawmidi_substream *s, int up) { struct snd_ice1712 *ice = s->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&ice->reg_lock, flags); + guard(spinlock_irqsave)(&ice->reg_lock); if (up) { ice->midi_input = 1; vt1724_midi_read(ice); } else { ice->midi_input = 0; } - spin_unlock_irqrestore(&ice->reg_lock, flags); } static const struct snd_rawmidi_ops vt1724_midi_input_ops = { @@ -394,40 +389,39 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id) status &= status_mask; if (status == 0) break; - spin_lock(&ice->reg_lock); - if (++timeout > 10) { - status = inb(ICEREG1724(ice, IRQSTAT)); - dev_err(ice->card->dev, - "Too long irq loop, status = 0x%x\n", status); + scoped_guard(spinlock, &ice->reg_lock) { + if (++timeout > 10) { + status = inb(ICEREG1724(ice, IRQSTAT)); + dev_err(ice->card->dev, + "Too long irq loop, status = 0x%x\n", status); + if (status & VT1724_IRQ_MPU_TX) { + dev_err(ice->card->dev, "Disabling MPU_TX\n"); + enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); + } + goto out; + } + handled = 1; if (status & VT1724_IRQ_MPU_TX) { - dev_err(ice->card->dev, "Disabling MPU_TX\n"); - enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); + if (ice->midi_output) + vt1724_midi_write(ice); + else + enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); + /* Due to mysterical reasons, MPU_TX is always + * generated (and can't be cleared) when a PCM + * playback is going. So let's ignore at the + * next loop. + */ + status_mask &= ~VT1724_IRQ_MPU_TX; } - spin_unlock(&ice->reg_lock); - break; - } - handled = 1; - if (status & VT1724_IRQ_MPU_TX) { - if (ice->midi_output) - vt1724_midi_write(ice); - else - enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); - /* Due to mysterical reasons, MPU_TX is always - * generated (and can't be cleared) when a PCM - * playback is going. So let's ignore at the - * next loop. - */ - status_mask &= ~VT1724_IRQ_MPU_TX; - } - if (status & VT1724_IRQ_MPU_RX) { - if (ice->midi_input) - vt1724_midi_read(ice); - else - vt1724_midi_clear_rx(ice); + if (status & VT1724_IRQ_MPU_RX) { + if (ice->midi_input) + vt1724_midi_read(ice); + else + vt1724_midi_clear_rx(ice); + } + /* ack MPU irq */ + outb(status, ICEREG1724(ice, IRQSTAT)); } - /* ack MPU irq */ - outb(status, ICEREG1724(ice, IRQSTAT)); - spin_unlock(&ice->reg_lock); if (status & VT1724_IRQ_MTPCM) { /* * Multi-track PCM @@ -481,6 +475,7 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id) } } + out: return IRQ_RETVAL(handled); } @@ -539,27 +534,27 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - spin_lock(&ice->reg_lock); - old = inb(ICEMT1724(ice, DMA_PAUSE)); - if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) - old |= what; - else - old &= ~what; - outb(old, ICEMT1724(ice, DMA_PAUSE)); - spin_unlock(&ice->reg_lock); + scoped_guard(spinlock, &ice->reg_lock) { + old = inb(ICEMT1724(ice, DMA_PAUSE)); + if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) + old |= what; + else + old &= ~what; + outb(old, ICEMT1724(ice, DMA_PAUSE)); + } break; case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: - spin_lock(&ice->reg_lock); - old = inb(ICEMT1724(ice, DMA_CONTROL)); - if (cmd == SNDRV_PCM_TRIGGER_START) - old |= what; - else - old &= ~what; - outb(old, ICEMT1724(ice, DMA_CONTROL)); - spin_unlock(&ice->reg_lock); + scoped_guard(spinlock, &ice->reg_lock) { + old = inb(ICEMT1724(ice, DMA_CONTROL)); + if (cmd == SNDRV_PCM_TRIGGER_START) + old |= what; + else + old &= ~what; + outb(old, ICEMT1724(ice, DMA_CONTROL)); + } break; case SNDRV_PCM_TRIGGER_RESUME: @@ -625,7 +620,6 @@ static unsigned char stdclock_set_mclk(struct snd_ice1712 *ice, static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, int force) { - unsigned long flags; unsigned char mclk_change; unsigned int i, old_rate; bool call_set_rate = false; @@ -633,34 +627,31 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, if (rate > ice->hw_rates->list[ice->hw_rates->count - 1]) return -EINVAL; - spin_lock_irqsave(&ice->reg_lock, flags); - if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || - (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) { - /* running? we cannot change the rate now... */ - spin_unlock_irqrestore(&ice->reg_lock, flags); - return ((rate == ice->cur_rate) && !force) ? 0 : -EBUSY; - } - if (!force && is_pro_rate_locked(ice)) { - /* comparing required and current rate - makes sense for - * internal clock only */ - spin_unlock_irqrestore(&ice->reg_lock, flags); - return (rate == ice->cur_rate) ? 0 : -EBUSY; - } + scoped_guard(spinlock_irqsave, &ice->reg_lock) { + if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || + (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) { + /* running? we cannot change the rate now... */ + return ((rate == ice->cur_rate) && !force) ? 0 : -EBUSY; + } + if (!force && is_pro_rate_locked(ice)) { + /* comparing required and current rate - makes sense for + * internal clock only */ + return (rate == ice->cur_rate) ? 0 : -EBUSY; + } - if (force || !ice->is_spdif_master(ice)) { - /* force means the rate was switched by ucontrol, otherwise - * setting clock rate for internal clock mode */ - old_rate = ice->get_rate(ice); - if (force || (old_rate != rate)) - call_set_rate = true; - else if (rate == ice->cur_rate) { - spin_unlock_irqrestore(&ice->reg_lock, flags); - return 0; + if (force || !ice->is_spdif_master(ice)) { + /* force means the rate was switched by ucontrol, otherwise + * setting clock rate for internal clock mode */ + old_rate = ice->get_rate(ice); + if (force || (old_rate != rate)) + call_set_rate = true; + else if (rate == ice->cur_rate) { + return 0; + } } - } - ice->cur_rate = rate; - spin_unlock_irqrestore(&ice->reg_lock, flags); + ice->cur_rate = rate; + } if (call_set_rate) ice->set_rate(ice, rate); @@ -684,24 +675,21 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, return 0; } -static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) +static int __snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); int i, chs; chs = params_channels(hw_params); - mutex_lock(&ice->open_mutex); /* mark surround channels */ if (substream == ice->playback_pro_substream) { /* PDMA0 can be multi-channel up to 8 */ chs = chs / 2 - 1; for (i = 0; i < chs; i++) { if (ice->pcm_reserved[i] && - ice->pcm_reserved[i] != substream) { - mutex_unlock(&ice->open_mutex); + ice->pcm_reserved[i] != substream) return -EBUSY; - } ice->pcm_reserved[i] = substream; } for (; i < 3; i++) { @@ -713,16 +701,28 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, /* check individual playback stream */ if (ice->playback_con_substream_ds[i] == substream) { if (ice->pcm_reserved[i] && - ice->pcm_reserved[i] != substream) { - mutex_unlock(&ice->open_mutex); + ice->pcm_reserved[i] != substream) return -EBUSY; - } ice->pcm_reserved[i] = substream; break; } } } - mutex_unlock(&ice->open_mutex); + + return 0; +} + +static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); + int err; + + scoped_guard(mutex, &ice->open_mutex) { + err = __snd_vt1724_pcm_hw_params(substream, hw_params); + if (err < 0) + return err; + } return snd_vt1724_set_pro_rate(ice, params_rate(hw_params), 0); } @@ -732,12 +732,11 @@ static int snd_vt1724_pcm_hw_free(struct snd_pcm_substream *substream) struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); int i; - mutex_lock(&ice->open_mutex); + guard(mutex)(&ice->open_mutex); /* unmark surround channels */ for (i = 0; i < 3; i++) if (ice->pcm_reserved[i] == substream) ice->pcm_reserved[i] = NULL; - mutex_unlock(&ice->open_mutex); return 0; } @@ -747,7 +746,7 @@ static int snd_vt1724_playback_pro_prepare(struct snd_pcm_substream *substream) unsigned char val; unsigned int size; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); val = (8 - substream->runtime->channels) >> 1; outb(val, ICEMT1724(ice, BURST)); @@ -762,8 +761,6 @@ static int snd_vt1724_playback_pro_prepare(struct snd_pcm_substream *substream) outw(size, ICEMT1724(ice, PLAYBACK_COUNT)); outb(size >> 16, ICEMT1724(ice, PLAYBACK_COUNT) + 2); - spin_unlock_irq(&ice->reg_lock); - /* dev_dbg(ice->card->dev, "pro prepare: ch = %d, addr = 0x%x, " "buffer = 0x%x, period = 0x%x\n", @@ -817,13 +814,12 @@ static int snd_vt1724_pcm_prepare(struct snd_pcm_substream *substream) struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); const struct vt1724_pcm_reg *reg = substream->runtime->private_data; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); outl(substream->runtime->dma_addr, ice->profi_port + reg->addr); outw((snd_pcm_lib_buffer_bytes(substream) >> 2) - 1, ice->profi_port + reg->size); outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ice->profi_port + reg->count); - spin_unlock_irq(&ice->reg_lock); return 0; } @@ -1013,18 +1009,18 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream) snd_pcm_set_sync(substream); snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); set_rate_constraints(ice, substream); - mutex_lock(&ice->open_mutex); - /* calculate the currently available channels */ - num_indeps = ice->num_total_dacs / 2 - 1; - for (chs = 0; chs < num_indeps; chs++) { - if (ice->pcm_reserved[chs]) - break; + scoped_guard(mutex, &ice->open_mutex) { + /* calculate the currently available channels */ + num_indeps = ice->num_total_dacs / 2 - 1; + for (chs = 0; chs < num_indeps; chs++) { + if (ice->pcm_reserved[chs]) + break; + } + chs = (chs + 1) * 2; + runtime->hw.channels_max = chs; + if (chs > 2) /* channels must be even */ + snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); } - chs = (chs + 1) * 2; - runtime->hw.channels_max = chs; - if (chs > 2) /* channels must be even */ - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); - mutex_unlock(&ice->open_mutex); snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, VT1724_BUFFER_ALIGN); snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, @@ -1152,9 +1148,8 @@ static void update_spdif_bits(struct snd_ice1712 *ice, unsigned int val) static void update_spdif_rate(struct snd_ice1712 *ice, unsigned int rate) { unsigned int val, nval; - unsigned long flags; - spin_lock_irqsave(&ice->reg_lock, flags); + guard(spinlock_irqsave)(&ice->reg_lock); nval = val = inw(ICEMT1724(ice, SPDIF_CTRL)); nval &= ~(7 << 12); switch (rate) { @@ -1168,7 +1163,6 @@ static void update_spdif_rate(struct snd_ice1712 *ice, unsigned int rate) } if (val != nval) update_spdif_bits(ice, nval); - spin_unlock_irqrestore(&ice->reg_lock, flags); } static int snd_vt1724_playback_spdif_prepare(struct snd_pcm_substream *substream) @@ -1354,11 +1348,11 @@ static int snd_vt1724_playback_indep_prepare(struct snd_pcm_substream *substream struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); unsigned char val; - spin_lock_irq(&ice->reg_lock); - val = 3 - substream->number; - if (inb(ICEMT1724(ice, BURST)) < val) - outb(val, ICEMT1724(ice, BURST)); - spin_unlock_irq(&ice->reg_lock); + scoped_guard(spinlock_irq, &ice->reg_lock) { + val = 3 - substream->number; + if (inb(ICEMT1724(ice, BURST)) < val) + outb(val, ICEMT1724(ice, BURST)); + } return snd_vt1724_pcm_prepare(substream); } @@ -1367,13 +1361,11 @@ static int snd_vt1724_playback_indep_open(struct snd_pcm_substream *substream) struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - mutex_lock(&ice->open_mutex); - /* already used by PDMA0? */ - if (ice->pcm_reserved[substream->number]) { - mutex_unlock(&ice->open_mutex); - return -EBUSY; /* FIXME: should handle blocking mode properly */ + scoped_guard(mutex, &ice->open_mutex) { + /* already used by PDMA0? */ + if (ice->pcm_reserved[substream->number]) + return -EBUSY; /* FIXME: should handle blocking mode properly */ } - mutex_unlock(&ice->open_mutex); runtime->private_data = (void *)&vt1724_playback_dma_regs[substream->number]; ice->playback_con_substream_ds[substream->number] = substream; runtime->hw = snd_vt1724_2ch_stereo; @@ -1658,11 +1650,10 @@ static int snd_vt1724_spdif_default_put(struct snd_kcontrol *kcontrol, unsigned int val, old; val = encode_spdif_bits(&ucontrol->value.iec958); - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); old = inw(ICEMT1724(ice, SPDIF_CTRL)); if (val != old) update_spdif_bits(ice, val); - spin_unlock_irq(&ice->reg_lock); return val != old; } @@ -1733,14 +1724,13 @@ static int snd_vt1724_spdif_sw_put(struct snd_kcontrol *kcontrol, struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned char old, val; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); old = val = inb(ICEREG1724(ice, SPDIF_CFG)); val &= ~VT1724_CFG_SPDIF_OUT_EN; if (ucontrol->value.integer.value[0]) val |= VT1724_CFG_SPDIF_OUT_EN; if (old != val) outb(val, ICEREG1724(ice, SPDIF_CFG)); - spin_unlock_irq(&ice->reg_lock); return old != val; } @@ -1836,7 +1826,7 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol, struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned int i, rate; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); if (ice->is_spdif_master(ice)) { ucontrol->value.enumerated.item[0] = ice->hw_rates->count + ice->get_spdif_master_type(ice); @@ -1850,7 +1840,6 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol, } } } - spin_unlock_irq(&ice->reg_lock); return 0; } @@ -1881,29 +1870,31 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, unsigned int old_rate, new_rate; unsigned int item = ucontrol->value.enumerated.item[0]; unsigned int first_ext_clock = ice->hw_rates->count; + bool set_pro_rate = false; if (item > first_ext_clock + ice->ext_clock_count - 1) return -EINVAL; /* if rate = 0 => external clock */ - spin_lock_irq(&ice->reg_lock); - if (ice->is_spdif_master(ice)) - old_rate = 0; - else - old_rate = ice->get_rate(ice); - if (item >= first_ext_clock) { - /* switching to external clock */ - ice->set_spdif_clock(ice, item - first_ext_clock); - new_rate = 0; - } else { - /* internal on-card clock */ - new_rate = ice->hw_rates->list[item]; - ice->pro_rate_default = new_rate; - spin_unlock_irq(&ice->reg_lock); - snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); - spin_lock_irq(&ice->reg_lock); + scoped_guard(spinlock_irq, &ice->reg_lock) { + if (ice->is_spdif_master(ice)) + old_rate = 0; + else + old_rate = ice->get_rate(ice); + if (item >= first_ext_clock) { + /* switching to external clock */ + ice->set_spdif_clock(ice, item - first_ext_clock); + new_rate = 0; + } else { + /* internal on-card clock */ + new_rate = ice->hw_rates->list[item]; + ice->pro_rate_default = new_rate; + set_pro_rate = true; + } } - spin_unlock_irq(&ice->reg_lock); + + if (set_pro_rate) + snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); /* the first switch to the ext. clock mode? */ if (old_rate != new_rate && !new_rate) { @@ -1943,10 +1934,9 @@ static int snd_vt1724_pro_rate_locking_put(struct snd_kcontrol *kcontrol, int change = 0, nval; nval = ucontrol->value.integer.value[0] ? 1 : 0; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); change = PRO_RATE_LOCKED != nval; PRO_RATE_LOCKED = nval; - spin_unlock_irq(&ice->reg_lock); return change; } @@ -1974,10 +1964,9 @@ static int snd_vt1724_pro_rate_reset_put(struct snd_kcontrol *kcontrol, int change = 0, nval; nval = ucontrol->value.integer.value[0] ? 1 : 0; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); change = PRO_RATE_RESET != nval; PRO_RATE_RESET = nval; - spin_unlock_irq(&ice->reg_lock); return change; } @@ -2132,13 +2121,12 @@ static int snd_vt1724_pro_peak_get(struct snd_kcontrol *kcontrol, struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int idx; - spin_lock_irq(&ice->reg_lock); + guard(spinlock_irq)(&ice->reg_lock); for (idx = 0; idx < 22; idx++) { outb(idx, ICEMT1724(ice, MONITOR_PEAKINDEX)); ucontrol->value.integer.value[idx] = inb(ICEMT1724(ice, MONITOR_PEAKDATA)); } - spin_unlock_irq(&ice->reg_lock); return 0; } @@ -2220,13 +2208,12 @@ unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, { unsigned char val; - mutex_lock(&ice->i2c_mutex); + guard(mutex)(&ice->i2c_mutex); wait_i2c_busy(ice); outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); wait_i2c_busy(ice); val = inb(ICEREG1724(ice, I2C_DATA)); - mutex_unlock(&ice->i2c_mutex); /* dev_dbg(ice->card->dev, "i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); */ @@ -2236,7 +2223,7 @@ unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, void snd_vt1724_write_i2c(struct snd_ice1712 *ice, unsigned char dev, unsigned char addr, unsigned char data) { - mutex_lock(&ice->i2c_mutex); + guard(mutex)(&ice->i2c_mutex); wait_i2c_busy(ice); /* dev_dbg(ice->card->dev, "i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); @@ -2245,7 +2232,6 @@ void snd_vt1724_write_i2c(struct snd_ice1712 *ice, outb(data, ICEREG1724(ice, I2C_DATA)); outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); wait_i2c_busy(ice); - mutex_unlock(&ice->i2c_mutex); } static int snd_vt1724_read_eeprom(struct snd_ice1712 *ice, @@ -2685,12 +2671,12 @@ static int snd_vt1724_suspend(struct device *dev) snd_ac97_suspend(ice->ac97); - spin_lock_irq(&ice->reg_lock); - ice->pm_saved_is_spdif_master = ice->is_spdif_master(ice); - ice->pm_saved_spdif_ctrl = inw(ICEMT1724(ice, SPDIF_CTRL)); - ice->pm_saved_spdif_cfg = inb(ICEREG1724(ice, SPDIF_CFG)); - ice->pm_saved_route = inl(ICEMT1724(ice, ROUTE_PLAYBACK)); - spin_unlock_irq(&ice->reg_lock); + scoped_guard(spinlock_irq, &ice->reg_lock) { + ice->pm_saved_is_spdif_master = ice->is_spdif_master(ice); + ice->pm_saved_spdif_ctrl = inw(ICEMT1724(ice, SPDIF_CTRL)); + ice->pm_saved_spdif_cfg = inb(ICEREG1724(ice, SPDIF_CFG)); + ice->pm_saved_route = inl(ICEMT1724(ice, ROUTE_PLAYBACK)); + } if (ice->pm_suspend) ice->pm_suspend(ice); diff --git a/sound/pci/ice1712/maya44.c b/sound/pci/ice1712/maya44.c index b46df1821251..551f478c59c4 100644 --- a/sound/pci/ice1712/maya44.c +++ b/sound/pci/ice1712/maya44.c @@ -175,10 +175,9 @@ static int maya_vol_get(struct snd_kcontrol *kcontrol, &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)]; unsigned int idx = kcontrol->private_value; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); ucontrol->value.integer.value[0] = wm->volumes[idx][0]; ucontrol->value.integer.value[1] = wm->volumes[idx][1]; - mutex_unlock(&chip->mutex); return 0; } @@ -193,7 +192,7 @@ static int maya_vol_put(struct snd_kcontrol *kcontrol, unsigned int val, data; int ch, changed = 0; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); for (ch = 0; ch < 2; ch++) { val = ucontrol->value.integer.value[ch]; if (val > vol->maxval) @@ -213,7 +212,6 @@ static int maya_vol_put(struct snd_kcontrol *kcontrol, val ? 0 : vol->mux_bits[ch]); wm->volumes[idx][ch] = val; } - mutex_unlock(&chip->mutex); return changed; } @@ -250,7 +248,7 @@ static int maya_sw_put(struct snd_kcontrol *kcontrol, unsigned int mask, val; int changed; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); mask = 1 << idx; wm->switch_bits &= ~mask; val = ucontrol->value.integer.value[0]; @@ -260,7 +258,6 @@ static int maya_sw_put(struct snd_kcontrol *kcontrol, changed = wm8776_write_bits(chip->ice, wm, GET_SW_VAL_REG(kcontrol->private_value), mask, val ? mask : 0); - mutex_unlock(&chip->mutex); return changed; } @@ -315,14 +312,13 @@ static int maya_gpio_sw_put(struct snd_kcontrol *kcontrol, unsigned int val, mask; int changed; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); mask = 1 << shift; val = ucontrol->value.integer.value[0]; if (GET_GPIO_VAL_INV(kcontrol->private_value)) val = !val; val = val ? mask : 0; changed = maya_set_gpio_bits(chip->ice, mask, val); - mutex_unlock(&chip->mutex); return changed; } @@ -369,11 +365,10 @@ static int maya_rec_src_put(struct snd_kcontrol *kcontrol, int sel = ucontrol->value.enumerated.item[0]; int changed; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); changed = maya_set_gpio_bits(chip->ice, 1 << GPIO_MIC_RELAY, sel ? (1 << GPIO_MIC_RELAY) : 0); wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN); - mutex_unlock(&chip->mutex); return changed; } @@ -635,12 +630,11 @@ static void set_rate(struct snd_ice1712 *ice, unsigned int rate) val |= 8; val |= ratio << 4; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); for (i = 0; i < 2; i++) wm8776_write_bits(ice, &chip->wm[i], WM8776_REG_MASTER_MODE_CONTROL, 0x180, val); - mutex_unlock(&chip->mutex); } /* diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c index 1e47e46ab8ac..151b740ce66d 100644 --- a/sound/pci/ice1712/phase.c +++ b/sound/pci/ice1712/phase.c @@ -287,10 +287,9 @@ static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -638,11 +637,10 @@ static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned short val; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; val = val > PCM_MIN ? (val - PCM_MIN) : 0; ucontrol->value.integer.value[0] = val; - mutex_unlock(&ice->gpio_mutex); return 0; } diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c index 683909ca147c..557473f0d59e 100644 --- a/sound/pci/ice1712/pontis.c +++ b/sound/pci/ice1712/pontis.c @@ -112,13 +112,12 @@ static int wm_dac_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val unsigned short val; int i; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (i = 0; i < 2; i++) { val = wm_get(ice, WM_DAC_ATTEN_L + i) & 0xff; val = val > DAC_MIN ? (val - DAC_MIN) : 0; ucontrol->value.integer.value[i] = val; } - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -128,7 +127,7 @@ static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val unsigned short oval, nval; int i, idx, change = 0; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (i = 0; i < 2; i++) { nval = ucontrol->value.integer.value[i]; nval = (nval ? (nval + DAC_MIN) : 0) & 0xff; @@ -140,7 +139,6 @@ static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val change = 1; } } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -167,13 +165,12 @@ static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val unsigned short val; int i; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (i = 0; i < 2; i++) { val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff; val = val > ADC_MIN ? (val - ADC_MIN) : 0; ucontrol->value.integer.value[i] = val; } - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -183,7 +180,7 @@ static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val unsigned short ovol, nvol; int i, idx, change = 0; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (i = 0; i < 2; i++) { nvol = ucontrol->value.integer.value[i]; nvol = nvol ? (nvol + ADC_MIN) : 0; @@ -194,7 +191,6 @@ static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val change = 1; } } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -208,9 +204,8 @@ static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int bit = kcontrol->private_value; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -221,7 +216,7 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val unsigned short oval, nval; int change; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); nval = oval = wm_get(ice, WM_ADC_MUX); if (ucontrol->value.integer.value[0]) nval |= (1 << bit); @@ -231,7 +226,6 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val if (change) { wm_put(ice, WM_ADC_MUX, nval); } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -244,9 +238,8 @@ static int wm_bypass_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -256,7 +249,7 @@ static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu unsigned short val, oval; int change = 0; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); val = oval = wm_get(ice, WM_OUT_MUX); if (ucontrol->value.integer.value[0]) val |= 0x04; @@ -266,7 +259,6 @@ static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu wm_put(ice, WM_OUT_MUX, val); change = 1; } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -279,9 +271,8 @@ static int wm_chswap_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -291,7 +282,7 @@ static int wm_chswap_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu unsigned short val, oval; int change = 0; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); oval = wm_get(ice, WM_DAC_CTRL1); val = oval & 0x0f; if (ucontrol->value.integer.value[0]) @@ -303,7 +294,6 @@ static int wm_chswap_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu wm_put_nocache(ice, WM_DAC_CTRL1, val); change = 1; } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -410,9 +400,8 @@ static int cs_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); ucontrol->value.enumerated.item[0] = ice->gpio.saved[0]; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -422,14 +411,13 @@ static int cs_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu unsigned char val; int change = 0; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); if (ucontrol->value.enumerated.item[0] != ice->gpio.saved[0]) { ice->gpio.saved[0] = ucontrol->value.enumerated.item[0] & 3; val = 0x80 | (ice->gpio.saved[0] << 3); spi_write(ice, CS_DEV, 0x04, val); change = 1; } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -449,10 +437,10 @@ static int pontis_gpio_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int pontis_gpio_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + + guard(mutex)(&ice->gpio_mutex); /* 4-7 reserved */ ucontrol->value.integer.value[0] = (~ice->gpio.write_mask & 0xffff) | 0x00f0; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -461,22 +449,22 @@ static int pontis_gpio_mask_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned int val; int changed; - mutex_lock(&ice->gpio_mutex); + + guard(mutex)(&ice->gpio_mutex); /* 4-7 reserved */ val = (~ucontrol->value.integer.value[0] & 0xffff) | 0x00f0; changed = val != ice->gpio.write_mask; ice->gpio.write_mask = val; - mutex_unlock(&ice->gpio_mutex); return changed; } static int pontis_gpio_dir_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + + guard(mutex)(&ice->gpio_mutex); /* 4-7 reserved */ ucontrol->value.integer.value[0] = ice->gpio.direction & 0xff0f; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -485,23 +473,23 @@ static int pontis_gpio_dir_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned int val; int changed; - mutex_lock(&ice->gpio_mutex); + + guard(mutex)(&ice->gpio_mutex); /* 4-7 reserved */ val = ucontrol->value.integer.value[0] & 0xff0f; changed = (val != ice->gpio.direction); ice->gpio.direction = val; - mutex_unlock(&ice->gpio_mutex); return changed; } static int pontis_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + + guard(mutex)(&ice->gpio_mutex); snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); ucontrol->value.integer.value[0] = snd_ice1712_gpio_read(ice) & 0xffff; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -510,7 +498,8 @@ static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned int val, nval; int changed = 0; - mutex_lock(&ice->gpio_mutex); + + guard(mutex)(&ice->gpio_mutex); snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); val = snd_ice1712_gpio_read(ice) & 0xffff; @@ -519,7 +508,6 @@ static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el snd_ice1712_gpio_write(ice, nval); changed = 1; } - mutex_unlock(&ice->gpio_mutex); return changed; } @@ -620,14 +608,14 @@ static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buf struct snd_ice1712 *ice = entry->private_data; char line[64]; unsigned int reg, val; - mutex_lock(&ice->gpio_mutex); + + guard(mutex)(&ice->gpio_mutex); while (!snd_info_get_line(buffer, line, sizeof(line))) { if (sscanf(line, "%x %x", ®, &val) != 2) continue; if (reg <= 0x17 && val <= 0xffff) wm_put(ice, reg, val); } - mutex_unlock(&ice->gpio_mutex); } static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) @@ -635,12 +623,11 @@ static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buff struct snd_ice1712 *ice = entry->private_data; int reg, val; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (reg = 0; reg <= 0x17; reg++) { val = wm_get(ice, reg); snd_iprintf(buffer, "%02x = %04x\n", reg, val); } - mutex_unlock(&ice->gpio_mutex); } static void wm_proc_init(struct snd_ice1712 *ice) @@ -654,14 +641,13 @@ static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buff struct snd_ice1712 *ice = entry->private_data; int reg, val; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (reg = 0; reg <= 0x26; reg++) { val = spi_read(ice, CS_DEV, reg); snd_iprintf(buffer, "%02x = %02x\n", reg, val); } val = spi_read(ice, CS_DEV, 0x7f); snd_iprintf(buffer, "%02x = %02x\n", 0x7f, val); - mutex_unlock(&ice->gpio_mutex); } static void cs_proc_init(struct snd_ice1712 *ice) diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c index a12dafbf53ab..cd7db2b65b51 100644 --- a/sound/pci/ice1712/prodigy192.c +++ b/sound/pci/ice1712/prodigy192.c @@ -110,21 +110,19 @@ static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); struct prodigy192_spec *spec = ice->spec; - int idx, change; + int idx; if (kcontrol->private_value) idx = STAC946X_MASTER_VOLUME; else idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; /* due to possible conflicts with stac9460_set_rate_val, mutexing */ - mutex_lock(&spec->mute_mutex); + guard(mutex)(&spec->mute_mutex); /* dev_dbg(ice->card->dev, "Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx, ucontrol->value.integer.value[0]); */ - change = stac9460_dac_mute(ice, idx, ucontrol->value.integer.value[0]); - mutex_unlock(&spec->mute_mutex); - return change; + return stac9460_dac_mute(ice, idx, ucontrol->value.integer.value[0]); } /* @@ -316,7 +314,7 @@ static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate) return; /* change detected, setting master clock, muting first */ /* due to possible conflicts with mute controls - mutexing */ - mutex_lock(&spec->mute_mutex); + guard(mutex)(&spec->mute_mutex); /* we have to remember current mute status for each DAC */ for (idx = 0; idx < 7 ; ++idx) changed[idx] = stac9460_dac_mute(ice, @@ -330,7 +328,6 @@ static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate) if (changed[idx]) stac9460_dac_mute(ice, STAC946X_MASTER_VOLUME + idx, 1); } - mutex_unlock(&spec->mute_mutex); } diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c index 9aa12a67d370..eac233093865 100644 --- a/sound/pci/ice1712/prodigy_hifi.c +++ b/sound/pci/ice1712/prodigy_hifi.c @@ -268,7 +268,7 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem int i; int change = 0; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (i = 0; i < 2; i++) { if (ucontrol->value.integer.value[i] != spec->vol[i]) { spec->vol[i] = ucontrol->value.integer.value[i]; @@ -277,7 +277,6 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem change = 1; } } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -376,7 +375,7 @@ static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val struct prodigy_hifi_spec *spec = ice->spec; int i, idx, change = 0; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (i = 0; i < 2; i++) { if (ucontrol->value.integer.value[i] != spec->vol[2 + i]) { idx = WM_DAC_ATTEN_L + i; @@ -386,7 +385,6 @@ static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val change = 1; } } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -428,7 +426,7 @@ static int wm8766_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val voices = kcontrol->private_value >> 8; ofs = kcontrol->private_value & 0xff; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (i = 0; i < voices; i++) { if (ucontrol->value.integer.value[i] != spec->vol[ofs + i]) { idx = WM8766_LDA1 + ofs + i; @@ -439,7 +437,6 @@ static int wm8766_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val change = 1; } } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -474,7 +471,7 @@ static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct prodigy_hifi_spec *spec = ice->spec; int ch, change = 0; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (ch = 0; ch < 2; ch++) { if (ucontrol->value.integer.value[ch] != spec->master[ch]) { spec->master[ch] = ucontrol->value.integer.value[ch]; @@ -494,7 +491,6 @@ static int wm_master_vol_put(struct snd_kcontrol *kcontrol, change = 1; } } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -535,9 +531,8 @@ static int wm_adc_mux_enum_get(struct snd_kcontrol *kcontrol, { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); ucontrol->value.enumerated.item[0] = wm_get(ice, WM_ADC_MUX) & 0x1f; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -548,14 +543,13 @@ static int wm_adc_mux_enum_put(struct snd_kcontrol *kcontrol, unsigned short oval, nval; int change = 0; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); oval = wm_get(ice, WM_ADC_MUX); nval = (oval & 0xe0) | ucontrol->value.enumerated.item[0]; if (nval != oval) { wm_put(ice, WM_ADC_MUX, nval); change = 1; } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -586,13 +580,12 @@ static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, unsigned short val; int i; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (i = 0; i < 2; i++) { val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff; val = val > ADC_MIN ? (val - ADC_MIN) : 0; ucontrol->value.integer.value[i] = val; } - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -603,7 +596,7 @@ static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, unsigned short ovol, nvol; int i, idx, change = 0; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (i = 0; i < 2; i++) { nvol = ucontrol->value.integer.value[i]; nvol = nvol ? (nvol + ADC_MIN) : 0; @@ -614,7 +607,6 @@ static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, change = 1; } } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -629,10 +621,9 @@ static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int bit = kcontrol->private_value; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -644,7 +635,7 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, unsigned short oval, nval; int change; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); nval = oval = wm_get(ice, WM_ADC_MUX); if (ucontrol->value.integer.value[0]) nval |= (1 << bit); @@ -654,7 +645,6 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, if (change) { wm_put(ice, WM_ADC_MUX, nval); } - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -668,10 +658,9 @@ static int wm_bypass_get(struct snd_kcontrol *kcontrol, { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -682,7 +671,7 @@ static int wm_bypass_put(struct snd_kcontrol *kcontrol, unsigned short val, oval; int change = 0; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); val = oval = wm_get(ice, WM_OUT_MUX); if (ucontrol->value.integer.value[0]) val |= 0x04; @@ -692,7 +681,6 @@ static int wm_bypass_put(struct snd_kcontrol *kcontrol, wm_put(ice, WM_OUT_MUX, val); change = 1; } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -706,10 +694,9 @@ static int wm_chswap_get(struct snd_kcontrol *kcontrol, { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90; - mutex_unlock(&ice->gpio_mutex); return 0; } @@ -720,7 +707,7 @@ static int wm_chswap_put(struct snd_kcontrol *kcontrol, unsigned short val, oval; int change = 0; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); oval = wm_get(ice, WM_DAC_CTRL1); val = oval & 0x0f; if (ucontrol->value.integer.value[0]) @@ -732,7 +719,6 @@ static int wm_chswap_put(struct snd_kcontrol *kcontrol, wm_put_nocache(ice, WM_DAC_CTRL1, val); change = 1; } - mutex_unlock(&ice->gpio_mutex); return change; } @@ -864,14 +850,14 @@ static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_ice1712 *ice = entry->private_data; char line[64]; unsigned int reg, val; - mutex_lock(&ice->gpio_mutex); + + guard(mutex)(&ice->gpio_mutex); while (!snd_info_get_line(buffer, line, sizeof(line))) { if (sscanf(line, "%x %x", ®, &val) != 2) continue; if (reg <= 0x17 && val <= 0xffff) wm_put(ice, reg, val); } - mutex_unlock(&ice->gpio_mutex); } static void wm_proc_regs_read(struct snd_info_entry *entry, @@ -880,12 +866,11 @@ static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_ice1712 *ice = entry->private_data; int reg, val; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); for (reg = 0; reg <= 0x17; reg++) { val = wm_get(ice, reg); snd_iprintf(buffer, "%02x = %04x\n", reg, val); } - mutex_unlock(&ice->gpio_mutex); } static void wm_proc_init(struct snd_ice1712 *ice) @@ -994,7 +979,7 @@ static int prodigy_hifi_resume(struct snd_ice1712 *ice) struct prodigy_hifi_spec *spec = ice->spec; int i, ch; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); /* reinitialize WM8776 and re-apply old register values */ wm8776_init(ice); @@ -1023,7 +1008,6 @@ static int prodigy_hifi_resume(struct snd_ice1712 *ice) wm_put(ice, WM_DAC_MUTE, 0x00); wm_put(ice, WM_DAC_CTRL1, 0x90); - mutex_unlock(&ice->gpio_mutex); return 0; } #endif @@ -1134,11 +1118,11 @@ static int prodigy_hd2_resume(struct snd_ice1712 *ice) /* initialize ak4396 codec and restore previous mixer volumes */ struct prodigy_hifi_spec *spec = ice->spec; int i; - mutex_lock(&ice->gpio_mutex); + + guard(mutex)(&ice->gpio_mutex); ak4396_init(ice); for (i = 0; i < 2; i++) ak4396_write(ice, AK4396_LCH_ATT + i, spec->vol[i] & 0xff); - mutex_unlock(&ice->gpio_mutex); return 0; } #endif diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c index f61ee9f5c754..099601edf1d0 100644 --- a/sound/pci/ice1712/quartet.c +++ b/sound/pci/ice1712/quartet.c @@ -396,7 +396,7 @@ static void reg_write(struct snd_ice1712 *ice, unsigned int reg, { unsigned int tmp; - mutex_lock(&ice->gpio_mutex); + guard(mutex)(&ice->gpio_mutex); /* set direction of used GPIOs*/ /* all outputs */ tmp = 0x00ffff; @@ -429,7 +429,6 @@ static void reg_write(struct snd_ice1712 *ice, unsigned int reg, ice->gpio.set_mask(ice, 0xffffff); /* outputs only 8-15 */ ice->gpio.set_dir(ice, 0x00ff00); - mutex_unlock(&ice->gpio_mutex); } static unsigned int get_scr(struct snd_ice1712 *ice) diff --git a/sound/pci/ice1712/wtm.c b/sound/pci/ice1712/wtm.c index f613f0067d8c..57a79536e7ba 100644 --- a/sound/pci/ice1712/wtm.c +++ b/sound/pci/ice1712/wtm.c @@ -118,7 +118,7 @@ static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, unsigned char val; int idx, id; - mutex_lock(&spec->mute_mutex); + guard(mutex)(&spec->mute_mutex); if (kcontrol->private_value) { idx = STAC946X_MASTER_VOLUME; @@ -133,7 +133,6 @@ static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, val = stac9460_2_get(ice, idx - 6); ucontrol->value.integer.value[0] = (~val >> 7) & 0x1; - mutex_unlock(&spec->mute_mutex); return 0; } @@ -455,7 +454,7 @@ static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate) return; /* change detected, setting master clock, muting first */ /* due to possible conflicts with mute controls - mutexing */ - mutex_lock(&spec->mute_mutex); + guard(mutex)(&spec->mute_mutex); /* we have to remember current mute status for each DAC */ changed = 0xFFFF; stac9460_dac_mute_all(ice, 0, &changed); @@ -466,7 +465,6 @@ static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate) /* unmuting - only originally unmuted dacs - * i.e. those changed when muting */ stac9460_dac_mute_all(ice, 1, &changed); - mutex_unlock(&spec->mute_mutex); } diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 9e6a5065ffbf..3b53c5e63c29 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -690,52 +690,51 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ichdev) { unsigned long port = ichdev->reg_offset; - unsigned long flags; int status, civ, i, step; int ack = 0; if (!(ichdev->prepared || chip->in_measurement) || ichdev->suspended) return; - spin_lock_irqsave(&chip->reg_lock, flags); - status = igetbyte(chip, port + ichdev->roff_sr); - civ = igetbyte(chip, port + ICH_REG_OFF_CIV); - if (!(status & ICH_BCIS)) { - step = 0; - } else if (civ == ichdev->civ) { - step = 1; - ichdev->civ++; - ichdev->civ &= ICH_REG_LVI_MASK; - } else { - step = civ - ichdev->civ; - if (step < 0) - step += ICH_REG_LVI_MASK + 1; - ichdev->civ = civ; - } - - ichdev->position += step * ichdev->fragsize1; - if (! chip->in_measurement) - ichdev->position %= ichdev->size; - ichdev->lvi += step; - ichdev->lvi &= ICH_REG_LVI_MASK; - iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi); - for (i = 0; i < step; i++) { - ichdev->lvi_frag++; - ichdev->lvi_frag %= ichdev->frags; - ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + status = igetbyte(chip, port + ichdev->roff_sr); + civ = igetbyte(chip, port + ICH_REG_OFF_CIV); + if (!(status & ICH_BCIS)) { + step = 0; + } else if (civ == ichdev->civ) { + step = 1; + ichdev->civ++; + ichdev->civ &= ICH_REG_LVI_MASK; + } else { + step = civ - ichdev->civ; + if (step < 0) + step += ICH_REG_LVI_MASK + 1; + ichdev->civ = civ; + } + + ichdev->position += step * ichdev->fragsize1; + if (! chip->in_measurement) + ichdev->position %= ichdev->size; + ichdev->lvi += step; + ichdev->lvi &= ICH_REG_LVI_MASK; + iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi); + for (i = 0; i < step; i++) { + ichdev->lvi_frag++; + ichdev->lvi_frag %= ichdev->frags; + ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1); #if 0 - dev_dbg(chip->card->dev, - "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", - ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], - ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), - inl(port + 4), inb(port + ICH_REG_OFF_CR)); + dev_dbg(chip->card->dev, + "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", + ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], + ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), + inl(port + 4), inb(port + ICH_REG_OFF_CR)); #endif - if (--ichdev->ack == 0) { - ichdev->ack = ichdev->ack_reload; - ack = 1; + if (--ichdev->ack == 0) { + ichdev->ack = ichdev->ack_reload; + ack = 1; + } } } - spin_unlock_irqrestore(&chip->reg_lock, flags); if (ack && ichdev->substream) { snd_pcm_period_elapsed(ichdev->substream); } @@ -917,7 +916,7 @@ static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip, unsigned int cnt; int dbl = runtime->rate > 48000; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); switch (chip->device_type) { case DEVICE_ALI: cnt = igetdword(chip, ICHREG(ALI_SCR)); @@ -963,7 +962,6 @@ static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip, iputdword(chip, ICHREG(GLOB_CNT), cnt); break; } - spin_unlock_irq(&chip->reg_lock); } static int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream) @@ -993,7 +991,7 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs int civ, timeout = 10; unsigned int position; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); do { civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV); ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb); @@ -1033,7 +1031,6 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs } } ichdev->last_pos = ptr; - spin_unlock(&chip->reg_lock); if (ptr >= ichdev->size) return 0; return bytes_to_frames(substream->runtime, ptr); @@ -1235,12 +1232,12 @@ static int snd_intel8x0_ali_ac97spdifout_open(struct snd_pcm_substream *substrea struct intel8x0 *chip = snd_pcm_substream_chip(substream); unsigned int val; - spin_lock_irq(&chip->reg_lock); - val = igetdword(chip, ICHREG(ALI_INTERFACECR)); - val |= ICH_ALI_IF_AC97SP; - iputdword(chip, ICHREG(ALI_INTERFACECR), val); - /* also needs to set ALI_SC_CODEC_SPDF correctly */ - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + val = igetdword(chip, ICHREG(ALI_INTERFACECR)); + val |= ICH_ALI_IF_AC97SP; + iputdword(chip, ICHREG(ALI_INTERFACECR), val); + /* also needs to set ALI_SC_CODEC_SPDF correctly */ + } return snd_intel8x0_pcm_open(substream, &chip->ichd[ALID_AC97SPDIFOUT]); } @@ -1251,11 +1248,10 @@ static int snd_intel8x0_ali_ac97spdifout_close(struct snd_pcm_substream *substre unsigned int val; chip->ichd[ALID_AC97SPDIFOUT].substream = NULL; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); val = igetdword(chip, ICHREG(ALI_INTERFACECR)); val &= ~ICH_ALI_IF_AC97SP; iputdword(chip, ICHREG(ALI_INTERFACECR), val); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -2662,53 +2658,53 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip) } snd_intel8x0_setup_periods(chip, ichdev); port = ichdev->reg_offset; - spin_lock_irq(&chip->reg_lock); - chip->in_measurement = 1; - /* trigger */ - if (chip->device_type != DEVICE_ALI) - iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE | ICH_STARTBM); - else { - iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE); - iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot); + scoped_guard(spinlock_irq, &chip->reg_lock) { + chip->in_measurement = 1; + /* trigger */ + if (chip->device_type != DEVICE_ALI) + iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE | ICH_STARTBM); + else { + iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE); + iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot); + } + start_time = ktime_get(); } - start_time = ktime_get(); - spin_unlock_irq(&chip->reg_lock); msleep(50); - spin_lock_irq(&chip->reg_lock); - /* check the position */ - do { - civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV); - pos1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb); - if (pos1 == 0) { - udelay(10); - continue; + scoped_guard(spinlock_irq, &chip->reg_lock) { + /* check the position */ + do { + civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV); + pos1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb); + if (pos1 == 0) { + udelay(10); + continue; + } + if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) && + pos1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) + break; + } while (timeout--); + if (pos1 == 0) { /* oops, this value is not reliable */ + pos = 0; + } else { + pos = ichdev->fragsize1; + pos -= pos1 << ichdev->pos_shift; + pos += ichdev->position; } - if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) && - pos1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) - break; - } while (timeout--); - if (pos1 == 0) { /* oops, this value is not reliable */ - pos = 0; - } else { - pos = ichdev->fragsize1; - pos -= pos1 << ichdev->pos_shift; - pos += ichdev->position; - } - chip->in_measurement = 0; - stop_time = ktime_get(); - /* stop */ - if (chip->device_type == DEVICE_ALI) { - iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 16)); - iputbyte(chip, port + ICH_REG_OFF_CR, 0); - while (igetbyte(chip, port + ICH_REG_OFF_CR)) - ; - } else { - iputbyte(chip, port + ICH_REG_OFF_CR, 0); - while (!(igetbyte(chip, port + ichdev->roff_sr) & ICH_DCH)) - ; + chip->in_measurement = 0; + stop_time = ktime_get(); + /* stop */ + if (chip->device_type == DEVICE_ALI) { + iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 16)); + iputbyte(chip, port + ICH_REG_OFF_CR, 0); + while (igetbyte(chip, port + ICH_REG_OFF_CR)) + ; + } else { + iputbyte(chip, port + ICH_REG_OFF_CR, 0); + while (!(igetbyte(chip, port + ichdev->roff_sr) & ICH_DCH)) + ; + } + iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS); } - iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS); - spin_unlock_irq(&chip->reg_lock); if (pos == 0) { dev_err(chip->card->dev, diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 9e5988583abe..84e1b7ea34e2 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -471,16 +471,13 @@ static irqreturn_t snd_intel8x0m_interrupt(int irq, void *dev_id) unsigned int status; unsigned int i; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); status = igetdword(chip, chip->int_sta_reg); - if (status == 0xffffffff) { /* we are not yet resumed */ - spin_unlock(&chip->reg_lock); + if (status == 0xffffffff) /* we are not yet resumed */ return IRQ_NONE; - } if ((status & chip->int_sta_mask) == 0) { if (status) iputdword(chip, chip->int_sta_reg, status); - spin_unlock(&chip->reg_lock); return IRQ_NONE; } @@ -492,7 +489,6 @@ static irqreturn_t snd_intel8x0m_interrupt(int irq, void *dev_id) /* ack them */ iputdword(chip, chip->int_sta_reg, status & chip->int_sta_mask); - spin_unlock(&chip->reg_lock); return IRQ_HANDLED; } diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 0a66d5cfc090..d16acf83668a 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -568,25 +568,19 @@ static void snd_korg1212_SendStop(struct snd_korg1212 *korg1212) static void snd_korg1212_SendStopAndWait(struct snd_korg1212 *korg1212) { - unsigned long flags; - spin_lock_irqsave(&korg1212->lock, flags); - snd_korg1212_SendStop(korg1212); - spin_unlock_irqrestore(&korg1212->lock, flags); + scoped_guard(spinlock_irqsave, &korg1212->lock) { + snd_korg1212_SendStop(korg1212); + } wait_event_timeout(korg1212->wait, !korg1212->dsp_stop_processing, HZ); } static int snd_korg1212_TurnOnIdleMonitor(struct snd_korg1212 *korg1212) { - unsigned long flags; - int rc; - udelay(INTERCOMMAND_DELAY); - spin_lock_irqsave(&korg1212->lock, flags); + guard(spinlock_irqsave)(&korg1212->lock); korg1212->idleMonitorOn = 1; - rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, - K1212_MODE_MonitorOn, 0, 0, 0); - spin_unlock_irqrestore(&korg1212->lock, flags); - return rc; + return snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, + K1212_MODE_MonitorOn, 0, 0, 0); } static void snd_korg1212_TurnOffIdleMonitor(struct snd_korg1212 *korg1212) @@ -606,13 +600,12 @@ static int snd_korg1212_OpenCard(struct snd_korg1212 * korg1212) { K1212_DEBUG_PRINTK("K1212_DEBUG: OpenCard [%s] %d\n", stateName[korg1212->cardState], korg1212->opencnt); - mutex_lock(&korg1212->open_mutex); + guard(mutex)(&korg1212->open_mutex); if (korg1212->opencnt++ == 0) { snd_korg1212_TurnOffIdleMonitor(korg1212); snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); } - mutex_unlock(&korg1212->open_mutex); return 1; } @@ -621,11 +614,9 @@ static int snd_korg1212_CloseCard(struct snd_korg1212 * korg1212) K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard [%s] %d\n", stateName[korg1212->cardState], korg1212->opencnt); - mutex_lock(&korg1212->open_mutex); - if (--(korg1212->opencnt)) { - mutex_unlock(&korg1212->open_mutex); + guard(mutex)(&korg1212->open_mutex); + if (--(korg1212->opencnt)) return 0; - } if (korg1212->cardState == K1212_STATE_SETUP) { int rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, @@ -633,10 +624,8 @@ static int snd_korg1212_CloseCard(struct snd_korg1212 * korg1212) if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard - RC = %d [%s]\n", rc, stateName[korg1212->cardState]); - if (rc != K1212_CMDRET_Success) { - mutex_unlock(&korg1212->open_mutex); + if (rc != K1212_CMDRET_Success) return 0; - } } else if (korg1212->cardState > K1212_STATE_SETUP) { snd_korg1212_SendStopAndWait(korg1212); } @@ -646,7 +635,6 @@ static int snd_korg1212_CloseCard(struct snd_korg1212 * korg1212) snd_korg1212_setCardState(korg1212, K1212_STATE_READY); } - mutex_unlock(&korg1212->open_mutex); return 0; } @@ -844,7 +832,6 @@ static int snd_korg1212_WriteADCSensitivity(struct snd_korg1212 *korg1212) u16 controlValue; // this keeps the current value to be written to // the card's eeprom control register. u16 count; - unsigned long flags; K1212_DEBUG_PRINTK("K1212_DEBUG: WriteADCSensivity [%s]\n", stateName[korg1212->cardState]); @@ -865,7 +852,7 @@ static int snd_korg1212_WriteADCSensitivity(struct snd_korg1212 *korg1212) } else monModeSet = 0; - spin_lock_irqsave(&korg1212->lock, flags); + guard(spinlock_irqsave)(&korg1212->lock); // ---------------------------------------------------------------------------- // we are about to send new values to the card, so clear the new values queued @@ -974,8 +961,6 @@ static int snd_korg1212_WriteADCSensitivity(struct snd_korg1212 *korg1212) rc, stateName[korg1212->cardState]); } - spin_unlock_irqrestore(&korg1212->lock, flags); - return 1; } @@ -1067,7 +1052,7 @@ static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id) if (!doorbellValue) return IRQ_NONE; - spin_lock(&korg1212->lock); + guard(spinlock)(&korg1212->lock); writel(doorbellValue, korg1212->inDoorbellPtr); @@ -1145,8 +1130,6 @@ static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id) korg1212->inIRQ--; - spin_unlock(&korg1212->lock); - return IRQ_HANDLED; } @@ -1332,7 +1315,6 @@ static void snd_korg1212_free_pcm(struct snd_pcm *pcm) static int snd_korg1212_playback_open(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; @@ -1344,15 +1326,13 @@ static int snd_korg1212_playback_open(struct snd_pcm_substream *substream) runtime->hw = snd_korg1212_playback_info; snd_pcm_set_runtime_buffer(substream, korg1212->dma_play); - spin_lock_irqsave(&korg1212->lock, flags); - - korg1212->playback_substream = substream; - korg1212->playback_pid = current->pid; - korg1212->periodsize = K1212_PERIODS; - korg1212->channels = K1212_CHANNELS; - korg1212->errorcnt = 0; - - spin_unlock_irqrestore(&korg1212->lock, flags); + scoped_guard(spinlock_irqsave, &korg1212->lock) { + korg1212->playback_substream = substream; + korg1212->playback_pid = current->pid; + korg1212->periodsize = K1212_PERIODS; + korg1212->channels = K1212_CHANNELS; + korg1212->errorcnt = 0; + } snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, kPlayBufferFrames); @@ -1363,7 +1343,6 @@ static int snd_korg1212_playback_open(struct snd_pcm_substream *substream) static int snd_korg1212_capture_open(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; @@ -1375,14 +1354,12 @@ static int snd_korg1212_capture_open(struct snd_pcm_substream *substream) runtime->hw = snd_korg1212_capture_info; snd_pcm_set_runtime_buffer(substream, korg1212->dma_rec); - spin_lock_irqsave(&korg1212->lock, flags); - - korg1212->capture_substream = substream; - korg1212->capture_pid = current->pid; - korg1212->periodsize = K1212_PERIODS; - korg1212->channels = K1212_CHANNELS; - - spin_unlock_irqrestore(&korg1212->lock, flags); + scoped_guard(spinlock_irqsave, &korg1212->lock) { + korg1212->capture_substream = substream; + korg1212->capture_pid = current->pid; + korg1212->periodsize = K1212_PERIODS; + korg1212->channels = K1212_CHANNELS; + } snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, kPlayBufferFrames); @@ -1391,7 +1368,6 @@ static int snd_korg1212_capture_open(struct snd_pcm_substream *substream) static int snd_korg1212_playback_close(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_close [%s]\n", @@ -1399,13 +1375,11 @@ static int snd_korg1212_playback_close(struct snd_pcm_substream *substream) snd_korg1212_silence(korg1212, 0, K1212_MAX_SAMPLES, 0, korg1212->channels * 2); - spin_lock_irqsave(&korg1212->lock, flags); - - korg1212->playback_pid = -1; - korg1212->playback_substream = NULL; - korg1212->periodsize = 0; - - spin_unlock_irqrestore(&korg1212->lock, flags); + scoped_guard(spinlock_irqsave, &korg1212->lock) { + korg1212->playback_pid = -1; + korg1212->playback_substream = NULL; + korg1212->periodsize = 0; + } snd_korg1212_CloseCard(korg1212); return 0; @@ -1413,19 +1387,16 @@ static int snd_korg1212_playback_close(struct snd_pcm_substream *substream) static int snd_korg1212_capture_close(struct snd_pcm_substream *substream) { - unsigned long flags; struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_close [%s]\n", stateName[korg1212->cardState]); - spin_lock_irqsave(&korg1212->lock, flags); - - korg1212->capture_pid = -1; - korg1212->capture_substream = NULL; - korg1212->periodsize = 0; - - spin_unlock_irqrestore(&korg1212->lock, flags); + scoped_guard(spinlock_irqsave, &korg1212->lock) { + korg1212->capture_pid = -1; + korg1212->capture_substream = NULL; + korg1212->periodsize = 0; + } snd_korg1212_CloseCard(korg1212); return 0; @@ -1451,7 +1422,6 @@ static int snd_korg1212_ioctl(struct snd_pcm_substream *substream, static int snd_korg1212_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - unsigned long flags; struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); int err; pid_t this_pid; @@ -1460,7 +1430,7 @@ static int snd_korg1212_hw_params(struct snd_pcm_substream *substream, K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_hw_params [%s]\n", stateName[korg1212->cardState]); - spin_lock_irqsave(&korg1212->lock, flags); + guard(spinlock_irqsave)(&korg1212->lock); if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { this_pid = korg1212->playback_pid; @@ -1478,26 +1448,20 @@ static int snd_korg1212_hw_params(struct snd_pcm_substream *substream, */ if ((int)params_rate(params) != korg1212->clkRate) { - spin_unlock_irqrestore(&korg1212->lock, flags); _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); return -EBUSY; } - spin_unlock_irqrestore(&korg1212->lock, flags); return 0; } err = snd_korg1212_SetRate(korg1212, params_rate(params)); - if (err < 0) { - spin_unlock_irqrestore(&korg1212->lock, flags); + if (err < 0) return err; - } korg1212->channels = params_channels(params); korg1212->periodsize = K1212_PERIOD_BYTES; - spin_unlock_irqrestore(&korg1212->lock, flags); - return 0; } @@ -1517,15 +1481,13 @@ static int snd_korg1212_prepare(struct snd_pcm_substream *substream) K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare [%s]\n", stateName[korg1212->cardState]); - spin_lock_irq(&korg1212->lock); + guard(spinlock_irq)(&korg1212->lock); korg1212->dsp_stop_processing = 0; rc = snd_korg1212_SetupForPlay(korg1212); korg1212->currentBuffer = 0; - spin_unlock_irq(&korg1212->lock); - return rc ? -EINVAL : 0; } @@ -1538,7 +1500,7 @@ static int snd_korg1212_trigger(struct snd_pcm_substream *substream, K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_trigger [%s] cmd=%d\n", stateName[korg1212->cardState], cmd); - spin_lock(&korg1212->lock); + guard(spinlock)(&korg1212->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: /* @@ -1566,7 +1528,6 @@ static int snd_korg1212_trigger(struct snd_pcm_substream *substream, rc = 1; break; } - spin_unlock(&korg1212->lock); return rc ? -EINVAL : 0; } @@ -1666,15 +1627,13 @@ static int snd_korg1212_control_phase_get(struct snd_kcontrol *kcontrol, struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); int i = kcontrol->private_value; - spin_lock_irq(&korg1212->lock); + guard(spinlock_irq)(&korg1212->lock); u->value.integer.value[0] = korg1212->volumePhase[i]; if (i >= 8) u->value.integer.value[1] = korg1212->volumePhase[i+1]; - spin_unlock_irq(&korg1212->lock); - return 0; } @@ -1685,7 +1644,7 @@ static int snd_korg1212_control_phase_put(struct snd_kcontrol *kcontrol, int change = 0; int i, val; - spin_lock_irq(&korg1212->lock); + guard(spinlock_irq)(&korg1212->lock); i = kcontrol->private_value; @@ -1711,8 +1670,6 @@ static int snd_korg1212_control_phase_put(struct snd_kcontrol *kcontrol, } } - spin_unlock_irq(&korg1212->lock); - return change; } @@ -1732,7 +1689,7 @@ static int snd_korg1212_control_volume_get(struct snd_kcontrol *kcontrol, struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); int i; - spin_lock_irq(&korg1212->lock); + guard(spinlock_irq)(&korg1212->lock); i = kcontrol->private_value; u->value.integer.value[0] = abs(korg1212->sharedBufferPtr->volumeData[i]); @@ -1740,8 +1697,6 @@ static int snd_korg1212_control_volume_get(struct snd_kcontrol *kcontrol, if (i >= 8) u->value.integer.value[1] = abs(korg1212->sharedBufferPtr->volumeData[i+1]); - spin_unlock_irq(&korg1212->lock); - return 0; } @@ -1753,7 +1708,7 @@ static int snd_korg1212_control_volume_put(struct snd_kcontrol *kcontrol, int i; int val; - spin_lock_irq(&korg1212->lock); + guard(spinlock_irq)(&korg1212->lock); i = kcontrol->private_value; @@ -1779,8 +1734,6 @@ static int snd_korg1212_control_volume_put(struct snd_kcontrol *kcontrol, } } - spin_unlock_irq(&korg1212->lock); - return change; } @@ -1798,7 +1751,7 @@ static int snd_korg1212_control_route_get(struct snd_kcontrol *kcontrol, struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); int i; - spin_lock_irq(&korg1212->lock); + guard(spinlock_irq)(&korg1212->lock); i = kcontrol->private_value; u->value.enumerated.item[0] = korg1212->sharedBufferPtr->routeData[i]; @@ -1806,8 +1759,6 @@ static int snd_korg1212_control_route_get(struct snd_kcontrol *kcontrol, if (i >= 8) u->value.enumerated.item[1] = korg1212->sharedBufferPtr->routeData[i+1]; - spin_unlock_irq(&korg1212->lock); - return 0; } @@ -1817,7 +1768,7 @@ static int snd_korg1212_control_route_put(struct snd_kcontrol *kcontrol, struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); int change = 0, i; - spin_lock_irq(&korg1212->lock); + guard(spinlock_irq)(&korg1212->lock); i = kcontrol->private_value; @@ -1837,8 +1788,6 @@ static int snd_korg1212_control_route_put(struct snd_kcontrol *kcontrol, } } - spin_unlock_irq(&korg1212->lock); - return change; } @@ -1857,13 +1806,11 @@ static int snd_korg1212_control_get(struct snd_kcontrol *kcontrol, { struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&korg1212->lock); + guard(spinlock_irq)(&korg1212->lock); u->value.integer.value[0] = korg1212->leftADCInSens; u->value.integer.value[1] = korg1212->rightADCInSens; - spin_unlock_irq(&korg1212->lock); - return 0; } @@ -1873,22 +1820,20 @@ static int snd_korg1212_control_put(struct snd_kcontrol *kcontrol, struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); int change = 0; - spin_lock_irq(&korg1212->lock); - - if (u->value.integer.value[0] >= k1212MinADCSens && - u->value.integer.value[0] <= k1212MaxADCSens && - u->value.integer.value[0] != korg1212->leftADCInSens) { - korg1212->leftADCInSens = u->value.integer.value[0]; - change = 1; - } - if (u->value.integer.value[1] >= k1212MinADCSens && - u->value.integer.value[1] <= k1212MaxADCSens && - u->value.integer.value[1] != korg1212->rightADCInSens) { - korg1212->rightADCInSens = u->value.integer.value[1]; - change = 1; - } - - spin_unlock_irq(&korg1212->lock); + scoped_guard(spinlock_irq, &korg1212->lock) { + if (u->value.integer.value[0] >= k1212MinADCSens && + u->value.integer.value[0] <= k1212MaxADCSens && + u->value.integer.value[0] != korg1212->leftADCInSens) { + korg1212->leftADCInSens = u->value.integer.value[0]; + change = 1; + } + if (u->value.integer.value[1] >= k1212MinADCSens && + u->value.integer.value[1] <= k1212MaxADCSens && + u->value.integer.value[1] != korg1212->rightADCInSens) { + korg1212->rightADCInSens = u->value.integer.value[1]; + change = 1; + } + } if (change) snd_korg1212_WriteADCSensitivity(korg1212); @@ -1907,11 +1852,9 @@ static int snd_korg1212_control_sync_get(struct snd_kcontrol *kcontrol, { struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&korg1212->lock); + guard(spinlock_irq)(&korg1212->lock); ucontrol->value.enumerated.item[0] = korg1212->clkSource; - - spin_unlock_irq(&korg1212->lock); return 0; } @@ -1923,10 +1866,9 @@ static int snd_korg1212_control_sync_put(struct snd_kcontrol *kcontrol, int change; val = ucontrol->value.enumerated.item[0] % 3; - spin_lock_irq(&korg1212->lock); + guard(spinlock_irq)(&korg1212->lock); change = val != korg1212->clkSource; snd_korg1212_SetClockSource(korg1212, val); - spin_unlock_irq(&korg1212->lock); return change; } diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c index 8d927ecba165..34a3ba17deb4 100644 --- a/sound/pci/lola/lola.c +++ b/sound/pci/lola/lola.c @@ -74,7 +74,6 @@ static int corb_send_verb(struct lola *chip, unsigned int nid, unsigned int verb, unsigned int data, unsigned int extdata) { - unsigned long flags; int ret = -EIO; chip->last_cmd_nid = nid; @@ -83,7 +82,7 @@ static int corb_send_verb(struct lola *chip, unsigned int nid, chip->last_extdata = extdata; data |= (nid << 20) | (verb << 8); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (chip->rirb.cmds < LOLA_CORB_ENTRIES - 1) { unsigned int wp = chip->corb.wp + 1; wp %= LOLA_CORB_ENTRIES; @@ -95,7 +94,6 @@ static int corb_send_verb(struct lola *chip, unsigned int nid, smp_wmb(); ret = 0; } - spin_unlock_irqrestore(&chip->reg_lock, flags); return ret; } diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c index 32193fae978d..6c046ecd6e08 100644 --- a/sound/pci/lola/lola_pcm.c +++ b/sound/pci/lola/lola_pcm.c @@ -214,11 +214,9 @@ static int lola_pcm_open(struct snd_pcm_substream *substream) struct lola_stream *str = lola_get_stream(substream); struct snd_pcm_runtime *runtime = substream->runtime; - mutex_lock(&chip->open_mutex); - if (str->opened) { - mutex_unlock(&chip->open_mutex); + guard(mutex)(&chip->open_mutex); + if (str->opened) return -EBUSY; - } str->substream = substream; str->master = NULL; str->opened = 1; @@ -239,7 +237,6 @@ static int lola_pcm_open(struct snd_pcm_substream *substream) chip->granularity); snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, chip->granularity); - mutex_unlock(&chip->open_mutex); return 0; } @@ -261,7 +258,7 @@ static int lola_pcm_close(struct snd_pcm_substream *substream) struct lola *chip = snd_pcm_substream_chip(substream); struct lola_stream *str = lola_get_stream(substream); - mutex_lock(&chip->open_mutex); + guard(mutex)(&chip->open_mutex); if (str->substream == substream) { str->substream = NULL; str->opened = 0; @@ -270,7 +267,6 @@ static int lola_pcm_close(struct snd_pcm_substream *substream) /* release sample rate */ chip->sample_rate = 0; } - mutex_unlock(&chip->open_mutex); return 0; } @@ -291,10 +287,9 @@ static int lola_pcm_hw_free(struct snd_pcm_substream *substream) struct lola_pcm *pcm = lola_get_pcm(substream); struct lola_stream *str = lola_get_stream(substream); - mutex_lock(&chip->open_mutex); + guard(mutex)(&chip->open_mutex); lola_stream_reset(chip, str); lola_cleanup_slave_streams(pcm, str); - mutex_unlock(&chip->open_mutex); return 0; } @@ -457,18 +452,16 @@ static int lola_pcm_prepare(struct snd_pcm_substream *substream) unsigned int bufsize, period_bytes, format_verb; int i, err; - mutex_lock(&chip->open_mutex); - lola_stream_reset(chip, str); - lola_cleanup_slave_streams(pcm, str); - if (str->index + runtime->channels > pcm->num_streams) { - mutex_unlock(&chip->open_mutex); - return -EINVAL; - } - for (i = 1; i < runtime->channels; i++) { - str[i].master = str; - str[i].opened = 1; + scoped_guard(mutex, &chip->open_mutex) { + lola_stream_reset(chip, str); + lola_cleanup_slave_streams(pcm, str); + if (str->index + runtime->channels > pcm->num_streams) + return -EINVAL; + for (i = 1; i < runtime->channels; i++) { + str[i].master = str; + str[i].opened = 1; + } } - mutex_unlock(&chip->open_mutex); bufsize = snd_pcm_lib_buffer_bytes(substream); period_bytes = snd_pcm_lib_period_bytes(substream); @@ -530,7 +523,7 @@ static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd) */ sync_streams = (start && snd_pcm_stream_linked(substream)); tstamp = lola_get_tstamp(chip, !sync_streams); - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); snd_pcm_group_for_each_entry(s, substream) { if (s->pcm->card != substream->pcm->card) continue; @@ -543,7 +536,6 @@ static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd) str->paused = !start; snd_pcm_trigger_done(s, substream); } - spin_unlock(&chip->reg_lock); return 0; } diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c index 9f12c936bb1f..96df00db51d5 100644 --- a/sound/pci/lx6464es/lx6464es.c +++ b/sound/pci/lx6464es/lx6464es.c @@ -207,7 +207,7 @@ static int lx_pcm_open(struct snd_pcm_substream *substream) int board_rate; dev_dbg(chip->card->dev, "->lx_pcm_open\n"); - mutex_lock(&chip->setup_mutex); + guard(mutex)(&chip->setup_mutex); /* copy the struct snd_pcm_hardware struct */ runtime->hw = lx_caps; @@ -218,7 +218,7 @@ static int lx_pcm_open(struct snd_pcm_substream *substream) SNDRV_PCM_HW_PARAM_PERIODS); if (err < 0) { dev_warn(chip->card->dev, "could not constrain periods\n"); - goto exit; + return err; } #endif @@ -229,7 +229,7 @@ static int lx_pcm_open(struct snd_pcm_substream *substream) if (err < 0) { dev_warn(chip->card->dev, "could not constrain periods\n"); - goto exit; + return err; } /* constrain period size */ @@ -240,7 +240,7 @@ static int lx_pcm_open(struct snd_pcm_substream *substream) if (err < 0) { dev_warn(chip->card->dev, "could not constrain period size\n"); - goto exit; + return err; } snd_pcm_hw_constraint_step(runtime, 0, @@ -249,10 +249,8 @@ static int lx_pcm_open(struct snd_pcm_substream *substream) snd_pcm_set_sync(substream); err = 0; -exit: runtime->private_data = chip; - mutex_unlock(&chip->setup_mutex); dev_dbg(chip->card->dev, "<-lx_pcm_open, %d\n", err); return err; } @@ -275,9 +273,8 @@ static snd_pcm_uframes_t lx_pcm_stream_pointer(struct snd_pcm_substream dev_dbg(chip->card->dev, "->lx_pcm_stream_pointer\n"); - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); pos = lx_stream->frame_pos * substream->runtime->period_size; - mutex_unlock(&chip->lock); dev_dbg(chip->card->dev, "stream_pointer at %ld\n", pos); return pos; @@ -291,21 +288,21 @@ static int lx_pcm_prepare(struct snd_pcm_substream *substream) dev_dbg(chip->card->dev, "->lx_pcm_prepare\n"); - mutex_lock(&chip->setup_mutex); + guard(mutex)(&chip->setup_mutex); if (chip->hardware_running[is_capture]) { err = lx_hardware_stop(chip, substream); if (err < 0) { dev_err(chip->card->dev, "failed to stop hardware. " "Error code %d\n", err); - goto exit; + return err; } err = lx_hardware_close(chip, substream); if (err < 0) { dev_err(chip->card->dev, "failed to close hardware. " "Error code %d\n", err); - goto exit; + return err; } } @@ -314,14 +311,14 @@ static int lx_pcm_prepare(struct snd_pcm_substream *substream) if (err < 0) { dev_err(chip->card->dev, "failed to open hardware. " "Error code %d\n", err); - goto exit; + return err; } err = lx_hardware_start(chip, substream); if (err < 0) { dev_err(chip->card->dev, "failed to start hardware. " "Error code %d\n", err); - goto exit; + return err; } chip->hardware_running[is_capture] = 1; @@ -331,8 +328,6 @@ static int lx_pcm_prepare(struct snd_pcm_substream *substream) chip->board_sample_rate = substream->runtime->rate; } -exit: - mutex_unlock(&chip->setup_mutex); return err; } @@ -343,14 +338,13 @@ static int lx_pcm_hw_params(struct snd_pcm_substream *substream, dev_dbg(chip->card->dev, "->lx_pcm_hw_params\n"); - mutex_lock(&chip->setup_mutex); + guard(mutex)(&chip->setup_mutex); if (is_capture) chip->capture_stream.stream = substream; else chip->playback_stream.stream = substream; - mutex_unlock(&chip->setup_mutex); return 0; } @@ -373,21 +367,21 @@ static int lx_pcm_hw_free(struct snd_pcm_substream *substream) int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); dev_dbg(chip->card->dev, "->lx_pcm_hw_free\n"); - mutex_lock(&chip->setup_mutex); + guard(mutex)(&chip->setup_mutex); if (chip->hardware_running[is_capture]) { err = lx_hardware_stop(chip, substream); if (err < 0) { dev_err(chip->card->dev, "failed to stop hardware. " "Error code %d\n", err); - goto exit; + return err; } err = lx_hardware_close(chip, substream); if (err < 0) { dev_err(chip->card->dev, "failed to close hardware. " "Error code %d\n", err); - goto exit; + return err; } chip->hardware_running[is_capture] = 0; @@ -398,9 +392,7 @@ static int lx_pcm_hw_free(struct snd_pcm_substream *substream) else chip->playback_stream.stream = NULL; -exit: - mutex_unlock(&chip->setup_mutex); - return err; + return 0; } static void lx_trigger_start(struct lx6464es *chip, struct lx_stream *lx_stream) @@ -486,9 +478,7 @@ static void lx_trigger_dispatch_stream(struct lx6464es *chip, static int lx_pcm_trigger_dispatch(struct lx6464es *chip, struct lx_stream *lx_stream, int cmd) { - int err = 0; - - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: lx_stream->status = LX_STREAM_STATUS_SCHEDULE_RUN; @@ -499,16 +489,13 @@ static int lx_pcm_trigger_dispatch(struct lx6464es *chip, break; default: - err = -EINVAL; - goto exit; + return -EINVAL; } lx_trigger_dispatch_stream(chip, &chip->capture_stream); lx_trigger_dispatch_stream(chip, &chip->playback_stream); -exit: - mutex_unlock(&chip->lock); - return err; + return 0; } diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index 9d95ecb299ae..6f0843cfb3be 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c @@ -316,26 +316,25 @@ polling_successful: /* low-level dsp access */ int lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version) { - u16 ret; + int ret; - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG); ret = lx_message_send_atomic(chip, &chip->rmh); *rdsp_version = chip->rmh.stat[1]; - mutex_unlock(&chip->msg_lock); return ret; } int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq) { - u16 ret = 0; u32 freq_raw = 0; u32 freq = 0; u32 frequency = 0; + int ret; - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG); ret = lx_message_send_atomic(chip, &chip->rmh); @@ -353,8 +352,6 @@ int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq) frequency = 48000; } - mutex_unlock(&chip->msg_lock); - *rfreq = frequency * chip->freq_ratio; return ret; @@ -381,23 +378,19 @@ int lx_dsp_get_mac(struct lx6464es *chip) int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran) { - int ret; - - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_02_SET_GRANULARITY); chip->rmh.cmd[0] |= gran; - ret = lx_message_send_atomic(chip, &chip->rmh); - mutex_unlock(&chip->msg_lock); - return ret; + return lx_message_send_atomic(chip, &chip->rmh); } int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data) { int ret; - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_04_GET_EVENT); chip->rmh.stat_len = 9; /* we don't necessarily need the full length */ @@ -407,7 +400,6 @@ int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data) if (!ret) memcpy(data, chip->rmh.stat, chip->rmh.stat_len * sizeof(u32)); - mutex_unlock(&chip->msg_lock); return ret; } @@ -423,14 +415,13 @@ int lx_pipe_allocate(struct lx6464es *chip, u32 pipe, int is_capture, int err; u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_06_ALLOCATE_PIPE); chip->rmh.cmd[0] |= pipe_cmd; chip->rmh.cmd[0] |= channels; err = lx_message_send_atomic(chip, &chip->rmh); - mutex_unlock(&chip->msg_lock); if (err != 0) dev_err(chip->card->dev, "could not allocate pipe\n"); @@ -440,18 +431,14 @@ int lx_pipe_allocate(struct lx6464es *chip, u32 pipe, int is_capture, int lx_pipe_release(struct lx6464es *chip, u32 pipe, int is_capture) { - int err; u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_07_RELEASE_PIPE); chip->rmh.cmd[0] |= pipe_cmd; - err = lx_message_send_atomic(chip, &chip->rmh); - mutex_unlock(&chip->msg_lock); - - return err; + return lx_message_send_atomic(chip, &chip->rmh); } int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture, @@ -468,7 +455,7 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture, *r_needed = 0; *r_freed = 0; - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_08_ASK_BUFFERS); chip->rmh.cmd[0] |= pipe_cmd; @@ -501,41 +488,32 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture, } } - mutex_unlock(&chip->msg_lock); return err; } int lx_pipe_stop(struct lx6464es *chip, u32 pipe, int is_capture) { - int err; u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_09_STOP_PIPE); chip->rmh.cmd[0] |= pipe_cmd; - err = lx_message_send_atomic(chip, &chip->rmh); - - mutex_unlock(&chip->msg_lock); - return err; + return lx_message_send_atomic(chip, &chip->rmh); } static int lx_pipe_toggle_state(struct lx6464es *chip, u32 pipe, int is_capture) { - int err; u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_0B_TOGGLE_PIPE_STATE); chip->rmh.cmd[0] |= pipe_cmd; - err = lx_message_send_atomic(chip, &chip->rmh); - - mutex_unlock(&chip->msg_lock); - return err; + return lx_message_send_atomic(chip, &chip->rmh); } @@ -572,7 +550,7 @@ int lx_pipe_sample_count(struct lx6464es *chip, u32 pipe, int is_capture, int err; u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT); chip->rmh.cmd[0] |= pipe_cmd; @@ -589,7 +567,6 @@ int lx_pipe_sample_count(struct lx6464es *chip, u32 pipe, int is_capture, + chip->rmh.stat[1]; /* lo part */ } - mutex_unlock(&chip->msg_lock); return err; } @@ -598,7 +575,7 @@ int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate) int err; u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT); chip->rmh.cmd[0] |= pipe_cmd; @@ -610,7 +587,6 @@ int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate) else *rstate = (chip->rmh.stat[0] >> PSTATE_OFFSET) & 0x0F; - mutex_unlock(&chip->msg_lock); return err; } @@ -651,29 +627,24 @@ int lx_pipe_wait_for_idle(struct lx6464es *chip, u32 pipe, int is_capture) int lx_stream_set_state(struct lx6464es *chip, u32 pipe, int is_capture, enum stream_state_t state) { - int err; u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_13_SET_STREAM_STATE); chip->rmh.cmd[0] |= pipe_cmd; chip->rmh.cmd[0] |= state; - err = lx_message_send_atomic(chip, &chip->rmh); - mutex_unlock(&chip->msg_lock); - - return err; + return lx_message_send_atomic(chip, &chip->rmh); } int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime, u32 pipe, int is_capture) { - int err; u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); u32 channels = runtime->channels; - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_0C_DEF_STREAM); chip->rmh.cmd[0] |= pipe_cmd; @@ -688,10 +659,7 @@ int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime, chip->rmh.cmd[0] |= channels-1; - err = lx_message_send_atomic(chip, &chip->rmh); - mutex_unlock(&chip->msg_lock); - - return err; + return lx_message_send_atomic(chip, &chip->rmh); } int lx_stream_state(struct lx6464es *chip, u32 pipe, int is_capture, @@ -700,7 +668,7 @@ int lx_stream_state(struct lx6464es *chip, u32 pipe, int is_capture, int err; u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT); chip->rmh.cmd[0] |= pipe_cmd; @@ -709,7 +677,6 @@ int lx_stream_state(struct lx6464es *chip, u32 pipe, int is_capture, *rstate = (chip->rmh.stat[0] & SF_START) ? START_STATE : PAUSE_STATE; - mutex_unlock(&chip->msg_lock); return err; } @@ -719,7 +686,7 @@ int lx_stream_sample_position(struct lx6464es *chip, u32 pipe, int is_capture, int err; u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT); chip->rmh.cmd[0] |= pipe_cmd; @@ -730,7 +697,6 @@ int lx_stream_sample_position(struct lx6464es *chip, u32 pipe, int is_capture, << 32) /* hi part */ + chip->rmh.stat[1]; /* lo part */ - mutex_unlock(&chip->msg_lock); return err; } @@ -742,7 +708,7 @@ int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture, int err; u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_0F_UPDATE_BUFFER); chip->rmh.cmd[0] |= pipe_cmd; @@ -763,7 +729,7 @@ int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture, if (err == 0) { *r_buffer_index = chip->rmh.stat[0]; - goto done; + return err; } if (err == EB_RBUFFERS_TABLE_OVERFLOW) @@ -778,8 +744,6 @@ int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture, dev_err(chip->card->dev, "lx_buffer_give EB_CMD_REFUSED\n"); - done: - mutex_unlock(&chip->msg_lock); return err; } @@ -789,7 +753,7 @@ int lx_buffer_free(struct lx6464es *chip, u32 pipe, int is_capture, int err; u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER); chip->rmh.cmd[0] |= pipe_cmd; @@ -801,26 +765,21 @@ int lx_buffer_free(struct lx6464es *chip, u32 pipe, int is_capture, if (err == 0) *r_buffer_size = chip->rmh.stat[0] & MASK_DATA_SIZE; - mutex_unlock(&chip->msg_lock); return err; } int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture, u32 buffer_index) { - int err; u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER); chip->rmh.cmd[0] |= pipe_cmd; chip->rmh.cmd[0] |= buffer_index; - err = lx_message_send_atomic(chip, &chip->rmh); - - mutex_unlock(&chip->msg_lock); - return err; + return lx_message_send_atomic(chip, &chip->rmh); } @@ -831,11 +790,10 @@ int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture, * */ int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute) { - int err; /* bit set to 1: channel muted */ u64 mute_mask = unmute ? 0 : 0xFFFFFFFFFFFFFFFFLLU; - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_0D_SET_MUTE); chip->rmh.cmd[0] |= PIPE_INFO_TO_CMD(is_capture, 0); @@ -847,10 +805,7 @@ int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute) "mute %x %x %x\n", chip->rmh.cmd[0], chip->rmh.cmd[1], chip->rmh.cmd[2]); - err = lx_message_send_atomic(chip, &chip->rmh); - - mutex_unlock(&chip->msg_lock); - return err; + return lx_message_send_atomic(chip, &chip->rmh); } static const u32 peak_map[] = { @@ -878,7 +833,7 @@ int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels, int err = 0; int i; - mutex_lock(&chip->msg_lock); + guard(mutex)(&chip->msg_lock); for (i = 0; i < channels; i += 4) { u32 s0, s1, s2, s3; @@ -903,7 +858,6 @@ int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels, r_levels += 4; } - mutex_unlock(&chip->msg_lock); return err; } @@ -1033,7 +987,7 @@ static int lx_interrupt_request_new_buffer(struct lx6464es *chip, dev_dbg(chip->card->dev, "->lx_interrupt_request_new_buffer\n"); - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed, size_array); dev_dbg(chip->card->dev, @@ -1047,7 +1001,6 @@ static int lx_interrupt_request_new_buffer(struct lx6464es *chip, buffer_index, (unsigned long)buf, period_bytes); lx_stream->frame_pos = next_pos; - mutex_unlock(&chip->lock); return err; } diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index e092097599ff..bddf47a1f263 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -1096,7 +1096,7 @@ snd_m3_pcm_trigger(struct snd_pcm_substream *subs, int cmd) if (snd_BUG_ON(!s)) return -ENXIO; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -1117,7 +1117,6 @@ snd_m3_pcm_trigger(struct snd_pcm_substream *subs, int cmd) } break; } - spin_unlock(&chip->reg_lock); return err; } @@ -1412,7 +1411,7 @@ snd_m3_pcm_prepare(struct snd_pcm_substream *subs) runtime->rate < 8000) return -EINVAL; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); snd_m3_pcm_setup1(chip, s, subs); @@ -1423,8 +1422,6 @@ snd_m3_pcm_prepare(struct snd_pcm_substream *subs) snd_m3_pcm_setup2(chip, s, runtime); - spin_unlock_irq(&chip->reg_lock); - return 0; } @@ -1466,9 +1463,8 @@ snd_m3_pcm_pointer(struct snd_pcm_substream *subs) if (snd_BUG_ON(!s)) return 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); ptr = snd_m3_get_pointer(chip, s, subs); - spin_unlock(&chip->reg_lock); return bytes_to_frames(subs->runtime, ptr); } @@ -1629,13 +1625,12 @@ static irqreturn_t snd_m3_interrupt(int irq, void *dev_id) if (ctl & DSP2HOST_REQ_TIMER) { outb(DSP2HOST_REQ_TIMER, chip->iobase + ASSP_HOST_INT_STATUS); /* update adc/dac info if it was a timer int */ - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); for (i = 0; i < chip->num_substreams; i++) { struct m3_dma *s = &chip->substreams[i]; if (s->running) snd_m3_update_ptr(chip, s); } - spin_unlock(&chip->reg_lock); } } } @@ -1707,18 +1702,16 @@ snd_m3_substream_open(struct snd_m3 *chip, struct snd_pcm_substream *subs) int i; struct m3_dma *s; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); for (i = 0; i < chip->num_substreams; i++) { s = &chip->substreams[i]; if (! s->opened) goto __found; } - spin_unlock_irq(&chip->reg_lock); return -ENOMEM; __found: s->opened = 1; s->running = 0; - spin_unlock_irq(&chip->reg_lock); subs->runtime->private_data = s; s->substream = subs; @@ -1742,7 +1735,7 @@ snd_m3_substream_close(struct snd_m3 *chip, struct snd_pcm_substream *subs) if (s == NULL) return; /* not opened properly */ - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); if (s->substream && s->running) snd_m3_pcm_stop(chip, s, s->substream); /* does this happen? */ if (s->in_lists) { @@ -1753,7 +1746,6 @@ snd_m3_substream_close(struct snd_m3 *chip, struct snd_pcm_substream *subs) } s->running = 0; s->opened = 0; - spin_unlock_irq(&chip->reg_lock); } static int @@ -2339,14 +2331,13 @@ static void snd_m3_free(struct snd_card *card) cancel_work_sync(&chip->hwvol_work); if (chip->substreams) { - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); for (i = 0; i < chip->num_substreams; i++) { s = &chip->substreams[i]; /* check surviving pcms; this should not happen though.. */ if (s->substream && s->running) snd_m3_pcm_stop(chip, s, s->substream); } - spin_unlock_irq(&chip->reg_lock); } if (chip->iobase) { outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */ diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index cdc0ba5dd1ad..c6319e75beab 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -603,7 +603,7 @@ static int snd_mixart_hw_params(struct snd_pcm_substream *subs, /* set up format for the stream */ format = params_format(hw); - mutex_lock(&mgr->setup_mutex); + guard(mutex)(&mgr->setup_mutex); /* update the stream levels */ if( stream->pcm_number <= MIXART_PCM_DIGITAL ) { @@ -618,10 +618,8 @@ static int snd_mixart_hw_params(struct snd_pcm_substream *subs, /* set the format to the board */ err = mixart_set_format(stream, format); - if(err < 0) { - mutex_unlock(&mgr->setup_mutex); + if (err < 0) return err; - } if (subs->runtime->buffer_changed) { struct mixart_bufferinfo *bufferinfo; @@ -641,7 +639,6 @@ static int snd_mixart_hw_params(struct snd_pcm_substream *subs, bufferinfo[i].available_length, subs->number); } - mutex_unlock(&mgr->setup_mutex); return 0; } @@ -712,7 +709,7 @@ static int snd_mixart_playback_open(struct snd_pcm_substream *subs) int err = 0; int pcm_number; - mutex_lock(&mgr->setup_mutex); + guard(mutex)(&mgr->setup_mutex); if ( pcm == chip->pcm ) { pcm_number = MIXART_PCM_ANALOG; @@ -734,25 +731,21 @@ static int snd_mixart_playback_open(struct snd_pcm_substream *subs) dev_err(chip->card->dev, "snd_mixart_playback_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number); - err = -EBUSY; - goto _exit_open; + return -EBUSY; } /* get pipe pointer (out pipe) */ pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 0, 0); - if (pipe == NULL) { - err = -EINVAL; - goto _exit_open; - } + if (pipe == NULL) + return -EINVAL; /* start the pipe if necessary */ err = mixart_set_pipe_state(chip->mgr, pipe, 1); if( err < 0 ) { dev_err(chip->card->dev, "error starting pipe!\n"); snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0); - err = -EINVAL; - goto _exit_open; + return -EINVAL; } stream->pipe = pipe; @@ -773,10 +766,7 @@ static int snd_mixart_playback_open(struct snd_pcm_substream *subs) } } - _exit_open: - mutex_unlock(&mgr->setup_mutex); - - return err; + return 0; } @@ -791,7 +781,7 @@ static int snd_mixart_capture_open(struct snd_pcm_substream *subs) int err = 0; int pcm_number; - mutex_lock(&mgr->setup_mutex); + guard(mutex)(&mgr->setup_mutex); if ( pcm == chip->pcm ) { pcm_number = MIXART_PCM_ANALOG; @@ -815,25 +805,21 @@ static int snd_mixart_capture_open(struct snd_pcm_substream *subs) dev_err(chip->card->dev, "snd_mixart_capture_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number); - err = -EBUSY; - goto _exit_open; + return -EBUSY; } /* get pipe pointer (in pipe) */ pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 1, 0); - if (pipe == NULL) { - err = -EINVAL; - goto _exit_open; - } + if (pipe == NULL) + return -EINVAL; /* start the pipe if necessary */ err = mixart_set_pipe_state(chip->mgr, pipe, 1); if( err < 0 ) { dev_err(chip->card->dev, "error starting pipe!\n"); snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0); - err = -EINVAL; - goto _exit_open; + return -EINVAL; } stream->pipe = pipe; @@ -854,10 +840,7 @@ static int snd_mixart_capture_open(struct snd_pcm_substream *subs) } } - _exit_open: - mutex_unlock(&mgr->setup_mutex); - - return err; + return 0; } @@ -868,7 +851,7 @@ static int snd_mixart_close(struct snd_pcm_substream *subs) struct mixart_mgr *mgr = chip->mgr; struct mixart_stream *stream = subs->runtime->private_data; - mutex_lock(&mgr->setup_mutex); + guard(mutex)(&mgr->setup_mutex); dev_dbg(chip->card->dev, "snd_mixart_close C%d/P%d/Sub%d\n", chip->chip_idx, stream->pcm_number, subs->number); @@ -890,7 +873,6 @@ static int snd_mixart_close(struct snd_pcm_substream *subs) stream->status = MIXART_STREAM_STATUS_FREE; stream->substream = NULL; - mutex_unlock(&mgr->setup_mutex); return 0; } diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index a047ed0f84e9..f7396ee4f6d7 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c @@ -226,17 +226,16 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int init_waitqueue_entry(&wait, current); - mutex_lock(&mgr->msg_lock); - /* send the message */ - err = send_msg(mgr, request, max_resp_size, 1, &msg_frame); /* send and mark the answer pending */ - if (err) { - mutex_unlock(&mgr->msg_lock); - return err; + scoped_guard(mutex, &mgr->msg_lock) { + /* send the message */ + err = send_msg(mgr, request, max_resp_size, 1, &msg_frame); /* send and mark the answer pending */ + if (err) + return err; + + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&mgr->msg_sleep, &wait); } - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&mgr->msg_sleep, &wait); - mutex_unlock(&mgr->msg_lock); timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES); remove_wait_queue(&mgr->msg_sleep, &wait); @@ -253,9 +252,9 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int resp.data = resp_data; resp.size = max_resp_size; - mutex_lock(&mgr->msg_lock); - err = get_msg(mgr, &resp, msg_frame); - mutex_unlock(&mgr->msg_lock); + scoped_guard(mutex, &mgr->msg_lock) { + err = get_msg(mgr, &resp, msg_frame); + } if( request->message_id != resp.message_id ) dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n"); @@ -280,17 +279,16 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, init_waitqueue_entry(&wait, current); - mutex_lock(&mgr->msg_lock); - /* send the message */ - err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, ¬if_event); /* send and mark the notification event pending */ - if(err) { - mutex_unlock(&mgr->msg_lock); - return err; + scoped_guard(mutex, &mgr->msg_lock) { + /* send the message */ + err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, ¬if_event); /* send and mark the notification event pending */ + if (err) + return err; + + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&mgr->msg_sleep, &wait); } - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&mgr->msg_sleep, &wait); - mutex_unlock(&mgr->msg_lock); timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES); remove_wait_queue(&mgr->msg_sleep, &wait); @@ -311,9 +309,8 @@ int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *requ int err; /* just send the message (do not mark it as a pending one) */ - mutex_lock(&mgr->msg_lock); + guard(mutex)(&mgr->msg_lock); err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame); - mutex_unlock(&mgr->msg_lock); /* the answer will be handled by snd_struct mixart_msgasklet() */ atomic_inc(&mgr->msg_processed); @@ -420,7 +417,7 @@ irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id) struct mixart_msg resp; u32 msg; - mutex_lock(&mgr->lock); + guard(mutex)(&mgr->lock); /* process interrupt */ while (retrieve_msg_frame(mgr, &msg)) { @@ -530,19 +527,19 @@ irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id) fallthrough; case MSG_TYPE_ANSWER: /* answer or notification to a message we are waiting for*/ - mutex_lock(&mgr->msg_lock); - if( (msg & ~MSG_TYPE_MASK) == mgr->pending_event ) { - wake_up(&mgr->msg_sleep); - mgr->pending_event = 0; - } - /* answer to a message we did't want to wait for */ - else { - mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg; - mgr->msg_fifo_writeptr++; - mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE; - snd_mixart_process_msg(mgr); + scoped_guard(mutex, &mgr->msg_lock) { + if ((msg & ~MSG_TYPE_MASK) == mgr->pending_event) { + wake_up(&mgr->msg_sleep); + mgr->pending_event = 0; + } + /* answer to a message we did't want to wait for */ + else { + mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg; + mgr->msg_fifo_writeptr++; + mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE; + snd_mixart_process_msg(mgr); + } } - mutex_unlock(&mgr->msg_lock); break; case MSG_TYPE_REQUEST: default: @@ -556,8 +553,6 @@ irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id) /* allow interrupt again */ writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET)); - mutex_unlock(&mgr->lock); - return IRQ_HANDLED; } diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c index 2727f3345795..f4081d323340 100644 --- a/sound/pci/mixart/mixart_mixer.c +++ b/sound/pci/mixart/mixart_mixer.c @@ -344,7 +344,8 @@ static int mixart_analog_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int mixart_analog_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); if(kcontrol->private_value == 0) { /* playback */ ucontrol->value.integer.value[0] = chip->analog_playback_volume[0]; ucontrol->value.integer.value[1] = chip->analog_playback_volume[1]; @@ -352,7 +353,6 @@ static int mixart_analog_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e ucontrol->value.integer.value[0] = chip->analog_capture_volume[0]; ucontrol->value.integer.value[1] = chip->analog_capture_volume[1]; } - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -362,7 +362,7 @@ static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e int changed = 0; int is_capture, i; - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); is_capture = (kcontrol->private_value != 0); for (i = 0; i < 2; i++) { int new_volume = ucontrol->value.integer.value[i]; @@ -385,7 +385,6 @@ static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e } if (changed) mixart_update_analog_audio_level(chip, is_capture); - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -409,10 +408,9 @@ static int mixart_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ele { struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->analog_playback_active[0]; ucontrol->value.integer.value[1] = chip->analog_playback_active[1]; - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -420,7 +418,8 @@ static int mixart_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele { struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); int i, changed = 0; - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); for (i = 0; i < 2; i++) { if (chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) { @@ -431,7 +430,6 @@ static int mixart_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele } if (changed) /* update playback levels */ mixart_update_analog_audio_level(chip, 0); - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -825,7 +823,8 @@ static int mixart_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem int *stored_volume; int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK; int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); if(is_capture) { if(is_aes) stored_volume = chip->digital_capture_volume[1]; /* AES capture */ else stored_volume = chip->digital_capture_volume[0]; /* analog capture */ @@ -836,7 +835,6 @@ static int mixart_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem } ucontrol->value.integer.value[0] = stored_volume[0]; ucontrol->value.integer.value[1] = stored_volume[1]; - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -849,7 +847,8 @@ static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; int* stored_volume; int i; - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); if (is_capture) { if (is_aes) /* AES capture */ stored_volume = chip->digital_capture_volume[1]; @@ -878,7 +877,6 @@ static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem else mixart_update_playback_stream_level(chip, is_aes, idx); } - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -903,12 +901,12 @@ static int mixart_pcm_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); if(kcontrol->private_value & MIXART_VOL_AES_MASK) /* AES playback */ idx += MIXART_PLAYBACK_STREAMS; ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0]; ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1]; - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -920,7 +918,8 @@ static int mixart_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ int i, j; snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); j = idx; if (is_aes) j += MIXART_PLAYBACK_STREAMS; @@ -934,7 +933,6 @@ static int mixart_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ } if (changed) mixart_update_playback_stream_level(chip, is_aes, idx); - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -985,10 +983,10 @@ static int mixart_update_monitoring(struct snd_mixart* chip, int channel) static int mixart_monitor_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->monitoring_volume[0]; ucontrol->value.integer.value[1] = chip->monitoring_volume[1]; - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -997,7 +995,8 @@ static int mixart_monitor_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); int changed = 0; int i; - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); for (i = 0; i < 2; i++) { if (chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) { @@ -1007,7 +1006,6 @@ static int mixart_monitor_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ changed = 1; } } - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -1029,10 +1027,10 @@ static const struct snd_kcontrol_new mixart_control_monitor_vol = { static int mixart_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->monitoring_active[0]; ucontrol->value.integer.value[1] = chip->monitoring_active[1]; - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -1041,7 +1039,8 @@ static int mixart_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); int changed = 0; int i; - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); for (i = 0; i < 2; i++) { if (chip->monitoring_active[i] != ucontrol->value.integer.value[i]) { @@ -1074,7 +1073,6 @@ static int mixart_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e } } - mutex_unlock(&chip->mgr->mixer_mutex); return (changed != 0); } diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 39464d171f6b..da74b923bc88 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -446,27 +446,25 @@ snd_nm256_set_format(struct nm256 *chip, struct nm256_stream *s, /* acquire interrupt */ static int snd_nm256_acquire_irq(struct nm256 *chip) { - mutex_lock(&chip->irq_mutex); + guard(mutex)(&chip->irq_mutex); if (chip->irq < 0) { if (request_irq(chip->pci->irq, chip->interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { dev_err(chip->card->dev, "unable to grab IRQ %d\n", chip->pci->irq); - mutex_unlock(&chip->irq_mutex); return -EBUSY; } chip->irq = chip->pci->irq; chip->card->sync_irq = chip->irq; } chip->irq_acks++; - mutex_unlock(&chip->irq_mutex); return 0; } /* release interrupt */ static void snd_nm256_release_irq(struct nm256 *chip) { - mutex_lock(&chip->irq_mutex); + guard(mutex)(&chip->irq_mutex); if (chip->irq_acks > 0) chip->irq_acks--; if (chip->irq_acks == 0 && chip->irq >= 0) { @@ -474,7 +472,6 @@ static void snd_nm256_release_irq(struct nm256 *chip) chip->irq = -1; chip->card->sync_irq = -1; } - mutex_unlock(&chip->irq_mutex); } /* @@ -547,12 +544,11 @@ snd_nm256_playback_trigger(struct snd_pcm_substream *substream, int cmd) { struct nm256 *chip = snd_pcm_substream_chip(substream); struct nm256_stream *s = substream->runtime->private_data; - int err = 0; if (snd_BUG_ON(!s)) return -ENXIO; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: s->suspended = 0; @@ -573,11 +569,9 @@ snd_nm256_playback_trigger(struct snd_pcm_substream *substream, int cmd) } break; default: - err = -EINVAL; - break; + return -EINVAL; } - spin_unlock(&chip->reg_lock); - return err; + return 0; } static int @@ -585,12 +579,11 @@ snd_nm256_capture_trigger(struct snd_pcm_substream *substream, int cmd) { struct nm256 *chip = snd_pcm_substream_chip(substream); struct nm256_stream *s = substream->runtime->private_data; - int err = 0; if (snd_BUG_ON(!s)) return -ENXIO; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -607,11 +600,9 @@ snd_nm256_capture_trigger(struct snd_pcm_substream *substream, int cmd) } break; default: - err = -EINVAL; - break; + return -EINVAL; } - spin_unlock(&chip->reg_lock); - return err; + return 0; } @@ -631,10 +622,9 @@ static int snd_nm256_pcm_prepare(struct snd_pcm_substream *substream) s->periods = substream->runtime->periods; s->cur_period = 0; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); s->running = 0; snd_nm256_set_format(chip, s, substream); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -999,7 +989,7 @@ snd_nm256_interrupt(int irq, void *dev_id) /* Rather boring; check for individual interrupts and process them. */ - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); if (status & NM_PLAYBACK_INT) { status &= ~NM_PLAYBACK_INT; NM_ACK_INT(chip, NM_PLAYBACK_INT); @@ -1038,7 +1028,6 @@ snd_nm256_interrupt(int irq, void *dev_id) NM_ACK_INT(chip, status); } - spin_unlock(&chip->reg_lock); return IRQ_HANDLED; } @@ -1065,7 +1054,7 @@ snd_nm256_interrupt_zx(int irq, void *dev_id) /* Rather boring; check for individual interrupts and process them. */ - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); if (status & NM2_PLAYBACK_INT) { status &= ~NM2_PLAYBACK_INT; NM2_ACK_INT(chip, NM2_PLAYBACK_INT); @@ -1103,7 +1092,6 @@ snd_nm256_interrupt_zx(int irq, void *dev_id) NM2_ACK_INT(chip, status); } - spin_unlock(&chip->reg_lock); return IRQ_HANDLED; } @@ -1392,9 +1380,8 @@ static int nm256_resume(struct device *dev) for (i = 0; i < 2; i++) { struct nm256_stream *s = &chip->streams[i]; if (s->substream && s->suspended) { - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); snd_nm256_set_format(chip, s, s->substream); - spin_unlock_irq(&chip->reg_lock); } } diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index ff7439634d76..e6f869cf8ca2 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c @@ -450,7 +450,7 @@ static int rolloff_put(struct snd_kcontrol *ctl, int changed; u8 reg; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); reg = data->ak4396_regs[0][AK4396_CONTROL_2]; if (value->value.enumerated.item[0]) reg |= AK4396_SLOW; @@ -461,7 +461,6 @@ static int rolloff_put(struct snd_kcontrol *ctl, for (i = 0; i < data->dacs; ++i) ak4396_write(chip, i, AK4396_CONTROL_2, reg); } - mutex_unlock(&chip->mutex); return changed; } @@ -499,14 +498,13 @@ static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) unsigned int reg; int changed; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); reg = data->wm8785_regs[WM8785_R2] & ~(WM8785_HPFR | WM8785_HPFL); if (value->value.enumerated.item[0]) reg |= WM8785_HPFR | WM8785_HPFL; changed = reg != data->wm8785_regs[WM8785_R2]; if (changed) wm8785_write(chip, WM8785_R2, reg); - mutex_unlock(&chip->mutex); return changed; } @@ -563,7 +561,7 @@ static int meridian_dig_source_put(struct snd_kcontrol *ctl, u16 old_reg, new_reg; int changed; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA); new_reg = old_reg & ~GPIO_MERIDIAN_DIG_MASK; if (value->value.enumerated.item[0] == 0) @@ -573,7 +571,6 @@ static int meridian_dig_source_put(struct snd_kcontrol *ctl, changed = new_reg != old_reg; if (changed) oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg); - mutex_unlock(&chip->mutex); return changed; } @@ -584,7 +581,7 @@ static int claro_dig_source_put(struct snd_kcontrol *ctl, u16 old_reg, new_reg; int changed; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA); new_reg = old_reg & ~GPIO_CLARO_DIG_COAX; if (value->value.enumerated.item[0]) @@ -592,7 +589,6 @@ static int claro_dig_source_put(struct snd_kcontrol *ctl, changed = new_reg != old_reg; if (changed) oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg); - mutex_unlock(&chip->mutex); return changed; } diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 9c7270e4c35e..6b096d654f9f 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c @@ -59,36 +59,34 @@ static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) if (!status) return IRQ_NONE; - spin_lock(&chip->reg_lock); - - clear = status & (OXYGEN_CHANNEL_A | - OXYGEN_CHANNEL_B | - OXYGEN_CHANNEL_C | - OXYGEN_CHANNEL_SPDIF | - OXYGEN_CHANNEL_MULTICH | - OXYGEN_CHANNEL_AC97 | - OXYGEN_INT_SPDIF_IN_DETECT | - OXYGEN_INT_GPIO | - OXYGEN_INT_AC97); - if (clear) { - if (clear & OXYGEN_INT_SPDIF_IN_DETECT) - chip->interrupt_mask &= ~OXYGEN_INT_SPDIF_IN_DETECT; - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, - chip->interrupt_mask & ~clear); - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, - chip->interrupt_mask); - } - - elapsed_streams = status & chip->pcm_running; + scoped_guard(spinlock, &chip->reg_lock) { + clear = status & (OXYGEN_CHANNEL_A | + OXYGEN_CHANNEL_B | + OXYGEN_CHANNEL_C | + OXYGEN_CHANNEL_SPDIF | + OXYGEN_CHANNEL_MULTICH | + OXYGEN_CHANNEL_AC97 | + OXYGEN_INT_SPDIF_IN_DETECT | + OXYGEN_INT_GPIO | + OXYGEN_INT_AC97); + if (clear) { + if (clear & OXYGEN_INT_SPDIF_IN_DETECT) + chip->interrupt_mask &= ~OXYGEN_INT_SPDIF_IN_DETECT; + oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, + chip->interrupt_mask & ~clear); + oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, + chip->interrupt_mask); + } - spin_unlock(&chip->reg_lock); + elapsed_streams = status & chip->pcm_running; + } for (i = 0; i < PCM_COUNT; ++i) if ((elapsed_streams & (1 << i)) && chip->streams[i]) snd_pcm_period_elapsed(chip->streams[i]); if (status & OXYGEN_INT_SPDIF_IN_DETECT) { - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); i = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); if (i & (OXYGEN_SPDIF_SENSE_INT | OXYGEN_SPDIF_LOCK_INT | OXYGEN_SPDIF_RATE_INT)) { @@ -96,7 +94,6 @@ static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, i); schedule_work(&chip->spdif_input_bits_work); } - spin_unlock(&chip->reg_lock); } if (status & OXYGEN_INT_GPIO) @@ -127,45 +124,45 @@ static void oxygen_spdif_input_bits_changed(struct work_struct *work) * changes. */ msleep(1); - spin_lock_irq(&chip->reg_lock); - reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); - if ((reg & (OXYGEN_SPDIF_SENSE_STATUS | - OXYGEN_SPDIF_LOCK_STATUS)) - == OXYGEN_SPDIF_SENSE_STATUS) { - /* - * If we detect activity on the SPDIF input but cannot lock to - * a signal, the clock bit is likely to be wrong. - */ - reg ^= OXYGEN_SPDIF_IN_CLOCK_MASK; - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg); - spin_unlock_irq(&chip->reg_lock); - msleep(1); - spin_lock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); if ((reg & (OXYGEN_SPDIF_SENSE_STATUS | OXYGEN_SPDIF_LOCK_STATUS)) == OXYGEN_SPDIF_SENSE_STATUS) { - /* nothing detected with either clock; give up */ - if ((reg & OXYGEN_SPDIF_IN_CLOCK_MASK) - == OXYGEN_SPDIF_IN_CLOCK_192) { - /* - * Reset clock to <= 96 kHz because this is - * more likely to be received next time. - */ - reg &= ~OXYGEN_SPDIF_IN_CLOCK_MASK; - reg |= OXYGEN_SPDIF_IN_CLOCK_96; - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg); + /* + * If we detect activity on the SPDIF input but cannot lock to + * a signal, the clock bit is likely to be wrong. + */ + reg ^= OXYGEN_SPDIF_IN_CLOCK_MASK; + oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg); + spin_unlock_irq(&chip->reg_lock); + msleep(1); + spin_lock_irq(&chip->reg_lock); + reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); + if ((reg & (OXYGEN_SPDIF_SENSE_STATUS | + OXYGEN_SPDIF_LOCK_STATUS)) + == OXYGEN_SPDIF_SENSE_STATUS) { + /* nothing detected with either clock; give up */ + if ((reg & OXYGEN_SPDIF_IN_CLOCK_MASK) + == OXYGEN_SPDIF_IN_CLOCK_192) { + /* + * Reset clock to <= 96 kHz because this is + * more likely to be received next time. + */ + reg &= ~OXYGEN_SPDIF_IN_CLOCK_MASK; + reg |= OXYGEN_SPDIF_IN_CLOCK_96; + oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg); + } } } } - spin_unlock_irq(&chip->reg_lock); if (chip->controls[CONTROL_SPDIF_INPUT_BITS]) { - spin_lock_irq(&chip->reg_lock); - chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT; - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, - chip->interrupt_mask); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT; + oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, + chip->interrupt_mask); + } /* * We don't actually know that any channel status bits have @@ -557,12 +554,11 @@ static void oxygen_init(struct oxygen *chip) static void oxygen_shutdown(struct oxygen *chip) { - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->interrupt_mask = 0; chip->pcm_running = 0; oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); - spin_unlock_irq(&chip->reg_lock); } static void oxygen_card_free(struct snd_card *card) @@ -686,13 +682,13 @@ static int __oxygen_pci_probe(struct pci_dev *pci, int index, char *id, oxygen_proc_init(chip); - spin_lock_irq(&chip->reg_lock); - if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) - chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT; - if (chip->has_ac97_0 | chip->has_ac97_1) - chip->interrupt_mask |= OXYGEN_INT_AC97; - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) + chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT; + if (chip->has_ac97_0 | chip->has_ac97_1) + chip->interrupt_mask |= OXYGEN_INT_AC97; + oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); + } err = snd_card_register(card); if (err < 0) @@ -724,12 +720,12 @@ static int oxygen_pci_suspend(struct device *dev) if (chip->model.suspend) chip->model.suspend(chip); - spin_lock_irq(&chip->reg_lock); - saved_interrupt_mask = chip->interrupt_mask; - chip->interrupt_mask = 0; - oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + saved_interrupt_mask = chip->interrupt_mask; + chip->interrupt_mask = 0; + oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); + oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); + } flush_work(&chip->spdif_input_bits_work); flush_work(&chip->gpio_work); diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index eb3aca16359c..256a601d7811 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c @@ -31,10 +31,9 @@ static int dac_volume_get(struct snd_kcontrol *ctl, struct oxygen *chip = ctl->private_data; unsigned int i; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); for (i = 0; i < chip->model.dac_channels_mixer; ++i) value->value.integer.value[i] = chip->dac_volume[i]; - mutex_unlock(&chip->mutex); return 0; } @@ -46,7 +45,7 @@ static int dac_volume_put(struct snd_kcontrol *ctl, int changed; changed = 0; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); for (i = 0; i < chip->model.dac_channels_mixer; ++i) if (value->value.integer.value[i] != chip->dac_volume[i]) { chip->dac_volume[i] = value->value.integer.value[i]; @@ -54,7 +53,6 @@ static int dac_volume_put(struct snd_kcontrol *ctl, } if (changed) chip->model.update_dac_volume(chip); - mutex_unlock(&chip->mutex); return changed; } @@ -63,9 +61,8 @@ static int dac_mute_get(struct snd_kcontrol *ctl, { struct oxygen *chip = ctl->private_data; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); value->value.integer.value[0] = !chip->dac_mute; - mutex_unlock(&chip->mutex); return 0; } @@ -75,13 +72,12 @@ static int dac_mute_put(struct snd_kcontrol *ctl, struct oxygen *chip = ctl->private_data; int changed; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); changed = (!value->value.integer.value[0]) != chip->dac_mute; if (changed) { chip->dac_mute = !value->value.integer.value[0]; chip->model.update_dac_mute(chip); } - mutex_unlock(&chip->mutex); return changed; } @@ -114,9 +110,8 @@ static int upmix_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) { struct oxygen *chip = ctl->private_data; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); value->value.enumerated.item[0] = chip->dac_routing; - mutex_unlock(&chip->mutex); return 0; } @@ -188,13 +183,12 @@ static int upmix_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) if (value->value.enumerated.item[0] >= count) return -EINVAL; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); changed = value->value.enumerated.item[0] != chip->dac_routing; if (changed) { chip->dac_routing = value->value.enumerated.item[0]; oxygen_update_dac_routing(chip); } - mutex_unlock(&chip->mutex); return changed; } @@ -203,9 +197,8 @@ static int spdif_switch_get(struct snd_kcontrol *ctl, { struct oxygen *chip = ctl->private_data; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); value->value.integer.value[0] = chip->spdif_playback_enable; - mutex_unlock(&chip->mutex); return 0; } @@ -279,7 +272,7 @@ static int spdif_switch_put(struct snd_kcontrol *ctl, struct oxygen *chip = ctl->private_data; int changed; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); changed = value->value.integer.value[0] != chip->spdif_playback_enable; if (changed) { chip->spdif_playback_enable = !!value->value.integer.value[0]; @@ -287,7 +280,6 @@ static int spdif_switch_put(struct snd_kcontrol *ctl, oxygen_update_spdif_source(chip); spin_unlock_irq(&chip->reg_lock); } - mutex_unlock(&chip->mutex); return changed; } @@ -336,9 +328,8 @@ static int spdif_default_get(struct snd_kcontrol *ctl, { struct oxygen *chip = ctl->private_data; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); oxygen_to_iec958(chip->spdif_bits, value); - mutex_unlock(&chip->mutex); return 0; } @@ -350,14 +341,13 @@ static int spdif_default_put(struct snd_kcontrol *ctl, int changed; new_bits = iec958_to_oxygen(value); - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); changed = new_bits != chip->spdif_bits; if (changed) { chip->spdif_bits = new_bits; if (!(chip->pcm_active & (1 << PCM_SPDIF))) write_spdif_bits(chip, new_bits); } - mutex_unlock(&chip->mutex); return changed; } @@ -376,9 +366,8 @@ static int spdif_pcm_get(struct snd_kcontrol *ctl, { struct oxygen *chip = ctl->private_data; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); oxygen_to_iec958(chip->spdif_pcm_bits, value); - mutex_unlock(&chip->mutex); return 0; } @@ -390,14 +379,13 @@ static int spdif_pcm_put(struct snd_kcontrol *ctl, int changed; new_bits = iec958_to_oxygen(value); - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); changed = new_bits != chip->spdif_pcm_bits; if (changed) { chip->spdif_pcm_bits = new_bits; if (chip->pcm_active & (1 << PCM_SPDIF)) write_spdif_bits(chip, new_bits); } - mutex_unlock(&chip->mutex); return changed; } @@ -444,7 +432,7 @@ static int spdif_bit_switch_put(struct snd_kcontrol *ctl, u32 oldreg, newreg; int changed; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); oldreg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); if (value->value.integer.value[0]) newreg = oldreg | bit; @@ -453,7 +441,6 @@ static int spdif_bit_switch_put(struct snd_kcontrol *ctl, changed = newreg != oldreg; if (changed) oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, newreg); - spin_unlock_irq(&chip->reg_lock); return changed; } @@ -488,7 +475,7 @@ static int monitor_put(struct snd_kcontrol *ctl, u8 oldreg, newreg; int changed; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); oldreg = oxygen_read8(chip, OXYGEN_ADC_MONITOR); if ((!!value->value.integer.value[0] ^ !!invert) != 0) newreg = oldreg | bit; @@ -497,7 +484,6 @@ static int monitor_put(struct snd_kcontrol *ctl, changed = newreg != oldreg; if (changed) oxygen_write8(chip, OXYGEN_ADC_MONITOR, newreg); - spin_unlock_irq(&chip->reg_lock); return changed; } @@ -511,9 +497,8 @@ static int ac97_switch_get(struct snd_kcontrol *ctl, int invert = ctl->private_value & (1 << 16); u16 reg; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); reg = oxygen_read_ac97(chip, codec, index); - mutex_unlock(&chip->mutex); if (!(reg & (1 << bitnr)) ^ !invert) value->value.integer.value[0] = 1; else @@ -550,7 +535,7 @@ static int ac97_switch_put(struct snd_kcontrol *ctl, u16 oldreg, newreg; int change; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); oldreg = oxygen_read_ac97(chip, codec, index); newreg = oldreg; if (!value->value.integer.value[0] ^ !invert) @@ -579,7 +564,6 @@ static int ac97_switch_put(struct snd_kcontrol *ctl, CM9780_GPO0, CM9780_GPO0); } } - mutex_unlock(&chip->mutex); return change; } @@ -604,9 +588,8 @@ static int ac97_volume_get(struct snd_kcontrol *ctl, unsigned int index = ctl->private_value & 0xff; u16 reg; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); reg = oxygen_read_ac97(chip, codec, index); - mutex_unlock(&chip->mutex); if (!stereo) { value->value.integer.value[0] = 31 - (reg & 0x1f); } else { @@ -626,7 +609,7 @@ static int ac97_volume_put(struct snd_kcontrol *ctl, u16 oldreg, newreg; int change; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); oldreg = oxygen_read_ac97(chip, codec, index); if (!stereo) { newreg = oldreg & ~0x1f; @@ -639,7 +622,6 @@ static int ac97_volume_put(struct snd_kcontrol *ctl, change = newreg != oldreg; if (change) oxygen_write_ac97(chip, codec, index, newreg); - mutex_unlock(&chip->mutex); return change; } @@ -656,10 +638,9 @@ static int mic_fmic_source_get(struct snd_kcontrol *ctl, { struct oxygen *chip = ctl->private_data; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); value->value.enumerated.item[0] = !!(oxygen_read_ac97(chip, 0, CM9780_JACK) & CM9780_FMIC2MIC); - mutex_unlock(&chip->mutex); return 0; } @@ -670,7 +651,7 @@ static int mic_fmic_source_put(struct snd_kcontrol *ctl, u16 oldreg, newreg; int change; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); oldreg = oxygen_read_ac97(chip, 0, CM9780_JACK); if (value->value.enumerated.item[0]) newreg = oldreg | CM9780_FMIC2MIC; @@ -679,7 +660,6 @@ static int mic_fmic_source_put(struct snd_kcontrol *ctl, change = newreg != oldreg; if (change) oxygen_write_ac97(chip, 0, CM9780_JACK, newreg); - mutex_unlock(&chip->mutex); return change; } @@ -699,9 +679,8 @@ static int ac97_fp_rec_volume_get(struct snd_kcontrol *ctl, struct oxygen *chip = ctl->private_data; u16 reg; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); reg = oxygen_read_ac97(chip, 1, AC97_REC_GAIN); - mutex_unlock(&chip->mutex); value->value.integer.value[0] = reg & 7; value->value.integer.value[1] = (reg >> 8) & 7; return 0; @@ -714,7 +693,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl, u16 oldreg, newreg; int change; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); oldreg = oxygen_read_ac97(chip, 1, AC97_REC_GAIN); newreg = oldreg & ~0x0707; newreg = newreg | (value->value.integer.value[0] & 7); @@ -722,7 +701,6 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl, change = newreg != oldreg; if (change) oxygen_write_ac97(chip, 1, AC97_REC_GAIN, newreg); - mutex_unlock(&chip->mutex); return change; } diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c index 643141f345bb..b716356010b8 100644 --- a/sound/pci/oxygen/oxygen_pcm.c +++ b/sound/pci/oxygen/oxygen_pcm.c @@ -171,7 +171,7 @@ static int oxygen_open(struct snd_pcm_substream *substream, snd_pcm_set_sync(substream); chip->streams[channel] = substream; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); chip->pcm_active |= 1 << channel; if (channel == PCM_SPDIF) { chip->spdif_pcm_bits = chip->spdif_bits; @@ -181,7 +181,6 @@ static int oxygen_open(struct snd_pcm_substream *substream, SNDRV_CTL_EVENT_MASK_INFO, &chip->controls[CONTROL_SPDIF_PCM]->id); } - mutex_unlock(&chip->mutex); return 0; } @@ -221,7 +220,7 @@ static int oxygen_close(struct snd_pcm_substream *substream) struct oxygen *chip = snd_pcm_substream_chip(substream); unsigned int channel = oxygen_substream_channel(substream); - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); chip->pcm_active &= ~(1 << channel); if (channel == PCM_SPDIF) { chip->controls[CONTROL_SPDIF_PCM]->vd[0].access |= @@ -232,7 +231,6 @@ static int oxygen_close(struct snd_pcm_substream *substream) } if (channel == PCM_SPDIF || channel == PCM_MULTICH) oxygen_update_spdif_source(chip); - mutex_unlock(&chip->mutex); chip->streams[channel] = NULL; return 0; @@ -351,24 +349,23 @@ static int oxygen_rec_a_hw_params(struct snd_pcm_substream *substream, if (err < 0) return err; - spin_lock_irq(&chip->reg_lock); - oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, - oxygen_format(hw_params) << OXYGEN_REC_FORMAT_A_SHIFT, - OXYGEN_REC_FORMAT_A_MASK); - oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, - oxygen_rate(hw_params) | - chip->model.adc_i2s_format | - get_mclk(chip, PCM_A, hw_params) | - oxygen_i2s_bits(hw_params), - OXYGEN_I2S_RATE_MASK | - OXYGEN_I2S_FORMAT_MASK | - OXYGEN_I2S_MCLK_MASK | - OXYGEN_I2S_BITS_MASK); - spin_unlock_irq(&chip->reg_lock); - - mutex_lock(&chip->mutex); + scoped_guard(spinlock_irq, &chip->reg_lock) { + oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, + oxygen_format(hw_params) << OXYGEN_REC_FORMAT_A_SHIFT, + OXYGEN_REC_FORMAT_A_MASK); + oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, + oxygen_rate(hw_params) | + chip->model.adc_i2s_format | + get_mclk(chip, PCM_A, hw_params) | + oxygen_i2s_bits(hw_params), + OXYGEN_I2S_RATE_MASK | + OXYGEN_I2S_FORMAT_MASK | + OXYGEN_I2S_MCLK_MASK | + OXYGEN_I2S_BITS_MASK); + } + + guard(mutex)(&chip->mutex); chip->model.set_adc_params(chip, hw_params); - mutex_unlock(&chip->mutex); return 0; } @@ -386,26 +383,25 @@ static int oxygen_rec_b_hw_params(struct snd_pcm_substream *substream, is_ac97 = chip->has_ac97_1 && (chip->model.device_config & CAPTURE_2_FROM_AC97_1); - spin_lock_irq(&chip->reg_lock); - oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, - oxygen_format(hw_params) << OXYGEN_REC_FORMAT_B_SHIFT, - OXYGEN_REC_FORMAT_B_MASK); - if (!is_ac97) - oxygen_write16_masked(chip, OXYGEN_I2S_B_FORMAT, - oxygen_rate(hw_params) | - chip->model.adc_i2s_format | - get_mclk(chip, PCM_B, hw_params) | - oxygen_i2s_bits(hw_params), - OXYGEN_I2S_RATE_MASK | - OXYGEN_I2S_FORMAT_MASK | - OXYGEN_I2S_MCLK_MASK | - OXYGEN_I2S_BITS_MASK); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, + oxygen_format(hw_params) << OXYGEN_REC_FORMAT_B_SHIFT, + OXYGEN_REC_FORMAT_B_MASK); + if (!is_ac97) + oxygen_write16_masked(chip, OXYGEN_I2S_B_FORMAT, + oxygen_rate(hw_params) | + chip->model.adc_i2s_format | + get_mclk(chip, PCM_B, hw_params) | + oxygen_i2s_bits(hw_params), + OXYGEN_I2S_RATE_MASK | + OXYGEN_I2S_FORMAT_MASK | + OXYGEN_I2S_MCLK_MASK | + OXYGEN_I2S_BITS_MASK); + } if (!is_ac97) { - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); chip->model.set_adc_params(chip, hw_params); - mutex_unlock(&chip->mutex); } return 0; } @@ -423,26 +419,25 @@ static int oxygen_rec_c_hw_params(struct snd_pcm_substream *substream, is_spdif = chip->model.device_config & CAPTURE_1_FROM_SPDIF; - spin_lock_irq(&chip->reg_lock); - oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, - oxygen_format(hw_params) << OXYGEN_REC_FORMAT_C_SHIFT, - OXYGEN_REC_FORMAT_C_MASK); - if (!is_spdif) - oxygen_write16_masked(chip, OXYGEN_I2S_C_FORMAT, - oxygen_rate(hw_params) | - chip->model.adc_i2s_format | - get_mclk(chip, PCM_B, hw_params) | - oxygen_i2s_bits(hw_params), - OXYGEN_I2S_RATE_MASK | - OXYGEN_I2S_FORMAT_MASK | - OXYGEN_I2S_MCLK_MASK | - OXYGEN_I2S_BITS_MASK); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, + oxygen_format(hw_params) << OXYGEN_REC_FORMAT_C_SHIFT, + OXYGEN_REC_FORMAT_C_MASK); + if (!is_spdif) + oxygen_write16_masked(chip, OXYGEN_I2S_C_FORMAT, + oxygen_rate(hw_params) | + chip->model.adc_i2s_format | + get_mclk(chip, PCM_B, hw_params) | + oxygen_i2s_bits(hw_params), + OXYGEN_I2S_RATE_MASK | + OXYGEN_I2S_FORMAT_MASK | + OXYGEN_I2S_MCLK_MASK | + OXYGEN_I2S_BITS_MASK); + } if (!is_spdif) { - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); chip->model.set_adc_params(chip, hw_params); - mutex_unlock(&chip->mutex); } return 0; } @@ -457,8 +452,8 @@ static int oxygen_spdif_hw_params(struct snd_pcm_substream *substream, if (err < 0) return err; - mutex_lock(&chip->mutex); - spin_lock_irq(&chip->reg_lock); + guard(mutex)(&chip->mutex); + guard(spinlock_irq)(&chip->reg_lock); oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, OXYGEN_SPDIF_OUT_ENABLE); oxygen_write8_masked(chip, OXYGEN_PLAY_FORMAT, @@ -468,8 +463,6 @@ static int oxygen_spdif_hw_params(struct snd_pcm_substream *substream, oxygen_rate(hw_params) << OXYGEN_SPDIF_OUT_RATE_SHIFT, OXYGEN_SPDIF_OUT_RATE_MASK); oxygen_update_spdif_source(chip); - spin_unlock_irq(&chip->reg_lock); - mutex_unlock(&chip->mutex); return 0; } @@ -483,29 +476,28 @@ static int oxygen_multich_hw_params(struct snd_pcm_substream *substream, if (err < 0) return err; - mutex_lock(&chip->mutex); - spin_lock_irq(&chip->reg_lock); - oxygen_write8_masked(chip, OXYGEN_PLAY_CHANNELS, - oxygen_play_channels(hw_params), - OXYGEN_PLAY_CHANNELS_MASK); - oxygen_write8_masked(chip, OXYGEN_PLAY_FORMAT, - oxygen_format(hw_params) << OXYGEN_MULTICH_FORMAT_SHIFT, - OXYGEN_MULTICH_FORMAT_MASK); - oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, - oxygen_rate(hw_params) | - chip->model.dac_i2s_format | - get_mclk(chip, PCM_MULTICH, hw_params) | - oxygen_i2s_bits(hw_params), - OXYGEN_I2S_RATE_MASK | - OXYGEN_I2S_FORMAT_MASK | - OXYGEN_I2S_MCLK_MASK | - OXYGEN_I2S_BITS_MASK); - oxygen_update_spdif_source(chip); - spin_unlock_irq(&chip->reg_lock); + guard(mutex)(&chip->mutex); + scoped_guard(spinlock_irq, &chip->reg_lock) { + oxygen_write8_masked(chip, OXYGEN_PLAY_CHANNELS, + oxygen_play_channels(hw_params), + OXYGEN_PLAY_CHANNELS_MASK); + oxygen_write8_masked(chip, OXYGEN_PLAY_FORMAT, + oxygen_format(hw_params) << OXYGEN_MULTICH_FORMAT_SHIFT, + OXYGEN_MULTICH_FORMAT_MASK); + oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, + oxygen_rate(hw_params) | + chip->model.dac_i2s_format | + get_mclk(chip, PCM_MULTICH, hw_params) | + oxygen_i2s_bits(hw_params), + OXYGEN_I2S_RATE_MASK | + OXYGEN_I2S_FORMAT_MASK | + OXYGEN_I2S_MCLK_MASK | + OXYGEN_I2S_BITS_MASK); + oxygen_update_spdif_source(chip); + } chip->model.set_dac_params(chip, hw_params); oxygen_update_dac_routing(chip); - mutex_unlock(&chip->mutex); return 0; } @@ -515,13 +507,12 @@ static int oxygen_hw_free(struct snd_pcm_substream *substream) unsigned int channel = oxygen_substream_channel(substream); unsigned int channel_mask = 1 << channel; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->interrupt_mask &= ~channel_mask; oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); oxygen_set_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); oxygen_clear_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -530,10 +521,10 @@ static int oxygen_spdif_hw_free(struct snd_pcm_substream *substream) { struct oxygen *chip = snd_pcm_substream_chip(substream); - spin_lock_irq(&chip->reg_lock); - oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, - OXYGEN_SPDIF_OUT_ENABLE); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, + OXYGEN_SPDIF_OUT_ENABLE); + } return oxygen_hw_free(substream); } @@ -543,7 +534,7 @@ static int oxygen_prepare(struct snd_pcm_substream *substream) unsigned int channel = oxygen_substream_channel(substream); unsigned int channel_mask = 1 << channel; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); oxygen_set_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); oxygen_clear_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); @@ -552,7 +543,6 @@ static int oxygen_prepare(struct snd_pcm_substream *substream) else chip->interrupt_mask |= channel_mask; oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -584,7 +574,7 @@ static int oxygen_trigger(struct snd_pcm_substream *substream, int cmd) } } - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); if (!pausing) { if (cmd == SNDRV_PCM_TRIGGER_START) chip->pcm_running |= mask; @@ -597,7 +587,6 @@ static int oxygen_trigger(struct snd_pcm_substream *substream, int cmd) else oxygen_clear_bits8(chip, OXYGEN_DMA_PAUSE, mask); } - spin_unlock(&chip->reg_lock); return 0; } diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c index 664b7759dd62..47b2758653e4 100644 --- a/sound/pci/oxygen/xonar_cs43xx.c +++ b/sound/pci/oxygen/xonar_cs43xx.c @@ -309,7 +309,7 @@ static int rolloff_put(struct snd_kcontrol *ctl, int changed; u8 reg; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); reg = data->cs4398_regs[7]; if (value->value.enumerated.item[0]) reg |= CS4398_FILT_SEL; @@ -324,7 +324,6 @@ static int rolloff_put(struct snd_kcontrol *ctl, reg = data->cs4362a_regs[0x04] & ~CS4362A_FILT_SEL; cs4362a_write(chip, 0x04, reg); } - mutex_unlock(&chip->mutex); return changed; } @@ -340,11 +339,10 @@ static void xonar_d1_line_mic_ac97_switch(struct oxygen *chip, unsigned int reg, unsigned int mute) { if (reg == AC97_LINE) { - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, mute ? GPIO_D1_INPUT_ROUTE : 0, GPIO_D1_INPUT_ROUTE); - spin_unlock_irq(&chip->reg_lock); } } diff --git a/sound/pci/oxygen/xonar_dg_mixer.c b/sound/pci/oxygen/xonar_dg_mixer.c index 198588562880..2179ff8e4d86 100644 --- a/sound/pci/oxygen/xonar_dg_mixer.c +++ b/sound/pci/oxygen/xonar_dg_mixer.c @@ -62,9 +62,8 @@ static int output_select_get(struct snd_kcontrol *ctl, struct oxygen *chip = ctl->private_data; struct dg *data = chip->model_data; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); value->value.enumerated.item[0] = data->output_sel; - mutex_unlock(&chip->mutex); return 0; } @@ -77,14 +76,13 @@ static int output_select_put(struct snd_kcontrol *ctl, int changed = 0; int ret; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); if (data->output_sel != new) { data->output_sel = new; ret = output_select_apply(chip); changed = ret >= 0 ? 1 : ret; oxygen_update_dac_routing(chip); } - mutex_unlock(&chip->mutex); return changed; } @@ -108,12 +106,11 @@ static int hp_stereo_volume_get(struct snd_kcontrol *ctl, struct dg *data = chip->model_data; unsigned int tmp; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); tmp = (~data->cs4245_shadow[CS4245_DAC_A_CTRL]) & 255; val->value.integer.value[0] = tmp; tmp = (~data->cs4245_shadow[CS4245_DAC_B_CTRL]) & 255; val->value.integer.value[1] = tmp; - mutex_unlock(&chip->mutex); return 0; } @@ -130,7 +127,7 @@ static int hp_stereo_volume_put(struct snd_kcontrol *ctl, if ((new1 > 255) || (new1 < 0) || (new2 > 255) || (new2 < 0)) return -EINVAL; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); if ((data->cs4245_shadow[CS4245_DAC_A_CTRL] != ~new1) || (data->cs4245_shadow[CS4245_DAC_B_CTRL] != ~new2)) { data->cs4245_shadow[CS4245_DAC_A_CTRL] = ~new1; @@ -140,7 +137,6 @@ static int hp_stereo_volume_put(struct snd_kcontrol *ctl, ret = cs4245_write_spi(chip, CS4245_DAC_B_CTRL); changed = ret >= 0 ? 1 : ret; } - mutex_unlock(&chip->mutex); return changed; } @@ -153,10 +149,9 @@ static int hp_mute_get(struct snd_kcontrol *ctl, struct oxygen *chip = ctl->private_data; struct dg *data = chip->model_data; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); val->value.integer.value[0] = !(data->cs4245_shadow[CS4245_DAC_CTRL_1] & CS4245_MUTE_DAC); - mutex_unlock(&chip->mutex); return 0; } @@ -170,13 +165,12 @@ static int hp_mute_put(struct snd_kcontrol *ctl, if (val->value.integer.value[0] > 1) return -EINVAL; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); data->cs4245_shadow[CS4245_DAC_CTRL_1] &= ~CS4245_MUTE_DAC; data->cs4245_shadow[CS4245_DAC_CTRL_1] |= (~val->value.integer.value[0] << 2) & CS4245_MUTE_DAC; ret = cs4245_write_spi(chip, CS4245_DAC_CTRL_1); changed = ret >= 0 ? 1 : ret; - mutex_unlock(&chip->mutex); return changed; } @@ -212,10 +206,9 @@ static int input_vol_get(struct snd_kcontrol *ctl, struct dg *data = chip->model_data; unsigned int idx = ctl->private_value; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); value->value.integer.value[0] = data->input_vol[idx][0]; value->value.integer.value[1] = data->input_vol[idx][1]; - mutex_unlock(&chip->mutex); return 0; } @@ -233,7 +226,7 @@ static int input_vol_put(struct snd_kcontrol *ctl, value->value.integer.value[1] < 2 * -12 || value->value.integer.value[1] > 2 * 12) return -EINVAL; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); changed = data->input_vol[idx][0] != value->value.integer.value[0] || data->input_vol[idx][1] != value->value.integer.value[1]; if (changed) { @@ -246,7 +239,6 @@ static int input_vol_put(struct snd_kcontrol *ctl, } changed = ret >= 0 ? 1 : ret; } - mutex_unlock(&chip->mutex); return changed; } @@ -282,9 +274,8 @@ static int input_sel_get(struct snd_kcontrol *ctl, struct oxygen *chip = ctl->private_data; struct dg *data = chip->model_data; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); value->value.enumerated.item[0] = data->input_sel; - mutex_unlock(&chip->mutex); return 0; } @@ -299,7 +290,7 @@ static int input_sel_put(struct snd_kcontrol *ctl, if (value->value.enumerated.item[0] > 3) return -EINVAL; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); changed = value->value.enumerated.item[0] != data->input_sel; if (changed) { data->input_sel = value->value.enumerated.item[0]; @@ -311,7 +302,6 @@ static int input_sel_put(struct snd_kcontrol *ctl, data->input_vol[data->input_sel][1]); changed = ret >= 0 ? 1 : ret; } - mutex_unlock(&chip->mutex); return changed; } @@ -341,7 +331,7 @@ static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) u8 reg; int changed; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); reg = data->cs4245_shadow[CS4245_ADC_CTRL] & ~CS4245_HPF_FREEZE; if (value->value.enumerated.item[0]) reg |= CS4245_HPF_FREEZE; @@ -350,7 +340,6 @@ static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) data->cs4245_shadow[CS4245_ADC_CTRL] = reg; cs4245_write_spi(chip, CS4245_ADC_CTRL); } - mutex_unlock(&chip->mutex); return changed; } diff --git a/sound/pci/oxygen/xonar_lib.c b/sound/pci/oxygen/xonar_lib.c index e951f5478075..0edf67ce37d1 100644 --- a/sound/pci/oxygen/xonar_lib.c +++ b/sound/pci/oxygen/xonar_lib.c @@ -109,7 +109,7 @@ int xonar_gpio_bit_switch_put(struct snd_kcontrol *ctl, u16 old_bits, new_bits; int changed; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); if (!!value->value.integer.value[0] ^ invert) new_bits = old_bits | bit; @@ -118,6 +118,5 @@ int xonar_gpio_bit_switch_put(struct snd_kcontrol *ctl, changed = new_bits != old_bits; if (changed) oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits); - spin_unlock_irq(&chip->reg_lock); return changed; } diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index cf801a235df9..837a9505382a 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c @@ -762,7 +762,7 @@ static int rolloff_put(struct snd_kcontrol *ctl, int changed; u8 reg; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); reg = data->pcm1796_regs[0][19 - PCM1796_REG_BASE]; reg &= ~PCM1796_FLT_MASK; if (!value->value.enumerated.item[0]) @@ -774,7 +774,6 @@ static int rolloff_put(struct snd_kcontrol *ctl, for (i = 0; i < data->dacs; ++i) pcm1796_write(chip, i, 19, reg); } - mutex_unlock(&chip->mutex); return changed; } @@ -806,7 +805,7 @@ static int deemph_put(struct snd_kcontrol *ctl, int changed; u8 reg; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); reg = data->pcm1796_regs[0][18 - PCM1796_REG_BASE]; if (!value->value.integer.value[0]) reg &= ~PCM1796_DME; @@ -817,7 +816,6 @@ static int deemph_put(struct snd_kcontrol *ctl, for (i = 0; i < data->dacs; ++i) pcm1796_write(chip, i, 18, reg); } - mutex_unlock(&chip->mutex); return changed; } @@ -872,7 +870,7 @@ static int st_output_switch_put(struct snd_kcontrol *ctl, struct xonar_pcm179x *data = chip->model_data; u16 gpio_old, gpio; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA); gpio = gpio_old; switch (value->value.enumerated.item[0]) { @@ -889,7 +887,6 @@ static int st_output_switch_put(struct snd_kcontrol *ctl, oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio); data->hp_active = gpio & GPIO_ST_HP; update_pcm1796_volume(chip); - mutex_unlock(&chip->mutex); return gpio != gpio_old; } @@ -909,7 +906,7 @@ static int st_hp_volume_offset_get(struct snd_kcontrol *ctl, struct oxygen *chip = ctl->private_data; struct xonar_pcm179x *data = chip->model_data; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); if (data->hp_gain_offset < 2*-12) value->value.enumerated.item[0] = 0; else if (data->hp_gain_offset < 2*-6) @@ -918,7 +915,6 @@ static int st_hp_volume_offset_get(struct snd_kcontrol *ctl, value->value.enumerated.item[0] = 2; else value->value.enumerated.item[0] = 3; - mutex_unlock(&chip->mutex); return 0; } @@ -935,13 +931,12 @@ static int st_hp_volume_offset_put(struct snd_kcontrol *ctl, if (value->value.enumerated.item[0] > 3) return -EINVAL; offset = offsets[value->value.enumerated.item[0]]; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); changed = offset != data->hp_gain_offset; if (changed) { data->hp_gain_offset = offset; update_pcm1796_volume(chip); } - mutex_unlock(&chip->mutex); return changed; } @@ -985,7 +980,7 @@ static int xense_output_switch_put(struct snd_kcontrol *ctl, struct xonar_pcm179x *data = chip->model_data; u16 gpio_old, gpio; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA); gpio = gpio_old; switch (value->value.enumerated.item[0]) { @@ -1002,7 +997,6 @@ static int xense_output_switch_put(struct snd_kcontrol *ctl, oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio); data->hp_active = !(gpio & GPIO_XENSE_SPEAKERS); update_pcm1796_volume(chip); - mutex_unlock(&chip->mutex); return gpio != gpio_old; } @@ -1027,11 +1021,10 @@ static void xonar_line_mic_ac97_switch(struct oxygen *chip, unsigned int reg, unsigned int mute) { if (reg == AC97_LINE) { - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, mute ? GPIO_INPUT_ROUTE : 0, GPIO_INPUT_ROUTE); - spin_unlock_irq(&chip->reg_lock); } } diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index 8aa92f3e5ee8..7d92e6e20c39 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c @@ -237,7 +237,7 @@ static void xonar_ds_handle_hp_jack(struct oxygen *chip) bool hp_plugged; unsigned int reg; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DS_HP_DETECT); @@ -252,8 +252,6 @@ static void xonar_ds_handle_hp_jack(struct oxygen *chip) wm8766_write_cached(chip, WM8766_DAC_CTRL, reg); snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0); - - mutex_unlock(&chip->mutex); } static void xonar_ds_init(struct oxygen *chip) @@ -521,14 +519,13 @@ static int wm8776_bit_switch_put(struct snd_kcontrol *ctl, bool invert = (ctl->private_value >> 24) & 1; int changed; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); reg_value = data->wm8776_regs[reg_index] & ~bit; if (value->value.integer.value[0] ^ invert) reg_value |= bit; changed = reg_value != data->wm8776_regs[reg_index]; if (changed) wm8776_write(chip, reg_index, reg_value); - mutex_unlock(&chip->mutex); return changed; } @@ -648,13 +645,12 @@ static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value) max = (ctl->private_value >> 12) & 0xf; if (value < min || value > max) return -EINVAL; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); changed = value != (ctl->private_value & 0xf); if (changed) { ctl->private_value = (ctl->private_value & ~0xf) | value; wm8776_field_set_from_ctl(ctl); } - mutex_unlock(&chip->mutex); return changed; } @@ -700,12 +696,11 @@ static int wm8776_hp_vol_get(struct snd_kcontrol *ctl, struct oxygen *chip = ctl->private_data; struct xonar_wm87x6 *data = chip->model_data; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); value->value.integer.value[0] = data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK; value->value.integer.value[1] = data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK; - mutex_unlock(&chip->mutex); return 0; } @@ -716,7 +711,7 @@ static int wm8776_hp_vol_put(struct snd_kcontrol *ctl, struct xonar_wm87x6 *data = chip->model_data; u8 to_update; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); to_update = (value->value.integer.value[0] != (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK)) << 0; @@ -744,7 +739,6 @@ static int wm8776_hp_vol_put(struct snd_kcontrol *ctl, value->value.integer.value[1] | WM8776_HPZCEN | WM8776_UPDATE); } - mutex_unlock(&chip->mutex); return to_update != 0; } @@ -770,7 +764,7 @@ static int wm8776_input_mux_put(struct snd_kcontrol *ctl, u16 reg; int changed; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); reg = data->wm8776_regs[WM8776_ADCMUX]; if (value->value.integer.value[0]) { reg |= mux_bit; @@ -794,7 +788,6 @@ static int wm8776_input_mux_put(struct snd_kcontrol *ctl, GPIO_DS_INPUT_ROUTE); wm8776_write(chip, WM8776_ADCMUX, reg); } - mutex_unlock(&chip->mutex); return changed; } @@ -814,12 +807,11 @@ static int wm8776_input_vol_get(struct snd_kcontrol *ctl, struct oxygen *chip = ctl->private_data; struct xonar_wm87x6 *data = chip->model_data; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); value->value.integer.value[0] = data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK; value->value.integer.value[1] = data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK; - mutex_unlock(&chip->mutex); return 0; } @@ -830,7 +822,7 @@ static int wm8776_input_vol_put(struct snd_kcontrol *ctl, struct xonar_wm87x6 *data = chip->model_data; int changed = 0; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); changed = (value->value.integer.value[0] != (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) || (value->value.integer.value[1] != @@ -839,7 +831,6 @@ static int wm8776_input_vol_put(struct snd_kcontrol *ctl, value->value.integer.value[0] | WM8776_ZCA); wm8776_write_cached(chip, WM8776_ADCRVOL, value->value.integer.value[1] | WM8776_ZCA); - mutex_unlock(&chip->mutex); return changed; } @@ -895,7 +886,7 @@ static int wm8776_level_control_put(struct snd_kcontrol *ctl, if (value->value.enumerated.item[0] >= 3) return -EINVAL; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); changed = value->value.enumerated.item[0] != ctl->private_value; if (changed) { ctl->private_value = value->value.enumerated.item[0]; @@ -926,7 +917,6 @@ static int wm8776_level_control_put(struct snd_kcontrol *ctl, for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i) activate_control(chip, data->lc_controls[i], mode); } - mutex_unlock(&chip->mutex); return changed; } @@ -956,14 +946,13 @@ static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) unsigned int reg; int changed; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD; if (!value->value.enumerated.item[0]) reg |= WM8776_ADCHPD; changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL]; if (changed) wm8776_write(chip, WM8776_ADCIFCTRL, reg); - mutex_unlock(&chip->mutex); return changed; } diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index bfd84c50e981..83066d08367e 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -701,7 +701,7 @@ static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr) start_time = ktime_get(); #endif - mutex_lock(&mgr->setup_mutex); + guard(mutex)(&mgr->setup_mutex); /* check the pipes concerned and build pipe_array */ for (i = 0; i < mgr->num_cards; i++) { @@ -720,7 +720,6 @@ static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr) } } if (capture_mask == 0 && playback_mask == 0) { - mutex_unlock(&mgr->setup_mutex); dev_err(&mgr->pci->dev, "%s : no pipes\n", __func__); return; } @@ -731,7 +730,6 @@ static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr) /* synchronous stop of all the pipes concerned */ err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0); if (err) { - mutex_unlock(&mgr->setup_mutex); dev_err(&mgr->pci->dev, "%s : " "error stop pipes (P%x C%x)\n", __func__, playback_mask, capture_mask); @@ -776,7 +774,6 @@ static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr) /* synchronous start of all the pipes concerned */ err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1); if (err) { - mutex_unlock(&mgr->setup_mutex); dev_err(&mgr->pci->dev, "%s : " "error start pipes (P%x C%x)\n", __func__, playback_mask, capture_mask); @@ -786,7 +783,7 @@ static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr) /* put the streams into the running state now * (increment pointer by interrupt) */ - mutex_lock(&mgr->lock); + guard(mutex)(&mgr->lock); for ( i =0; i < mgr->num_cards; i++) { struct pcxhr_stream *stream; chip = mgr->chip[i]; @@ -804,9 +801,6 @@ static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr) } } } - mutex_unlock(&mgr->lock); - - mutex_unlock(&mgr->setup_mutex); #ifdef CONFIG_SND_DEBUG_VERBOSE stop_time = ktime_get(); @@ -907,7 +901,7 @@ static int pcxhr_prepare(struct snd_pcm_substream *subs) subs->runtime->period_size, subs->runtime->periods, subs->runtime->buffer_size); - mutex_lock(&mgr->setup_mutex); + guard(mutex)(&mgr->setup_mutex); do { /* only the first stream can choose the sample rate */ @@ -923,8 +917,6 @@ static int pcxhr_prepare(struct snd_pcm_substream *subs) } } while(0); /* do only once (so we can use break instead of goto) */ - mutex_unlock(&mgr->setup_mutex); - return err; } @@ -939,15 +931,13 @@ static int pcxhr_hw_params(struct snd_pcm_substream *subs, struct pcxhr_mgr *mgr = chip->mgr; struct pcxhr_stream *stream = subs->runtime->private_data; - mutex_lock(&mgr->setup_mutex); + guard(mutex)(&mgr->setup_mutex); /* set up channels */ stream->channels = params_channels(hw); /* set up format for the stream */ stream->format = params_format(hw); - mutex_unlock(&mgr->setup_mutex); - return 0; } @@ -990,7 +980,7 @@ static int pcxhr_open(struct snd_pcm_substream *subs) struct pcxhr_stream *stream; int err; - mutex_lock(&mgr->setup_mutex); + guard(mutex)(&mgr->setup_mutex); /* copy the struct snd_pcm_hardware struct */ runtime->hw = pcxhr_caps; @@ -1012,7 +1002,6 @@ static int pcxhr_open(struct snd_pcm_substream *subs) /* streams in use */ dev_err(chip->card->dev, "%s chip%d subs%d in use\n", __func__, chip->chip_idx, subs->number); - mutex_unlock(&mgr->setup_mutex); return -EBUSY; } @@ -1023,10 +1012,8 @@ static int pcxhr_open(struct snd_pcm_substream *subs) /* buffer-size should better be multiple of period-size */ err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) { - mutex_unlock(&mgr->setup_mutex); + if (err < 0) return err; - } /* if a sample rate is already used or fixed by external clock, * the stream cannot change @@ -1040,7 +1027,6 @@ static int pcxhr_open(struct snd_pcm_substream *subs) &external_rate) || external_rate == 0) { /* cannot detect the external clock rate */ - mutex_unlock(&mgr->setup_mutex); return -EBUSY; } runtime->hw.rate_min = external_rate; @@ -1063,7 +1049,6 @@ static int pcxhr_open(struct snd_pcm_substream *subs) mgr->ref_count_rate++; - mutex_unlock(&mgr->setup_mutex); return 0; } @@ -1074,7 +1059,7 @@ static int pcxhr_close(struct snd_pcm_substream *subs) struct pcxhr_mgr *mgr = chip->mgr; struct pcxhr_stream *stream = subs->runtime->private_data; - mutex_lock(&mgr->setup_mutex); + guard(mutex)(&mgr->setup_mutex); dev_dbg(chip->card->dev, "%s chip%d subs%d\n", __func__, chip->chip_idx, subs->number); @@ -1088,8 +1073,6 @@ static int pcxhr_close(struct snd_pcm_substream *subs) stream->status = PCXHR_STREAM_STATUS_FREE; stream->substream = NULL; - mutex_unlock(&mgr->setup_mutex); - return 0; } @@ -1102,14 +1085,12 @@ static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs) struct snd_pcm_runtime *runtime = subs->runtime; struct pcxhr_stream *stream = runtime->private_data; - mutex_lock(&chip->mgr->lock); + guard(mutex)(&chip->mgr->lock); /* get the period fragment and the nb of periods in the buffer */ timer_period_frag = stream->timer_period_frag; timer_buf_periods = stream->timer_buf_periods; - mutex_unlock(&chip->mgr->lock); - return (snd_pcm_uframes_t)((timer_buf_periods * runtime->period_size) + timer_period_frag); } diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index 23f253effb4f..b3b9ab4f303e 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c @@ -754,12 +754,8 @@ void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh *rmh, int capture, */ int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) { - int err; - - mutex_lock(&mgr->msg_lock); - err = pcxhr_send_msg_nolock(mgr, rmh); - mutex_unlock(&mgr->msg_lock); - return err; + guard(mutex)(&mgr->msg_lock); + return pcxhr_send_msg_nolock(mgr, rmh); } static inline int pcxhr_pipes_running(struct pcxhr_mgr *mgr) @@ -962,14 +958,13 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask, struct pcxhr_rmh rmh; int err; - mutex_lock(&mgr->msg_lock); + guard(mutex)(&mgr->msg_lock); if ((mgr->io_num_reg_cont & mask) == value) { dev_dbg(&mgr->pci->dev, "IO_NUM_REG_CONT mask %x already is set to %x\n", mask, value); if (changed) *changed = 0; - mutex_unlock(&mgr->msg_lock); return 0; /* already programmed */ } pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); @@ -984,7 +979,6 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask, if (changed) *changed = 1; } - mutex_unlock(&mgr->msg_lock); return err; } @@ -1269,7 +1263,7 @@ irqreturn_t pcxhr_threaded_irq(int irq, void *dev_id) int i, j; struct snd_pcxhr *chip; - mutex_lock(&mgr->lock); + guard(mutex)(&mgr->lock); if (mgr->src_it_dsp & PCXHR_IRQ_TIMER) { /* is a 24 bit counter */ int dsp_time_new = @@ -1328,6 +1322,5 @@ irqreturn_t pcxhr_threaded_irq(int irq, void *dev_id) } pcxhr_msg_thread(mgr); - mutex_unlock(&mgr->lock); return IRQ_HANDLED; } diff --git a/sound/pci/pcxhr/pcxhr_mix22.c b/sound/pci/pcxhr/pcxhr_mix22.c index e1435afc4907..80d22e22ea30 100644 --- a/sound/pci/pcxhr/pcxhr_mix22.c +++ b/sound/pci/pcxhr/pcxhr_mix22.c @@ -710,9 +710,9 @@ static int hr222_mic_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->mic_volume; - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -721,13 +721,13 @@ static int hr222_mic_vol_put(struct snd_kcontrol *kcontrol, { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int changed = 0; - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); if (chip->mic_volume != ucontrol->value.integer.value[0]) { changed = 1; chip->mic_volume = ucontrol->value.integer.value[0]; hr222_update_analog_audio_level(chip, 1, 0); } - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -760,9 +760,9 @@ static int hr222_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->mic_boost; - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -771,13 +771,13 @@ static int hr222_mic_boost_put(struct snd_kcontrol *kcontrol, { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int changed = 0; - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); if (chip->mic_boost != ucontrol->value.integer.value[0]) { changed = 1; chip->mic_boost = ucontrol->value.integer.value[0]; hr222_micro_boost(chip->mgr, chip->mic_boost); } - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -800,9 +800,9 @@ static int hr222_phantom_power_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->phantom_power; - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -812,14 +812,13 @@ static int hr222_phantom_power_put(struct snd_kcontrol *kcontrol, struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int power, changed = 0; - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); power = !!ucontrol->value.integer.value[0]; if (chip->phantom_power != power) { hr222_phantom_power(chip->mgr, power); chip->phantom_power = power; changed = 1; } - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c index aec509461dd6..03daa2832b1b 100644 --- a/sound/pci/pcxhr/pcxhr_mixer.c +++ b/sound/pci/pcxhr/pcxhr_mixer.c @@ -110,7 +110,8 @@ static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); if (kcontrol->private_value == 0) { /* playback */ ucontrol->value.integer.value[0] = chip->analog_playback_volume[0]; ucontrol->value.integer.value[1] = chip->analog_playback_volume[1]; @@ -118,7 +119,6 @@ static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] = chip->analog_capture_volume[0]; ucontrol->value.integer.value[1] = chip->analog_capture_volume[1]; } - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -129,7 +129,7 @@ static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol, int changed = 0; int is_capture, i; - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); is_capture = (kcontrol->private_value != 0); for (i = 0; i < 2; i++) { int new_volume = ucontrol->value.integer.value[i]; @@ -168,7 +168,6 @@ static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol, is_capture, i); } } - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -192,10 +191,9 @@ static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol, { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->analog_playback_active[0]; ucontrol->value.integer.value[1] = chip->analog_playback_active[1]; - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -204,7 +202,8 @@ static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol, { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int i, changed = 0; - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); for(i = 0; i < 2; i++) { if (chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) { @@ -218,7 +217,6 @@ static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol, pcxhr_update_analog_audio_level(chip, 0, i); } } - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -352,14 +350,13 @@ static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol, int *stored_volume; int is_capture = kcontrol->private_value; - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); if (is_capture) /* digital capture */ stored_volume = chip->digital_capture_volume; else /* digital playback */ stored_volume = chip->digital_playback_volume[idx]; ucontrol->value.integer.value[0] = stored_volume[0]; ucontrol->value.integer.value[1] = stored_volume[1]; - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -373,7 +370,7 @@ static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol, int *stored_volume; int i; - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); if (is_capture) /* digital capture */ stored_volume = chip->digital_capture_volume; else /* digital playback */ @@ -392,7 +389,6 @@ static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol, } if (!is_capture && changed) /* update playback volume */ pcxhr_update_playback_stream_level(chip, idx); - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -416,10 +412,9 @@ static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol, struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0]; ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1]; - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -431,7 +426,7 @@ static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ int i, j; - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); j = idx; for (i = 0; i < 2; i++) { if (chip->digital_playback_active[j][i] != @@ -443,7 +438,6 @@ static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, } if (changed) pcxhr_update_playback_stream_level(chip, idx); - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -465,10 +459,10 @@ static int pcxhr_monitor_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->monitoring_volume[0]; ucontrol->value.integer.value[1] = chip->monitoring_volume[1]; - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -479,7 +473,7 @@ static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol, int changed = 0; int i; - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); for (i = 0; i < 2; i++) { if (chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) { @@ -492,7 +486,6 @@ static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol, changed = 1; } } - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -515,10 +508,10 @@ static int pcxhr_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); + + guard(mutex)(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->monitoring_active[0]; ucontrol->value.integer.value[1] = chip->monitoring_active[1]; - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -529,7 +522,7 @@ static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol, int changed = 0; int i; - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); for (i = 0; i < 2; i++) { if (chip->monitoring_active[i] != ucontrol->value.integer.value[i]) { @@ -545,7 +538,6 @@ static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol, /* update right monitoring volume and mute */ pcxhr_update_audio_pipe_level(chip, 0, 1); - mutex_unlock(&chip->mgr->mixer_mutex); return (changed != 0); } @@ -671,7 +663,7 @@ static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol, } if (ucontrol->value.enumerated.item[0] >= i) return -EINVAL; - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) { chip->audio_capture_source = ucontrol->value.enumerated.item[0]; if (chip->mgr->is_hr_stereo) @@ -680,7 +672,6 @@ static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol, pcxhr_set_audio_source(chip); ret = 1; } - mutex_unlock(&chip->mgr->mixer_mutex); return ret; } @@ -760,9 +751,9 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol, } if (ucontrol->value.enumerated.item[0] >= clock_items) return -EINVAL; - mutex_lock(&mgr->mixer_mutex); + guard(mutex)(&mgr->mixer_mutex); if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) { - mutex_lock(&mgr->setup_mutex); + guard(mutex)(&mgr->setup_mutex); mgr->use_clock_type = ucontrol->value.enumerated.item[0]; rate = 0; if (mgr->use_clock_type != PCXHR_CLOCK_TYPE_INTERNAL) { @@ -778,10 +769,8 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol, if (mgr->sample_rate) mgr->sample_rate = rate; } - mutex_unlock(&mgr->setup_mutex); ret = 1; /* return 1 even if the set was not done. ok ? */ } - mutex_unlock(&mgr->mixer_mutex); return ret; } @@ -814,7 +803,7 @@ static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol, struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); int i, err, rate; - mutex_lock(&mgr->mixer_mutex); + guard(mutex)(&mgr->mixer_mutex); for(i = 0; i < 3 + mgr->capture_chips; i++) { if (i == PCXHR_CLOCK_TYPE_INTERNAL) rate = mgr->sample_rate_real; @@ -825,7 +814,6 @@ static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol, } ucontrol->value.integer.value[i] = rate; } - mutex_unlock(&mgr->mixer_mutex); return 0; } @@ -918,7 +906,7 @@ static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, unsigned char aes_bits; int i, err; - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); for(i = 0; i < 5; i++) { if (kcontrol->private_value == 0) /* playback */ aes_bits = chip->aes_bits[i]; @@ -934,7 +922,6 @@ static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, } ucontrol->value.iec958.status[i] = aes_bits; } - mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -988,7 +975,7 @@ static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol, int i, changed = 0; /* playback */ - mutex_lock(&chip->mgr->mixer_mutex); + guard(mutex)(&chip->mgr->mixer_mutex); for (i = 0; i < 5; i++) { if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) { if (chip->mgr->is_hr_stereo) @@ -1000,7 +987,6 @@ static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol, changed = 1; } } - mutex_unlock(&chip->mgr->mixer_mutex); return changed; } diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index f07b6023473a..ca9bbf554650 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -646,35 +646,27 @@ snd_rme32_playback_hw_params(struct snd_pcm_substream *substream, runtime->dma_bytes = RME32_BUFFER_SIZE; } - spin_lock_irq(&rme32->lock); + guard(spinlock_irq)(&rme32->lock); rate = 0; if (rme32->rcreg & RME32_RCR_KMODE) rate = snd_rme32_capture_getrate(rme32, &dummy); if (rate > 0) { /* AutoSync */ - if ((int)params_rate(params) != rate) { - spin_unlock_irq(&rme32->lock); + if ((int)params_rate(params) != rate) return -EIO; - } } else { err = snd_rme32_playback_setrate(rme32, params_rate(params)); - if (err < 0) { - spin_unlock_irq(&rme32->lock); + if (err < 0) return err; - } } err = snd_rme32_setformat(rme32, params_format(params)); - if (err < 0) { - spin_unlock_irq(&rme32->lock); + if (err < 0) return err; - } snd_rme32_setframelog(rme32, params_channels(params), 1); if (rme32->capture_periodsize != 0) { - if (params_period_size(params) << rme32->playback_frlog != rme32->capture_periodsize) { - spin_unlock_irq(&rme32->lock); + if (params_period_size(params) << rme32->playback_frlog != rme32->capture_periodsize) return -EBUSY; - } } rme32->playback_periodsize = params_period_size(params) << rme32->playback_frlog; /* S/PDIF setup */ @@ -683,7 +675,6 @@ snd_rme32_playback_hw_params(struct snd_pcm_substream *substream, rme32->wcreg |= rme32->wcreg_spdif_stream; writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); } - spin_unlock_irq(&rme32->lock); return 0; } @@ -703,32 +694,24 @@ snd_rme32_capture_hw_params(struct snd_pcm_substream *substream, runtime->dma_bytes = RME32_BUFFER_SIZE; } - spin_lock_irq(&rme32->lock); + guard(spinlock_irq)(&rme32->lock); /* enable AutoSync for record-preparing */ rme32->wcreg |= RME32_WCR_AUTOSYNC; writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); err = snd_rme32_setformat(rme32, params_format(params)); - if (err < 0) { - spin_unlock_irq(&rme32->lock); + if (err < 0) return err; - } err = snd_rme32_playback_setrate(rme32, params_rate(params)); - if (err < 0) { - spin_unlock_irq(&rme32->lock); + if (err < 0) return err; - } rate = snd_rme32_capture_getrate(rme32, &isadat); if (rate > 0) { - if ((int)params_rate(params) != rate) { - spin_unlock_irq(&rme32->lock); + if ((int)params_rate(params) != rate) return -EIO; - } if ((isadat && runtime->hw.channels_min == 2) || - (!isadat && runtime->hw.channels_min == 8)) { - spin_unlock_irq(&rme32->lock); + (!isadat && runtime->hw.channels_min == 8)) return -EIO; - } } /* AutoSync off for recording */ rme32->wcreg &= ~RME32_WCR_AUTOSYNC; @@ -737,14 +720,11 @@ snd_rme32_capture_hw_params(struct snd_pcm_substream *substream, snd_rme32_setframelog(rme32, params_channels(params), 0); if (rme32->playback_periodsize != 0) { if (params_period_size(params) << rme32->capture_frlog != - rme32->playback_periodsize) { - spin_unlock_irq(&rme32->lock); + rme32->playback_periodsize) return -EBUSY; - } } rme32->capture_periodsize = params_period_size(params) << rme32->capture_frlog; - spin_unlock_irq(&rme32->lock); return 0; } @@ -824,15 +804,13 @@ static int snd_rme32_playback_spdif_open(struct snd_pcm_substream *substream) snd_pcm_set_sync(substream); - spin_lock_irq(&rme32->lock); - if (rme32->playback_substream != NULL) { - spin_unlock_irq(&rme32->lock); - return -EBUSY; + scoped_guard(spinlock_irq, &rme32->lock) { + if (rme32->playback_substream != NULL) + return -EBUSY; + rme32->wcreg &= ~RME32_WCR_ADAT; + writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); + rme32->playback_substream = substream; } - rme32->wcreg &= ~RME32_WCR_ADAT; - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - rme32->playback_substream = substream; - spin_unlock_irq(&rme32->lock); if (rme32->fullduplex_mode) runtime->hw = snd_rme32_spdif_fd_info; @@ -869,13 +847,11 @@ static int snd_rme32_capture_spdif_open(struct snd_pcm_substream *substream) snd_pcm_set_sync(substream); - spin_lock_irq(&rme32->lock); - if (rme32->capture_substream != NULL) { - spin_unlock_irq(&rme32->lock); - return -EBUSY; - } - rme32->capture_substream = substream; - spin_unlock_irq(&rme32->lock); + scoped_guard(spinlock_irq, &rme32->lock) { + if (rme32->capture_substream != NULL) + return -EBUSY; + rme32->capture_substream = substream; + } if (rme32->fullduplex_mode) runtime->hw = snd_rme32_spdif_fd_info; @@ -909,15 +885,13 @@ snd_rme32_playback_adat_open(struct snd_pcm_substream *substream) snd_pcm_set_sync(substream); - spin_lock_irq(&rme32->lock); - if (rme32->playback_substream != NULL) { - spin_unlock_irq(&rme32->lock); - return -EBUSY; - } - rme32->wcreg |= RME32_WCR_ADAT; - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - rme32->playback_substream = substream; - spin_unlock_irq(&rme32->lock); + scoped_guard(spinlock_irq, &rme32->lock) { + if (rme32->playback_substream != NULL) + return -EBUSY; + rme32->wcreg |= RME32_WCR_ADAT; + writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); + rme32->playback_substream = substream; + } if (rme32->fullduplex_mode) runtime->hw = snd_rme32_adat_fd_info; @@ -960,13 +934,11 @@ snd_rme32_capture_adat_open(struct snd_pcm_substream *substream) snd_pcm_set_sync(substream); - spin_lock_irq(&rme32->lock); - if (rme32->capture_substream != NULL) { - spin_unlock_irq(&rme32->lock); - return -EBUSY; - } - rme32->capture_substream = substream; - spin_unlock_irq(&rme32->lock); + scoped_guard(spinlock_irq, &rme32->lock) { + if (rme32->capture_substream != NULL) + return -EBUSY; + rme32->capture_substream = substream; + } snd_rme32_set_buffer_constraint(rme32, runtime); return 0; @@ -977,11 +949,11 @@ static int snd_rme32_playback_close(struct snd_pcm_substream *substream) struct rme32 *rme32 = snd_pcm_substream_chip(substream); int spdif = 0; - spin_lock_irq(&rme32->lock); - rme32->playback_substream = NULL; - rme32->playback_periodsize = 0; - spdif = (rme32->wcreg & RME32_WCR_ADAT) == 0; - spin_unlock_irq(&rme32->lock); + scoped_guard(spinlock_irq, &rme32->lock) { + rme32->playback_substream = NULL; + rme32->playback_periodsize = 0; + spdif = (rme32->wcreg & RME32_WCR_ADAT) == 0; + } if (spdif) { rme32->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; snd_ctl_notify(rme32->card, SNDRV_CTL_EVENT_MASK_VALUE | @@ -995,10 +967,9 @@ static int snd_rme32_capture_close(struct snd_pcm_substream *substream) { struct rme32 *rme32 = snd_pcm_substream_chip(substream); - spin_lock_irq(&rme32->lock); + guard(spinlock_irq)(&rme32->lock); rme32->capture_substream = NULL; rme32->capture_periodsize = 0; - spin_unlock_irq(&rme32->lock); return 0; } @@ -1006,7 +977,7 @@ static int snd_rme32_playback_prepare(struct snd_pcm_substream *substream) { struct rme32 *rme32 = snd_pcm_substream_chip(substream); - spin_lock_irq(&rme32->lock); + guard(spinlock_irq)(&rme32->lock); if (rme32->fullduplex_mode) { memset(&rme32->playback_pcm, 0, sizeof(rme32->playback_pcm)); rme32->playback_pcm.hw_buffer_size = RME32_BUFFER_SIZE; @@ -1017,7 +988,6 @@ static int snd_rme32_playback_prepare(struct snd_pcm_substream *substream) if (rme32->wcreg & RME32_WCR_SEL) rme32->wcreg &= ~RME32_WCR_MUTE; writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - spin_unlock_irq(&rme32->lock); return 0; } @@ -1025,7 +995,7 @@ static int snd_rme32_capture_prepare(struct snd_pcm_substream *substream) { struct rme32 *rme32 = snd_pcm_substream_chip(substream); - spin_lock_irq(&rme32->lock); + guard(spinlock_irq)(&rme32->lock); if (rme32->fullduplex_mode) { memset(&rme32->capture_pcm, 0, sizeof(rme32->capture_pcm)); rme32->capture_pcm.hw_buffer_size = RME32_BUFFER_SIZE; @@ -1034,7 +1004,6 @@ static int snd_rme32_capture_prepare(struct snd_pcm_substream *substream) } else { writel(0, rme32->iobase + RME32_IO_RESET_POS); } - spin_unlock_irq(&rme32->lock); return 0; } @@ -1044,7 +1013,7 @@ snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct rme32 *rme32 = snd_pcm_substream_chip(substream); struct snd_pcm_substream *s; - spin_lock(&rme32->lock); + guard(spinlock)(&rme32->lock); snd_pcm_group_for_each_entry(s, substream) { if (s != rme32->playback_substream && s != rme32->capture_substream) @@ -1088,7 +1057,6 @@ snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd) snd_rme32_pcm_start(rme32, 1); break; } - spin_unlock(&rme32->lock); return 0; } @@ -1124,11 +1092,11 @@ static int snd_rme32_playback_fd_ack(struct snd_pcm_substream *substream) rec = &rme32->playback_pcm; cprec = &rme32->capture_pcm; - spin_lock(&rme32->lock); - rec->hw_queue_size = RME32_BUFFER_SIZE; - if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) - rec->hw_queue_size -= cprec->hw_ready; - spin_unlock(&rme32->lock); + scoped_guard(spinlock, &rme32->lock) { + rec->hw_queue_size = RME32_BUFFER_SIZE; + if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) + rec->hw_queue_size -= cprec->hw_ready; + } return snd_pcm_indirect_playback_transfer(substream, rec, snd_rme32_pb_trans_copy); } @@ -1513,10 +1481,9 @@ snd_rme32_get_loopback_control(struct snd_kcontrol *kcontrol, { struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme32->lock); + guard(spinlock_irq)(&rme32->lock); ucontrol->value.integer.value[0] = rme32->wcreg & RME32_WCR_SEL ? 0 : 1; - spin_unlock_irq(&rme32->lock); return 0; } static int @@ -1528,7 +1495,7 @@ snd_rme32_put_loopback_control(struct snd_kcontrol *kcontrol, int change; val = ucontrol->value.integer.value[0] ? 0 : RME32_WCR_SEL; - spin_lock_irq(&rme32->lock); + guard(spinlock_irq)(&rme32->lock); val = (rme32->wcreg & ~RME32_WCR_SEL) | val; change = val != rme32->wcreg; if (ucontrol->value.integer.value[0]) @@ -1537,7 +1504,6 @@ snd_rme32_put_loopback_control(struct snd_kcontrol *kcontrol, val |= RME32_WCR_MUTE; rme32->wcreg = val; writel(val, rme32->iobase + RME32_IO_CONTROL_REGISTER); - spin_unlock_irq(&rme32->lock); return change; } @@ -1572,7 +1538,7 @@ snd_rme32_get_inputtype_control(struct snd_kcontrol *kcontrol, struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); unsigned int items = 3; - spin_lock_irq(&rme32->lock); + guard(spinlock_irq)(&rme32->lock); ucontrol->value.enumerated.item[0] = snd_rme32_getinputtype(rme32); switch (rme32->pci->device) { @@ -1591,7 +1557,6 @@ snd_rme32_get_inputtype_control(struct snd_kcontrol *kcontrol, ucontrol->value.enumerated.item[0] = items - 1; } - spin_unlock_irq(&rme32->lock); return 0; } static int @@ -1616,10 +1581,9 @@ snd_rme32_put_inputtype_control(struct snd_kcontrol *kcontrol, } val = ucontrol->value.enumerated.item[0] % items; - spin_lock_irq(&rme32->lock); + guard(spinlock_irq)(&rme32->lock); change = val != (unsigned int)snd_rme32_getinputtype(rme32); snd_rme32_setinputtype(rme32, val); - spin_unlock_irq(&rme32->lock); return change; } @@ -1640,9 +1604,8 @@ snd_rme32_get_clockmode_control(struct snd_kcontrol *kcontrol, { struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme32->lock); + guard(spinlock_irq)(&rme32->lock); ucontrol->value.enumerated.item[0] = snd_rme32_getclockmode(rme32); - spin_unlock_irq(&rme32->lock); return 0; } static int @@ -1654,10 +1617,9 @@ snd_rme32_put_clockmode_control(struct snd_kcontrol *kcontrol, int change; val = ucontrol->value.enumerated.item[0] % 3; - spin_lock_irq(&rme32->lock); + guard(spinlock_irq)(&rme32->lock); change = val != (unsigned int)snd_rme32_getclockmode(rme32); snd_rme32_setclockmode(rme32, val); - spin_unlock_irq(&rme32->lock); return change; } @@ -1707,10 +1669,9 @@ static int snd_rme32_control_spdif_put(struct snd_kcontrol *kcontrol, u32 val; val = snd_rme32_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&rme32->lock); + guard(spinlock_irq)(&rme32->lock); change = val != rme32->wcreg_spdif; rme32->wcreg_spdif = val; - spin_unlock_irq(&rme32->lock); return change; } @@ -1742,13 +1703,12 @@ static int snd_rme32_control_spdif_stream_put(struct snd_kcontrol *kcontrol, u32 val; val = snd_rme32_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&rme32->lock); + guard(spinlock_irq)(&rme32->lock); change = val != rme32->wcreg_spdif_stream; rme32->wcreg_spdif_stream = val; rme32->wcreg &= ~(RME32_WCR_PRO | RME32_WCR_EMP); rme32->wcreg |= val; writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - spin_unlock_irq(&rme32->lock); return change; } diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 5cdbbe9cf994..58b8ebf1a24e 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -964,48 +964,45 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream, runtime->dma_addr = rme96->port + RME96_IO_PLAY_BUFFER; runtime->dma_bytes = RME96_BUFFER_SIZE; - spin_lock_irq(&rme96->lock); - rate = 0; - if (!(rme96->wcreg & RME96_WCR_MASTER) && - snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG) - rate = snd_rme96_capture_getrate(rme96, &dummy); - if (rate > 0) { - /* slave clock */ - if ((int)params_rate(params) != rate) { - err = -EIO; - goto error; + scoped_guard(spinlock_irq, &rme96->lock) { + rate = 0; + if (!(rme96->wcreg & RME96_WCR_MASTER) && + snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG) + rate = snd_rme96_capture_getrate(rme96, &dummy); + if (rate > 0) { + /* slave clock */ + if ((int)params_rate(params) != rate) + return -EIO; + } else { + err = snd_rme96_playback_setrate(rme96, params_rate(params)); + if (err < 0) + return err; + apply_dac_volume = err > 0; /* need to restore volume later? */ } - } else { - err = snd_rme96_playback_setrate(rme96, params_rate(params)); - if (err < 0) - goto error; - apply_dac_volume = err > 0; /* need to restore volume later? */ - } - err = snd_rme96_playback_setformat(rme96, params_format(params)); - if (err < 0) - goto error; - snd_rme96_setframelog(rme96, params_channels(params), 1); - if (rme96->capture_periodsize != 0) { - if (params_period_size(params) << rme96->playback_frlog != - rme96->capture_periodsize) - { - err = -EBUSY; + err = snd_rme96_playback_setformat(rme96, params_format(params)); + if (err < 0) goto error; + snd_rme96_setframelog(rme96, params_channels(params), 1); + if (rme96->capture_periodsize != 0) { + if (params_period_size(params) << rme96->playback_frlog != + rme96->capture_periodsize) { + err = -EBUSY; + goto error; + } + } + rme96->playback_periodsize = + params_period_size(params) << rme96->playback_frlog; + snd_rme96_set_period_properties(rme96, rme96->playback_periodsize); + /* S/PDIF setup */ + if ((rme96->wcreg & RME96_WCR_ADAT) == 0) { + rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP); + writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER); } - } - rme96->playback_periodsize = - params_period_size(params) << rme96->playback_frlog; - snd_rme96_set_period_properties(rme96, rme96->playback_periodsize); - /* S/PDIF setup */ - if ((rme96->wcreg & RME96_WCR_ADAT) == 0) { - rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP); - writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER); - } - err = 0; + err = 0; + } error: - spin_unlock_irq(&rme96->lock); if (apply_dac_volume) { usleep_range(3000, 10000); snd_rme96_apply_dac_volume(rme96); @@ -1027,45 +1024,33 @@ snd_rme96_capture_hw_params(struct snd_pcm_substream *substream, runtime->dma_addr = rme96->port + RME96_IO_REC_BUFFER; runtime->dma_bytes = RME96_BUFFER_SIZE; - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); err = snd_rme96_capture_setformat(rme96, params_format(params)); - if (err < 0) { - spin_unlock_irq(&rme96->lock); + if (err < 0) return err; - } if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { err = snd_rme96_capture_analog_setrate(rme96, params_rate(params)); - if (err < 0) { - spin_unlock_irq(&rme96->lock); + if (err < 0) return err; - } } else { rate = snd_rme96_capture_getrate(rme96, &isadat); if (rate > 0) { - if ((int)params_rate(params) != rate) { - spin_unlock_irq(&rme96->lock); + if ((int)params_rate(params) != rate) return -EIO; - } if ((isadat && runtime->hw.channels_min == 2) || - (!isadat && runtime->hw.channels_min == 8)) { - spin_unlock_irq(&rme96->lock); + (!isadat && runtime->hw.channels_min == 8)) return -EIO; - } } } snd_rme96_setframelog(rme96, params_channels(params), 0); if (rme96->playback_periodsize != 0) { if (params_period_size(params) << rme96->capture_frlog != rme96->playback_periodsize) - { - spin_unlock_irq(&rme96->lock); return -EBUSY; - } } rme96->capture_periodsize = params_period_size(params) << rme96->capture_frlog; snd_rme96_set_period_properties(rme96, rme96->capture_periodsize); - spin_unlock_irq(&rme96->lock); return 0; } @@ -1165,15 +1150,13 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_set_sync(substream); - spin_lock_irq(&rme96->lock); - if (rme96->playback_substream) { - spin_unlock_irq(&rme96->lock); - return -EBUSY; - } - rme96->wcreg &= ~RME96_WCR_ADAT; - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - rme96->playback_substream = substream; - spin_unlock_irq(&rme96->lock); + scoped_guard(spinlock_irq, &rme96->lock) { + if (rme96->playback_substream) + return -EBUSY; + rme96->wcreg &= ~RME96_WCR_ADAT; + writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); + rme96->playback_substream = substream; + } runtime->hw = snd_rme96_playback_spdif_info; if (!(rme96->wcreg & RME96_WCR_MASTER) && @@ -1215,13 +1198,11 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream) } } - spin_lock_irq(&rme96->lock); - if (rme96->capture_substream) { - spin_unlock_irq(&rme96->lock); - return -EBUSY; - } - rme96->capture_substream = substream; - spin_unlock_irq(&rme96->lock); + scoped_guard(spinlock_irq, &rme96->lock) { + if (rme96->capture_substream) + return -EBUSY; + rme96->capture_substream = substream; + } rme96_set_buffer_size_constraint(rme96, runtime); return 0; @@ -1235,15 +1216,13 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_set_sync(substream); - spin_lock_irq(&rme96->lock); - if (rme96->playback_substream) { - spin_unlock_irq(&rme96->lock); - return -EBUSY; - } - rme96->wcreg |= RME96_WCR_ADAT; - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - rme96->playback_substream = substream; - spin_unlock_irq(&rme96->lock); + scoped_guard(spinlock_irq, &rme96->lock) { + if (rme96->playback_substream) + return -EBUSY; + rme96->wcreg |= RME96_WCR_ADAT; + writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); + rme96->playback_substream = substream; + } runtime->hw = snd_rme96_playback_adat_info; if (!(rme96->wcreg & RME96_WCR_MASTER) && @@ -1285,13 +1264,11 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream) runtime->hw.rate_max = rate; } - spin_lock_irq(&rme96->lock); - if (rme96->capture_substream) { - spin_unlock_irq(&rme96->lock); - return -EBUSY; - } - rme96->capture_substream = substream; - spin_unlock_irq(&rme96->lock); + scoped_guard(spinlock_irq, &rme96->lock) { + if (rme96->capture_substream) + return -EBUSY; + rme96->capture_substream = substream; + } rme96_set_buffer_size_constraint(rme96, runtime); return 0; @@ -1303,14 +1280,13 @@ snd_rme96_playback_close(struct snd_pcm_substream *substream) struct rme96 *rme96 = snd_pcm_substream_chip(substream); int spdif = 0; - spin_lock_irq(&rme96->lock); - if (RME96_ISPLAYING(rme96)) { - snd_rme96_trigger(rme96, RME96_STOP_PLAYBACK); + scoped_guard(spinlock_irq, &rme96->lock) { + if (RME96_ISPLAYING(rme96)) + snd_rme96_trigger(rme96, RME96_STOP_PLAYBACK); + rme96->playback_substream = NULL; + rme96->playback_periodsize = 0; + spdif = (rme96->wcreg & RME96_WCR_ADAT) == 0; } - rme96->playback_substream = NULL; - rme96->playback_periodsize = 0; - spdif = (rme96->wcreg & RME96_WCR_ADAT) == 0; - spin_unlock_irq(&rme96->lock); if (spdif) { rme96->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; snd_ctl_notify(rme96->card, SNDRV_CTL_EVENT_MASK_VALUE | @@ -1324,13 +1300,12 @@ snd_rme96_capture_close(struct snd_pcm_substream *substream) { struct rme96 *rme96 = snd_pcm_substream_chip(substream); - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); if (RME96_ISRECORDING(rme96)) { snd_rme96_trigger(rme96, RME96_STOP_CAPTURE); } rme96->capture_substream = NULL; rme96->capture_periodsize = 0; - spin_unlock_irq(&rme96->lock); return 0; } @@ -1339,12 +1314,11 @@ snd_rme96_playback_prepare(struct snd_pcm_substream *substream) { struct rme96 *rme96 = snd_pcm_substream_chip(substream); - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); if (RME96_ISPLAYING(rme96)) { snd_rme96_trigger(rme96, RME96_STOP_PLAYBACK); } writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); - spin_unlock_irq(&rme96->lock); return 0; } @@ -1353,12 +1327,11 @@ snd_rme96_capture_prepare(struct snd_pcm_substream *substream) { struct rme96 *rme96 = snd_pcm_substream_chip(substream); - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); if (RME96_ISRECORDING(rme96)) { snd_rme96_trigger(rme96, RME96_STOP_CAPTURE); } writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); - spin_unlock_irq(&rme96->lock); return 0; } @@ -1829,9 +1802,8 @@ snd_rme96_get_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_ele { struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); ucontrol->value.integer.value[0] = rme96->wcreg & RME96_WCR_SEL ? 0 : 1; - spin_unlock_irq(&rme96->lock); return 0; } static int @@ -1842,12 +1814,11 @@ snd_rme96_put_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_ele int change; val = ucontrol->value.integer.value[0] ? 0 : RME96_WCR_SEL; - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); val = (rme96->wcreg & ~RME96_WCR_SEL) | val; change = val != rme96->wcreg; rme96->wcreg = val; writel(val, rme96->iobase + RME96_IO_CONTROL_REGISTER); - spin_unlock_irq(&rme96->lock); return change; } @@ -1893,7 +1864,7 @@ snd_rme96_get_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_el struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); unsigned int items = 3; - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); ucontrol->value.enumerated.item[0] = snd_rme96_getinputtype(rme96); switch (rme96->pci->device) { @@ -1923,7 +1894,6 @@ snd_rme96_get_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_el ucontrol->value.enumerated.item[0] = items - 1; } - spin_unlock_irq(&rme96->lock); return 0; } static int @@ -1961,10 +1931,9 @@ snd_rme96_put_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_el } } - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); change = (int)val != snd_rme96_getinputtype(rme96); snd_rme96_setinputtype(rme96, val); - spin_unlock_irq(&rme96->lock); return change; } @@ -1980,9 +1949,8 @@ snd_rme96_get_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_el { struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); ucontrol->value.enumerated.item[0] = snd_rme96_getclockmode(rme96); - spin_unlock_irq(&rme96->lock); return 0; } static int @@ -1993,10 +1961,9 @@ snd_rme96_put_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_el int change; val = ucontrol->value.enumerated.item[0] % 3; - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); change = (int)val != snd_rme96_getclockmode(rme96); snd_rme96_setclockmode(rme96, val); - spin_unlock_irq(&rme96->lock); return change; } @@ -2014,9 +1981,8 @@ snd_rme96_get_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_ { struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); ucontrol->value.enumerated.item[0] = snd_rme96_getattenuation(rme96); - spin_unlock_irq(&rme96->lock); return 0; } static int @@ -2027,11 +1993,10 @@ snd_rme96_put_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_ int change; val = ucontrol->value.enumerated.item[0] % 4; - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); change = (int)val != snd_rme96_getattenuation(rme96); snd_rme96_setattenuation(rme96, val); - spin_unlock_irq(&rme96->lock); return change; } @@ -2047,9 +2012,8 @@ snd_rme96_get_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_el { struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); ucontrol->value.enumerated.item[0] = snd_rme96_getmontracks(rme96); - spin_unlock_irq(&rme96->lock); return 0; } static int @@ -2060,10 +2024,9 @@ snd_rme96_put_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_el int change; val = ucontrol->value.enumerated.item[0] % 4; - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); change = (int)val != snd_rme96_getmontracks(rme96); snd_rme96_setmontracks(rme96, val); - spin_unlock_irq(&rme96->lock); return change; } @@ -2111,10 +2074,9 @@ static int snd_rme96_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd u32 val; val = snd_rme96_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); change = val != rme96->wcreg_spdif; rme96->wcreg_spdif = val; - spin_unlock_irq(&rme96->lock); return change; } @@ -2140,13 +2102,12 @@ static int snd_rme96_control_spdif_stream_put(struct snd_kcontrol *kcontrol, str u32 val; val = snd_rme96_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); change = val != rme96->wcreg_spdif_stream; rme96->wcreg_spdif_stream = val; rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP); rme96->wcreg |= val; writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - spin_unlock_irq(&rme96->lock); return change; } @@ -2180,10 +2141,9 @@ snd_rme96_dac_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu { struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); u->value.integer.value[0] = rme96->vol[0]; u->value.integer.value[1] = rme96->vol[1]; - spin_unlock_irq(&rme96->lock); return 0; } @@ -2199,7 +2159,7 @@ snd_rme96_dac_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu if (!RME96_HAS_ANALOG_OUT(rme96)) return -EINVAL; maxvol = RME96_185X_MAX_OUT(rme96); - spin_lock_irq(&rme96->lock); + guard(spinlock_irq)(&rme96->lock); vol = u->value.integer.value[0]; if (vol != rme96->vol[0] && vol <= maxvol) { rme96->vol[0] = vol; @@ -2212,7 +2172,6 @@ snd_rme96_dac_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu } if (change) snd_rme96_apply_dac_volume(rme96); - spin_unlock_irq(&rme96->lock); return change; } diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 7ce73746168a..31cc2d91c8d2 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -691,7 +691,6 @@ static int hdsp_wait_for_iobox(struct hdsp *hdsp, unsigned int loops, static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { int i; - unsigned long flags; const u32 *cache; if (hdsp->fw_uploaded) @@ -746,9 +745,8 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { if (hdsp->state & HDSP_InitializationComplete) { dev_info(hdsp->card->dev, "firmware loaded from cache, restoring defaults\n"); - spin_lock_irqsave(&hdsp->lock, flags); + guard(spinlock_irqsave)(&hdsp->lock); snd_hdsp_set_defaults(hdsp); - spin_unlock_irqrestore(&hdsp->lock, flags); } hdsp->state |= HDSP_FirmwareLoaded; @@ -939,14 +937,12 @@ static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp) { - unsigned long flags; int ret = 1; - spin_lock_irqsave(&hdsp->lock, flags); + guard(spinlock_irqsave)(&hdsp->lock); if ((hdsp->playback_pid != hdsp->capture_pid) && (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0)) ret = 0; - spin_unlock_irqrestore(&hdsp->lock, flags); return ret; } @@ -1063,8 +1059,6 @@ static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames) { int n; - spin_lock_irq(&s->lock); - frames >>= 7; n = 0; while (frames) { @@ -1079,8 +1073,6 @@ static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames) hdsp_compute_period_size(s); - spin_unlock_irq(&s->lock); - return 0; } @@ -1306,7 +1298,6 @@ static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id) static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi) { - unsigned long flags; int n_pending; int to_write; int i; @@ -1314,7 +1305,7 @@ static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi) /* Output is not interrupt driven */ - spin_lock_irqsave (&hmidi->lock, flags); + guard(spinlock_irqsave)(&hmidi->lock); if (hmidi->output) { if (!snd_rawmidi_transmit_empty (hmidi->output)) { n_pending = snd_hdsp_midi_output_possible(hmidi->hdsp, hmidi->id); @@ -1330,40 +1321,38 @@ static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi) } } } - spin_unlock_irqrestore (&hmidi->lock, flags); return 0; } static int snd_hdsp_midi_input_read (struct hdsp_midi *hmidi) { unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */ - unsigned long flags; int n_pending; int i; - spin_lock_irqsave (&hmidi->lock, flags); - n_pending = snd_hdsp_midi_input_available(hmidi->hdsp, hmidi->id); - if (n_pending > 0) { - if (hmidi->input) { - if (n_pending > (int)sizeof (buf)) - n_pending = sizeof (buf); - for (i = 0; i < n_pending; ++i) - buf[i] = snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id); - if (n_pending) - snd_rawmidi_receive (hmidi->input, buf, n_pending); - } else { - /* flush the MIDI input FIFO */ - while (--n_pending) - snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id); + scoped_guard(spinlock_irqsave, &hmidi->lock) { + n_pending = snd_hdsp_midi_input_available(hmidi->hdsp, hmidi->id); + if (n_pending > 0) { + if (hmidi->input) { + if (n_pending > (int)sizeof(buf)) + n_pending = sizeof(buf); + for (i = 0; i < n_pending; ++i) + buf[i] = snd_hdsp_midi_read_byte(hmidi->hdsp, hmidi->id); + if (n_pending) + snd_rawmidi_receive(hmidi->input, buf, n_pending); + } else { + /* flush the MIDI input FIFO */ + while (--n_pending) + snd_hdsp_midi_read_byte(hmidi->hdsp, hmidi->id); + } } + hmidi->pending = 0; + if (hmidi->id) + hmidi->hdsp->control_register |= HDSP_Midi1InterruptEnable; + else + hmidi->hdsp->control_register |= HDSP_Midi0InterruptEnable; + hdsp_write(hmidi->hdsp, HDSP_controlRegister, hmidi->hdsp->control_register); } - hmidi->pending = 0; - if (hmidi->id) - hmidi->hdsp->control_register |= HDSP_Midi1InterruptEnable; - else - hmidi->hdsp->control_register |= HDSP_Midi0InterruptEnable; - hdsp_write(hmidi->hdsp, HDSP_controlRegister, hmidi->hdsp->control_register); - spin_unlock_irqrestore (&hmidi->lock, flags); return snd_hdsp_midi_output_write (hmidi); } @@ -1371,13 +1360,12 @@ static void snd_hdsp_midi_input_trigger(struct snd_rawmidi_substream *substream, { struct hdsp *hdsp; struct hdsp_midi *hmidi; - unsigned long flags; u32 ie; hmidi = (struct hdsp_midi *) substream->rmidi->private_data; hdsp = hmidi->hdsp; ie = hmidi->id ? HDSP_Midi1InterruptEnable : HDSP_Midi0InterruptEnable; - spin_lock_irqsave (&hdsp->lock, flags); + guard(spinlock_irqsave)(&hdsp->lock); if (up) { if (!(hdsp->control_register & ie)) { snd_hdsp_flush_midi_input (hdsp, hmidi->id); @@ -1388,16 +1376,14 @@ static void snd_hdsp_midi_input_trigger(struct snd_rawmidi_substream *substream, } hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - spin_unlock_irqrestore (&hdsp->lock, flags); } static void snd_hdsp_midi_output_timer(struct timer_list *t) { struct hdsp_midi *hmidi = timer_container_of(hmidi, t, timer); - unsigned long flags; snd_hdsp_midi_output_write(hmidi); - spin_lock_irqsave (&hmidi->lock, flags); + guard(spinlock_irqsave)(&hmidi->lock); /* this does not bump hmidi->istimer, because the kernel automatically removed the timer when it @@ -1407,29 +1393,26 @@ static void snd_hdsp_midi_output_timer(struct timer_list *t) if (hmidi->istimer) mod_timer(&hmidi->timer, 1 + jiffies); - - spin_unlock_irqrestore (&hmidi->lock, flags); } static void snd_hdsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { struct hdsp_midi *hmidi; - unsigned long flags; hmidi = (struct hdsp_midi *) substream->rmidi->private_data; - spin_lock_irqsave (&hmidi->lock, flags); - if (up) { - if (!hmidi->istimer) { - timer_setup(&hmidi->timer, snd_hdsp_midi_output_timer, - 0); - mod_timer(&hmidi->timer, 1 + jiffies); - hmidi->istimer++; + scoped_guard(spinlock_irqsave, &hmidi->lock) { + if (up) { + if (!hmidi->istimer) { + timer_setup(&hmidi->timer, snd_hdsp_midi_output_timer, + 0); + mod_timer(&hmidi->timer, 1 + jiffies); + hmidi->istimer++; + } + } else { + if (hmidi->istimer && --hmidi->istimer <= 0) + timer_delete(&hmidi->timer); } - } else { - if (hmidi->istimer && --hmidi->istimer <= 0) - timer_delete(&hmidi->timer); } - spin_unlock_irqrestore (&hmidi->lock, flags); if (up) snd_hdsp_midi_output_write(hmidi); } @@ -1439,10 +1422,9 @@ static int snd_hdsp_midi_input_open(struct snd_rawmidi_substream *substream) struct hdsp_midi *hmidi; hmidi = (struct hdsp_midi *) substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); + guard(spinlock_irq)(&hmidi->lock); snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id); hmidi->input = substream; - spin_unlock_irq (&hmidi->lock); return 0; } @@ -1452,9 +1434,8 @@ static int snd_hdsp_midi_output_open(struct snd_rawmidi_substream *substream) struct hdsp_midi *hmidi; hmidi = (struct hdsp_midi *) substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); + guard(spinlock_irq)(&hmidi->lock); hmidi->output = substream; - spin_unlock_irq (&hmidi->lock); return 0; } @@ -1466,9 +1447,8 @@ static int snd_hdsp_midi_input_close(struct snd_rawmidi_substream *substream) snd_hdsp_midi_input_trigger (substream, 0); hmidi = (struct hdsp_midi *) substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); + guard(spinlock_irq)(&hmidi->lock); hmidi->input = NULL; - spin_unlock_irq (&hmidi->lock); return 0; } @@ -1480,9 +1460,8 @@ static int snd_hdsp_midi_output_close(struct snd_rawmidi_substream *substream) snd_hdsp_midi_output_trigger (substream, 0); hmidi = (struct hdsp_midi *) substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); + guard(spinlock_irq)(&hmidi->lock); hmidi->output = NULL; - spin_unlock_irq (&hmidi->lock); return 0; } @@ -1579,10 +1558,9 @@ static int snd_hdsp_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ u32 val; val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); change = val != hdsp->creg_spdif; hdsp->creg_spdif = val; - spin_unlock_irq(&hdsp->lock); return change; } @@ -1608,12 +1586,11 @@ static int snd_hdsp_control_spdif_stream_put(struct snd_kcontrol *kcontrol, stru u32 val; val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); change = val != hdsp->creg_spdif_stream; hdsp->creg_spdif_stream = val; hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis); hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val); - spin_unlock_irq(&hdsp->lock); return change; } @@ -1679,11 +1656,10 @@ static int snd_hdsp_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3); - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); change = val != hdsp_spdif_in(hdsp); if (change) hdsp_set_spdif_input(hdsp, val); - spin_unlock_irq(&hdsp->lock); return change; } @@ -1720,9 +1696,8 @@ static int snd_hdsp_get_toggle_setting(struct snd_kcontrol *kcontrol, struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); u32 regmask = kcontrol->private_value; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); ucontrol->value.integer.value[0] = hdsp_toggle_setting(hdsp, regmask); - spin_unlock_irq(&hdsp->lock); return 0; } @@ -1737,11 +1712,10 @@ static int snd_hdsp_put_toggle_setting(struct snd_kcontrol *kcontrol, if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); change = (int) val != hdsp_toggle_setting(hdsp, regmask); if (change) hdsp_set_toggle_setting(hdsp, regmask, val); - spin_unlock_irq(&hdsp->lock); return change; } @@ -2047,12 +2021,11 @@ static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_c if (val > 6) val = 6; } - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); if (val != hdsp_clock_source(hdsp)) change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0; else change = 0; - spin_unlock_irq(&hdsp->lock); return change; } @@ -2147,12 +2120,11 @@ static int snd_hdsp_put_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_el val = ucontrol->value.enumerated.item[0]; if (val < 0) val = 0; if (val > 2) val = 2; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); if (val != hdsp_da_gain(hdsp)) change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0; else change = 0; - spin_unlock_irq(&hdsp->lock); return change; } @@ -2226,12 +2198,11 @@ static int snd_hdsp_put_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_el val = ucontrol->value.enumerated.item[0]; if (val < 0) val = 0; if (val > 2) val = 2; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); if (val != hdsp_ad_gain(hdsp)) change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0; else change = 0; - spin_unlock_irq(&hdsp->lock); return change; } @@ -2305,12 +2276,11 @@ static int snd_hdsp_put_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl val = ucontrol->value.enumerated.item[0]; if (val < 0) val = 0; if (val > 2) val = 2; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); if (val != hdsp_phone_gain(hdsp)) change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0; else change = 0; - spin_unlock_irq(&hdsp->lock); return change; } @@ -2436,10 +2406,9 @@ static int snd_hdsp_put_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ } val = ucontrol->value.enumerated.item[0] % max; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); change = (int)val != hdsp_pref_sync_ref(hdsp); hdsp_set_pref_sync_ref(hdsp, val); - spin_unlock_irq(&hdsp->lock); return change; } @@ -2519,9 +2488,8 @@ static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct sn { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); ucontrol->value.integer.value[0] = hdsp->precise_ptr; - spin_unlock_irq(&hdsp->lock); return 0; } @@ -2534,10 +2502,9 @@ static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct sn if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); change = (int)val != hdsp->precise_ptr; hdsp_set_precise_pointer(hdsp, val); - spin_unlock_irq(&hdsp->lock); return change; } @@ -2565,9 +2532,8 @@ static int snd_hdsp_get_use_midi_work(struct snd_kcontrol *kcontrol, struct snd_ { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); ucontrol->value.integer.value[0] = hdsp->use_midi_work; - spin_unlock_irq(&hdsp->lock); return 0; } @@ -2580,10 +2546,9 @@ static int snd_hdsp_put_use_midi_work(struct snd_kcontrol *kcontrol, struct snd_ if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); change = (int)val != hdsp->use_midi_work; hdsp_set_use_midi_work(hdsp, val); - spin_unlock_irq(&hdsp->lock); return change; } @@ -2624,9 +2589,8 @@ static int snd_hdsp_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem else addr = hdsp_input_to_output_key(hdsp,source, destination); - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr); - spin_unlock_irq(&hdsp->lock); return 0; } @@ -2652,11 +2616,10 @@ static int snd_hdsp_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem gain = ucontrol->value.integer.value[2]; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); change = gain != hdsp_read_gain(hdsp, addr); if (change) hdsp_write_gain(hdsp, addr, gain); - spin_unlock_irq(&hdsp->lock); return change; } @@ -2869,12 +2832,11 @@ static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.integer.value[0]; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); if (val != hdsp_dds_offset(hdsp)) change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0; else change = 0; - spin_unlock_irq(&hdsp->lock); return change; } @@ -3018,12 +2980,11 @@ static int snd_hdsp_put_rpm_input12(struct snd_kcontrol *kcontrol, struct snd_ct val = 0; if (val > 4) val = 4; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); if (val != hdsp_rpm_input12(hdsp)) change = (hdsp_set_rpm_input12(hdsp, val) == 0) ? 1 : 0; else change = 0; - spin_unlock_irq(&hdsp->lock); return change; } @@ -3103,12 +3064,11 @@ static int snd_hdsp_put_rpm_input34(struct snd_kcontrol *kcontrol, struct snd_ct val = 0; if (val > 4) val = 4; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); if (val != hdsp_rpm_input34(hdsp)) change = (hdsp_set_rpm_input34(hdsp, val) == 0) ? 1 : 0; else change = 0; - spin_unlock_irq(&hdsp->lock); return change; } @@ -3149,10 +3109,9 @@ static int snd_hdsp_put_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); change = (int)val != hdsp_rpm_bypass(hdsp); hdsp_set_rpm_bypass(hdsp, val); - spin_unlock_irq(&hdsp->lock); return change; } @@ -3201,10 +3160,9 @@ static int snd_hdsp_put_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); change = (int)val != hdsp_rpm_disconnect(hdsp); hdsp_set_rpm_disconnect(hdsp, val); - spin_unlock_irq(&hdsp->lock); return change; } @@ -4051,7 +4009,7 @@ static int snd_hdsp_hw_params(struct snd_pcm_substream *substream, if (hdsp_check_for_firmware(hdsp, 1)) return -EIO; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis); @@ -4071,39 +4029,31 @@ static int snd_hdsp_hw_params(struct snd_pcm_substream *substream, */ if (params_rate(params) != hdsp->system_sample_rate) { - spin_unlock_irq(&hdsp->lock); _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); return -EBUSY; } if (params_period_size(params) != hdsp->period_bytes / 4) { - spin_unlock_irq(&hdsp->lock); _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); return -EBUSY; } /* We're fine. */ - spin_unlock_irq(&hdsp->lock); return 0; - } else { - spin_unlock_irq(&hdsp->lock); } /* how to make sure that the rate matches an externally-set one ? */ - spin_lock_irq(&hdsp->lock); if (! hdsp->clock_source_locked) { err = hdsp_set_rate(hdsp, params_rate(params), 0); if (err < 0) { - spin_unlock_irq(&hdsp->lock); _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); return err; } } - spin_unlock_irq(&hdsp->lock); err = hdsp_set_interrupt_interval(hdsp, params_period_size(params)); if (err < 0) { @@ -4160,7 +4110,7 @@ static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd) if (hdsp_check_for_firmware(hdsp, 0)) /* no auto-loading in trigger */ return -EIO; - spin_lock(&hdsp->lock); + guard(spinlock)(&hdsp->lock); running = hdsp->running; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -4171,7 +4121,6 @@ static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd) break; default: snd_BUG(); - spin_unlock(&hdsp->lock); return -EINVAL; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -4211,7 +4160,6 @@ static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd) else if (hdsp->running && !running) hdsp_stop_audio(hdsp); hdsp->running = running; - spin_unlock(&hdsp->lock); return 0; } @@ -4227,10 +4175,9 @@ static int snd_hdsp_prepare(struct snd_pcm_substream *substream) if (hdsp_check_for_firmware(hdsp, 1)) return -EIO; - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); if (!hdsp->running) hdsp_reset_hw_pointer(hdsp); - spin_unlock_irq(&hdsp->lock); return result; } @@ -4473,17 +4420,15 @@ static int snd_hdsp_playback_open(struct snd_pcm_substream *substream) if (hdsp_check_for_firmware(hdsp, 1)) return -EIO; - spin_lock_irq(&hdsp->lock); + scoped_guard(spinlock_irq, &hdsp->lock) { + snd_pcm_set_sync(substream); - snd_pcm_set_sync(substream); + runtime->hw = snd_hdsp_playback_subinfo; + snd_pcm_set_runtime_buffer(substream, &hdsp->playback_dma_buf); - runtime->hw = snd_hdsp_playback_subinfo; - snd_pcm_set_runtime_buffer(substream, &hdsp->playback_dma_buf); - - hdsp->playback_pid = current->pid; - hdsp->playback_substream = substream; - - spin_unlock_irq(&hdsp->lock); + hdsp->playback_pid = current->pid; + hdsp->playback_substream = substream; + } snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes); @@ -4523,12 +4468,10 @@ static int snd_hdsp_playback_release(struct snd_pcm_substream *substream) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); - spin_lock_irq(&hdsp->lock); - - hdsp->playback_pid = -1; - hdsp->playback_substream = NULL; - - spin_unlock_irq(&hdsp->lock); + scoped_guard(spinlock_irq, &hdsp->lock) { + hdsp->playback_pid = -1; + hdsp->playback_substream = NULL; + } if (RPM != hdsp->io_type) { hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; @@ -4550,17 +4493,15 @@ static int snd_hdsp_capture_open(struct snd_pcm_substream *substream) if (hdsp_check_for_firmware(hdsp, 1)) return -EIO; - spin_lock_irq(&hdsp->lock); - - snd_pcm_set_sync(substream); + scoped_guard(spinlock_irq, &hdsp->lock) { + snd_pcm_set_sync(substream); - runtime->hw = snd_hdsp_capture_subinfo; - snd_pcm_set_runtime_buffer(substream, &hdsp->capture_dma_buf); + runtime->hw = snd_hdsp_capture_subinfo; + snd_pcm_set_runtime_buffer(substream, &hdsp->capture_dma_buf); - hdsp->capture_pid = current->pid; - hdsp->capture_substream = substream; - - spin_unlock_irq(&hdsp->lock); + hdsp->capture_pid = current->pid; + hdsp->capture_substream = substream; + } snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes); @@ -4588,12 +4529,11 @@ static int snd_hdsp_capture_release(struct snd_pcm_substream *substream) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); - spin_lock_irq(&hdsp->lock); + guard(spinlock_irq)(&hdsp->lock); hdsp->capture_pid = -1; hdsp->capture_substream = NULL; - spin_unlock_irq(&hdsp->lock); return 0; } @@ -4756,7 +4696,6 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne } case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: { struct hdsp_config_info info; - unsigned long flags; int i; err = hdsp_check_for_iobox(hdsp); @@ -4768,48 +4707,48 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne return err; memset(&info, 0, sizeof(info)); - spin_lock_irqsave(&hdsp->lock, flags); - info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp); - info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp); - if (hdsp->io_type != H9632) - info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp); - info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp); - for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632) ? 3 : 1); ++i) - info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i); - info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp); - info.spdif_out = (unsigned char)hdsp_toggle_setting(hdsp, - HDSP_SPDIFOpticalOut); - info.spdif_professional = (unsigned char) - hdsp_toggle_setting(hdsp, HDSP_SPDIFProfessional); - info.spdif_emphasis = (unsigned char) - hdsp_toggle_setting(hdsp, HDSP_SPDIFEmphasis); - info.spdif_nonaudio = (unsigned char) - hdsp_toggle_setting(hdsp, HDSP_SPDIFNonAudio); - info.spdif_sample_rate = hdsp_spdif_sample_rate(hdsp); - info.system_sample_rate = hdsp->system_sample_rate; - info.autosync_sample_rate = hdsp_external_sample_rate(hdsp); - info.system_clock_mode = (unsigned char)hdsp_system_clock_mode(hdsp); - info.clock_source = (unsigned char)hdsp_clock_source(hdsp); - info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp); - info.line_out = (unsigned char) - hdsp_toggle_setting(hdsp, HDSP_LineOut); - if (hdsp->io_type == H9632) { - info.da_gain = (unsigned char)hdsp_da_gain(hdsp); - info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp); - info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp); - info.xlr_breakout_cable = - (unsigned char)hdsp_toggle_setting(hdsp, - HDSP_XLRBreakoutCable); - - } else if (hdsp->io_type == RPM) { - info.da_gain = (unsigned char) hdsp_rpm_input12(hdsp); - info.ad_gain = (unsigned char) hdsp_rpm_input34(hdsp); + scoped_guard(spinlock_irqsave, &hdsp->lock) { + info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp); + info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp); + if (hdsp->io_type != H9632) + info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp); + info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp); + for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632) ? 3 : 1); ++i) + info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i); + info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp); + info.spdif_out = (unsigned char)hdsp_toggle_setting(hdsp, + HDSP_SPDIFOpticalOut); + info.spdif_professional = (unsigned char) + hdsp_toggle_setting(hdsp, HDSP_SPDIFProfessional); + info.spdif_emphasis = (unsigned char) + hdsp_toggle_setting(hdsp, HDSP_SPDIFEmphasis); + info.spdif_nonaudio = (unsigned char) + hdsp_toggle_setting(hdsp, HDSP_SPDIFNonAudio); + info.spdif_sample_rate = hdsp_spdif_sample_rate(hdsp); + info.system_sample_rate = hdsp->system_sample_rate; + info.autosync_sample_rate = hdsp_external_sample_rate(hdsp); + info.system_clock_mode = (unsigned char)hdsp_system_clock_mode(hdsp); + info.clock_source = (unsigned char)hdsp_clock_source(hdsp); + info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp); + info.line_out = (unsigned char) + hdsp_toggle_setting(hdsp, HDSP_LineOut); + if (hdsp->io_type == H9632) { + info.da_gain = (unsigned char)hdsp_da_gain(hdsp); + info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp); + info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp); + info.xlr_breakout_cable = + (unsigned char)hdsp_toggle_setting(hdsp, + HDSP_XLRBreakoutCable); + + } else if (hdsp->io_type == RPM) { + info.da_gain = (unsigned char) hdsp_rpm_input12(hdsp); + info.ad_gain = (unsigned char) hdsp_rpm_input34(hdsp); + } + if (hdsp->io_type == H9632 || hdsp->io_type == H9652) + info.analog_extension_board = + (unsigned char)hdsp_toggle_setting(hdsp, + HDSP_AnalogExtensionBoard); } - if (hdsp->io_type == H9632 || hdsp->io_type == H9652) - info.analog_extension_board = - (unsigned char)hdsp_toggle_setting(hdsp, - HDSP_AnalogExtensionBoard); - spin_unlock_irqrestore(&hdsp->lock, flags); if (copy_to_user(argp, &info, sizeof(info))) return -EFAULT; break; diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index a0976824beda..3ba5bdc96d9d 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1204,16 +1204,11 @@ static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v) /* check if same process is writing and reading */ static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm) { - unsigned long flags; - int ret = 1; - - spin_lock_irqsave(&hdspm->lock, flags); + guard(spinlock_irqsave)(&hdspm->lock); if ((hdspm->playback_pid != hdspm->capture_pid) && - (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) { - ret = 0; - } - spin_unlock_irqrestore(&hdspm->lock, flags); - return ret; + (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) + return 0; + return 1; } /* round arbitrary sample rates to commonly known rates */ @@ -1527,7 +1522,7 @@ static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames) { int n; - spin_lock_irq(&s->lock); + guard(spinlock_irq)(&s->lock); if (32 == frames) { /* Special case for new RME cards like RayDAT/AIO which @@ -1557,8 +1552,6 @@ static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames) hdspm_compute_period_size(s); - spin_unlock_irq(&s->lock); - return 0; } @@ -1846,7 +1839,6 @@ static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id) static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) { - unsigned long flags; int n_pending; int to_write; int i; @@ -1854,7 +1846,7 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) /* Output is not interrupt driven */ - spin_lock_irqsave (&hmidi->lock, flags); + guard(spinlock_irqsave)(&hmidi->lock); if (hmidi->output && !snd_rawmidi_transmit_empty (hmidi->output)) { n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, @@ -1873,7 +1865,6 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) } } } - spin_unlock_irqrestore (&hmidi->lock, flags); return 0; } @@ -1882,37 +1873,36 @@ static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi) unsigned char buf[128]; /* this buffer is designed to match the MIDI * input FIFO size */ - unsigned long flags; int n_pending; int i; - spin_lock_irqsave (&hmidi->lock, flags); - n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id); - if (n_pending > 0) { - if (hmidi->input) { - if (n_pending > (int)sizeof (buf)) - n_pending = sizeof (buf); - for (i = 0; i < n_pending; ++i) - buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, - hmidi->id); - if (n_pending) - snd_rawmidi_receive (hmidi->input, buf, - n_pending); - } else { - /* flush the MIDI input FIFO */ - while (n_pending--) - snd_hdspm_midi_read_byte (hmidi->hdspm, - hmidi->id); + scoped_guard(spinlock_irqsave, &hmidi->lock) { + n_pending = snd_hdspm_midi_input_available(hmidi->hdspm, hmidi->id); + if (n_pending > 0) { + if (hmidi->input) { + if (n_pending > (int)sizeof(buf)) + n_pending = sizeof(buf); + for (i = 0; i < n_pending; ++i) + buf[i] = snd_hdspm_midi_read_byte(hmidi->hdspm, + hmidi->id); + if (n_pending) + snd_rawmidi_receive(hmidi->input, buf, + n_pending); + } else { + /* flush the MIDI input FIFO */ + while (n_pending--) + snd_hdspm_midi_read_byte(hmidi->hdspm, + hmidi->id); + } } + hmidi->pending = 0; } - hmidi->pending = 0; - spin_unlock_irqrestore(&hmidi->lock, flags); - spin_lock_irqsave(&hmidi->hdspm->lock, flags); - hmidi->hdspm->control_register |= hmidi->ie; - hdspm_write(hmidi->hdspm, HDSPM_controlRegister, - hmidi->hdspm->control_register); - spin_unlock_irqrestore(&hmidi->hdspm->lock, flags); + scoped_guard(spinlock_irqsave, &hmidi->hdspm->lock) { + hmidi->hdspm->control_register |= hmidi->ie; + hdspm_write(hmidi->hdspm, HDSPM_controlRegister, + hmidi->hdspm->control_register); + } return snd_hdspm_midi_output_write (hmidi); } @@ -1922,12 +1912,11 @@ snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) { struct hdspm *hdspm; struct hdspm_midi *hmidi; - unsigned long flags; hmidi = substream->rmidi->private_data; hdspm = hmidi->hdspm; - spin_lock_irqsave (&hdspm->lock, flags); + guard(spinlock_irqsave)(&hdspm->lock); if (up) { if (!(hdspm->control_register & hmidi->ie)) { snd_hdspm_flush_midi_input (hdspm, hmidi->id); @@ -1938,16 +1927,14 @@ snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) } hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - spin_unlock_irqrestore (&hdspm->lock, flags); } static void snd_hdspm_midi_output_timer(struct timer_list *t) { struct hdspm_midi *hmidi = timer_container_of(hmidi, t, timer); - unsigned long flags; snd_hdspm_midi_output_write(hmidi); - spin_lock_irqsave (&hmidi->lock, flags); + guard(spinlock_irqsave)(&hmidi->lock); /* this does not bump hmidi->istimer, because the kernel automatically removed the timer when it @@ -1957,30 +1944,27 @@ static void snd_hdspm_midi_output_timer(struct timer_list *t) if (hmidi->istimer) mod_timer(&hmidi->timer, 1 + jiffies); - - spin_unlock_irqrestore (&hmidi->lock, flags); } static void snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { struct hdspm_midi *hmidi; - unsigned long flags; hmidi = substream->rmidi->private_data; - spin_lock_irqsave (&hmidi->lock, flags); - if (up) { - if (!hmidi->istimer) { - timer_setup(&hmidi->timer, - snd_hdspm_midi_output_timer, 0); - mod_timer(&hmidi->timer, 1 + jiffies); - hmidi->istimer++; + scoped_guard(spinlock_irqsave, &hmidi->lock) { + if (up) { + if (!hmidi->istimer) { + timer_setup(&hmidi->timer, + snd_hdspm_midi_output_timer, 0); + mod_timer(&hmidi->timer, 1 + jiffies); + hmidi->istimer++; + } + } else { + if (hmidi->istimer && --hmidi->istimer <= 0) + timer_delete(&hmidi->timer); } - } else { - if (hmidi->istimer && --hmidi->istimer <= 0) - timer_delete(&hmidi->timer); } - spin_unlock_irqrestore (&hmidi->lock, flags); if (up) snd_hdspm_midi_output_write(hmidi); } @@ -1990,10 +1974,9 @@ static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream) struct hdspm_midi *hmidi; hmidi = substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); + guard(spinlock_irq)(&hmidi->lock); snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id); hmidi->input = substream; - spin_unlock_irq (&hmidi->lock); return 0; } @@ -2003,9 +1986,8 @@ static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream) struct hdspm_midi *hmidi; hmidi = substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); + guard(spinlock_irq)(&hmidi->lock); hmidi->output = substream; - spin_unlock_irq (&hmidi->lock); return 0; } @@ -2017,9 +1999,8 @@ static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream) snd_hdspm_midi_input_trigger (substream, 0); hmidi = substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); + guard(spinlock_irq)(&hmidi->lock); hmidi->input = NULL; - spin_unlock_irq (&hmidi->lock); return 0; } @@ -2031,9 +2012,8 @@ static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream) snd_hdspm_midi_output_trigger (substream, 0); hmidi = substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); + guard(spinlock_irq)(&hmidi->lock); hmidi->output = NULL; - spin_unlock_irq (&hmidi->lock); return 0; } @@ -2671,12 +2651,11 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol, val = 0; if (val > 9) val = 9; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); if (val != hdspm_clock_source(hdspm)) change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0; else change = 0; - spin_unlock_irq(&hdspm->lock); return change; } @@ -2999,11 +2978,10 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol, else if (val >= hdspm->texts_autosync_items) val = hdspm->texts_autosync_items-1; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); if (val != hdspm_pref_sync_ref(hdspm)) change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0; - spin_unlock_irq(&hdspm->lock); return change; } @@ -3239,9 +3217,8 @@ static int snd_hdspm_get_toggle_setting(struct snd_kcontrol *kcontrol, struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); u32 regmask = kcontrol->private_value; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); ucontrol->value.integer.value[0] = hdspm_toggle_setting(hdspm, regmask); - spin_unlock_irq(&hdspm->lock); return 0; } @@ -3256,10 +3233,9 @@ static int snd_hdspm_put_toggle_setting(struct snd_kcontrol *kcontrol, if (!snd_hdspm_use_is_exclusive(hdspm)) return -EBUSY; val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); change = (int) val != hdspm_toggle_setting(hdspm, regmask); hdspm_set_toggle_setting(hdspm, regmask, val); - spin_unlock_irq(&hdspm->lock); return change; } @@ -3301,9 +3277,8 @@ static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol, { struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm); - spin_unlock_irq(&hdspm->lock); return 0; } @@ -3317,10 +3292,9 @@ static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol, if (!snd_hdspm_use_is_exclusive(hdspm)) return -EBUSY; val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); change = (int) val != hdspm_input_select(hdspm); hdspm_set_input_select(hdspm, val); - spin_unlock_irq(&hdspm->lock); return change; } @@ -3363,9 +3337,8 @@ static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol, { struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm); - spin_unlock_irq(&hdspm->lock); return 0; } @@ -3379,10 +3352,9 @@ static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol, if (!snd_hdspm_use_is_exclusive(hdspm)) return -EBUSY; val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); change = (int) val != hdspm_ds_wire(hdspm); hdspm_set_ds_wire(hdspm, val); - spin_unlock_irq(&hdspm->lock); return change; } @@ -3436,9 +3408,8 @@ static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol, { struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm); - spin_unlock_irq(&hdspm->lock); return 0; } @@ -3456,10 +3427,9 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol, val = 0; if (val > 2) val = 2; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); change = val != hdspm_qs_wire(hdspm); hdspm_set_qs_wire(hdspm, val); - spin_unlock_irq(&hdspm->lock); return change; } @@ -3512,9 +3482,8 @@ static int snd_hdspm_get_tristate(struct snd_kcontrol *kcontrol, struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); u32 regmask = kcontrol->private_value; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); ucontrol->value.enumerated.item[0] = hdspm_tristate(hdspm, regmask); - spin_unlock_irq(&hdspm->lock); return 0; } @@ -3534,10 +3503,9 @@ static int snd_hdspm_put_tristate(struct snd_kcontrol *kcontrol, if (val > 2) val = 2; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); change = val != hdspm_tristate(hdspm, regmask); hdspm_set_tristate(hdspm, val, regmask); - spin_unlock_irq(&hdspm->lock); return change; } @@ -3590,9 +3558,8 @@ static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol, { struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm); - spin_unlock_irq(&hdspm->lock); return 0; } @@ -3610,10 +3577,9 @@ static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol, val = 0; if (val > 2) val = 2; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); change = val != hdspm_madi_speedmode(hdspm); hdspm_set_madi_speedmode(hdspm, val); - spin_unlock_irq(&hdspm->lock); return change; } @@ -3659,7 +3625,7 @@ static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol, else if (destination >= HDSPM_MAX_CHANNELS) destination = HDSPM_MAX_CHANNELS - 1; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); if (source >= HDSPM_MAX_CHANNELS) ucontrol->value.integer.value[2] = hdspm_read_pb_gain(hdspm, destination, @@ -3668,8 +3634,6 @@ static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[2] = hdspm_read_in_gain(hdspm, destination, source); - spin_unlock_irq(&hdspm->lock); - return 0; } @@ -3695,7 +3659,7 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol, gain = ucontrol->value.integer.value[2]; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); if (source >= HDSPM_MAX_CHANNELS) change = gain != hdspm_read_pb_gain(hdspm, destination, @@ -3714,7 +3678,6 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol, hdspm_write_in_gain(hdspm, destination, source, gain); } - spin_unlock_irq(&hdspm->lock); return change; } @@ -3755,10 +3718,9 @@ static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol, if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) return -EINVAL; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); ucontrol->value.integer.value[0] = (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN; - spin_unlock_irq(&hdspm->lock); return 0; } @@ -3781,14 +3743,13 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol, gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64; - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); change = gain != hdspm_read_pb_gain(hdspm, channel, channel); if (change) hdspm_write_pb_gain(hdspm, channel, channel, gain); - spin_unlock_irq(&hdspm->lock); return change; } @@ -5496,53 +5457,50 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, pid_t this_pid; pid_t other_pid; - spin_lock_irq(&hdspm->lock); + scoped_guard(spinlock_irq, &hdspm->lock) { - if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { - this_pid = hdspm->playback_pid; - other_pid = hdspm->capture_pid; - } else { - this_pid = hdspm->capture_pid; - other_pid = hdspm->playback_pid; - } + if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { + this_pid = hdspm->playback_pid; + other_pid = hdspm->capture_pid; + } else { + this_pid = hdspm->capture_pid; + other_pid = hdspm->playback_pid; + } - if (other_pid > 0 && this_pid != other_pid) { + if (other_pid > 0 && this_pid != other_pid) { - /* The other stream is open, and not by the same - task as this one. Make sure that the parameters - that matter are the same. - */ + /* The other stream is open, and not by the same + task as this one. Make sure that the parameters + that matter are the same. + */ - if (params_rate(params) != hdspm->system_sample_rate) { - spin_unlock_irq(&hdspm->lock); - _snd_pcm_hw_param_setempty(params, - SNDRV_PCM_HW_PARAM_RATE); - return -EBUSY; - } + if (params_rate(params) != hdspm->system_sample_rate) { + _snd_pcm_hw_param_setempty(params, + SNDRV_PCM_HW_PARAM_RATE); + return -EBUSY; + } - if (params_period_size(params) != hdspm->period_bytes / 4) { - spin_unlock_irq(&hdspm->lock); - _snd_pcm_hw_param_setempty(params, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - return -EBUSY; - } + if (params_period_size(params) != hdspm->period_bytes / 4) { + _snd_pcm_hw_param_setempty(params, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE); + return -EBUSY; + } + } } /* We're fine. */ - spin_unlock_irq(&hdspm->lock); /* how to make sure that the rate matches an externally-set one ? */ - spin_lock_irq(&hdspm->lock); - err = hdspm_set_rate(hdspm, params_rate(params), 0); - if (err < 0) { - dev_info(hdspm->card->dev, "err on hdspm_set_rate: %d\n", err); - spin_unlock_irq(&hdspm->lock); - _snd_pcm_hw_param_setempty(params, - SNDRV_PCM_HW_PARAM_RATE); - return err; + scoped_guard(spinlock_irq, &hdspm->lock) { + err = hdspm_set_rate(hdspm, params_rate(params), 0); + if (err < 0) { + dev_info(hdspm->card->dev, "err on hdspm_set_rate: %d\n", err); + _snd_pcm_hw_param_setempty(params, + SNDRV_PCM_HW_PARAM_RATE); + return err; + } } - spin_unlock_irq(&hdspm->lock); err = hdspm_set_interrupt_interval(hdspm, params_period_size(params)); @@ -5750,7 +5708,7 @@ static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd) struct snd_pcm_substream *other; int running; - spin_lock(&hdspm->lock); + guard(spinlock)(&hdspm->lock); running = hdspm->running; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -5761,7 +5719,6 @@ static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd) break; default: snd_BUG(); - spin_unlock(&hdspm->lock); return -EINVAL; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -5802,7 +5759,6 @@ _ok: else if (hdspm->running && !running) hdspm_stop_audio(hdspm); hdspm->running = running; - spin_unlock(&hdspm->lock); return 0; } @@ -6035,27 +5991,26 @@ static int snd_hdspm_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - spin_lock_irq(&hdspm->lock); - snd_pcm_set_sync(substream); - runtime->hw = (playback) ? snd_hdspm_playback_subinfo : - snd_hdspm_capture_subinfo; + scoped_guard(spinlock_irq, &hdspm->lock) { + snd_pcm_set_sync(substream); + runtime->hw = (playback) ? snd_hdspm_playback_subinfo : + snd_hdspm_capture_subinfo; - if (playback) { - if (!hdspm->capture_substream) - hdspm_stop_audio(hdspm); + if (playback) { + if (!hdspm->capture_substream) + hdspm_stop_audio(hdspm); - hdspm->playback_pid = current->pid; - hdspm->playback_substream = substream; - } else { - if (!hdspm->playback_substream) - hdspm_stop_audio(hdspm); + hdspm->playback_pid = current->pid; + hdspm->playback_substream = substream; + } else { + if (!hdspm->playback_substream) + hdspm_stop_audio(hdspm); - hdspm->capture_pid = current->pid; - hdspm->capture_substream = substream; + hdspm->capture_pid = current->pid; + hdspm->capture_substream = substream; + } } - spin_unlock_irq(&hdspm->lock); - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); @@ -6108,7 +6063,7 @@ static int snd_hdspm_release(struct snd_pcm_substream *substream) struct hdspm *hdspm = snd_pcm_substream_chip(substream); bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - spin_lock_irq(&hdspm->lock); + guard(spinlock_irq)(&hdspm->lock); if (playback) { hdspm->playback_pid = -1; @@ -6118,8 +6073,6 @@ static int snd_hdspm_release(struct snd_pcm_substream *substream) hdspm->capture_substream = NULL; } - spin_unlock_irq(&hdspm->lock); - return 0; } @@ -6242,19 +6195,19 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, case SNDRV_HDSPM_IOCTL_GET_CONFIG: memset(&info, 0, sizeof(info)); - spin_lock_irq(&hdspm->lock); - info.pref_sync_ref = hdspm_pref_sync_ref(hdspm); - info.wordclock_sync_check = hdspm_wc_sync_check(hdspm); - - info.system_sample_rate = hdspm->system_sample_rate; - info.autosync_sample_rate = - hdspm_external_sample_rate(hdspm); - info.system_clock_mode = hdspm_system_clock_mode(hdspm); - info.clock_source = hdspm_clock_source(hdspm); - info.autosync_ref = hdspm_autosync_ref(hdspm); - info.line_out = hdspm_toggle_setting(hdspm, HDSPM_LineOut); - info.passthru = 0; - spin_unlock_irq(&hdspm->lock); + scoped_guard(spinlock_irq, &hdspm->lock) { + info.pref_sync_ref = hdspm_pref_sync_ref(hdspm); + info.wordclock_sync_check = hdspm_wc_sync_check(hdspm); + + info.system_sample_rate = hdspm->system_sample_rate; + info.autosync_sample_rate = + hdspm_external_sample_rate(hdspm); + info.system_clock_mode = hdspm_system_clock_mode(hdspm); + info.clock_source = hdspm_clock_source(hdspm); + info.autosync_ref = hdspm_autosync_ref(hdspm); + info.line_out = hdspm_toggle_setting(hdspm, HDSPM_LineOut); + info.passthru = 0; + } if (copy_to_user(argp, &info, sizeof(info))) return -EFAULT; break; diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 7dc8e3777c37..3be30cb57a2e 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -308,16 +308,11 @@ static inline unsigned int rme9652_read(struct snd_rme9652 *rme9652, int reg) static inline int snd_rme9652_use_is_exclusive(struct snd_rme9652 *rme9652) { - unsigned long flags; - int ret = 1; - - spin_lock_irqsave(&rme9652->lock, flags); + guard(spinlock_irqsave)(&rme9652->lock); if ((rme9652->playback_pid != rme9652->capture_pid) && - (rme9652->playback_pid >= 0) && (rme9652->capture_pid >= 0)) { - ret = 0; - } - spin_unlock_irqrestore(&rme9652->lock, flags); - return ret; + (rme9652->playback_pid >= 0) && (rme9652->capture_pid >= 0)) + return 0; + return 1; } static inline int rme9652_adat_sample_rate(struct snd_rme9652 *rme9652) @@ -428,7 +423,7 @@ static int rme9652_set_interrupt_interval(struct snd_rme9652 *s, int restart = 0; int n; - spin_lock_irq(&s->lock); + guard(spinlock_irq)(&s->lock); restart = s->running; if (restart) @@ -451,8 +446,6 @@ static int rme9652_set_interrupt_interval(struct snd_rme9652 *s, if (restart) rme9652_start(s); - spin_unlock_irq(&s->lock); - return 0; } @@ -477,7 +470,7 @@ static int rme9652_set_rate(struct snd_rme9652 *rme9652, int rate) is to flag rate changes in the read/write routines. */ - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); xrate = rme9652_adat_sample_rate(rme9652); switch (rate) { @@ -506,14 +499,11 @@ static int rme9652_set_rate(struct snd_rme9652 *rme9652, int rate) rate = RME9652_DS | RME9652_freq; break; default: - spin_unlock_irq(&rme9652->lock); return -EINVAL; } - if (reject_if_open && (rme9652->capture_pid >= 0 || rme9652->playback_pid >= 0)) { - spin_unlock_irq(&rme9652->lock); + if (reject_if_open && (rme9652->capture_pid >= 0 || rme9652->playback_pid >= 0)) return -EBUSY; - } restart = rme9652->running; if (restart) @@ -539,7 +529,6 @@ static int rme9652_set_rate(struct snd_rme9652 *rme9652, int rate) } } - spin_unlock_irq(&rme9652->lock); return 0; } @@ -798,10 +787,9 @@ static int snd_rme9652_control_spdif_put(struct snd_kcontrol *kcontrol, struct s u32 val; val = snd_rme9652_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); change = val != rme9652->creg_spdif; rme9652->creg_spdif = val; - spin_unlock_irq(&rme9652->lock); return change; } @@ -827,12 +815,11 @@ static int snd_rme9652_control_spdif_stream_put(struct snd_kcontrol *kcontrol, s u32 val; val = snd_rme9652_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); change = val != rme9652->creg_spdif_stream; rme9652->creg_spdif_stream = val; rme9652->control_register &= ~(RME9652_PRO | RME9652_Dolby | RME9652_EMP); rme9652_write(rme9652, RME9652_control_register, rme9652->control_register |= val); - spin_unlock_irq(&rme9652->lock); return change; } @@ -897,9 +884,8 @@ static int snd_rme9652_get_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ct { struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); ucontrol->value.enumerated.item[0] = rme9652_adat1_in(rme9652); - spin_unlock_irq(&rme9652->lock); return 0; } @@ -912,11 +898,10 @@ static int snd_rme9652_put_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ct if (!snd_rme9652_use_is_exclusive(rme9652)) return -EBUSY; val = ucontrol->value.enumerated.item[0] % 2; - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); change = val != rme9652_adat1_in(rme9652); if (change) rme9652_set_adat1_input(rme9652, val); - spin_unlock_irq(&rme9652->lock); return change; } @@ -961,9 +946,8 @@ static int snd_rme9652_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ct { struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); ucontrol->value.enumerated.item[0] = rme9652_spdif_in(rme9652); - spin_unlock_irq(&rme9652->lock); return 0; } @@ -976,11 +960,10 @@ static int snd_rme9652_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ct if (!snd_rme9652_use_is_exclusive(rme9652)) return -EBUSY; val = ucontrol->value.enumerated.item[0] % 3; - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); change = val != rme9652_spdif_in(rme9652); if (change) rme9652_set_spdif_input(rme9652, val); - spin_unlock_irq(&rme9652->lock); return change; } @@ -1022,9 +1005,8 @@ static int snd_rme9652_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_c { struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); ucontrol->value.integer.value[0] = rme9652_spdif_out(rme9652); - spin_unlock_irq(&rme9652->lock); return 0; } @@ -1037,10 +1019,9 @@ static int snd_rme9652_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_c if (!snd_rme9652_use_is_exclusive(rme9652)) return -EBUSY; val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); change = (int)val != rme9652_spdif_out(rme9652); rme9652_set_spdif_output(rme9652, val); - spin_unlock_irq(&rme9652->lock); return change; } @@ -1104,9 +1085,8 @@ static int snd_rme9652_get_sync_mode(struct snd_kcontrol *kcontrol, struct snd_c { struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); ucontrol->value.enumerated.item[0] = rme9652_sync_mode(rme9652); - spin_unlock_irq(&rme9652->lock); return 0; } @@ -1117,10 +1097,9 @@ static int snd_rme9652_put_sync_mode(struct snd_kcontrol *kcontrol, struct snd_c unsigned int val; val = ucontrol->value.enumerated.item[0] % 3; - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); change = (int)val != rme9652_sync_mode(rme9652); rme9652_set_sync_mode(rme9652, val); - spin_unlock_irq(&rme9652->lock); return change; } @@ -1193,9 +1172,8 @@ static int snd_rme9652_get_sync_pref(struct snd_kcontrol *kcontrol, struct snd_c { struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); ucontrol->value.enumerated.item[0] = rme9652_sync_pref(rme9652); - spin_unlock_irq(&rme9652->lock); return 0; } @@ -1209,10 +1187,9 @@ static int snd_rme9652_put_sync_pref(struct snd_kcontrol *kcontrol, struct snd_c return -EBUSY; max = rme9652->ss_channels == RME9652_NCHANNELS ? 4 : 3; val = ucontrol->value.enumerated.item[0] % max; - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); change = (int)val != rme9652_sync_pref(rme9652); rme9652_set_sync_pref(rme9652, val); - spin_unlock_irq(&rme9652->lock); return change; } @@ -1253,7 +1230,7 @@ static int snd_rme9652_put_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_el thru_bits |= 1 << chn; } - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); change = thru_bits ^ rme9652->thru_bits; if (change) { for (chn = 0; chn < rme9652->ss_channels; ++chn) { @@ -1262,7 +1239,6 @@ static int snd_rme9652_put_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_el rme9652_set_thru(rme9652,chn,thru_bits&(1<<chn)); } } - spin_unlock_irq(&rme9652->lock); return !!change; } @@ -1278,9 +1254,8 @@ static int snd_rme9652_get_passthru(struct snd_kcontrol *kcontrol, struct snd_ct { struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); ucontrol->value.integer.value[0] = rme9652->passthru; - spin_unlock_irq(&rme9652->lock); return 0; } @@ -1295,11 +1270,10 @@ static int snd_rme9652_put_passthru(struct snd_kcontrol *kcontrol, struct snd_ct return -EBUSY; val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); change = (ucontrol->value.integer.value[0] != rme9652->passthru); if (change) err = rme9652_set_passthru(rme9652, val); - spin_unlock_irq(&rme9652->lock); return err ? err : change; } @@ -1324,9 +1298,8 @@ static int snd_rme9652_get_spdif_rate(struct snd_kcontrol *kcontrol, struct snd_ { struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); ucontrol->value.integer.value[0] = rme9652_spdif_sample_rate(rme9652); - spin_unlock_irq(&rme9652->lock); return 0; } @@ -1931,45 +1904,39 @@ static int snd_rme9652_hw_params(struct snd_pcm_substream *substream, pid_t this_pid; pid_t other_pid; - spin_lock_irq(&rme9652->lock); - - if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { - rme9652->control_register &= ~(RME9652_PRO | RME9652_Dolby | RME9652_EMP); - rme9652_write(rme9652, RME9652_control_register, rme9652->control_register |= rme9652->creg_spdif_stream); - this_pid = rme9652->playback_pid; - other_pid = rme9652->capture_pid; - } else { - this_pid = rme9652->capture_pid; - other_pid = rme9652->playback_pid; - } - - if ((other_pid > 0) && (this_pid != other_pid)) { - - /* The other stream is open, and not by the same - task as this one. Make sure that the parameters - that matter are the same. - */ + scoped_guard(spinlock_irq, &rme9652->lock) { - if ((int)params_rate(params) != - rme9652_adat_sample_rate(rme9652)) { - spin_unlock_irq(&rme9652->lock); - _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); - return -EBUSY; + if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { + rme9652->control_register &= ~(RME9652_PRO | RME9652_Dolby | RME9652_EMP); + rme9652_write(rme9652, RME9652_control_register, rme9652->control_register |= rme9652->creg_spdif_stream); + this_pid = rme9652->playback_pid; + other_pid = rme9652->capture_pid; + } else { + this_pid = rme9652->capture_pid; + other_pid = rme9652->playback_pid; } - if (params_period_size(params) != rme9652->period_bytes / 4) { - spin_unlock_irq(&rme9652->lock); - _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - return -EBUSY; - } + if ((other_pid > 0) && (this_pid != other_pid)) { - /* We're fine. */ + /* The other stream is open, and not by the same + task as this one. Make sure that the parameters + that matter are the same. + */ - spin_unlock_irq(&rme9652->lock); - return 0; + if ((int)params_rate(params) != + rme9652_adat_sample_rate(rme9652)) { + _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); + return -EBUSY; + } - } else { - spin_unlock_irq(&rme9652->lock); + if (params_period_size(params) != rme9652->period_bytes / 4) { + _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); + return -EBUSY; + } + + /* We're fine. */ + return 0; + } } /* how to make sure that the rate matches an externally-set one ? @@ -2041,7 +2008,8 @@ static int snd_rme9652_trigger(struct snd_pcm_substream *substream, struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); struct snd_pcm_substream *other; int running; - spin_lock(&rme9652->lock); + + guard(spinlock)(&rme9652->lock); running = rme9652->running; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -2052,7 +2020,6 @@ static int snd_rme9652_trigger(struct snd_pcm_substream *substream, break; default: snd_BUG(); - spin_unlock(&rme9652->lock); return -EINVAL; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -2092,7 +2059,6 @@ static int snd_rme9652_trigger(struct snd_pcm_substream *substream, else if (rme9652->running && !running) rme9652_stop(rme9652); rme9652->running = running; - spin_unlock(&rme9652->lock); return 0; } @@ -2100,12 +2066,10 @@ static int snd_rme9652_trigger(struct snd_pcm_substream *substream, static int snd_rme9652_prepare(struct snd_pcm_substream *substream) { struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - unsigned long flags; - spin_lock_irqsave(&rme9652->lock, flags); + guard(spinlock_irqsave)(&rme9652->lock); if (!rme9652->running) rme9652_reset_hw_pointer(rme9652); - spin_unlock_irqrestore(&rme9652->lock, flags); return 0; } @@ -2226,23 +2190,21 @@ static int snd_rme9652_playback_open(struct snd_pcm_substream *substream) struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - spin_lock_irq(&rme9652->lock); + scoped_guard(spinlock_irq, &rme9652->lock) { + snd_pcm_set_sync(substream); - snd_pcm_set_sync(substream); + runtime->hw = snd_rme9652_playback_subinfo; + snd_pcm_set_runtime_buffer(substream, &rme9652->playback_dma_buf); - runtime->hw = snd_rme9652_playback_subinfo; - snd_pcm_set_runtime_buffer(substream, &rme9652->playback_dma_buf); + if (rme9652->capture_substream == NULL) { + rme9652_stop(rme9652); + rme9652_set_thru(rme9652, -1, 0); + } - if (rme9652->capture_substream == NULL) { - rme9652_stop(rme9652); - rme9652_set_thru(rme9652, -1, 0); + rme9652->playback_pid = current->pid; + rme9652->playback_substream = substream; } - rme9652->playback_pid = current->pid; - rme9652->playback_substream = substream; - - spin_unlock_irq(&rme9652->lock); - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes); snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, @@ -2266,12 +2228,10 @@ static int snd_rme9652_playback_release(struct snd_pcm_substream *substream) { struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - spin_lock_irq(&rme9652->lock); - - rme9652->playback_pid = -1; - rme9652->playback_substream = NULL; - - spin_unlock_irq(&rme9652->lock); + scoped_guard(spinlock_irq, &rme9652->lock) { + rme9652->playback_pid = -1; + rme9652->playback_substream = NULL; + } rme9652->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; snd_ctl_notify(rme9652->card, SNDRV_CTL_EVENT_MASK_VALUE | @@ -2285,23 +2245,21 @@ static int snd_rme9652_capture_open(struct snd_pcm_substream *substream) struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - spin_lock_irq(&rme9652->lock); + scoped_guard(spinlock_irq, &rme9652->lock) { + snd_pcm_set_sync(substream); - snd_pcm_set_sync(substream); + runtime->hw = snd_rme9652_capture_subinfo; + snd_pcm_set_runtime_buffer(substream, &rme9652->capture_dma_buf); - runtime->hw = snd_rme9652_capture_subinfo; - snd_pcm_set_runtime_buffer(substream, &rme9652->capture_dma_buf); + if (rme9652->playback_substream == NULL) { + rme9652_stop(rme9652); + rme9652_set_thru(rme9652, -1, 0); + } - if (rme9652->playback_substream == NULL) { - rme9652_stop(rme9652); - rme9652_set_thru(rme9652, -1, 0); + rme9652->capture_pid = current->pid; + rme9652->capture_substream = substream; } - rme9652->capture_pid = current->pid; - rme9652->capture_substream = substream; - - spin_unlock_irq(&rme9652->lock); - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes); snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, @@ -2320,12 +2278,11 @@ static int snd_rme9652_capture_release(struct snd_pcm_substream *substream) { struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - spin_lock_irq(&rme9652->lock); + guard(spinlock_irq)(&rme9652->lock); rme9652->capture_pid = -1; rme9652->capture_substream = NULL; - spin_unlock_irq(&rme9652->lock); return 0; } diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index 3d7abcb31679..4be085d27712 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -383,9 +383,7 @@ static void __sis_unmap_silence(struct sis7019 *sis) static void sis_free_voice(struct sis7019 *sis, struct voice *voice) { - unsigned long flags; - - spin_lock_irqsave(&sis->voice_lock, flags); + guard(spinlock_irqsave)(&sis->voice_lock); if (voice->timing) { __sis_unmap_silence(sis); voice->timing->flags &= ~(VOICE_IN_USE | VOICE_SSO_TIMING | @@ -393,7 +391,6 @@ static void sis_free_voice(struct sis7019 *sis, struct voice *voice) voice->timing = NULL; } voice->flags &= ~(VOICE_IN_USE | VOICE_SSO_TIMING | VOICE_SYNC_TIMING); - spin_unlock_irqrestore(&sis->voice_lock, flags); } static struct voice *__sis_alloc_playback_voice(struct sis7019 *sis) @@ -417,14 +414,8 @@ found_one: static struct voice *sis_alloc_playback_voice(struct sis7019 *sis) { - struct voice *voice; - unsigned long flags; - - spin_lock_irqsave(&sis->voice_lock, flags); - voice = __sis_alloc_playback_voice(sis); - spin_unlock_irqrestore(&sis->voice_lock, flags); - - return voice; + guard(spinlock_irqsave)(&sis->voice_lock); + return __sis_alloc_playback_voice(sis); } static int sis_alloc_timing_voice(struct snd_pcm_substream *substream, @@ -434,7 +425,6 @@ static int sis_alloc_timing_voice(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct voice *voice = runtime->private_data; unsigned int period_size, buffer_size; - unsigned long flags; int needed; /* If there are one or two periods per buffer, we don't need a @@ -447,11 +437,11 @@ static int sis_alloc_timing_voice(struct snd_pcm_substream *substream, period_size != (buffer_size / 2)); if (needed && !voice->timing) { - spin_lock_irqsave(&sis->voice_lock, flags); - voice->timing = __sis_alloc_playback_voice(sis); - if (voice->timing) - __sis_map_silence(sis); - spin_unlock_irqrestore(&sis->voice_lock, flags); + scoped_guard(spinlock_irqsave, &sis->voice_lock) { + voice->timing = __sis_alloc_playback_voice(sis); + if (voice->timing) + __sis_map_silence(sis); + } if (!voice->timing) return -ENOMEM; voice->timing->substream = substream; @@ -645,17 +635,16 @@ static int sis_capture_open(struct snd_pcm_substream *substream) struct sis7019 *sis = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct voice *voice = &sis->capture_voice; - unsigned long flags; /* FIXME: The driver only supports recording from one channel * at the moment, but it could support more. */ - spin_lock_irqsave(&sis->voice_lock, flags); - if (voice->flags & VOICE_IN_USE) - voice = NULL; - else - voice->flags |= VOICE_IN_USE; - spin_unlock_irqrestore(&sis->voice_lock, flags); + scoped_guard(spinlock_irqsave, &sis->voice_lock) { + if (voice->flags & VOICE_IN_USE) + voice = NULL; + else + voice->flags |= VOICE_IN_USE; + } if (!voice) return -EAGAIN; @@ -902,7 +891,7 @@ static unsigned short sis_ac97_rw(struct sis7019 *sis, int codec, u32 cmd) /* Get the AC97 semaphore -- software first, so we don't spin * pounding out IO reads on the hardware semaphore... */ - mutex_lock(&sis->ac97_mutex); + guard(mutex)(&sis->ac97_mutex); count = 0xffff; while ((inw(io + SIS_AC97_SEMA) & SIS_AC97_SEMA_BUSY) && --count) @@ -941,8 +930,6 @@ static unsigned short sis_ac97_rw(struct sis7019 *sis, int codec, u32 cmd) timeout_sema: outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); timeout: - mutex_unlock(&sis->ac97_mutex); - if (!count) { dev_err(&sis->pci->dev, "ac97 codec %d timeout cmd 0x%08x\n", codec, cmd); diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index f85a9556dacb..a4c72799d034 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -303,14 +303,11 @@ static void snd_sonicvibes_out(struct sonicvibes * sonic, unsigned char reg, unsigned char value) { - unsigned long flags; - - spin_lock_irqsave(&sonic->reg_lock, flags); + guard(spinlock_irqsave)(&sonic->reg_lock); outb(reg, SV_REG(sonic, INDEX)); udelay(10); outb(value, SV_REG(sonic, DATA)); udelay(10); - spin_unlock_irqrestore(&sonic->reg_lock, flags); } static unsigned char snd_sonicvibes_in1(struct sonicvibes * sonic, unsigned char reg) @@ -326,15 +323,13 @@ static unsigned char snd_sonicvibes_in1(struct sonicvibes * sonic, unsigned char static unsigned char snd_sonicvibes_in(struct sonicvibes * sonic, unsigned char reg) { - unsigned long flags; unsigned char value; - spin_lock_irqsave(&sonic->reg_lock, flags); + guard(spinlock_irqsave)(&sonic->reg_lock); outb(reg, SV_REG(sonic, INDEX)); udelay(10); value = inb(SV_REG(sonic, DATA)); udelay(10); - spin_unlock_irqrestore(&sonic->reg_lock, flags); return value; } @@ -448,9 +443,7 @@ static void snd_sonicvibes_setfmt(struct sonicvibes * sonic, unsigned char mask, unsigned char value) { - unsigned long flags; - - spin_lock_irqsave(&sonic->reg_lock, flags); + guard(spinlock_irqsave)(&sonic->reg_lock); outb(SV_MCE | SV_IREG_DMA_DATA_FMT, SV_REG(sonic, INDEX)); if (mask) { sonic->format = inb(SV_REG(sonic, DATA)); @@ -461,7 +454,6 @@ static void snd_sonicvibes_setfmt(struct sonicvibes * sonic, udelay(10); outb(0, SV_REG(sonic, INDEX)); udelay(10); - spin_unlock_irqrestore(&sonic->reg_lock, flags); } static void snd_sonicvibes_pll(unsigned int rate, @@ -506,21 +498,18 @@ static void snd_sonicvibes_setpll(struct sonicvibes * sonic, unsigned char reg, unsigned int rate) { - unsigned long flags; unsigned int r, m, n; snd_sonicvibes_pll(rate, &r, &m, &n); if (sonic != NULL) { - spin_lock_irqsave(&sonic->reg_lock, flags); + guard(spinlock_irqsave)(&sonic->reg_lock); snd_sonicvibes_out1(sonic, reg, m); snd_sonicvibes_out1(sonic, reg + 1, r | n); - spin_unlock_irqrestore(&sonic->reg_lock, flags); } } static void snd_sonicvibes_set_adc_rate(struct sonicvibes * sonic, unsigned int rate) { - unsigned long flags; unsigned int div; unsigned char clock; @@ -533,10 +522,9 @@ static void snd_sonicvibes_set_adc_rate(struct sonicvibes * sonic, unsigned int clock = 0x00; snd_sonicvibes_setpll(sonic, SV_IREG_ADC_PLL, rate); } - spin_lock_irqsave(&sonic->reg_lock, flags); + guard(spinlock_irqsave)(&sonic->reg_lock); snd_sonicvibes_out1(sonic, SV_IREG_ADC_ALT_RATE, (div - 1) << 4); snd_sonicvibes_out1(sonic, SV_IREG_ADC_CLOCK, clock); - spin_unlock_irqrestore(&sonic->reg_lock, flags); } static int snd_sonicvibes_hw_constraint_dac_rate(struct snd_pcm_hw_params *params, @@ -567,22 +555,18 @@ static int snd_sonicvibes_hw_constraint_dac_rate(struct snd_pcm_hw_params *param static void snd_sonicvibes_set_dac_rate(struct sonicvibes * sonic, unsigned int rate) { unsigned int div; - unsigned long flags; div = DIV_ROUND_CLOSEST(rate * 65536, SV_FULLRATE); if (div > 65535) div = 65535; - spin_lock_irqsave(&sonic->reg_lock, flags); + guard(spinlock_irqsave)(&sonic->reg_lock); snd_sonicvibes_out1(sonic, SV_IREG_PCM_RATE_HIGH, div >> 8); snd_sonicvibes_out1(sonic, SV_IREG_PCM_RATE_LOW, div); - spin_unlock_irqrestore(&sonic->reg_lock, flags); } static int snd_sonicvibes_trigger(struct sonicvibes * sonic, int what, int cmd) { - int result = 0; - - spin_lock(&sonic->reg_lock); + guard(spinlock)(&sonic->reg_lock); if (cmd == SNDRV_PCM_TRIGGER_START) { if (!(sonic->enable & what)) { sonic->enable |= what; @@ -594,10 +578,9 @@ static int snd_sonicvibes_trigger(struct sonicvibes * sonic, int what, int cmd) snd_sonicvibes_out1(sonic, SV_IREG_PC_ENABLE, sonic->enable); } } else { - result = -EINVAL; + return -EINVAL; } - spin_unlock(&sonic->reg_lock); - return result; + return 0; } static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id) @@ -628,34 +611,34 @@ static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id) unsigned char udreg; int vol, oleft, oright, mleft, mright; - spin_lock(&sonic->reg_lock); - udreg = snd_sonicvibes_in1(sonic, SV_IREG_UD_BUTTON); - vol = udreg & 0x3f; - if (!(udreg & 0x40)) - vol = -vol; - oleft = mleft = snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ANALOG); - oright = mright = snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ANALOG); - oleft &= 0x1f; - oright &= 0x1f; - oleft += vol; - if (oleft < 0) - oleft = 0; - if (oleft > 0x1f) - oleft = 0x1f; - oright += vol; - if (oright < 0) - oright = 0; - if (oright > 0x1f) - oright = 0x1f; - if (udreg & 0x80) { - mleft ^= 0x80; - mright ^= 0x80; + scoped_guard(spinlock, &sonic->reg_lock) { + udreg = snd_sonicvibes_in1(sonic, SV_IREG_UD_BUTTON); + vol = udreg & 0x3f; + if (!(udreg & 0x40)) + vol = -vol; + oleft = mleft = snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ANALOG); + oright = mright = snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ANALOG); + oleft &= 0x1f; + oright &= 0x1f; + oleft += vol; + if (oleft < 0) + oleft = 0; + if (oleft > 0x1f) + oleft = 0x1f; + oright += vol; + if (oright < 0) + oright = 0; + if (oright > 0x1f) + oright = 0x1f; + if (udreg & 0x80) { + mleft ^= 0x80; + mright ^= 0x80; + } + oleft |= mleft & 0x80; + oright |= mright & 0x80; + snd_sonicvibes_out1(sonic, SV_IREG_LEFT_ANALOG, oleft); + snd_sonicvibes_out1(sonic, SV_IREG_RIGHT_ANALOG, oright); } - oleft |= mleft & 0x80; - oright |= mright & 0x80; - snd_sonicvibes_out1(sonic, SV_IREG_LEFT_ANALOG, oleft); - snd_sonicvibes_out1(sonic, SV_IREG_RIGHT_ANALOG, oright); - spin_unlock(&sonic->reg_lock); snd_ctl_notify(sonic->card, SNDRV_CTL_EVENT_MASK_VALUE, &sonic->master_mute->id); snd_ctl_notify(sonic->card, SNDRV_CTL_EVENT_MASK_VALUE, &sonic->master_volume->id); } @@ -696,11 +679,10 @@ static int snd_sonicvibes_playback_prepare(struct snd_pcm_substream *substream) fmt |= 2; snd_sonicvibes_setfmt(sonic, ~3, fmt); snd_sonicvibes_set_dac_rate(sonic, runtime->rate); - spin_lock_irq(&sonic->reg_lock); + guard(spinlock_irq)(&sonic->reg_lock); snd_sonicvibes_setdmaa(sonic, runtime->dma_addr, size); snd_sonicvibes_out1(sonic, SV_IREG_DMA_A_UPPER, count >> 8); snd_sonicvibes_out1(sonic, SV_IREG_DMA_A_LOWER, count); - spin_unlock_irq(&sonic->reg_lock); return 0; } @@ -721,11 +703,10 @@ static int snd_sonicvibes_capture_prepare(struct snd_pcm_substream *substream) fmt |= 0x20; snd_sonicvibes_setfmt(sonic, ~0x30, fmt); snd_sonicvibes_set_adc_rate(sonic, runtime->rate); - spin_lock_irq(&sonic->reg_lock); + guard(spinlock_irq)(&sonic->reg_lock); snd_sonicvibes_setdmac(sonic, runtime->dma_addr, size); snd_sonicvibes_out1(sonic, SV_IREG_DMA_C_UPPER, count >> 8); snd_sonicvibes_out1(sonic, SV_IREG_DMA_C_LOWER, count); - spin_unlock_irq(&sonic->reg_lock); return 0; } @@ -894,10 +875,9 @@ static int snd_sonicvibes_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ { struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&sonic->reg_lock); + guard(spinlock_irq)(&sonic->reg_lock); ucontrol->value.enumerated.item[0] = ((snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC) & SV_RECSRC_OUT) >> 5) - 1; ucontrol->value.enumerated.item[1] = ((snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC) & SV_RECSRC_OUT) >> 5) - 1; - spin_unlock_irq(&sonic->reg_lock); return 0; } @@ -912,7 +892,7 @@ static int snd_sonicvibes_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ return -EINVAL; left = (ucontrol->value.enumerated.item[0] + 1) << 5; right = (ucontrol->value.enumerated.item[1] + 1) << 5; - spin_lock_irq(&sonic->reg_lock); + guard(spinlock_irq)(&sonic->reg_lock); oval1 = snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC); oval2 = snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC); left = (oval1 & ~SV_RECSRC_OUT) | left; @@ -920,7 +900,6 @@ static int snd_sonicvibes_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ change = left != oval1 || right != oval2; snd_sonicvibes_out1(sonic, SV_IREG_LEFT_ADC, left); snd_sonicvibes_out1(sonic, SV_IREG_RIGHT_ADC, right); - spin_unlock_irq(&sonic->reg_lock); return change; } @@ -949,9 +928,8 @@ static int snd_sonicvibes_get_single(struct snd_kcontrol *kcontrol, struct snd_c int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - spin_lock_irq(&sonic->reg_lock); + guard(spinlock_irq)(&sonic->reg_lock); ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, reg)>> shift) & mask; - spin_unlock_irq(&sonic->reg_lock); if (invert) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; return 0; @@ -971,12 +949,11 @@ static int snd_sonicvibes_put_single(struct snd_kcontrol *kcontrol, struct snd_c if (invert) val = mask - val; val <<= shift; - spin_lock_irq(&sonic->reg_lock); + guard(spinlock_irq)(&sonic->reg_lock); oval = snd_sonicvibes_in1(sonic, reg); val = (oval & ~(mask << shift)) | val; change = val != oval; snd_sonicvibes_out1(sonic, reg, val); - spin_unlock_irq(&sonic->reg_lock); return change; } @@ -1007,10 +984,9 @@ static int snd_sonicvibes_get_double(struct snd_kcontrol *kcontrol, struct snd_c int mask = (kcontrol->private_value >> 24) & 0xff; int invert = (kcontrol->private_value >> 22) & 1; - spin_lock_irq(&sonic->reg_lock); + guard(spinlock_irq)(&sonic->reg_lock); ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, left_reg) >> shift_left) & mask; ucontrol->value.integer.value[1] = (snd_sonicvibes_in1(sonic, right_reg) >> shift_right) & mask; - spin_unlock_irq(&sonic->reg_lock); if (invert) { ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; @@ -1038,7 +1014,7 @@ static int snd_sonicvibes_put_double(struct snd_kcontrol *kcontrol, struct snd_c } val1 <<= shift_left; val2 <<= shift_right; - spin_lock_irq(&sonic->reg_lock); + guard(spinlock_irq)(&sonic->reg_lock); oval1 = snd_sonicvibes_in1(sonic, left_reg); oval2 = snd_sonicvibes_in1(sonic, right_reg); val1 = (oval1 & ~(mask << shift_left)) | val1; @@ -1046,7 +1022,6 @@ static int snd_sonicvibes_put_double(struct snd_kcontrol *kcontrol, struct snd_c change = val1 != oval1 || val2 != oval2; snd_sonicvibes_out1(sonic, left_reg, val1); snd_sonicvibes_out1(sonic, right_reg, val2); - spin_unlock_irq(&sonic->reg_lock); return change; } diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 39ed52bf8631..55515c58b8aa 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -107,10 +107,9 @@ static unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned sho { unsigned int data = 0, treg; unsigned short count = 0xffff; - unsigned long flags; struct snd_trident *trident = ac97->private_data; - spin_lock_irqsave(&trident->reg_lock, flags); + guard(spinlock_irqsave)(&trident->reg_lock); if (trident->device == TRIDENT_DEVICE_ID_DX) { data = (DX_AC97_BUSY_READ | (reg & 0x000000ff)); outl(data, TRID_REG(trident, DX_ACR1_AC97_R)); @@ -147,7 +146,6 @@ static unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned sho data = 0; } - spin_unlock_irqrestore(&trident->reg_lock, flags); return ((unsigned short) (data >> 16)); } @@ -170,12 +168,11 @@ static void snd_trident_codec_write(struct snd_ac97 *ac97, unsigned short reg, { unsigned int address, data; unsigned short count = 0xffff; - unsigned long flags; struct snd_trident *trident = ac97->private_data; data = ((unsigned long) wdata) << 16; - spin_lock_irqsave(&trident->reg_lock, flags); + guard(spinlock_irqsave)(&trident->reg_lock); if (trident->device == TRIDENT_DEVICE_ID_DX) { address = DX_ACR0_AC97_W; @@ -213,12 +210,9 @@ static void snd_trident_codec_write(struct snd_ac97 *ac97, unsigned short reg, count = 0; /* return */ } - if (count == 0) { - spin_unlock_irqrestore(&trident->reg_lock, flags); + if (count == 0) return; - } outl(data, TRID_REG(trident, address)); - spin_unlock_irqrestore(&trident->reg_lock, flags); } /*--------------------------------------------------------------------------- @@ -911,7 +905,7 @@ static int snd_trident_playback_prepare(struct snd_pcm_substream *substream) struct snd_trident_voice *evoice = voice->extra; struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[substream->number]; - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); /* set delta (rate) value */ voice->Delta = snd_trident_convert_rate(runtime->rate); @@ -972,8 +966,6 @@ static int snd_trident_playback_prepare(struct snd_pcm_substream *substream) evoice->ESO = (runtime->period_size * 2) - 1; } - spin_unlock_irq(&trident->reg_lock); - return 0; } @@ -1013,7 +1005,7 @@ static int snd_trident_capture_prepare(struct snd_pcm_substream *substream) struct snd_trident_voice *voice = runtime->private_data; unsigned int val, ESO_bytes; - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); // Initialize the channel and set channel Mode outb(0, TRID_REG(trident, LEGACY_DMAR15)); @@ -1082,7 +1074,6 @@ static int snd_trident_capture_prepare(struct snd_pcm_substream *substream) snd_trident_write_voice_regs(trident, voice); - spin_unlock_irq(&trident->reg_lock); return 0; } @@ -1147,7 +1138,7 @@ static int snd_trident_si7018_capture_prepare(struct snd_pcm_substream *substrea struct snd_trident_voice *voice = runtime->private_data; struct snd_trident_voice *evoice = voice->extra; - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); voice->LBA = runtime->dma_addr; voice->Delta = snd_trident_convert_adc_rate(runtime->rate); @@ -1196,7 +1187,6 @@ static int snd_trident_si7018_capture_prepare(struct snd_pcm_substream *substrea evoice->ESO = (runtime->period_size * 2) - 1; } - spin_unlock_irq(&trident->reg_lock); return 0; } @@ -1218,7 +1208,7 @@ static int snd_trident_foldback_prepare(struct snd_pcm_substream *substream) struct snd_trident_voice *voice = runtime->private_data; struct snd_trident_voice *evoice = voice->extra; - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); /* Set channel buffer Address */ if (voice->memblk) @@ -1273,7 +1263,6 @@ static int snd_trident_foldback_prepare(struct snd_pcm_substream *substream) evoice->ESO = (runtime->period_size * 2) - 1; } - spin_unlock_irq(&trident->reg_lock); return 0; } @@ -1307,35 +1296,33 @@ static int snd_trident_spdif_hw_params(struct snd_pcm_substream *substream, } /* prepare SPDIF channel */ - spin_lock_irq(&trident->reg_lock); - old_bits = trident->spdif_pcm_bits; - if (old_bits & IEC958_AES0_PROFESSIONAL) - trident->spdif_pcm_bits &= ~IEC958_AES0_PRO_FS; - else - trident->spdif_pcm_bits &= ~(IEC958_AES3_CON_FS << 24); - if (params_rate(hw_params) >= 48000) { - trident->spdif_pcm_ctrl = 0x3c; // 48000 Hz - trident->spdif_pcm_bits |= - trident->spdif_bits & IEC958_AES0_PROFESSIONAL ? + scoped_guard(spinlock_irq, &trident->reg_lock) { + old_bits = trident->spdif_pcm_bits; + if (old_bits & IEC958_AES0_PROFESSIONAL) + trident->spdif_pcm_bits &= ~IEC958_AES0_PRO_FS; + else + trident->spdif_pcm_bits &= ~(IEC958_AES3_CON_FS << 24); + if (params_rate(hw_params) >= 48000) { + trident->spdif_pcm_ctrl = 0x3c; // 48000 Hz + trident->spdif_pcm_bits |= + trident->spdif_bits & IEC958_AES0_PROFESSIONAL ? IEC958_AES0_PRO_FS_48000 : (IEC958_AES3_CON_FS_48000 << 24); - } - else if (params_rate(hw_params) >= 44100) { - trident->spdif_pcm_ctrl = 0x3e; // 44100 Hz - trident->spdif_pcm_bits |= - trident->spdif_bits & IEC958_AES0_PROFESSIONAL ? + } else if (params_rate(hw_params) >= 44100) { + trident->spdif_pcm_ctrl = 0x3e; // 44100 Hz + trident->spdif_pcm_bits |= + trident->spdif_bits & IEC958_AES0_PROFESSIONAL ? IEC958_AES0_PRO_FS_44100 : (IEC958_AES3_CON_FS_44100 << 24); - } - else { - trident->spdif_pcm_ctrl = 0x3d; // 32000 Hz - trident->spdif_pcm_bits |= - trident->spdif_bits & IEC958_AES0_PROFESSIONAL ? + } else { + trident->spdif_pcm_ctrl = 0x3d; // 32000 Hz + trident->spdif_pcm_bits |= + trident->spdif_bits & IEC958_AES0_PROFESSIONAL ? IEC958_AES0_PRO_FS_32000 : (IEC958_AES3_CON_FS_32000 << 24); + } + change = old_bits != trident->spdif_pcm_bits; } - change = old_bits != trident->spdif_pcm_bits; - spin_unlock_irq(&trident->reg_lock); if (change) snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE, &trident->spdif_pcm_ctl->id); @@ -1364,7 +1351,7 @@ static int snd_trident_spdif_prepare(struct snd_pcm_substream *substream) unsigned int RESO, LBAO; unsigned int temp; - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); if (trident->device != TRIDENT_DEVICE_ID_SI7018) { @@ -1476,8 +1463,6 @@ static int snd_trident_spdif_prepare(struct snd_pcm_substream *substream) outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); } - spin_unlock_irq(&trident->reg_lock); - return 0; } @@ -1518,7 +1503,7 @@ static int snd_trident_trigger(struct snd_pcm_substream *substream, return -EINVAL; } what = whati = capture_flag = spdif_flag = 0; - spin_lock(&trident->reg_lock); + guard(spinlock)(&trident->reg_lock); val = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff; snd_pcm_group_for_each_entry(s, substream) { if ((struct snd_trident *) snd_pcm_substream_chip(s) == trident) { @@ -1577,7 +1562,6 @@ static int snd_trident_trigger(struct snd_pcm_substream *substream, if (capture_flag && trident->device != TRIDENT_DEVICE_ID_SI7018) outb(0x00, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD)); } - spin_unlock(&trident->reg_lock); return 0; } @@ -1602,7 +1586,7 @@ static snd_pcm_uframes_t snd_trident_playback_pointer(struct snd_pcm_substream * if (!voice->running) return 0; - spin_lock(&trident->reg_lock); + guard(spinlock)(&trident->reg_lock); outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); @@ -1612,8 +1596,6 @@ static snd_pcm_uframes_t snd_trident_playback_pointer(struct snd_pcm_substream * cso = (unsigned int) inl(TRID_REG(trident, CH_NX_DELTA_CSO)) & 0x00ffffff; } - spin_unlock(&trident->reg_lock); - if (cso >= runtime->buffer_size) cso = 0; @@ -1866,9 +1848,9 @@ static int snd_trident_spdif_open(struct snd_pcm_substream *substream) return -EAGAIN; voice->spdif = 1; voice->substream = substream; - spin_lock_irq(&trident->reg_lock); - trident->spdif_pcm_bits = trident->spdif_bits; - spin_unlock_irq(&trident->reg_lock); + scoped_guard(spinlock_irq, &trident->reg_lock) { + trident->spdif_pcm_bits = trident->spdif_bits; + } runtime->private_data = voice; runtime->private_free = snd_trident_pcm_free_substream; @@ -1901,22 +1883,22 @@ static int snd_trident_spdif_close(struct snd_pcm_substream *substream) struct snd_trident *trident = snd_pcm_substream_chip(substream); unsigned int temp; - spin_lock_irq(&trident->reg_lock); - // restore default SPDIF setting - if (trident->device != TRIDENT_DEVICE_ID_SI7018) { - outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3)); - outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS)); - } else { - outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS)); - temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)); - if (trident->spdif_ctrl) { - temp |= SPDIF_EN; + scoped_guard(spinlock_irq, &trident->reg_lock) { + // restore default SPDIF setting + if (trident->device != TRIDENT_DEVICE_ID_SI7018) { + outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3)); + outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS)); } else { - temp &= ~SPDIF_EN; + outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS)); + temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)); + if (trident->spdif_ctrl) { + temp |= SPDIF_EN; + } else { + temp &= ~SPDIF_EN; + } + outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); } - outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); } - spin_unlock_irq(&trident->reg_lock); trident->spdif_pcm_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, &trident->spdif_pcm_ctl->id); @@ -2013,9 +1995,8 @@ static int snd_trident_foldback_close(struct snd_pcm_substream *substream) voice = runtime->private_data; /* stop capture channel */ - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); outb(0x00, TRID_REG(trident, T4D_RCI + voice->foldback_chan)); - spin_unlock_irq(&trident->reg_lock); return 0; } @@ -2269,10 +2250,9 @@ static int snd_trident_spdif_control_get(struct snd_kcontrol *kcontrol, struct snd_trident *trident = snd_kcontrol_chip(kcontrol); unsigned char val; - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); val = trident->spdif_ctrl; ucontrol->value.integer.value[0] = val == kcontrol->private_value; - spin_unlock_irq(&trident->reg_lock); return 0; } @@ -2284,7 +2264,7 @@ static int snd_trident_spdif_control_put(struct snd_kcontrol *kcontrol, int change; val = ucontrol->value.integer.value[0] ? (unsigned char) kcontrol->private_value : 0x00; - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); /* S/PDIF C Channel bits 0-31 : 48khz, SCMS disabled */ change = trident->spdif_ctrl != val; trident->spdif_ctrl = val; @@ -2303,7 +2283,6 @@ static int snd_trident_spdif_control_put(struct snd_kcontrol *kcontrol, outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); } } - spin_unlock_irq(&trident->reg_lock); return change; } @@ -2336,12 +2315,11 @@ static int snd_trident_spdif_default_get(struct snd_kcontrol *kcontrol, { struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); ucontrol->value.iec958.status[0] = (trident->spdif_bits >> 0) & 0xff; ucontrol->value.iec958.status[1] = (trident->spdif_bits >> 8) & 0xff; ucontrol->value.iec958.status[2] = (trident->spdif_bits >> 16) & 0xff; ucontrol->value.iec958.status[3] = (trident->spdif_bits >> 24) & 0xff; - spin_unlock_irq(&trident->reg_lock); return 0; } @@ -2356,7 +2334,7 @@ static int snd_trident_spdif_default_put(struct snd_kcontrol *kcontrol, (ucontrol->value.iec958.status[1] << 8) | (ucontrol->value.iec958.status[2] << 16) | (ucontrol->value.iec958.status[3] << 24); - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); change = trident->spdif_bits != val; trident->spdif_bits = val; if (trident->device != TRIDENT_DEVICE_ID_SI7018) { @@ -2366,7 +2344,6 @@ static int snd_trident_spdif_default_put(struct snd_kcontrol *kcontrol, if (trident->spdif == NULL) outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS)); } - spin_unlock_irq(&trident->reg_lock); return change; } @@ -2431,12 +2408,11 @@ static int snd_trident_spdif_stream_get(struct snd_kcontrol *kcontrol, { struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); ucontrol->value.iec958.status[0] = (trident->spdif_pcm_bits >> 0) & 0xff; ucontrol->value.iec958.status[1] = (trident->spdif_pcm_bits >> 8) & 0xff; ucontrol->value.iec958.status[2] = (trident->spdif_pcm_bits >> 16) & 0xff; ucontrol->value.iec958.status[3] = (trident->spdif_pcm_bits >> 24) & 0xff; - spin_unlock_irq(&trident->reg_lock); return 0; } @@ -2451,7 +2427,7 @@ static int snd_trident_spdif_stream_put(struct snd_kcontrol *kcontrol, (ucontrol->value.iec958.status[1] << 8) | (ucontrol->value.iec958.status[2] << 16) | (ucontrol->value.iec958.status[3] << 24); - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); change = trident->spdif_pcm_bits != val; trident->spdif_pcm_bits = val; if (trident->spdif != NULL) { @@ -2461,7 +2437,6 @@ static int snd_trident_spdif_stream_put(struct snd_kcontrol *kcontrol, outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS)); } } - spin_unlock_irq(&trident->reg_lock); return change; } @@ -2489,10 +2464,9 @@ static int snd_trident_ac97_control_get(struct snd_kcontrol *kcontrol, struct snd_trident *trident = snd_kcontrol_chip(kcontrol); unsigned char val; - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)); ucontrol->value.integer.value[0] = (val & (1 << kcontrol->private_value)) ? 1 : 0; - spin_unlock_irq(&trident->reg_lock); return 0; } @@ -2503,7 +2477,7 @@ static int snd_trident_ac97_control_put(struct snd_kcontrol *kcontrol, unsigned char val; int change = 0; - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)); val &= ~(1 << kcontrol->private_value); if (ucontrol->value.integer.value[0]) @@ -2511,7 +2485,6 @@ static int snd_trident_ac97_control_put(struct snd_kcontrol *kcontrol, change = val != trident->ac97_ctrl; trident->ac97_ctrl = val; outl(trident->ac97_ctrl = val, TRID_REG(trident, NX_ACR0_AC97_COM_STAT)); - spin_unlock_irq(&trident->reg_lock); return change; } @@ -2562,14 +2535,13 @@ static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol, unsigned int val; int change = 0; - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); val = trident->musicvol_wavevol; val &= ~(0xffff << kcontrol->private_value); val |= ((255 - (ucontrol->value.integer.value[0] & 0xff)) | ((255 - (ucontrol->value.integer.value[1] & 0xff)) << 8)) << kcontrol->private_value; change = val != trident->musicvol_wavevol; outl(trident->musicvol_wavevol = val, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL)); - spin_unlock_irq(&trident->reg_lock); return change; } @@ -2642,12 +2614,11 @@ static int snd_trident_pcm_vol_control_put(struct snd_kcontrol *kcontrol, } else { val = (255 - (ucontrol->value.integer.value[0] & 255)) << 2; } - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); change = val != mix->vol; mix->vol = val; if (mix->voice != NULL) snd_trident_write_vol_reg(trident, mix->voice, val); - spin_unlock_irq(&trident->reg_lock); return change; } @@ -2706,12 +2677,11 @@ static int snd_trident_pcm_pan_control_put(struct snd_kcontrol *kcontrol, val = ucontrol->value.integer.value[0] & 0x3f; else val = (0x3f - (ucontrol->value.integer.value[0] & 0x3f)) | 0x40; - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); change = val != mix->pan; mix->pan = val; if (mix->voice != NULL) snd_trident_write_pan_reg(trident, mix->voice, val); - spin_unlock_irq(&trident->reg_lock); return change; } @@ -2761,12 +2731,11 @@ static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol *kcontrol, int change = 0; val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f); - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); change = val != mix->rvol; mix->rvol = val; if (mix->voice != NULL) snd_trident_write_rvol_reg(trident, mix->voice, val); - spin_unlock_irq(&trident->reg_lock); return change; } @@ -2819,12 +2788,11 @@ static int snd_trident_pcm_cvol_control_put(struct snd_kcontrol *kcontrol, int change = 0; val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f); - spin_lock_irq(&trident->reg_lock); + guard(spinlock_irq)(&trident->reg_lock); change = val != mix->cvol; mix->cvol = val; if (mix->voice != NULL) snd_trident_write_cvol_reg(trident, mix->voice, val); - spin_unlock_irq(&trident->reg_lock); return change; } @@ -3659,79 +3627,76 @@ static irqreturn_t snd_trident_interrupt(int irq, void *dev_id) return IRQ_NONE; if (audio_int & ADDRESS_IRQ) { // get interrupt status for all channels - spin_lock(&trident->reg_lock); - stimer = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff; - chn_int = inl(TRID_REG(trident, T4D_AINT_A)); - if (chn_int == 0) - goto __skip1; - outl(chn_int, TRID_REG(trident, T4D_AINT_A)); /* ack */ - __skip1: - chn_int = inl(TRID_REG(trident, T4D_AINT_B)); - if (chn_int == 0) - goto __skip2; - for (channel = 63; channel >= 32; channel--) { - mask = 1 << (channel&0x1f); - if ((chn_int & mask) == 0) - continue; - voice = &trident->synth.voices[channel]; - if (!voice->pcm || voice->substream == NULL) { - outl(mask, TRID_REG(trident, T4D_STOP_B)); - continue; - } - delta = (int)stimer - (int)voice->stimer; - if (delta < 0) - delta = -delta; - if ((unsigned int)delta < voice->spurious_threshold) { - /* do some statistics here */ - trident->spurious_irq_count++; - if (trident->spurious_irq_max_delta < (unsigned int)delta) - trident->spurious_irq_max_delta = delta; - continue; - } - voice->stimer = stimer; - if (voice->isync) { - if (!voice->isync3) { - tmp = inw(TRID_REG(trident, T4D_SBBL_SBCL)); - if (trident->bDMAStart & 0x40) - tmp >>= 1; - if (tmp > 0) - tmp = voice->isync_max - tmp; - } else { - tmp = inl(TRID_REG(trident, NX_SPCTRL_SPCSO)) & 0x00ffffff; + scoped_guard(spinlock, &trident->reg_lock) { + stimer = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff; + chn_int = inl(TRID_REG(trident, T4D_AINT_A)); + if (chn_int) + outl(chn_int, TRID_REG(trident, T4D_AINT_A)); /* ack */ + chn_int = inl(TRID_REG(trident, T4D_AINT_B)); + if (chn_int == 0) + break; + for (channel = 63; channel >= 32; channel--) { + mask = 1 << (channel&0x1f); + if ((chn_int & mask) == 0) + continue; + voice = &trident->synth.voices[channel]; + if (!voice->pcm || voice->substream == NULL) { + outl(mask, TRID_REG(trident, T4D_STOP_B)); + continue; + } + delta = (int)stimer - (int)voice->stimer; + if (delta < 0) + delta = -delta; + if ((unsigned int)delta < voice->spurious_threshold) { + /* do some statistics here */ + trident->spurious_irq_count++; + if (trident->spurious_irq_max_delta < (unsigned int)delta) + trident->spurious_irq_max_delta = delta; + continue; } - if (tmp < voice->isync_mark) { - if (tmp > 0x10) - tmp = voice->isync_ESO - 7; - else - tmp = voice->isync_ESO + 2; - /* update ESO for IRQ voice to preserve sync */ + voice->stimer = stimer; + if (voice->isync) { + if (!voice->isync3) { + tmp = inw(TRID_REG(trident, T4D_SBBL_SBCL)); + if (trident->bDMAStart & 0x40) + tmp >>= 1; + if (tmp > 0) + tmp = voice->isync_max - tmp; + } else { + tmp = inl(TRID_REG(trident, NX_SPCTRL_SPCSO)) & 0x00ffffff; + } + if (tmp < voice->isync_mark) { + if (tmp > 0x10) + tmp = voice->isync_ESO - 7; + else + tmp = voice->isync_ESO + 2; + /* update ESO for IRQ voice to preserve sync */ + snd_trident_stop_voice(trident, voice->number); + snd_trident_write_eso_reg(trident, voice, tmp); + snd_trident_start_voice(trident, voice->number); + } + } else if (voice->isync2) { + voice->isync2 = 0; + /* write original ESO and update CSO for IRQ voice to preserve sync */ snd_trident_stop_voice(trident, voice->number); - snd_trident_write_eso_reg(trident, voice, tmp); + snd_trident_write_cso_reg(trident, voice, voice->isync_mark); + snd_trident_write_eso_reg(trident, voice, voice->ESO); snd_trident_start_voice(trident, voice->number); } - } else if (voice->isync2) { - voice->isync2 = 0; - /* write original ESO and update CSO for IRQ voice to preserve sync */ - snd_trident_stop_voice(trident, voice->number); - snd_trident_write_cso_reg(trident, voice, voice->isync_mark); - snd_trident_write_eso_reg(trident, voice, voice->ESO); - snd_trident_start_voice(trident, voice->number); - } #if 0 - if (voice->extra) { - /* update CSO for extra voice to preserve sync */ - snd_trident_stop_voice(trident, voice->extra->number); - snd_trident_write_cso_reg(trident, voice->extra, 0); - snd_trident_start_voice(trident, voice->extra->number); - } + if (voice->extra) { + /* update CSO for extra voice to preserve sync */ + snd_trident_stop_voice(trident, voice->extra->number); + snd_trident_write_cso_reg(trident, voice->extra, 0); + snd_trident_start_voice(trident, voice->extra->number); + } #endif - spin_unlock(&trident->reg_lock); - snd_pcm_period_elapsed(voice->substream); - spin_lock(&trident->reg_lock); + spin_unlock(&trident->reg_lock); + snd_pcm_period_elapsed(voice->substream); + spin_lock(&trident->reg_lock); + } + outl(chn_int, TRID_REG(trident, T4D_AINT_B)); /* ack */ } - outl(chn_int, TRID_REG(trident, T4D_AINT_B)); /* ack */ - __skip2: - spin_unlock(&trident->reg_lock); } if (audio_int & MPU401_IRQ) { if (trident->rmidi) { @@ -3747,16 +3712,13 @@ static irqreturn_t snd_trident_interrupt(int irq, void *dev_id) struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type, int client, int port) { struct snd_trident_voice *pvoice; - unsigned long flags; int idx; - spin_lock_irqsave(&trident->voice_alloc, flags); + guard(spinlock_irqsave)(&trident->voice_alloc); if (type == SNDRV_TRIDENT_VOICE_TYPE_PCM) { idx = snd_trident_allocate_pcm_channel(trident); - if(idx < 0) { - spin_unlock_irqrestore(&trident->voice_alloc, flags); + if (idx < 0) return NULL; - } pvoice = &trident->synth.voices[idx]; pvoice->use = 1; pvoice->pcm = 1; @@ -3764,27 +3726,22 @@ struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, pvoice->spdif = 0; pvoice->memblk = NULL; pvoice->substream = NULL; - spin_unlock_irqrestore(&trident->voice_alloc, flags); return pvoice; } if (type == SNDRV_TRIDENT_VOICE_TYPE_SYNTH) { idx = snd_trident_allocate_synth_channel(trident); - if(idx < 0) { - spin_unlock_irqrestore(&trident->voice_alloc, flags); + if (idx < 0) return NULL; - } pvoice = &trident->synth.voices[idx]; pvoice->use = 1; pvoice->synth = 1; pvoice->client = client; pvoice->port = port; pvoice->memblk = NULL; - spin_unlock_irqrestore(&trident->voice_alloc, flags); return pvoice; } if (type == SNDRV_TRIDENT_VOICE_TYPE_MIDI) { } - spin_unlock_irqrestore(&trident->voice_alloc, flags); return NULL; } @@ -3792,26 +3749,25 @@ EXPORT_SYMBOL(snd_trident_alloc_voice); void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice) { - unsigned long flags; void (*private_free)(struct snd_trident_voice *); if (voice == NULL || !voice->use) return; snd_trident_clear_voices(trident, voice->number, voice->number); - spin_lock_irqsave(&trident->voice_alloc, flags); - private_free = voice->private_free; - voice->private_free = NULL; - voice->private_data = NULL; - if (voice->pcm) - snd_trident_free_pcm_channel(trident, voice->number); - if (voice->synth) - snd_trident_free_synth_channel(trident, voice->number); - voice->use = voice->pcm = voice->synth = voice->midi = 0; - voice->capture = voice->spdif = 0; - voice->sample_ops = NULL; - voice->substream = NULL; - voice->extra = NULL; - spin_unlock_irqrestore(&trident->voice_alloc, flags); + scoped_guard(spinlock_irqsave, &trident->voice_alloc) { + private_free = voice->private_free; + voice->private_free = NULL; + voice->private_data = NULL; + if (voice->pcm) + snd_trident_free_pcm_channel(trident, voice->number); + if (voice->synth) + snd_trident_free_synth_channel(trident, voice->number); + voice->use = voice->pcm = voice->synth = voice->midi = 0; + voice->capture = voice->spdif = 0; + voice->sample_ops = NULL; + voice->substream = NULL; + voice->extra = NULL; + } if (private_free) private_free(voice); } diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index 4a36f194c7f8..81f6348191dc 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c @@ -172,12 +172,10 @@ snd_trident_alloc_sg_pages(struct snd_trident *trident, - mutex_lock(&hdr->block_mutex); + guard(mutex)(&hdr->block_mutex); blk = search_empty(hdr, runtime->dma_bytes); - if (blk == NULL) { - mutex_unlock(&hdr->block_mutex); + if (blk == NULL) return NULL; - } /* set TLB entries */ idx = 0; @@ -186,12 +184,10 @@ snd_trident_alloc_sg_pages(struct snd_trident *trident, dma_addr_t addr = snd_pcm_sgbuf_get_addr(substream, ofs); if (!is_valid_page(trident, addr)) { __snd_util_mem_free(hdr, blk); - mutex_unlock(&hdr->block_mutex); return NULL; } set_tlb_bus(trident, page, addr); } - mutex_unlock(&hdr->block_mutex); return blk; } @@ -216,12 +212,10 @@ snd_trident_alloc_cont_pages(struct snd_trident *trident, if (snd_BUG_ON(!hdr)) return NULL; - mutex_lock(&hdr->block_mutex); + guard(mutex)(&hdr->block_mutex); blk = search_empty(hdr, runtime->dma_bytes); - if (blk == NULL) { - mutex_unlock(&hdr->block_mutex); + if (blk == NULL) return NULL; - } /* set TLB entries */ addr = runtime->dma_addr; @@ -229,12 +223,10 @@ snd_trident_alloc_cont_pages(struct snd_trident *trident, addr += SNDRV_TRIDENT_PAGE_SIZE) { if (!is_valid_page(trident, addr)) { __snd_util_mem_free(hdr, blk); - mutex_unlock(&hdr->block_mutex); return NULL; } set_tlb_bus(trident, page, addr); } - mutex_unlock(&hdr->block_mutex); return blk; } @@ -267,12 +259,11 @@ int snd_trident_free_pages(struct snd_trident *trident, return -EINVAL; hdr = trident->tlb.memhdr; - mutex_lock(&hdr->block_mutex); + guard(mutex)(&hdr->block_mutex); /* reset TLB entries */ for (page = firstpg(blk); page <= lastpg(blk); page++) set_silent_tlb(trident, page); /* free memory block */ __snd_util_mem_free(hdr, blk); - mutex_unlock(&hdr->block_mutex); return 0; } diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 0753c0c73f51..2b0f9e38863e 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -628,7 +628,7 @@ static irqreturn_t snd_via686_interrupt(int irq, void *dev_id) } /* check status for each stream */ - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); for (i = 0; i < chip->num_devs; i++) { struct viadev *viadev = &chip->devs[i]; unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); @@ -652,7 +652,6 @@ static irqreturn_t snd_via686_interrupt(int irq, void *dev_id) } outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ } - spin_unlock(&chip->reg_lock); return IRQ_HANDLED; } @@ -667,7 +666,7 @@ static irqreturn_t snd_via8233_interrupt(int irq, void *dev_id) int irqreturn = 0; /* check status for each stream */ - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); status = inl(VIAREG(chip, SGD_SHADOW)); for (i = 0; i < chip->num_devs; i++) { @@ -706,7 +705,6 @@ static irqreturn_t snd_via8233_interrupt(int irq, void *dev_id) outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ irqreturn = 1; } - spin_unlock(&chip->reg_lock); return IRQ_RETVAL(irqreturn); } @@ -833,7 +831,7 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substr if (!(inb(VIADEV_REG(viadev, OFFSET_STATUS)) & VIA_REG_STAT_ACTIVE)) return 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)) & 0xffffff; /* The via686a does not have the current index register, * so we need to calculate the index from CURR_PTR. @@ -845,7 +843,6 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substr idx = ((ptr - (unsigned int)viadev->table.addr) / 8 - 1) % viadev->tbl_entries; res = calc_linear_pos(chip, viadev, idx, count); viadev->lastpos = res; /* remember the last position */ - spin_unlock(&chip->reg_lock); return bytes_to_frames(substream->runtime, res); } @@ -863,7 +860,7 @@ static snd_pcm_uframes_t snd_via8233_pcm_pointer(struct snd_pcm_substream *subst if (snd_BUG_ON(!viadev->tbl_entries)) return 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)); status = viadev->in_interrupt; if (!status) @@ -904,7 +901,6 @@ static snd_pcm_uframes_t snd_via8233_pcm_pointer(struct snd_pcm_substream *subst } unlock: viadev->lastpos = res; - spin_unlock(&chip->reg_lock); return bytes_to_frames(substream->runtime, res); } @@ -997,7 +993,7 @@ static int via_lock_rate(struct via_rate_lock *rec, int rate) { int changed = 0; - spin_lock_irq(&rec->lock); + guard(spinlock_irq)(&rec->lock); if (rec->rate != rate) { if (rec->rate && rec->used > 1) /* already set */ changed = -EINVAL; @@ -1006,7 +1002,6 @@ static int via_lock_rate(struct via_rate_lock *rec, int rate) changed = 1; } } - spin_unlock_irq(&rec->lock); return changed; } @@ -1167,33 +1162,33 @@ static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev, /* set the hw rate condition */ ratep = &chip->rates[viadev->direction]; - spin_lock_irq(&ratep->lock); - ratep->used++; - if (chip->spdif_on && viadev->reg_offset == 0x30) { - /* DXS#3 and spdif is on */ - runtime->hw.rates = chip->ac97->rates[AC97_RATES_SPDIF]; - snd_pcm_limit_hw_rates(runtime); - } else if (chip->dxs_fixed && viadev->reg_offset < 0x40) { - /* fixed DXS playback rate */ - runtime->hw.rates = SNDRV_PCM_RATE_48000; - runtime->hw.rate_min = runtime->hw.rate_max = 48000; - } else if (chip->dxs_src && viadev->reg_offset < 0x40) { - /* use full SRC capabilities of DXS */ - runtime->hw.rates = (SNDRV_PCM_RATE_CONTINUOUS | - SNDRV_PCM_RATE_8000_48000); - runtime->hw.rate_min = 8000; - runtime->hw.rate_max = 48000; - use_src = true; - } else if (! ratep->rate) { - int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC; - runtime->hw.rates = chip->ac97->rates[idx]; - snd_pcm_limit_hw_rates(runtime); - } else { - /* a fixed rate */ - runtime->hw.rates = SNDRV_PCM_RATE_KNOT; - runtime->hw.rate_max = runtime->hw.rate_min = ratep->rate; + scoped_guard(spinlock_irq, &ratep->lock) { + ratep->used++; + if (chip->spdif_on && viadev->reg_offset == 0x30) { + /* DXS#3 and spdif is on */ + runtime->hw.rates = chip->ac97->rates[AC97_RATES_SPDIF]; + snd_pcm_limit_hw_rates(runtime); + } else if (chip->dxs_fixed && viadev->reg_offset < 0x40) { + /* fixed DXS playback rate */ + runtime->hw.rates = SNDRV_PCM_RATE_48000; + runtime->hw.rate_min = runtime->hw.rate_max = 48000; + } else if (chip->dxs_src && viadev->reg_offset < 0x40) { + /* use full SRC capabilities of DXS */ + runtime->hw.rates = (SNDRV_PCM_RATE_CONTINUOUS | + SNDRV_PCM_RATE_8000_48000); + runtime->hw.rate_min = 8000; + runtime->hw.rate_max = 48000; + use_src = true; + } else if (!ratep->rate) { + int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC; + runtime->hw.rates = chip->ac97->rates[idx]; + snd_pcm_limit_hw_rates(runtime); + } else { + /* a fixed rate */ + runtime->hw.rates = SNDRV_PCM_RATE_KNOT; + runtime->hw.rate_max = runtime->hw.rate_min = ratep->rate; + } } - spin_unlock_irq(&ratep->lock); /* we may remove following constaint when we modify table entries in interrupt */ @@ -1311,11 +1306,11 @@ static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream) /* release the rate lock */ ratep = &chip->rates[viadev->direction]; - spin_lock_irq(&ratep->lock); - ratep->used--; - if (! ratep->used) - ratep->rate = 0; - spin_unlock_irq(&ratep->lock); + scoped_guard(spinlock_irq, &ratep->lock) { + ratep->used--; + if (!ratep->used) + ratep->rate = 0; + } if (! ratep->rate) { if (! viadev->direction) { snd_ac97_update_power(chip->ac97, @@ -1606,14 +1601,13 @@ static int snd_via8233_capture_source_put(struct snd_kcontrol *kcontrol, unsigned long port = chip->port + (kcontrol->id.index ? (VIA_REG_CAPTURE_CHANNEL + 0x10) : VIA_REG_CAPTURE_CHANNEL); u8 val, oval; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); oval = inb(port); val = oval & ~VIA_REG_CAPTURE_CHANNEL_MIC; if (ucontrol->value.enumerated.item[0]) val |= VIA_REG_CAPTURE_CHANNEL_MIC; if (val != oval) outb(val, port); - spin_unlock_irq(&chip->reg_lock); return val != oval; } diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 12a8c620724d..6ce2cd88cda6 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -483,7 +483,7 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id) // _skip_sgd: /* check status for each stream */ - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); for (i = 0; i < chip->num_devs; i++) { struct viadev *viadev = &chip->devs[i]; unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); @@ -497,7 +497,6 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id) } outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ } - spin_unlock(&chip->reg_lock); return IRQ_HANDLED; } @@ -616,7 +615,7 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substr if (!(inb(VIADEV_REG(viadev, OFFSET_STATUS)) & VIA_REG_STAT_ACTIVE)) return 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)) & 0xffffff; /* The via686a does not have the current index register, * so we need to calculate the index from CURR_PTR. @@ -628,7 +627,6 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substr idx = ((ptr - (unsigned int)viadev->table.addr) / 8 - 1) % viadev->tbl_entries; res = calc_linear_pos(chip, viadev, idx, count); - spin_unlock(&chip->reg_lock); return bytes_to_frames(substream->runtime, res); } diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index 3e7e928b24f8..b6459dbdb1b0 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c @@ -868,10 +868,10 @@ static int vx_input_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem { struct vx_core *_chip = snd_kcontrol_chip(kcontrol); struct snd_vx222 *chip = to_vx222(_chip); - mutex_lock(&_chip->mixer_mutex); + + guard(mutex)(&_chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->input_level[0]; ucontrol->value.integer.value[1] = chip->input_level[1]; - mutex_unlock(&_chip->mixer_mutex); return 0; } @@ -885,16 +885,14 @@ static int vx_input_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem if (ucontrol->value.integer.value[1] < 0 || ucontrol->value.integer.value[1] > MIC_LEVEL_MAX) return -EINVAL; - mutex_lock(&_chip->mixer_mutex); + guard(mutex)(&_chip->mixer_mutex); if (chip->input_level[0] != ucontrol->value.integer.value[0] || chip->input_level[1] != ucontrol->value.integer.value[1]) { chip->input_level[0] = ucontrol->value.integer.value[0]; chip->input_level[1] = ucontrol->value.integer.value[1]; vx2_set_input_level(chip); - mutex_unlock(&_chip->mixer_mutex); return 1; } - mutex_unlock(&_chip->mixer_mutex); return 0; } @@ -923,14 +921,12 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v if (ucontrol->value.integer.value[0] < 0 || ucontrol->value.integer.value[0] > MIC_LEVEL_MAX) return -EINVAL; - mutex_lock(&_chip->mixer_mutex); + guard(mutex)(&_chip->mixer_mutex); if (chip->mic_level != ucontrol->value.integer.value[0]) { chip->mic_level = ucontrol->value.integer.value[0]; vx2_set_input_level(chip); - mutex_unlock(&_chip->mixer_mutex); return 1; } - mutex_unlock(&_chip->mixer_mutex); return 0; } diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 75e013b66c5b..eb373d9395e3 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -159,26 +159,21 @@ static u32 snd_ymfpci_calc_lpfQ(u32 rate) static void snd_ymfpci_hw_start(struct snd_ymfpci *chip) { - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (chip->start_count++ > 0) - goto __end; + return; snd_ymfpci_writel(chip, YDSXGR_MODE, snd_ymfpci_readl(chip, YDSXGR_MODE) | 3); chip->active_bank = snd_ymfpci_readl(chip, YDSXGR_CTRLSELECT) & 1; - __end: - spin_unlock_irqrestore(&chip->reg_lock, flags); } static void snd_ymfpci_hw_stop(struct snd_ymfpci *chip) { - unsigned long flags; long timeout = 1000; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (--chip->start_count > 0) - goto __end; + return; snd_ymfpci_writel(chip, YDSXGR_MODE, snd_ymfpci_readl(chip, YDSXGR_MODE) & ~3); while (timeout-- > 0) { @@ -189,8 +184,6 @@ static void snd_ymfpci_hw_stop(struct snd_ymfpci *chip) atomic_set(&chip->interrupt_sleep_count, 0); wake_up(&chip->interrupt_sleep); } - __end: - spin_unlock_irqrestore(&chip->reg_lock, flags); } /* @@ -239,7 +232,6 @@ static int snd_ymfpci_voice_alloc(struct snd_ymfpci *chip, enum snd_ymfpci_voice_type type, int pair, struct snd_ymfpci_voice **rvoice) { - unsigned long flags; int result; if (snd_BUG_ON(!rvoice)) @@ -247,7 +239,7 @@ static int snd_ymfpci_voice_alloc(struct snd_ymfpci *chip, if (snd_BUG_ON(pair && type != YMFPCI_PCM)) return -EINVAL; - spin_lock_irqsave(&chip->voice_lock, flags); + guard(spinlock_irqsave)(&chip->voice_lock); for (;;) { result = voice_alloc(chip, type, pair, rvoice); if (result == 0 || type != YMFPCI_PCM) @@ -255,18 +247,15 @@ static int snd_ymfpci_voice_alloc(struct snd_ymfpci *chip, /* TODO: synth/midi voice deallocation */ break; } - spin_unlock_irqrestore(&chip->voice_lock, flags); return result; } static int snd_ymfpci_voice_free(struct snd_ymfpci *chip, struct snd_ymfpci_voice *pvoice) { - unsigned long flags; - if (snd_BUG_ON(!pvoice)) return -EINVAL; snd_ymfpci_hw_stop(chip); - spin_lock_irqsave(&chip->voice_lock, flags); + guard(spinlock_irqsave)(&chip->voice_lock); if (pvoice->number == chip->src441_used) { chip->src441_used = -1; pvoice->ypcm->use_441_slot = 0; @@ -274,7 +263,6 @@ static int snd_ymfpci_voice_free(struct snd_ymfpci *chip, struct snd_ymfpci_voic pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0; pvoice->ypcm = NULL; pvoice->interrupt = NULL; - spin_unlock_irqrestore(&chip->voice_lock, flags); return 0; } @@ -292,7 +280,7 @@ static void snd_ymfpci_pcm_interrupt(struct snd_ymfpci *chip, struct snd_ymfpci_ return; if (ypcm->substream == NULL) return; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); if (ypcm->running) { pos = le32_to_cpu(voice->bank[chip->active_bank].start); if (pos < ypcm->last_pos) @@ -334,7 +322,6 @@ static void snd_ymfpci_pcm_interrupt(struct snd_ymfpci *chip, struct snd_ymfpci_ ypcm->update_pcm_vol--; } } - spin_unlock(&chip->reg_lock); } static void snd_ymfpci_pcm_capture_interrupt(struct snd_pcm_substream *substream) @@ -344,7 +331,7 @@ static void snd_ymfpci_pcm_capture_interrupt(struct snd_pcm_substream *substream struct snd_ymfpci *chip = ypcm->chip; u32 pos, delta; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); if (ypcm->running) { pos = le32_to_cpu(chip->bank_capture[ypcm->capture_bank_number][chip->active_bank]->start) >> ypcm->shift; if (pos < ypcm->last_pos) @@ -366,7 +353,6 @@ static void snd_ymfpci_pcm_capture_interrupt(struct snd_pcm_substream *substream spin_lock(&chip->reg_lock); } } - spin_unlock(&chip->reg_lock); } static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, @@ -377,11 +363,9 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, struct snd_kcontrol *kctl = NULL; int result = 0; - spin_lock(&chip->reg_lock); - if (ypcm->voices[0] == NULL) { - result = -EINVAL; - goto __unlock; - } + guard(spinlock)(&chip->reg_lock); + if (ypcm->voices[0] == NULL) + return -EINVAL; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: @@ -405,11 +389,8 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, ypcm->running = 0; break; default: - result = -EINVAL; - break; + return -EINVAL; } - __unlock: - spin_unlock(&chip->reg_lock); if (kctl) snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id); return result; @@ -422,7 +403,7 @@ static int snd_ymfpci_capture_trigger(struct snd_pcm_substream *substream, int result = 0; u32 tmp; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: @@ -442,7 +423,6 @@ static int snd_ymfpci_capture_trigger(struct snd_pcm_substream *substream, result = -EINVAL; break; } - spin_unlock(&chip->reg_lock); return result; } @@ -489,7 +469,6 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int unsigned int nbank; __le32 vol_left, vol_right; u8 use_left, use_right; - unsigned long flags; if (snd_BUG_ON(!voice)) return; @@ -509,26 +488,26 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int vol_left = cpu_to_le32(0x40000000); vol_right = cpu_to_le32(0x40000000); } - spin_lock_irqsave(&ypcm->chip->voice_lock, flags); - format = runtime->channels == 2 ? 0x00010000 : 0; - if (snd_pcm_format_width(runtime->format) == 8) - format |= 0x80000000; - else if (ypcm->chip->device_id == PCI_DEVICE_ID_YAMAHA_754 && - runtime->rate == 44100 && runtime->channels == 2 && - voiceidx == 0 && (ypcm->chip->src441_used == -1 || - ypcm->chip->src441_used == voice->number)) { - ypcm->chip->src441_used = voice->number; - ypcm->use_441_slot = 1; - format |= 0x10000000; - } - if (ypcm->chip->src441_used == voice->number && - (format & 0x10000000) == 0) { - ypcm->chip->src441_used = -1; - ypcm->use_441_slot = 0; + scoped_guard(spinlock_irqsave, &ypcm->chip->voice_lock) { + format = runtime->channels == 2 ? 0x00010000 : 0; + if (snd_pcm_format_width(runtime->format) == 8) + format |= 0x80000000; + else if (ypcm->chip->device_id == PCI_DEVICE_ID_YAMAHA_754 && + runtime->rate == 44100 && runtime->channels == 2 && + voiceidx == 0 && (ypcm->chip->src441_used == -1 || + ypcm->chip->src441_used == voice->number)) { + ypcm->chip->src441_used = voice->number; + ypcm->use_441_slot = 1; + format |= 0x10000000; + } + if (ypcm->chip->src441_used == voice->number && + (format & 0x10000000) == 0) { + ypcm->chip->src441_used = -1; + ypcm->use_441_slot = 0; + } + if (runtime->channels == 2 && (voiceidx & 1) != 0) + format |= 1; } - if (runtime->channels == 2 && (voiceidx & 1) != 0) - format |= 1; - spin_unlock_irqrestore(&ypcm->chip->voice_lock, flags); for (nbank = 0; nbank < 2; nbank++) { bank = &voice->bank[nbank]; memset(bank, 0, sizeof(*bank)); @@ -596,19 +575,18 @@ static int snd_ymfpci_ac3_init(struct snd_ymfpci *chip) chip->bank_effect[4][0]->loop_end = chip->bank_effect[4][1]->loop_end = cpu_to_le32(1024); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); snd_ymfpci_writel(chip, YDSXGR_MAPOFEFFECT, snd_ymfpci_readl(chip, YDSXGR_MAPOFEFFECT) | 3 << 3); - spin_unlock_irq(&chip->reg_lock); return 0; } static int snd_ymfpci_ac3_done(struct snd_ymfpci *chip) { - spin_lock_irq(&chip->reg_lock); - snd_ymfpci_writel(chip, YDSXGR_MAPOFEFFECT, - snd_ymfpci_readl(chip, YDSXGR_MAPOFEFFECT) & ~(3 << 3)); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + snd_ymfpci_writel(chip, YDSXGR_MAPOFEFFECT, + snd_ymfpci_readl(chip, YDSXGR_MAPOFEFFECT) & ~(3 << 3)); + } // snd_ymfpci_irq_wait(chip); if (chip->ac3_tmp_base.area) { snd_dma_free_pages(&chip->ac3_tmp_base); @@ -778,28 +756,28 @@ static irqreturn_t snd_ymfpci_interrupt(int irq, void *dev_id) status = snd_ymfpci_readl(chip, YDSXGR_STATUS); if (status & 0x80000000) { chip->active_bank = snd_ymfpci_readl(chip, YDSXGR_CTRLSELECT) & 1; - spin_lock(&chip->voice_lock); - for (nvoice = 0; nvoice < YDSXG_PLAYBACK_VOICES; nvoice++) { - voice = &chip->voices[nvoice]; - if (voice->interrupt) - voice->interrupt(chip, voice); - } - for (nvoice = 0; nvoice < YDSXG_CAPTURE_VOICES; nvoice++) { - if (chip->capture_substream[nvoice]) - snd_ymfpci_pcm_capture_interrupt(chip->capture_substream[nvoice]); - } + scoped_guard(spinlock, &chip->voice_lock) { + for (nvoice = 0; nvoice < YDSXG_PLAYBACK_VOICES; nvoice++) { + voice = &chip->voices[nvoice]; + if (voice->interrupt) + voice->interrupt(chip, voice); + } + for (nvoice = 0; nvoice < YDSXG_CAPTURE_VOICES; nvoice++) { + if (chip->capture_substream[nvoice]) + snd_ymfpci_pcm_capture_interrupt(chip->capture_substream[nvoice]); + } #if 0 - for (nvoice = 0; nvoice < YDSXG_EFFECT_VOICES; nvoice++) { - if (chip->effect_substream[nvoice]) - snd_ymfpci_pcm_effect_interrupt(chip->effect_substream[nvoice]); - } + for (nvoice = 0; nvoice < YDSXG_EFFECT_VOICES; nvoice++) { + if (chip->effect_substream[nvoice]) + snd_ymfpci_pcm_effect_interrupt(chip->effect_substream[nvoice]); + } #endif - spin_unlock(&chip->voice_lock); - spin_lock(&chip->reg_lock); - snd_ymfpci_writel(chip, YDSXGR_STATUS, 0x80000000); - mode = snd_ymfpci_readl(chip, YDSXGR_MODE) | 2; - snd_ymfpci_writel(chip, YDSXGR_MODE, mode); - spin_unlock(&chip->reg_lock); + } + scoped_guard(spinlock, &chip->reg_lock) { + snd_ymfpci_writel(chip, YDSXGR_STATUS, 0x80000000); + mode = snd_ymfpci_readl(chip, YDSXGR_MODE) | 2; + snd_ymfpci_writel(chip, YDSXGR_MODE, mode); + } if (atomic_read(&chip->interrupt_sleep_count)) { atomic_set(&chip->interrupt_sleep_count, 0); @@ -936,12 +914,11 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream) ypcm->output_front = 1; ypcm->output_rear = chip->mode_dup4ch ? 1 : 0; ypcm->swap_rear = 0; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); if (ypcm->output_rear) { ymfpci_open_extension(chip); chip->rear_opened++; } - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -959,14 +936,14 @@ static int snd_ymfpci_playback_spdif_open(struct snd_pcm_substream *substream) ypcm->output_front = 0; ypcm->output_rear = 1; ypcm->swap_rear = 1; - spin_lock_irq(&chip->reg_lock); - snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL, - snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) | 2); - ymfpci_open_extension(chip); - chip->spdif_pcm_bits = chip->spdif_bits; - snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_pcm_bits); - chip->spdif_opened++; - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL, + snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) | 2); + ymfpci_open_extension(chip); + chip->spdif_pcm_bits = chip->spdif_bits; + snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_pcm_bits); + chip->spdif_opened++; + } chip->spdif_pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE | @@ -988,10 +965,9 @@ static int snd_ymfpci_playback_4ch_open(struct snd_pcm_substream *substream) ypcm->output_front = 0; ypcm->output_rear = 1; ypcm->swap_rear = 0; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); ymfpci_open_extension(chip); chip->rear_opened++; - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1048,12 +1024,12 @@ static int snd_ymfpci_playback_close(struct snd_pcm_substream *substream) struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; - spin_lock_irq(&chip->reg_lock); - if (ypcm->output_rear && chip->rear_opened > 0) { - chip->rear_opened--; - ymfpci_close_extension(chip); + scoped_guard(spinlock_irq, &chip->reg_lock) { + if (ypcm->output_rear && chip->rear_opened > 0) { + chip->rear_opened--; + ymfpci_close_extension(chip); + } } - spin_unlock_irq(&chip->reg_lock); return snd_ymfpci_playback_close_1(substream); } @@ -1061,13 +1037,13 @@ static int snd_ymfpci_playback_spdif_close(struct snd_pcm_substream *substream) { struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - spin_lock_irq(&chip->reg_lock); - chip->spdif_opened = 0; - ymfpci_close_extension(chip); - snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL, - snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & ~2); - snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits); - spin_unlock_irq(&chip->reg_lock); + scoped_guard(spinlock_irq, &chip->reg_lock) { + chip->spdif_opened = 0; + ymfpci_close_extension(chip); + snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL, + snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & ~2); + snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits); + } chip->spdif_pcm_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, &chip->spdif_pcm_ctl->id); @@ -1078,12 +1054,12 @@ static int snd_ymfpci_playback_4ch_close(struct snd_pcm_substream *substream) { struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - spin_lock_irq(&chip->reg_lock); - if (chip->rear_opened > 0) { - chip->rear_opened--; - ymfpci_close_extension(chip); + scoped_guard(spinlock_irq, &chip->reg_lock) { + if (chip->rear_opened > 0) { + chip->rear_opened--; + ymfpci_close_extension(chip); + } } - spin_unlock_irq(&chip->reg_lock); return snd_ymfpci_playback_close_1(substream); } @@ -1264,11 +1240,10 @@ static int snd_ymfpci_spdif_default_get(struct snd_kcontrol *kcontrol, { struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); ucontrol->value.iec958.status[0] = (chip->spdif_bits >> 0) & 0xff; ucontrol->value.iec958.status[1] = (chip->spdif_bits >> 8) & 0xff; ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1281,12 +1256,11 @@ static int snd_ymfpci_spdif_default_put(struct snd_kcontrol *kcontrol, val = ((ucontrol->value.iec958.status[0] & 0x3e) << 0) | (ucontrol->value.iec958.status[1] << 8); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); change = chip->spdif_bits != val; chip->spdif_bits = val; if ((snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & 1) && chip->pcm_spdif == NULL) snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits); - spin_unlock_irq(&chip->reg_lock); return change; } @@ -1311,10 +1285,9 @@ static int snd_ymfpci_spdif_mask_get(struct snd_kcontrol *kcontrol, { struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); ucontrol->value.iec958.status[0] = 0x3e; ucontrol->value.iec958.status[1] = 0xff; - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1339,11 +1312,10 @@ static int snd_ymfpci_spdif_stream_get(struct snd_kcontrol *kcontrol, { struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); ucontrol->value.iec958.status[0] = (chip->spdif_pcm_bits >> 0) & 0xff; ucontrol->value.iec958.status[1] = (chip->spdif_pcm_bits >> 8) & 0xff; ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1356,12 +1328,11 @@ static int snd_ymfpci_spdif_stream_put(struct snd_kcontrol *kcontrol, val = ((ucontrol->value.iec958.status[0] & 0x3e) << 0) | (ucontrol->value.iec958.status[1] << 8); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); change = chip->spdif_pcm_bits != val; chip->spdif_pcm_bits = val; if ((snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & 2)) snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_pcm_bits); - spin_unlock_irq(&chip->reg_lock); return change; } @@ -1387,9 +1358,8 @@ static int snd_ymfpci_drec_source_get(struct snd_kcontrol *kcontrol, struct snd_ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); u16 reg; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); reg = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL); - spin_unlock_irq(&chip->reg_lock); if (!(reg & 0x100)) value->value.enumerated.item[0] = 0; else @@ -1402,14 +1372,13 @@ static int snd_ymfpci_drec_source_put(struct snd_kcontrol *kcontrol, struct snd_ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); u16 reg, old_reg; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); old_reg = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL); if (value->value.enumerated.item[0] == 0) reg = old_reg & ~0x100; else reg = (old_reg & ~0x300) | 0x100 | ((value->value.enumerated.item[0] == 2) << 9); snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, reg); - spin_unlock_irq(&chip->reg_lock); return reg != old_reg; } @@ -1469,12 +1438,11 @@ static int snd_ymfpci_put_single(struct snd_kcontrol *kcontrol, } val = (ucontrol->value.integer.value[0] & mask); val <<= shift; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); oval = snd_ymfpci_readl(chip, reg); val = (oval & ~(mask << shift)) | val; change = val != oval; snd_ymfpci_writel(chip, reg, val); - spin_unlock_irq(&chip->reg_lock); return change; } @@ -1510,9 +1478,8 @@ static int snd_ymfpci_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (reg < 0x80 || reg >= 0xc0) return -EINVAL; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); val = snd_ymfpci_readl(chip, reg); - spin_unlock_irq(&chip->reg_lock); ucontrol->value.integer.value[0] = (val >> shift_left) & mask; ucontrol->value.integer.value[1] = (val >> shift_right) & mask; return 0; @@ -1532,12 +1499,11 @@ static int snd_ymfpci_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e val2 = ucontrol->value.integer.value[1] & mask; val1 <<= shift_left; val2 <<= shift_right; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); oval = snd_ymfpci_readl(chip, reg); val1 = (oval & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2; change = val1 != oval; snd_ymfpci_writel(chip, reg, val1); - spin_unlock_irq(&chip->reg_lock); return change; } @@ -1552,12 +1518,11 @@ static int snd_ymfpci_put_nativedacvol(struct snd_kcontrol *kcontrol, value = ucontrol->value.integer.value[0] & 0x3fff; value |= (ucontrol->value.integer.value[1] & 0x3fff) << 16; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); oval = snd_ymfpci_readl(chip, reg); change = value != oval; snd_ymfpci_writel(chip, reg, value); snd_ymfpci_writel(chip, reg2, value); - spin_unlock_irq(&chip->reg_lock); return change; } @@ -1629,9 +1594,8 @@ YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("Loop",NONE,NONE), 0, YDSXGR_SPDIFINCTRL, 4) static int snd_ymfpci_get_gpio_out(struct snd_ymfpci *chip, int pin) { u16 reg, mode; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); reg = snd_ymfpci_readw(chip, YDSXGR_GPIOFUNCENABLE); reg &= ~(1 << (pin + 8)); reg |= (1 << pin); @@ -1642,23 +1606,20 @@ static int snd_ymfpci_get_gpio_out(struct snd_ymfpci *chip, int pin) snd_ymfpci_writew(chip, YDSXGR_GPIOTYPECONFIG, mode); snd_ymfpci_writew(chip, YDSXGR_GPIOFUNCENABLE, reg | (1 << (pin + 8))); mode = snd_ymfpci_readw(chip, YDSXGR_GPIOINSTATUS); - spin_unlock_irqrestore(&chip->reg_lock, flags); return (mode >> pin) & 1; } static int snd_ymfpci_set_gpio_out(struct snd_ymfpci *chip, int pin, int enable) { u16 reg; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); reg = snd_ymfpci_readw(chip, YDSXGR_GPIOFUNCENABLE); reg &= ~(1 << pin); reg &= ~(1 << (pin + 8)); snd_ymfpci_writew(chip, YDSXGR_GPIOFUNCENABLE, reg); snd_ymfpci_writew(chip, YDSXGR_GPIOOUTCTRL, enable << pin); snd_ymfpci_writew(chip, YDSXGR_GPIOFUNCENABLE, reg | (1 << (pin + 8))); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } @@ -1726,7 +1687,6 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); unsigned int subs = kcontrol->id.subdevice; struct snd_pcm_substream *substream; - unsigned long flags; if (ucontrol->value.integer.value[0] != chip->pcm_mixer[subs].left || ucontrol->value.integer.value[1] != chip->pcm_mixer[subs].right) { @@ -1738,13 +1698,12 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol, chip->pcm_mixer[subs].right = 0x8000; substream = (struct snd_pcm_substream *)kcontrol->private_value; - spin_lock_irqsave(&chip->voice_lock, flags); + guard(spinlock_irqsave)(&chip->voice_lock); if (substream->runtime && substream->runtime->private_data) { struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; if (!ypcm->use_441_slot) ypcm->update_pcm_vol = 2; } - spin_unlock_irqrestore(&chip->voice_lock, flags); return 1; } return 0; @@ -1884,11 +1843,10 @@ int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) static int snd_ymfpci_timer_start(struct snd_timer *timer) { struct snd_ymfpci *chip; - unsigned long flags; unsigned int count; chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (timer->sticks > 1) { chip->timer_ticks = timer->sticks; count = timer->sticks - 1; @@ -1902,19 +1860,16 @@ static int snd_ymfpci_timer_start(struct snd_timer *timer) } snd_ymfpci_writew(chip, YDSXGR_TIMERCOUNT, count); snd_ymfpci_writeb(chip, YDSXGR_TIMERCTRL, 0x03); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } static int snd_ymfpci_timer_stop(struct snd_timer *timer) { struct snd_ymfpci *chip; - unsigned long flags; chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); snd_ymfpci_writeb(chip, YDSXGR_TIMERCTRL, 0x00); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } @@ -2273,10 +2228,9 @@ static int snd_ymfpci_resume(struct device *dev) /* start hw again */ if (chip->start_count > 0) { - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); snd_ymfpci_writel(chip, YDSXGR_MODE, chip->saved_ydsxgr_mode); chip->active_bank = snd_ymfpci_readl(chip, YDSXGR_CTRLSELECT); - spin_unlock_irq(&chip->reg_lock); } snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c index 11aacc7e3f0b..a104baac3a94 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c @@ -161,14 +161,13 @@ static void snd_pdacf_ak4117_change(struct ak4117 *ak4117, unsigned char c0, uns if (!(c0 & AK4117_UNLCK)) return; - mutex_lock(&chip->reg_lock); + guard(mutex)(&chip->reg_lock); val = chip->regmap[PDAUDIOCF_REG_SCR>>1]; if (ak4117->rcs0 & AK4117_UNLCK) val |= PDAUDIOCF_BLUE_LED_OFF; else val &= ~PDAUDIOCF_BLUE_LED_OFF; pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val); - mutex_unlock(&chip->reg_lock); } int snd_pdacf_ak4117_create(struct snd_pdacf *chip) diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index 20aba745f1dc..228822996ef7 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -64,21 +64,20 @@ static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd) default: return -EINVAL; } - mutex_lock(&chip->reg_lock); - chip->pcm_running += inc; - tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); - if (chip->pcm_running) { - if ((chip->ak4117->rcs0 & AK4117_UNLCK) || runtime->rate != rate) { - chip->pcm_running -= inc; - ret = -EIO; - goto __end; + scoped_guard(mutex, &chip->reg_lock) { + chip->pcm_running += inc; + tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); + if (chip->pcm_running) { + if ((chip->ak4117->rcs0 & AK4117_UNLCK) || runtime->rate != rate) { + chip->pcm_running -= inc; + ret = -EIO; + break; + } } + tmp &= ~mask; + tmp |= val; + pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp); } - tmp &= ~mask; - tmp |= val; - pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp); - __end: - mutex_unlock(&chip->reg_lock); snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_RATE); return ret; } diff --git a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c index bc2114475810..998cea2d0318 100644 --- a/sound/pcmcia/vx/vxp_mixer.c +++ b/sound/pcmcia/vx/vxp_mixer.c @@ -43,14 +43,12 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v if (val > MIC_LEVEL_MAX) return -EINVAL; - mutex_lock(&_chip->mixer_mutex); + guard(mutex)(&_chip->mixer_mutex); if (chip->mic_level != ucontrol->value.integer.value[0]) { vx_set_mic_level(_chip, ucontrol->value.integer.value[0]); chip->mic_level = ucontrol->value.integer.value[0]; - mutex_unlock(&_chip->mixer_mutex); return 1; } - mutex_unlock(&_chip->mixer_mutex); return 0; } @@ -85,14 +83,13 @@ static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v struct vx_core *_chip = snd_kcontrol_chip(kcontrol); struct snd_vxpocket *chip = to_vxpocket(_chip); int val = !!ucontrol->value.integer.value[0]; - mutex_lock(&_chip->mixer_mutex); + + guard(mutex)(&_chip->mixer_mutex); if (chip->mic_level != val) { vx_set_mic_boost(_chip, val); chip->mic_level = val; - mutex_unlock(&_chip->mixer_mutex); return 1; } - mutex_unlock(&_chip->mixer_mutex); return 0; } diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c index 0bc5c5d9d157..4211e7239138 100644 --- a/sound/pcmcia/vx/vxp_ops.c +++ b/sound/pcmcia/vx/vxp_ops.c @@ -463,7 +463,7 @@ void vx_set_mic_boost(struct vx_core *chip, int boost) if (chip->chip_status & VX_STAT_IS_STALE) return; - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); if (pchip->regCDSP & P24_CDSP_MICS_SEL_MASK) { if (boost) { /* boost: 38 dB */ @@ -476,7 +476,6 @@ void vx_set_mic_boost(struct vx_core *chip, int boost) } vx_outb(chip, CDSP, pchip->regCDSP); } - mutex_unlock(&chip->lock); } /* @@ -505,12 +504,11 @@ void vx_set_mic_level(struct vx_core *chip, int level) if (chip->chip_status & VX_STAT_IS_STALE) return; - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); if (pchip->regCDSP & VXP_CDSP_MIC_SEL_MASK) { level = vx_compute_mic_level(level); vx_outb(chip, MICRO, level); } - mutex_unlock(&chip->lock); } diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c index 13a6f3af13ef..c231a9d6d1de 100644 --- a/sound/ppc/awacs.c +++ b/sound/ppc/awacs.c @@ -137,13 +137,11 @@ static int snd_pmac_awacs_get_volume(struct snd_kcontrol *kcontrol, int reg = kcontrol->private_value & 0xff; int lshift = (kcontrol->private_value >> 8) & 0xff; int inverted = (kcontrol->private_value >> 16) & 1; - unsigned long flags; int vol[2]; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); vol[0] = (chip->awacs_reg[reg] >> lshift) & 0xf; vol[1] = chip->awacs_reg[reg] & 0xf; - spin_unlock_irqrestore(&chip->reg_lock, flags); if (inverted) { vol[0] = 0x0f - vol[0]; vol[1] = 0x0f - vol[1]; @@ -161,7 +159,6 @@ static int snd_pmac_awacs_put_volume(struct snd_kcontrol *kcontrol, int lshift = (kcontrol->private_value >> 8) & 0xff; int inverted = (kcontrol->private_value >> 16) & 1; int val, oldval; - unsigned long flags; unsigned int vol[2]; vol[0] = ucontrol->value.integer.value[0]; @@ -174,14 +171,13 @@ static int snd_pmac_awacs_put_volume(struct snd_kcontrol *kcontrol, } vol[0] &= 0x0f; vol[1] &= 0x0f; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); oldval = chip->awacs_reg[reg]; val = oldval & ~(0xf | (0xf << lshift)); val |= vol[0] << lshift; val |= vol[1]; if (oldval != val) snd_pmac_awacs_write_reg(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); return oldval != reg; } @@ -204,11 +200,9 @@ static int snd_pmac_awacs_get_switch(struct snd_kcontrol *kcontrol, int shift = (kcontrol->private_value >> 8) & 0xff; int invert = (kcontrol->private_value >> 16) & 1; int val; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); val = (chip->awacs_reg[reg] >> shift) & 1; - spin_unlock_irqrestore(&chip->reg_lock, flags); if (invert) val = 1 - val; ucontrol->value.integer.value[0] = val; @@ -224,16 +218,14 @@ static int snd_pmac_awacs_put_switch(struct snd_kcontrol *kcontrol, int invert = (kcontrol->private_value >> 16) & 1; int mask = 1 << shift; int val, changed; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); val = chip->awacs_reg[reg] & ~mask; if (ucontrol->value.integer.value[0] != invert) val |= mask; changed = chip->awacs_reg[reg] != val; if (changed) snd_pmac_awacs_write_reg(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); return changed; } @@ -541,14 +533,12 @@ static int snd_pmac_screamer_mic_boost_get(struct snd_kcontrol *kcontrol, { struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); int val = 0; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (chip->awacs_reg[6] & MASK_MIC_BOOST) val |= 2; if (chip->awacs_reg[0] & MASK_GAINLINE) val |= 1; - spin_unlock_irqrestore(&chip->reg_lock, flags); ucontrol->value.integer.value[0] = val; return 0; } @@ -559,9 +549,8 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); int changed = 0; int val0, val6; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); val0 = chip->awacs_reg[0] & ~MASK_GAINLINE; val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST; if (ucontrol->value.integer.value[0] & 1) @@ -576,7 +565,6 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol, snd_pmac_awacs_write_reg(chip, 6, val6); changed = 1; } - spin_unlock_irqrestore(&chip->reg_lock, flags); return changed; } diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c index bf289783eafd..ab2468790b0c 100644 --- a/sound/ppc/beep.c +++ b/sound/ppc/beep.c @@ -88,7 +88,6 @@ static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, { struct snd_pmac *chip; struct pmac_beep *beep; - unsigned long flags; int beep_speed = 0; int srate; int period, ncycles, nsamples; @@ -112,10 +111,9 @@ static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, return -1; if (! hz) { - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (beep->running) snd_pmac_beep_stop(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } @@ -125,13 +123,11 @@ static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) hz = 1000; - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->playback.running || chip->capture.running || beep->running) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + if (chip->playback.running || chip->capture.running || beep->running) + return 0; + beep->running = 1; } - beep->running = 1; - spin_unlock_irqrestore(&chip->reg_lock, flags); if (hz == beep->hz && beep->volume == beep->volume_play) { nsamples = beep->nsamples; @@ -151,9 +147,8 @@ static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, beep->nsamples = nsamples; } - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); snd_pmac_beep_dma_start(chip, beep->nsamples * 4, beep->addr, beep_speed); - spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c index ba15bc34c9ec..5d6accce3a72 100644 --- a/sound/ppc/burgundy.c +++ b/sound/ppc/burgundy.c @@ -59,9 +59,8 @@ static unsigned snd_pmac_burgundy_rcw(struct snd_pmac *chip, unsigned addr) { unsigned val = 0; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); out_le32(&chip->awacs->codec_ctrl, addr + 0x100000); snd_pmac_burgundy_busy_wait(chip); @@ -83,8 +82,6 @@ snd_pmac_burgundy_rcw(struct snd_pmac *chip, unsigned addr) snd_pmac_burgundy_extend_wait(chip); val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<24; - spin_unlock_irqrestore(&chip->reg_lock, flags); - return val; } @@ -100,17 +97,14 @@ static unsigned snd_pmac_burgundy_rcb(struct snd_pmac *chip, unsigned int addr) { unsigned val = 0; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); out_le32(&chip->awacs->codec_ctrl, addr + 0x100000); snd_pmac_burgundy_busy_wait(chip); snd_pmac_burgundy_extend_wait(chip); val += (in_le32(&chip->awacs->codec_stat) >> 4) & 0xff; - spin_unlock_irqrestore(&chip->reg_lock, flags); - return val; } diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index a3d346f1cc05..6d7dab26ddf2 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -206,32 +206,32 @@ static int snd_pmac_pcm_prepare(struct snd_pmac *chip, struct pmac_stream *rec, * common to many PowerBook G3 systems and random noise otherwise * captured on iBook2's about every third time. -ReneR */ - spin_lock_irq(&chip->reg_lock); - snd_pmac_dma_stop(rec); - chip->extra_dma.cmds->command = cpu_to_le16(DBDMA_STOP); - snd_pmac_dma_set_command(rec, &chip->extra_dma); - snd_pmac_dma_run(rec, RUN); - spin_unlock_irq(&chip->reg_lock); - mdelay(5); - spin_lock_irq(&chip->reg_lock); - /* continuous DMA memory type doesn't provide the physical address, - * so we need to resolve the address here... - */ - offset = runtime->dma_addr; - for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) { - cp->phy_addr = cpu_to_le32(offset); - cp->req_count = cpu_to_le16(rec->period_size); - /*cp->res_count = cpu_to_le16(0);*/ - cp->xfer_status = cpu_to_le16(0); - offset += rec->period_size; + scoped_guard(spinlock_irq, &chip->reg_lock) { + snd_pmac_dma_stop(rec); + chip->extra_dma.cmds->command = cpu_to_le16(DBDMA_STOP); + snd_pmac_dma_set_command(rec, &chip->extra_dma); + snd_pmac_dma_run(rec, RUN); } - /* make loop */ - cp->command = cpu_to_le16(DBDMA_NOP | BR_ALWAYS); - cp->cmd_dep = cpu_to_le32(rec->cmd.addr); + mdelay(5); + scoped_guard(spinlock_irq, &chip->reg_lock) { + /* continuous DMA memory type doesn't provide the physical address, + * so we need to resolve the address here... + */ + offset = runtime->dma_addr; + for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) { + cp->phy_addr = cpu_to_le32(offset); + cp->req_count = cpu_to_le16(rec->period_size); + /*cp->res_count = cpu_to_le16(0);*/ + cp->xfer_status = cpu_to_le16(0); + offset += rec->period_size; + } + /* make loop */ + cp->command = cpu_to_le16(DBDMA_NOP | BR_ALWAYS); + cp->cmd_dep = cpu_to_le32(rec->cmd.addr); - snd_pmac_dma_stop(rec); - snd_pmac_dma_set_command(rec, &rec->cmd); - spin_unlock_irq(&chip->reg_lock); + snd_pmac_dma_stop(rec); + snd_pmac_dma_set_command(rec, &rec->cmd); + } return 0; } @@ -253,26 +253,26 @@ static int snd_pmac_pcm_trigger(struct snd_pmac *chip, struct pmac_stream *rec, return -EBUSY; command = (subs->stream == SNDRV_PCM_STREAM_PLAYBACK ? OUTPUT_MORE : INPUT_MORE) + INTR_ALWAYS; - spin_lock(&chip->reg_lock); - snd_pmac_beep_stop(chip); - snd_pmac_pcm_set_format(chip); - for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) - out_le16(&cp->command, command); - snd_pmac_dma_set_command(rec, &rec->cmd); - (void)in_le32(&rec->dma->status); - snd_pmac_dma_run(rec, RUN|WAKE); - rec->running = 1; - spin_unlock(&chip->reg_lock); + scoped_guard(spinlock, &chip->reg_lock) { + snd_pmac_beep_stop(chip); + snd_pmac_pcm_set_format(chip); + for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) + out_le16(&cp->command, command); + snd_pmac_dma_set_command(rec, &rec->cmd); + (void)in_le32(&rec->dma->status); + snd_pmac_dma_run(rec, RUN|WAKE); + rec->running = 1; + } break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: - spin_lock(&chip->reg_lock); - rec->running = 0; - snd_pmac_dma_stop(rec); - for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) - out_le16(&cp->command, DBDMA_STOP); - spin_unlock(&chip->reg_lock); + scoped_guard(spinlock, &chip->reg_lock) { + rec->running = 0; + snd_pmac_dma_stop(rec); + for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) + out_le16(&cp->command, DBDMA_STOP); + } break; default: @@ -1321,14 +1321,12 @@ int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) void snd_pmac_suspend(struct snd_pmac *chip) { - unsigned long flags; - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); if (chip->suspend) chip->suspend(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_pmac_beep_stop(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); + scoped_guard(spinlock_irqsave, &chip->reg_lock) { + snd_pmac_beep_stop(chip); + } if (chip->irq >= 0) disable_irq(chip->irq); if (chip->tx_irq >= 0) diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index ce7ee2713f9d..225b20f0b71a 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -221,7 +221,6 @@ static int snd_ps3_program_dma(struct snd_ps3_card_info *card, int fill_stages, dma_ch, stage; enum snd_ps3_ch ch; uint32_t ch0_kick_event = 0; /* initialize to mute gcc */ - unsigned long irqsave; int silent = 0; switch (filltype) { @@ -242,7 +241,7 @@ static int snd_ps3_program_dma(struct snd_ps3_card_info *card, snd_ps3_verify_dma_stop(card, 700, 0); fill_stages = 4; - spin_lock_irqsave(&card->dma_lock, irqsave); + guard(spinlock_irqsave)(&card->dma_lock); for (ch = 0; ch < 2; ch++) { for (stage = 0; stage < fill_stages; stage++) { dma_ch = stage * 2 + ch; @@ -289,7 +288,6 @@ static int snd_ps3_program_dma(struct snd_ps3_card_info *card, } /* ensure the hardware sees the change */ wmb(); - spin_unlock_irqrestore(&card->dma_lock, irqsave); return 0; } @@ -561,7 +559,6 @@ static int snd_ps3_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); - unsigned long irqsave; if (!snd_ps3_set_avsetting(substream)) { /* some parameter changed */ @@ -578,8 +575,7 @@ static int snd_ps3_pcm_prepare(struct snd_pcm_substream *substream) } /* restart ring buffer pointer */ - spin_lock_irqsave(&card->dma_lock, irqsave); - { + scoped_guard(spinlock_irqsave, &card->dma_lock) { card->dma_buffer_size = runtime->dma_bytes; card->dma_last_transfer_vaddr[SND_PS3_CH_L] = @@ -600,7 +596,6 @@ static int snd_ps3_pcm_prepare(struct snd_pcm_substream *substream) card->dma_start_bus_addr[SND_PS3_CH_L]); } - spin_unlock_irqrestore(&card->dma_lock, irqsave); /* ensure the hardware sees the change */ mb(); @@ -618,11 +613,9 @@ static int snd_ps3_pcm_trigger(struct snd_pcm_substream *substream, /* clear outstanding interrupts */ update_reg(PS3_AUDIO_AX_IS, 0); - spin_lock(&card->dma_lock); - { + scoped_guard(spinlock, &card->dma_lock) { card->running = 1; } - spin_unlock(&card->dma_lock); snd_ps3_program_dma(card, SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL); @@ -636,11 +629,9 @@ static int snd_ps3_pcm_trigger(struct snd_pcm_substream *substream, break; case SNDRV_PCM_TRIGGER_STOP: - spin_lock(&card->dma_lock); - { + scoped_guard(spinlock, &card->dma_lock) { card->running = 0; } - spin_unlock(&card->dma_lock); snd_ps3_wait_for_dma_stop(card); break; default: @@ -661,12 +652,10 @@ static snd_pcm_uframes_t snd_ps3_pcm_pointer( size_t bytes; snd_pcm_uframes_t ret; - spin_lock(&card->dma_lock); - { + scoped_guard(spinlock, &card->dma_lock) { bytes = (size_t)(card->dma_last_transfer_vaddr[SND_PS3_CH_L] - card->dma_start_vaddr[SND_PS3_CH_L]); } - spin_unlock(&card->dma_lock); ret = bytes_to_frames(substream->runtime, bytes * 2); diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index aeffd24710e7..7e9c07488dcc 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -147,7 +147,7 @@ static int rembrandt_audio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acp_chip_info *chip; - u32 ret; + int ret; chip = dev_get_platdata(&pdev->dev); if (!chip || !chip->base) { diff --git a/sound/soc/amd/acp/amd-sdw-acpi.c b/sound/soc/amd/acp/amd-sdw-acpi.c index 238b584887ee..0160b0df26a0 100644 --- a/sound/soc/amd/acp/amd-sdw-acpi.c +++ b/sound/soc/amd/acp/amd-sdw-acpi.c @@ -17,8 +17,8 @@ #include <linux/device.h> #include <linux/errno.h> #include <linux/export.h> -#include <linux/fwnode.h> #include <linux/module.h> +#include <linux/property.h> #include <linux/soundwire/sdw_amd.h> #include <linux/string.h> diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c index e7f2a05e802c..352485dd98b1 100644 --- a/sound/soc/amd/raven/acp3x-i2s.c +++ b/sound/soc/amd/raven/acp3x-i2s.c @@ -149,8 +149,9 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct i2s_stream_instance *rtd; - u32 ret, val, period_bytes, reg_val, ier_val, water_val; + u32 val, period_bytes, reg_val, ier_val, water_val; u32 buf_size, buf_reg; + int ret; rtd = substream->runtime->private_data; period_bytes = frames_to_bytes(substream->runtime, diff --git a/sound/soc/amd/vangogh/acp5x-i2s.c b/sound/soc/amd/vangogh/acp5x-i2s.c index 7dbe33f4b867..bf719f628617 100644 --- a/sound/soc/amd/vangogh/acp5x-i2s.c +++ b/sound/soc/amd/vangogh/acp5x-i2s.c @@ -234,8 +234,9 @@ static int acp5x_i2s_trigger(struct snd_pcm_substream *substream, { struct i2s_stream_instance *rtd; struct i2s_dev_data *adata; - u32 ret, val, period_bytes, reg_val, ier_val, water_val; + u32 val, period_bytes, reg_val, ier_val, water_val; u32 buf_size, buf_reg; + int ret; adata = snd_soc_dai_get_drvdata(dai); rtd = substream->runtime->private_data; diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c index 5dd24ab90d0f..c4dcb2b54591 100644 --- a/sound/soc/apple/mca.c +++ b/sound/soc/apple/mca.c @@ -1191,6 +1191,7 @@ static void apple_mca_remove(struct platform_device *pdev) } static const struct of_device_id apple_mca_of_match[] = { + { .compatible = "apple,t8103-mca", }, { .compatible = "apple,mca", }, {} }; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index dfe907c62604..160c07699a8b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -125,6 +125,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_ES7134 imply SND_SOC_ES7241 imply SND_SOC_FRAMER + imply SND_SOC_FS210X imply SND_SOC_GTM601 imply SND_SOC_HDAC_HDMI imply SND_SOC_HDAC_HDA @@ -177,6 +178,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_NAU8825 imply SND_SOC_HDMI_CODEC imply SND_SOC_PCM1681 + imply SND_SOC_PCM1754 imply SND_SOC_PCM1789_I2C imply SND_SOC_PCM179X_I2C imply SND_SOC_PCM179X_SPI @@ -192,6 +194,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_PCM512x_SPI imply SND_SOC_PCM6240 imply SND_SOC_PEB2466 + imply SND_SOC_PM4125_SDW imply SND_SOC_RK3308 imply SND_SOC_RK3328 imply SND_SOC_RK817 @@ -265,6 +268,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_TAS2770 imply SND_SOC_TAS2780 imply SND_SOC_TAS2781_I2C + imply SND_SOC_TAS2783_SDW imply SND_SOC_TAS5086 imply SND_SOC_TAS571X imply SND_SOC_TAS5720 @@ -300,7 +304,6 @@ config SND_SOC_ALL_CODECS imply SND_SOC_LPASS_MACRO_COMMON imply SND_SOC_LPASS_RX_MACRO imply SND_SOC_LPASS_TX_MACRO - imply SND_SOC_WL1273 imply SND_SOC_WM0010 imply SND_SOC_WM1250_EV1 imply SND_SOC_WM2000 @@ -622,6 +625,7 @@ config SND_SOC_AK4619 config SND_SOC_AK4641 tristate depends on I2C + depends on GPIOLIB_LEGACY config SND_SOC_AK4642 tristate "AKM AK4642 CODEC" @@ -1232,6 +1236,21 @@ config SND_SOC_FRAMER To compile this driver as a module, choose M here: the module will be called snd-soc-framer. +config SND_SOC_FS_AMP_LIB + select CRC16 + tristate + +config SND_SOC_FS210X + tristate 'FourSemi FS2104/5S digital audio amplifier' + depends on I2C + select GPIOLIB + select REGMAP_I2C + select SND_SOC_FS_AMP_LIB + help + Enable support for FourSemi FS2104/5S digital audio amplifier. + The FS2104/5S are Inductor-Less, Stereo, Closed-Loop, + Digital Input Class-D Power Amplifiers with Enhanced Signal Processing. + The amplifiers support I2C and I2S/TDM. config SND_SOC_GTM601 tristate 'GTM601 UMTS modem audio codec' @@ -1426,6 +1445,10 @@ config SND_SOC_PCM1681 tristate "Texas Instruments PCM1681 CODEC" depends on I2C +config SND_SOC_PCM1754 + tristate "Texas Instruments PCM1754 CODEC" + depends on GPIOLIB + config SND_SOC_PCM1789 tristate @@ -1542,6 +1565,23 @@ config SND_SOC_PEB2466 To compile this driver as a module, choose M here: the module will be called snd-soc-peb2466. +config SND_SOC_PM4125 + depends on SND_SOC_PM4125_SDW + tristate + depends on SOUNDWIRE || !SOUNDWIRE + +config SND_SOC_PM4125_SDW + tristate "PM4125 audio codec - SDW" + select SND_SOC_PM4125 + select SND_SOC_WCD_MBHC + select REGMAP_IRQ + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + help + The PMIC PM4125 has an in-built audio codec IC used with SoCs + like QCM2290, and it is connected via soundwire and SPMI. + To compile this codec driver say Y or m. + config SND_SOC_RK3308 tristate "Rockchip RK3308 audio CODEC" depends on ARM64 || COMPILE_TEST @@ -2059,6 +2099,19 @@ config SND_SOC_TAS2781_I2C algo coefficient setting, for one, two or even multiple TAS2781 chips. +config SND_SOC_TAS2783_SDW + tristate "Texas Instruments TAS2783 speaker amplifier (sdw)" + depends on SOUNDWIRE + depends on EFI + select REGMAP_SOUNDWIRE + select REGMAP_SOUNDWIRE_MBQ + select CRC32 + help + Enable support for Texas Instruments TAS2783A Digital input + mono Class-D and DSP-inside audio power amplifiers. TAS2783 + driver implements a flexible and configurable algorithm + cofficient setting, for one, two or multiple TAS2783 chips. + config SND_SOC_TAS5086 tristate "Texas Instruments TAS5086 speaker amplifier" depends on I2C @@ -2176,6 +2229,7 @@ config SND_SOC_TLV320AIC3X_SPI config SND_SOC_TLV320DAC33 tristate depends on I2C + depends on GPIOLIB_LEGACY config SND_SOC_TLV320ADCX140 tristate "Texas Instruments TLV320ADCX140 CODEC family" @@ -2230,10 +2284,14 @@ config SND_SOC_UDA1342 config SND_SOC_UDA1380 tristate depends on I2C + depends on GPIOLIB_LEGACY config SND_SOC_WCD_CLASSH tristate +config SND_SOC_WCD_COMMON + tristate + config SND_SOC_WCD9335 tristate "WCD9335 Codec" depends on SLIMBUS @@ -2255,6 +2313,7 @@ config SND_SOC_WCD934X select REGMAP_IRQ select REGMAP_SLIMBUS select SND_SOC_WCD_CLASSH + select SND_SOC_WCD_COMMON select SND_SOC_WCD_MBHC depends on MFD_WCD934X || COMPILE_TEST help @@ -2266,6 +2325,7 @@ config SND_SOC_WCD937X tristate depends on SOUNDWIRE || !SOUNDWIRE select SND_SOC_WCD_CLASSH + select SND_SOC_WCD_COMMON config SND_SOC_WCD937X_SDW tristate "WCD9370/WCD9375 Codec - SDW" @@ -2285,6 +2345,7 @@ config SND_SOC_WCD938X tristate depends on SOUNDWIRE || !SOUNDWIRE select SND_SOC_WCD_CLASSH + select SND_SOC_WCD_COMMON select MULTIPLEXER config SND_SOC_WCD938X_SDW @@ -2304,6 +2365,7 @@ config SND_SOC_WCD939X depends on SOUNDWIRE || !SOUNDWIRE depends on TYPEC || !TYPEC select SND_SOC_WCD_CLASSH + select SND_SOC_WCD_COMMON config SND_SOC_WCD939X_SDW tristate "WCD9390/WCD9395 Codec - SDW" @@ -2317,9 +2379,6 @@ config SND_SOC_WCD939X_SDW The WCD9390/9395 is a audio codec IC Integrated in Qualcomm SoCs like SM8650. -config SND_SOC_WL1273 - tristate - config SND_SOC_WM0010 tristate depends on SPI_MASTER diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index a68c3d192a1b..bd95a7c911d5 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -137,6 +137,8 @@ snd-soc-es8328-spi-y := es8328-spi.o snd-soc-es8375-y := es8375.o snd-soc-es8389-y := es8389.o snd-soc-framer-y := framer-codec.o +snd-soc-fs-amp-lib-y := fs-amp-lib.o +snd-soc-fs210x-y := fs210x.o snd-soc-gtm601-y := gtm601.o snd-soc-hdac-hdmi-y := hdac_hdmi.o snd-soc-hdac-hda-y := hdac_hda.o @@ -201,6 +203,7 @@ snd-soc-ntp8918-y := ntp8918.o snd-soc-ntpfw-y := ntpfw.o snd-soc-hdmi-codec-y := hdmi-codec.o snd-soc-pcm1681-y := pcm1681.o +snd-soc-pcm1754-y := pcm1754.o snd-soc-pcm1789-codec-y := pcm1789.o snd-soc-pcm1789-i2c-y := pcm1789-i2c.o snd-soc-pcm179x-codec-y := pcm179x.o @@ -222,6 +225,8 @@ snd-soc-pcm512x-i2c-y := pcm512x-i2c.o snd-soc-pcm512x-spi-y := pcm512x-spi.o snd-soc-pcm6240-y := pcm6240.o snd-soc-peb2466-y := peb2466.o +snd-soc-pm4125-y := pm4125.o +snd-soc-pm4125-sdw-y := pm4125-sdw.o snd-soc-rk3308-y := rk3308_codec.o snd-soc-rk3328-y := rk3328_codec.o snd-soc-rk817-y := rk817_codec.o @@ -314,6 +319,7 @@ snd-soc-tas2781-comlib-y := tas2781-comlib.o snd-soc-tas2781-comlib-i2c-y := tas2781-comlib-i2c.o snd-soc-tas2781-fmwlib-y := tas2781-fmwlib.o snd-soc-tas2781-i2c-y := tas2781-i2c.o +snd-soc-tas2783-sdw-y := tas2783-sdw.o snd-soc-tfa9879-y := tfa9879.o snd-soc-tfa989x-y := tfa989x.o snd-soc-tlv320adc3xxx-y := tlv320adc3xxx.o @@ -339,6 +345,7 @@ snd-soc-uda1334-y := uda1334.o snd-soc-uda1342-y := uda1342.o snd-soc-uda1380-y := uda1380.o snd-soc-wcd-classh-y := wcd-clsh-v2.o +snd-soc-wcd-common-y := wcd-common.o snd-soc-wcd-mbhc-y := wcd-mbhc-v2.o snd-soc-wcd9335-y := wcd9335.o snd-soc-wcd934x-y := wcd934x.o @@ -348,7 +355,6 @@ snd-soc-wcd938x-y := wcd938x.o snd-soc-wcd938x-sdw-y := wcd938x-sdw.o snd-soc-wcd939x-y := wcd939x.o snd-soc-wcd939x-sdw-y := wcd939x-sdw.o -snd-soc-wl1273-y := wl1273.o snd-soc-wm-adsp-y := wm_adsp.o snd-soc-wm0010-y := wm0010.o snd-soc-wm1250-ev1-y := wm1250-ev1.o @@ -562,6 +568,8 @@ obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o obj-$(CONFIG_SND_SOC_ES8375) += snd-soc-es8375.o obj-$(CONFIG_SND_SOC_ES8389) += snd-soc-es8389.o obj-$(CONFIG_SND_SOC_FRAMER) += snd-soc-framer.o +obj-$(CONFIG_SND_SOC_FS_AMP_LIB)+= snd-soc-fs-amp-lib.o +obj-$(CONFIG_SND_SOC_FS210X) += snd-soc-fs210x.o obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o obj-$(CONFIG_SND_SOC_HDAC_HDA) += snd-soc-hdac-hda.o @@ -621,6 +629,7 @@ obj-$(CONFIG_SND_SOC_NTP8918) += snd-soc-ntp8918.o obj-$(CONFIG_SND_SOC_NTPFW) += snd-soc-ntpfw.o obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o +obj-$(CONFIG_SND_SOC_PCM1754) += snd-soc-pcm1754.o obj-$(CONFIG_SND_SOC_PCM179X) += snd-soc-pcm179x-codec.o obj-$(CONFIG_SND_SOC_PCM1789_I2C) += snd-soc-pcm1789-i2c.o obj-$(CONFIG_SND_SOC_PCM1789) += snd-soc-pcm1789-codec.o @@ -642,6 +651,12 @@ obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o obj-$(CONFIG_SND_SOC_PCM6240) += snd-soc-pcm6240.o obj-$(CONFIG_SND_SOC_PEB2466) += snd-soc-peb2466.o +obj-$(CONFIG_SND_SOC_PM4125_SDW) += snd-soc-pm4125-sdw.o +obj-$(CONFIG_SND_SOC_PM4125) += snd-soc-pm4125.o +ifdef CONFIG_SND_SOC_PM4125_SDW +# avoid link failure by forcing sdw code built-in when needed +obj-$(CONFIG_SND_SOC_PM4125) += snd-soc-pm4125-sdw.o +endif obj-$(CONFIG_SND_SOC_RK3308) += snd-soc-rk3308.o obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o @@ -729,6 +744,7 @@ obj-$(CONFIG_SND_SOC_TAS2781_COMLIB) += snd-soc-tas2781-comlib.o obj-$(CONFIG_SND_SOC_TAS2781_COMLIB_I2C) += snd-soc-tas2781-comlib-i2c.o obj-$(CONFIG_SND_SOC_TAS2781_FMWLIB) += snd-soc-tas2781-fmwlib.o obj-$(CONFIG_SND_SOC_TAS2781_I2C) += snd-soc-tas2781-i2c.o +obj-$(CONFIG_SND_SOC_TAS2783_SDW) += snd-soc-tas2783-sdw.o obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o @@ -761,6 +777,7 @@ obj-$(CONFIG_SND_SOC_UDA1334) += snd-soc-uda1334.o obj-$(CONFIG_SND_SOC_UDA1342) += snd-soc-uda1342.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WCD_CLASSH) += snd-soc-wcd-classh.o +obj-$(CONFIG_SND_SOC_WCD_COMMON) += snd-soc-wcd-common.o obj-$(CONFIG_SND_SOC_WCD_MBHC) += snd-soc-wcd-mbhc.o obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o obj-$(CONFIG_SND_SOC_WCD934X) += snd-soc-wcd934x.o @@ -779,7 +796,6 @@ ifdef CONFIG_SND_SOC_WCD939X_SDW # avoid link failure by forcing sdw code built-in when needed obj-$(CONFIG_SND_SOC_WCD939X) += snd-soc-wcd939x-sdw.o endif -obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o obj-$(CONFIG_SND_SOC_WM0010) += snd-soc-wm0010.o obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c index ae59efb38f26..c193a9f22f59 100644 --- a/sound/soc/codecs/adau1977.c +++ b/sound/soc/codecs/adau1977.c @@ -795,7 +795,7 @@ static int adau1977_set_sysclk(struct snd_soc_component *component, struct adau1977 *adau1977 = snd_soc_component_get_drvdata(component); unsigned int mask = 0; unsigned int clk_src; - unsigned int ret; + int ret; if (dir != SND_SOC_CLOCK_IN) return -EINVAL; diff --git a/sound/soc/codecs/cs-amp-lib-test.c b/sound/soc/codecs/cs-amp-lib-test.c index f53650128fc3..2fde84309338 100644 --- a/sound/soc/codecs/cs-amp-lib-test.c +++ b/sound/soc/codecs/cs-amp-lib-test.c @@ -19,6 +19,14 @@ #include <linux/random.h> #include <sound/cs-amp-lib.h> +#define LENOVO_SPEAKER_ID_EFI_NAME L"SdwSpeaker" +#define LENOVO_SPEAKER_ID_EFI_GUID \ + EFI_GUID(0x48df970e, 0xe27f, 0x460a, 0xb5, 0x86, 0x77, 0x19, 0x80, 0x1d, 0x92, 0x82) + +#define HP_SPEAKER_ID_EFI_NAME L"HPSpeakerID" +#define HP_SPEAKER_ID_EFI_GUID \ + EFI_GUID(0xc49593a4, 0xd099, 0x419b, 0xa2, 0xc3, 0x67, 0xe9, 0x80, 0xe6, 0x1d, 0x1e) + KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy, struct faux_device *) @@ -196,8 +204,40 @@ static efi_status_t cs_amp_lib_test_get_efi_variable(efi_char16_t *name, KUNIT_EXPECT_NOT_ERR_OR_NULL(test, guid); KUNIT_EXPECT_NOT_ERR_OR_NULL(test, size); - KUNIT_EXPECT_MEMEQ(test, name, expected_name, sizeof(expected_name)); - KUNIT_EXPECT_MEMEQ(test, guid, &expected_guid, sizeof(expected_guid)); + if (memcmp(name, expected_name, sizeof(expected_name)) || + efi_guidcmp(*guid, expected_guid)) + return -EFI_NOT_FOUND; + + if (!buf) { + *size = priv->cal_blob->size; + return EFI_BUFFER_TOO_SMALL; + } + + KUNIT_ASSERT_GE_MSG(test, ksize(buf), priv->cal_blob->size, "Buffer to small"); + + memcpy(buf, priv->cal_blob, priv->cal_blob->size); + + return EFI_SUCCESS; +} + +static efi_status_t cs_amp_lib_test_get_hp_cal_efi_variable(efi_char16_t *name, + efi_guid_t *guid, + unsigned long *size, + void *buf) +{ + static const efi_char16_t expected_name[] = L"SmartAmpCalibrationData"; + static const efi_guid_t expected_guid = + EFI_GUID(0x53559579, 0x8753, 0x4f5c, 0x91, 0x30, 0xe8, 0x2a, 0xcf, 0xb8, 0xd8, 0x93); + struct kunit *test = kunit_get_current_test(); + struct cs_amp_lib_test_priv *priv = test->priv; + + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, name); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, guid); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, size); + + if (memcmp(name, expected_name, sizeof(expected_name)) || + efi_guidcmp(*guid, expected_guid)) + return -EFI_NOT_FOUND; if (!buf) { *size = priv->cal_blob->size; @@ -211,6 +251,25 @@ static efi_status_t cs_amp_lib_test_get_efi_variable(efi_char16_t *name, return EFI_SUCCESS; } +/* Get cal data block from HP variable. */ +static void cs_amp_lib_test_get_hp_efi_cal(struct kunit *test) +{ + struct cs_amp_lib_test_priv *priv = test->priv; + struct cirrus_amp_cal_data result_data; + int ret; + + cs_amp_lib_test_init_dummy_cal_blob(test, 2); + + kunit_activate_static_stub(test, + cs_amp_test_hooks->get_efi_variable, + cs_amp_lib_test_get_hp_cal_efi_variable); + + ret = cs_amp_get_efi_calibration_data(&priv->amp_dev->dev, 0, 0, &result_data); + KUNIT_EXPECT_EQ(test, ret, 0); + + KUNIT_EXPECT_MEMEQ(test, &result_data, &priv->cal_blob->data[0], sizeof(result_data)); +} + /* Get cal data block for a given amp, matched by target UID. */ static void cs_amp_lib_test_get_efi_cal_by_uid_test(struct kunit *test) { @@ -642,6 +701,185 @@ static void cs_amp_lib_test_write_cal_data_test(struct kunit *test) KUNIT_EXPECT_EQ(test, entry->value, data.calStatus); } +static void cs_amp_lib_test_spkid_lenovo_not_present(struct kunit *test) +{ + struct cs_amp_lib_test_priv *priv = test->priv; + struct device *dev = &priv->amp_dev->dev; + + kunit_activate_static_stub(test, + cs_amp_test_hooks->get_efi_variable, + cs_amp_lib_test_get_efi_variable_none); + + KUNIT_EXPECT_EQ(test, -ENOENT, cs_amp_get_vendor_spkid(dev)); +} + +static efi_status_t cs_amp_lib_test_get_efi_variable_lenovo_d0(efi_char16_t *name, + efi_guid_t *guid, + unsigned long *size, + void *buf) +{ + struct kunit *test = kunit_get_current_test(); + + if (efi_guidcmp(*guid, LENOVO_SPEAKER_ID_EFI_GUID) || + memcmp(name, LENOVO_SPEAKER_ID_EFI_NAME, sizeof(LENOVO_SPEAKER_ID_EFI_NAME))) + return EFI_NOT_FOUND; + + KUNIT_ASSERT_EQ(test, *size, 1); + *size = 1; + *(u8 *)buf = 0xd0; + + return EFI_SUCCESS; +} + +static efi_status_t cs_amp_lib_test_get_efi_variable_lenovo_d1(efi_char16_t *name, + efi_guid_t *guid, + unsigned long *size, + void *buf) +{ + struct kunit *test = kunit_get_current_test(); + + if (efi_guidcmp(*guid, LENOVO_SPEAKER_ID_EFI_GUID) || + memcmp(name, LENOVO_SPEAKER_ID_EFI_NAME, sizeof(LENOVO_SPEAKER_ID_EFI_NAME))) + return EFI_NOT_FOUND; + + KUNIT_ASSERT_EQ(test, *size, 1); + *size = 1; + *(u8 *)buf = 0xd1; + + return EFI_SUCCESS; +} + +static efi_status_t cs_amp_lib_test_get_efi_variable_lenovo_00(efi_char16_t *name, + efi_guid_t *guid, + unsigned long *size, + void *buf) +{ + struct kunit *test = kunit_get_current_test(); + + KUNIT_ASSERT_EQ(test, 0, efi_guidcmp(*guid, LENOVO_SPEAKER_ID_EFI_GUID)); + KUNIT_ASSERT_EQ(test, *size, 1); + *size = 1; + *(u8 *)buf = 0; + + return EFI_SUCCESS; +} + +static void cs_amp_lib_test_spkid_lenovo_d0(struct kunit *test) +{ + struct cs_amp_lib_test_priv *priv = test->priv; + struct device *dev = &priv->amp_dev->dev; + + kunit_activate_static_stub(test, + cs_amp_test_hooks->get_efi_variable, + cs_amp_lib_test_get_efi_variable_lenovo_d0); + + KUNIT_EXPECT_EQ(test, 0, cs_amp_get_vendor_spkid(dev)); +} + +static void cs_amp_lib_test_spkid_lenovo_d1(struct kunit *test) +{ + struct cs_amp_lib_test_priv *priv = test->priv; + struct device *dev = &priv->amp_dev->dev; + + kunit_activate_static_stub(test, + cs_amp_test_hooks->get_efi_variable, + cs_amp_lib_test_get_efi_variable_lenovo_d1); + + KUNIT_EXPECT_EQ(test, 1, cs_amp_get_vendor_spkid(dev)); +} + +static void cs_amp_lib_test_spkid_lenovo_illegal(struct kunit *test) +{ + struct cs_amp_lib_test_priv *priv = test->priv; + struct device *dev = &priv->amp_dev->dev; + + kunit_activate_static_stub(test, + cs_amp_test_hooks->get_efi_variable, + cs_amp_lib_test_get_efi_variable_lenovo_00); + + KUNIT_EXPECT_LT(test, cs_amp_get_vendor_spkid(dev), 0); +} + +static efi_status_t cs_amp_lib_test_get_efi_variable_buf_too_small(efi_char16_t *name, + efi_guid_t *guid, + unsigned long *size, + void *buf) +{ + return EFI_BUFFER_TOO_SMALL; +} + +static void cs_amp_lib_test_spkid_lenovo_oversize(struct kunit *test) +{ + struct cs_amp_lib_test_priv *priv = test->priv; + struct device *dev = &priv->amp_dev->dev; + + kunit_activate_static_stub(test, + cs_amp_test_hooks->get_efi_variable, + cs_amp_lib_test_get_efi_variable_buf_too_small); + + KUNIT_EXPECT_LT(test, cs_amp_get_vendor_spkid(dev), 0); +} + +static efi_status_t cs_amp_lib_test_get_efi_variable_hp_30(efi_char16_t *name, + efi_guid_t *guid, + unsigned long *size, + void *buf) +{ + struct kunit *test = kunit_get_current_test(); + + if (efi_guidcmp(*guid, HP_SPEAKER_ID_EFI_GUID) || + memcmp(name, HP_SPEAKER_ID_EFI_NAME, sizeof(HP_SPEAKER_ID_EFI_NAME))) + return EFI_NOT_FOUND; + + KUNIT_ASSERT_EQ(test, *size, 1); + *size = 1; + *(u8 *)buf = 0x30; + + return EFI_SUCCESS; +} + +static efi_status_t cs_amp_lib_test_get_efi_variable_hp_31(efi_char16_t *name, + efi_guid_t *guid, + unsigned long *size, + void *buf) +{ + struct kunit *test = kunit_get_current_test(); + + if (efi_guidcmp(*guid, HP_SPEAKER_ID_EFI_GUID) || + memcmp(name, HP_SPEAKER_ID_EFI_NAME, sizeof(HP_SPEAKER_ID_EFI_NAME))) + return EFI_NOT_FOUND; + + KUNIT_ASSERT_EQ(test, *size, 1); + *size = 1; + *(u8 *)buf = 0x31; + + return EFI_SUCCESS; +} + +static void cs_amp_lib_test_spkid_hp_30(struct kunit *test) +{ + struct cs_amp_lib_test_priv *priv = test->priv; + struct device *dev = &priv->amp_dev->dev; + + kunit_activate_static_stub(test, + cs_amp_test_hooks->get_efi_variable, + cs_amp_lib_test_get_efi_variable_hp_30); + + KUNIT_EXPECT_EQ(test, 0, cs_amp_get_vendor_spkid(dev)); +} + +static void cs_amp_lib_test_spkid_hp_31(struct kunit *test) +{ + struct cs_amp_lib_test_priv *priv = test->priv; + struct device *dev = &priv->amp_dev->dev; + + kunit_activate_static_stub(test, + cs_amp_test_hooks->get_efi_variable, + cs_amp_lib_test_get_efi_variable_hp_31); + + KUNIT_EXPECT_EQ(test, 1, cs_amp_get_vendor_spkid(dev)); +} + static int cs_amp_lib_test_case_init(struct kunit *test) { struct cs_amp_lib_test_priv *priv; @@ -722,6 +960,7 @@ static struct kunit_case cs_amp_lib_test_cases[] = { KUNIT_CASE(cs_amp_lib_test_get_efi_cal_no_uid_index_not_found_test), KUNIT_CASE(cs_amp_lib_test_get_efi_cal_no_uid_no_index_test), KUNIT_CASE(cs_amp_lib_test_get_efi_cal_zero_not_matched_test), + KUNIT_CASE(cs_amp_lib_test_get_hp_efi_cal), KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_uid_test, cs_amp_lib_test_get_cal_gen_params), KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_index_unchecked_test, @@ -737,6 +976,15 @@ static struct kunit_case cs_amp_lib_test_cases[] = { /* Tests for writing calibration data */ KUNIT_CASE(cs_amp_lib_test_write_cal_data_test), + /* Test cases for speaker ID */ + KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_not_present), + KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_d0), + KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_d1), + KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_illegal), + KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_oversize), + KUNIT_CASE(cs_amp_lib_test_spkid_hp_30), + KUNIT_CASE(cs_amp_lib_test_spkid_hp_31), + { } /* terminator */ }; diff --git a/sound/soc/codecs/cs-amp-lib.c b/sound/soc/codecs/cs-amp-lib.c index 808e67c90f7c..8434d5196107 100644 --- a/sound/soc/codecs/cs-amp-lib.c +++ b/sound/soc/codecs/cs-amp-lib.c @@ -16,10 +16,35 @@ #include <linux/types.h> #include <sound/cs-amp-lib.h> -#define CS_AMP_CAL_GUID \ +#define CIRRUS_LOGIC_CALIBRATION_EFI_NAME L"CirrusSmartAmpCalibrationData" +#define CIRRUS_LOGIC_CALIBRATION_EFI_GUID \ EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3) -#define CS_AMP_CAL_NAME L"CirrusSmartAmpCalibrationData" +#define LENOVO_SPEAKER_ID_EFI_NAME L"SdwSpeaker" +#define LENOVO_SPEAKER_ID_EFI_GUID \ + EFI_GUID(0x48df970e, 0xe27f, 0x460a, 0xb5, 0x86, 0x77, 0x19, 0x80, 0x1d, 0x92, 0x82) + +#define HP_SPEAKER_ID_EFI_NAME L"HPSpeakerID" +#define HP_SPEAKER_ID_EFI_GUID \ + EFI_GUID(0xc49593a4, 0xd099, 0x419b, 0xa2, 0xc3, 0x67, 0xe9, 0x80, 0xe6, 0x1d, 0x1e) + +#define HP_CALIBRATION_EFI_NAME L"SmartAmpCalibrationData" +#define HP_CALIBRATION_EFI_GUID \ + EFI_GUID(0x53559579, 0x8753, 0x4f5c, 0x91, 0x30, 0xe8, 0x2a, 0xcf, 0xb8, 0xd8, 0x93) + +static const struct cs_amp_lib_cal_efivar { + efi_char16_t *name; + efi_guid_t *guid; +} cs_amp_lib_cal_efivars[] = { + { + .name = HP_CALIBRATION_EFI_NAME, + .guid = &HP_CALIBRATION_EFI_GUID, + }, + { + .name = CIRRUS_LOGIC_CALIBRATION_EFI_NAME, + .guid = &CIRRUS_LOGIC_CALIBRATION_EFI_GUID, + }, +}; static int cs_amp_write_cal_coeff(struct cs_dsp *dsp, const struct cirrus_amp_cal_controls *controls, @@ -115,16 +140,41 @@ static efi_status_t cs_amp_get_efi_variable(efi_char16_t *name, return EFI_NOT_FOUND; } +static int cs_amp_convert_efi_status(efi_status_t status) +{ + switch (status) { + case EFI_SUCCESS: + return 0; + case EFI_NOT_FOUND: + return -ENOENT; + case EFI_BUFFER_TOO_SMALL: + return -EFBIG; + case EFI_UNSUPPORTED: + case EFI_ACCESS_DENIED: + case EFI_SECURITY_VIOLATION: + return -EACCES; + default: + return -EIO; + } +} + static struct cirrus_amp_efi_data *cs_amp_get_cal_efi_buffer(struct device *dev) { struct cirrus_amp_efi_data *efi_data; unsigned long data_size = 0; u8 *data; efi_status_t status; - int ret; + int i, ret; + + /* Find EFI variable and get size */ + for (i = 0; i < ARRAY_SIZE(cs_amp_lib_cal_efivars); i++) { + status = cs_amp_get_efi_variable(cs_amp_lib_cal_efivars[i].name, + cs_amp_lib_cal_efivars[i].guid, + &data_size, NULL); + if (status == EFI_BUFFER_TOO_SMALL) + break; + } - /* Get real size of UEFI variable */ - status = cs_amp_get_efi_variable(CS_AMP_CAL_NAME, &CS_AMP_CAL_GUID, &data_size, NULL); if (status != EFI_BUFFER_TOO_SMALL) return ERR_PTR(-ENOENT); @@ -138,7 +188,9 @@ static struct cirrus_amp_efi_data *cs_amp_get_cal_efi_buffer(struct device *dev) if (!data) return ERR_PTR(-ENOMEM); - status = cs_amp_get_efi_variable(CS_AMP_CAL_NAME, &CS_AMP_CAL_GUID, &data_size, data); + status = cs_amp_get_efi_variable(cs_amp_lib_cal_efivars[i].name, + cs_amp_lib_cal_efivars[i].guid, + &data_size, data); if (status != EFI_SUCCESS) { ret = -EINVAL; goto err; @@ -273,6 +325,81 @@ int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_ } EXPORT_SYMBOL_NS_GPL(cs_amp_get_efi_calibration_data, "SND_SOC_CS_AMP_LIB"); +struct cs_amp_spkid_efi { + efi_char16_t *name; + efi_guid_t *guid; + u8 values[2]; +}; + +static int cs_amp_get_efi_byte_spkid(struct device *dev, const struct cs_amp_spkid_efi *info) +{ + efi_status_t status; + unsigned long size; + u8 spkid; + int i, ret; + + size = sizeof(spkid); + status = cs_amp_get_efi_variable(info->name, info->guid, &size, &spkid); + ret = cs_amp_convert_efi_status(status); + if (ret < 0) + return ret; + + if (size == 0) + return -ENOENT; + + for (i = 0; i < ARRAY_SIZE(info->values); i++) { + if (info->values[i] == spkid) + return i; + } + + dev_err(dev, "EFI speaker ID bad value %#x\n", spkid); + + return -EINVAL; +} + +static const struct cs_amp_spkid_efi cs_amp_spkid_byte_types[] = { + { + .name = LENOVO_SPEAKER_ID_EFI_NAME, + .guid = &LENOVO_SPEAKER_ID_EFI_GUID, + .values = { 0xd0, 0xd1 }, + }, + { + .name = HP_SPEAKER_ID_EFI_NAME, + .guid = &HP_SPEAKER_ID_EFI_GUID, + .values = { 0x30, 0x31 }, + }, +}; + +/** + * cs_amp_get_vendor_spkid - get a speaker ID from vendor-specific storage + * @dev: pointer to struct device + * + * Known vendor-specific methods of speaker ID are checked and if one is + * found its speaker ID value is returned. + * + * Return: >=0 is a valid speaker ID. -ENOENT if a vendor-specific method + * was not found. -EACCES if the vendor-specific storage could not + * be read. Other error values indicate that the data from the + * vendor-specific storage was found but could not be understood. + */ +int cs_amp_get_vendor_spkid(struct device *dev) +{ + int i, ret; + + if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE) && + !IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST)) + return -ENOENT; + + for (i = 0; i < ARRAY_SIZE(cs_amp_spkid_byte_types); i++) { + ret = cs_amp_get_efi_byte_spkid(dev, &cs_amp_spkid_byte_types[i]); + if (ret != -ENOENT) + return ret; + } + + return -ENOENT; +} +EXPORT_SYMBOL_NS_GPL(cs_amp_get_vendor_spkid, "SND_SOC_CS_AMP_LIB"); + static const struct cs_amp_test_hooks cs_amp_test_hook_ptrs = { .get_efi_variable = cs_amp_get_efi_variable, .write_cal_coeff = cs_amp_write_cal_coeff, diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index 224d65987a8d..173d7c59b725 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -7,6 +7,7 @@ // Author: David Rhodes <david.rhodes@cirrus.com> #include <linux/acpi.h> +#include <acpi/acpi_bus.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/init.h> @@ -1147,45 +1148,55 @@ err_dsp: return ret; } -#ifdef CONFIG_ACPI -static int cs35l41_acpi_get_name(struct cs35l41_private *cs35l41) +static int cs35l41_get_system_name(struct cs35l41_private *cs35l41) { struct acpi_device *adev = ACPI_COMPANION(cs35l41->dev); - acpi_handle handle = acpi_device_handle(adev); - const char *hid; - const char *sub; - - /* If there is no acpi_device, there is no ACPI for this system, return 0 */ - if (!adev) - return 0; + const char *sub = NULL; + const char *tmp; + int ret = 0; - sub = acpi_get_subsystem_id(handle); - if (IS_ERR(sub)) { - /* If no _SUB, fallback to _HID, otherwise fail */ - if (PTR_ERR(sub) == -ENODATA) { - hid = acpi_device_hid(adev); - /* If dummy hid, return 0 and fallback to legacy firmware path */ - if (!strcmp(hid, "device")) - return 0; - sub = kstrdup(hid, GFP_KERNEL); - if (!sub) - sub = ERR_PTR(-ENOMEM); - - } else - return PTR_ERR(sub); + /* If there is no acpi_device, there is no ACPI for this system, skip checking ACPI */ + if (adev) { + acpi_handle handle = acpi_device_handle(adev); + + sub = acpi_get_subsystem_id(handle); + ret = PTR_ERR_OR_ZERO(sub); + if (ret) { + sub = NULL; + /* If no _SUB, fallback to _HID, otherwise fail */ + if (ret == -ENODATA) { + tmp = acpi_device_hid(adev); + /* If dummy hid, return 0 and fallback to legacy firmware path */ + if (!strcmp(tmp, "device")) { + ret = 0; + goto err; + } + sub = kstrdup(tmp, GFP_KERNEL); + if (!sub) { + ret = -ENOMEM; + goto err; + } + } + } + } else { + if (!device_property_read_string(cs35l41->dev, "cirrus,subsystem-id", &tmp)) { + sub = kstrdup(tmp, GFP_KERNEL); + if (!sub) { + ret = -ENOMEM; + goto err; + } + } } - cs35l41->dsp.system_name = sub; - dev_dbg(cs35l41->dev, "Subsystem ID: %s\n", cs35l41->dsp.system_name); +err: + if (sub) { + cs35l41->dsp.system_name = sub; + dev_info(cs35l41->dev, "Subsystem ID: %s\n", cs35l41->dsp.system_name); + } else + dev_warn(cs35l41->dev, "Subsystem ID not found\n"); - return 0; -} -#else -static int cs35l41_acpi_get_name(struct cs35l41_private *cs35l41) -{ - return 0; + return ret; } -#endif /* CONFIG_ACPI */ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *hw_cfg) { @@ -1317,7 +1328,7 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg * goto err; } - ret = cs35l41_acpi_get_name(cs35l41); + ret = cs35l41_get_system_name(cs35l41); if (ret < 0) goto err; diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c index 073f1796ae29..0492ddc4102d 100644 --- a/sound/soc/codecs/cs35l56-i2c.c +++ b/sound/soc/codecs/cs35l56-i2c.c @@ -35,11 +35,11 @@ static int cs35l56_i2c_probe(struct i2c_client *client) switch (id) { case 0x3556: regmap_config = &cs35l56_regmap_i2c; - cs35l56->base.fw_reg = &cs35l56_fw_reg; + cs35l56->base.type = 0x56; break; case 0x3563: regmap_config = &cs35l63_regmap_i2c; - cs35l56->base.fw_reg = &cs35l63_fw_reg; + cs35l56->base.type = 0x63; break; default: return -ENODEV; diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index 3905c9cb188a..42d24ac2977f 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -527,16 +527,16 @@ static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_devi case 0x3556: case 0x3557: regmap_config = &cs35l56_regmap_sdw; - cs35l56->base.fw_reg = &cs35l56_fw_reg; break; case 0x3563: regmap_config = &cs35l63_regmap_sdw; - cs35l56->base.fw_reg = &cs35l63_fw_reg; break; default: return -ENODEV; } + cs35l56->base.type = ((unsigned int)id->driver_data) & 0xff; + cs35l56->base.regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw, peripheral, regmap_config); if (IS_ERR(cs35l56->base.regmap)) { diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 850fcf385996..9e6b9ca2f354 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -309,6 +309,58 @@ static bool cs35l63_volatile_reg(struct device *dev, unsigned int reg) } } +static const struct cs35l56_fw_reg cs35l56_fw_reg = { + .fw_ver = CS35L56_DSP1_FW_VER, + .halo_state = CS35L56_DSP1_HALO_STATE, + .pm_cur_stat = CS35L56_DSP1_PM_CUR_STATE, + .prot_sts = CS35L56_PROTECTION_STATUS, + .transducer_actual_ps = CS35L56_TRANSDUCER_ACTUAL_PS, + .user_mute = CS35L56_MAIN_RENDER_USER_MUTE, + .user_volume = CS35L56_MAIN_RENDER_USER_VOLUME, + .posture_number = CS35L56_MAIN_POSTURE_NUMBER, +}; + +static const struct cs35l56_fw_reg cs35l56_b2_fw_reg = { + .fw_ver = CS35L56_DSP1_FW_VER, + .halo_state = CS35L56_B2_DSP1_HALO_STATE, + .pm_cur_stat = CS35L56_B2_DSP1_PM_CUR_STATE, + .prot_sts = CS35L56_PROTECTION_STATUS, + .transducer_actual_ps = CS35L56_TRANSDUCER_ACTUAL_PS, + .user_mute = CS35L56_MAIN_RENDER_USER_MUTE, + .user_volume = CS35L56_MAIN_RENDER_USER_VOLUME, + .posture_number = CS35L56_MAIN_POSTURE_NUMBER, +}; + +static const struct cs35l56_fw_reg cs35l63_fw_reg = { + .fw_ver = CS35L63_DSP1_FW_VER, + .halo_state = CS35L63_DSP1_HALO_STATE, + .pm_cur_stat = CS35L63_DSP1_PM_CUR_STATE, + .prot_sts = CS35L63_PROTECTION_STATUS, + .transducer_actual_ps = CS35L63_TRANSDUCER_ACTUAL_PS, + .user_mute = CS35L63_MAIN_RENDER_USER_MUTE, + .user_volume = CS35L63_MAIN_RENDER_USER_VOLUME, + .posture_number = CS35L63_MAIN_POSTURE_NUMBER, +}; + +static void cs35l56_set_fw_reg_table(struct cs35l56_base *cs35l56_base) +{ + switch (cs35l56_base->type) { + default: + switch (cs35l56_base->rev) { + case 0xb0: + cs35l56_base->fw_reg = &cs35l56_fw_reg; + break; + default: + cs35l56_base->fw_reg = &cs35l56_b2_fw_reg; + break; + } + break; + case 0x63: + cs35l56_base->fw_reg = &cs35l63_fw_reg; + break; + } +} + int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command) { unsigned int val; @@ -468,6 +520,11 @@ static const struct reg_sequence cs35l56_system_reset_seq[] = { REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), }; +static const struct reg_sequence cs35l56_b2_system_reset_seq[] = { + REG_SEQ0(CS35L56_B2_DSP1_HALO_STATE, 0), + REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), +}; + static const struct reg_sequence cs35l63_system_reset_seq[] = { REG_SEQ0(CS35L63_DSP1_HALO_STATE, 0), REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), @@ -490,9 +547,18 @@ void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire) case 0x54: case 0x56: case 0x57: - regmap_multi_reg_write_bypassed(cs35l56_base->regmap, - cs35l56_system_reset_seq, - ARRAY_SIZE(cs35l56_system_reset_seq)); + switch (cs35l56_base->rev) { + case 0xb0: + regmap_multi_reg_write_bypassed(cs35l56_base->regmap, + cs35l56_system_reset_seq, + ARRAY_SIZE(cs35l56_system_reset_seq)); + break; + default: + regmap_multi_reg_write_bypassed(cs35l56_base->regmap, + cs35l56_b2_system_reset_seq, + ARRAY_SIZE(cs35l56_b2_system_reset_seq)); + break; + } break; case 0x63: regmap_multi_reg_write_bypassed(cs35l56_base->regmap, @@ -979,6 +1045,7 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) return ret; } cs35l56_base->rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK); + cs35l56_set_fw_reg_table(cs35l56_base); ret = cs35l56_wait_for_firmware_boot(cs35l56_base); if (ret) @@ -1054,7 +1121,17 @@ int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base) u32 speaker_id; int i, ret; - /* Attempt to read the speaker type from a device property first */ + /* Check for vendor-specific speaker ID method */ + ret = cs_amp_get_vendor_spkid(cs35l56_base->dev); + if (ret >= 0) { + dev_dbg(cs35l56_base->dev, "Vendor Speaker ID = %d\n", ret); + return ret; + } else if (ret != -ENOENT) { + dev_err(cs35l56_base->dev, "Error getting vendor Speaker ID: %d\n", ret); + return ret; + } + + /* Attempt to read the speaker type from a device property */ ret = device_property_read_u32(cs35l56_base->dev, "cirrus,speaker-id", &speaker_id); if (!ret) { dev_dbg(cs35l56_base->dev, "Speaker ID = %d\n", speaker_id); @@ -1270,30 +1347,6 @@ const struct regmap_config cs35l63_regmap_sdw = { }; EXPORT_SYMBOL_NS_GPL(cs35l63_regmap_sdw, "SND_SOC_CS35L56_SHARED"); -const struct cs35l56_fw_reg cs35l56_fw_reg = { - .fw_ver = CS35L56_DSP1_FW_VER, - .halo_state = CS35L56_DSP1_HALO_STATE, - .pm_cur_stat = CS35L56_DSP1_PM_CUR_STATE, - .prot_sts = CS35L56_PROTECTION_STATUS, - .transducer_actual_ps = CS35L56_TRANSDUCER_ACTUAL_PS, - .user_mute = CS35L56_MAIN_RENDER_USER_MUTE, - .user_volume = CS35L56_MAIN_RENDER_USER_VOLUME, - .posture_number = CS35L56_MAIN_POSTURE_NUMBER, -}; -EXPORT_SYMBOL_NS_GPL(cs35l56_fw_reg, "SND_SOC_CS35L56_SHARED"); - -const struct cs35l56_fw_reg cs35l63_fw_reg = { - .fw_ver = CS35L63_DSP1_FW_VER, - .halo_state = CS35L63_DSP1_HALO_STATE, - .pm_cur_stat = CS35L63_DSP1_PM_CUR_STATE, - .prot_sts = CS35L63_PROTECTION_STATUS, - .transducer_actual_ps = CS35L63_TRANSDUCER_ACTUAL_PS, - .user_mute = CS35L63_MAIN_RENDER_USER_MUTE, - .user_volume = CS35L63_MAIN_RENDER_USER_VOLUME, - .posture_number = CS35L63_MAIN_POSTURE_NUMBER, -}; -EXPORT_SYMBOL_NS_GPL(cs35l63_fw_reg, "SND_SOC_CS35L56_SHARED"); - MODULE_DESCRIPTION("ASoC CS35L56 Shared"); MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>"); diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c index c2ddee22cd23..9bc9b7c98390 100644 --- a/sound/soc/codecs/cs35l56-spi.c +++ b/sound/soc/codecs/cs35l56-spi.c @@ -26,7 +26,7 @@ static int cs35l56_spi_probe(struct spi_device *spi) spi_set_drvdata(spi, cs35l56); - cs35l56->base.fw_reg = &cs35l56_fw_reg; + cs35l56->base.type = 0x56; cs35l56->base.regmap = devm_regmap_init_spi(spi, regmap_config); if (IS_ERR(cs35l56->base.regmap)) { diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c index 2a0a4986a9ce..867e23d4fb8d 100644 --- a/sound/soc/codecs/cs42l43-jack.c +++ b/sound/soc/codecs/cs42l43-jack.c @@ -684,7 +684,7 @@ static int cs42l43_run_type_detect(struct cs42l43_codec *priv) } } -static void cs42l43_clear_jack(struct cs42l43_codec *priv) +void cs42l43_clear_jack(struct cs42l43_codec *priv) { struct cs42l43 *cs42l43 = priv->core; @@ -703,8 +703,6 @@ static void cs42l43_clear_jack(struct cs42l43_codec *priv) regmap_update_bits(cs42l43->regmap, CS42L43_HS2, CS42L43_HSDET_MODE_MASK | CS42L43_HSDET_MANUAL_MODE_MASK, 0x2 << CS42L43_HSDET_MODE_SHIFT); - - snd_soc_jack_report(priv->jack_hp, 0, 0xFFFF); } void cs42l43_tip_sense_work(struct work_struct *work) @@ -753,6 +751,8 @@ void cs42l43_tip_sense_work(struct work_struct *work) cs42l43_clear_jack(priv); + snd_soc_jack_report(priv->jack_hp, 0, 0xFFFF); + if (cs42l43->sdw && priv->jack_present) { pm_runtime_put(priv->dev); priv->jack_present = false; @@ -903,6 +903,8 @@ int cs42l43_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u cs42l43_clear_jack(priv); + snd_soc_jack_report(priv->jack_hp, 0, 0xFFFF); + if (!override) { queue_delayed_work(system_long_wq, &priv->tip_sense_work, 0); } else { diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c index b0c27d696c58..b61df09f20cf 100644 --- a/sound/soc/codecs/cs42l43.c +++ b/sound/soc/codecs/cs42l43.c @@ -2210,13 +2210,12 @@ static const struct cs42l43_irq cs42l43_irqs[] = { }; static int cs42l43_request_irq(struct cs42l43_codec *priv, - struct irq_domain *dom, const char * const name, - unsigned int irq, irq_handler_t handler, - unsigned long flags) + const char * const name, unsigned int irq, + irq_handler_t handler, unsigned long flags) { int ret; - ret = irq_create_mapping(dom, irq); + ret = irq_create_mapping(priv->dom, irq); if (ret < 0) return dev_err_probe(priv->dev, ret, "Failed to map IRQ %s\n", name); @@ -2230,13 +2229,29 @@ static int cs42l43_request_irq(struct cs42l43_codec *priv, return 0; } -static int cs42l43_shutter_irq(struct cs42l43_codec *priv, - struct irq_domain *dom, unsigned int shutter, - const char * const open_name, - const char * const close_name, +static void cs42l43_disable_irq(struct cs42l43_codec *priv, unsigned int irq) +{ + int ret; + + ret = irq_find_mapping(priv->dom, irq); + if (ret > 0) + disable_irq(ret); +} + +static void cs42l43_enable_irq(struct cs42l43_codec *priv, unsigned int irq) +{ + int ret; + + ret = irq_find_mapping(priv->dom, irq); + if (ret > 0) + enable_irq(ret); +} + +static int cs42l43_shutter_irq(struct cs42l43_codec *priv, unsigned int shutter, + const char * const open_name, unsigned int *open_irq, + const char * const close_name, unsigned int *close_irq, irq_handler_t handler) { - unsigned int open_irq, close_irq; int ret; switch (shutter) { @@ -2244,40 +2259,35 @@ static int cs42l43_shutter_irq(struct cs42l43_codec *priv, dev_warn(priv->dev, "Manual shutters, notifications not available\n"); return 0; case 0x2: - open_irq = CS42L43_GPIO1_RISE; - close_irq = CS42L43_GPIO1_FALL; + *open_irq = CS42L43_GPIO1_RISE; + *close_irq = CS42L43_GPIO1_FALL; break; case 0x4: - open_irq = CS42L43_GPIO2_RISE; - close_irq = CS42L43_GPIO2_FALL; + *open_irq = CS42L43_GPIO2_RISE; + *close_irq = CS42L43_GPIO2_FALL; break; case 0x8: - open_irq = CS42L43_GPIO3_RISE; - close_irq = CS42L43_GPIO3_FALL; + *open_irq = CS42L43_GPIO3_RISE; + *close_irq = CS42L43_GPIO3_FALL; break; default: return 0; } - ret = cs42l43_request_irq(priv, dom, close_name, close_irq, handler, IRQF_SHARED); + ret = cs42l43_request_irq(priv, close_name, *close_irq, handler, IRQF_SHARED); if (ret) return ret; - return cs42l43_request_irq(priv, dom, open_name, open_irq, handler, IRQF_SHARED); + return cs42l43_request_irq(priv, open_name, *open_irq, handler, IRQF_SHARED); } static int cs42l43_codec_probe(struct platform_device *pdev) { struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent); struct cs42l43_codec *priv; - struct irq_domain *dom; unsigned int val; int i, ret; - dom = irq_find_matching_fwnode(dev_fwnode(cs42l43->dev), DOMAIN_BUS_ANY); - if (!dom) - return -EPROBE_DEFER; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -2285,6 +2295,10 @@ static int cs42l43_codec_probe(struct platform_device *pdev) priv->dev = &pdev->dev; priv->core = cs42l43; + priv->dom = irq_find_matching_fwnode(dev_fwnode(cs42l43->dev), DOMAIN_BUS_ANY); + if (!priv->dom) + return -EPROBE_DEFER; + platform_set_drvdata(pdev, priv); mutex_init(&priv->jack_lock); @@ -2314,7 +2328,7 @@ static int cs42l43_codec_probe(struct platform_device *pdev) goto err_pm; for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) { - ret = cs42l43_request_irq(priv, dom, cs42l43_irqs[i].name, + ret = cs42l43_request_irq(priv, cs42l43_irqs[i].name, cs42l43_irqs[i].irq, cs42l43_irqs[i].handler, 0); if (ret) @@ -2327,15 +2341,17 @@ static int cs42l43_codec_probe(struct platform_device *pdev) goto err_pm; } - ret = cs42l43_shutter_irq(priv, dom, val & CS42L43_MIC_SHUTTER_CFG_MASK, - "mic shutter open", "mic shutter close", + ret = cs42l43_shutter_irq(priv, val & CS42L43_MIC_SHUTTER_CFG_MASK, + "mic shutter open", &priv->shutter_irqs[0], + "mic shutter close", &priv->shutter_irqs[1], cs42l43_mic_shutter); if (ret) goto err_pm; - ret = cs42l43_shutter_irq(priv, dom, (val & CS42L43_SPK_SHUTTER_CFG_MASK) >> + ret = cs42l43_shutter_irq(priv, (val & CS42L43_SPK_SHUTTER_CFG_MASK) >> CS42L43_SPK_SHUTTER_CFG_SHIFT, - "spk shutter open", "spk shutter close", + "spk shutter open", &priv->shutter_irqs[2], + "spk shutter close", &priv->shutter_irqs[3], cs42l43_spk_shutter); if (ret) goto err_pm; @@ -2386,22 +2402,53 @@ static int cs42l43_codec_runtime_resume(struct device *dev) return 0; } -static int cs42l43_codec_runtime_force_suspend(struct device *dev) +static int cs42l43_codec_suspend(struct device *dev) { struct cs42l43_codec *priv = dev_get_drvdata(dev); + int i; - dev_dbg(priv->dev, "Runtime suspend\n"); + dev_dbg(priv->dev, "System suspend\n"); priv->suspend_jack_debounce = true; - pm_runtime_force_suspend(dev); + for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) + cs42l43_disable_irq(priv, cs42l43_irqs[i].irq); + + for (i = 0; i < ARRAY_SIZE(priv->shutter_irqs); i++) + if (priv->shutter_irqs[i]) + cs42l43_disable_irq(priv, priv->shutter_irqs[i]); + + cancel_delayed_work_sync(&priv->bias_sense_timeout); + cancel_delayed_work_sync(&priv->tip_sense_work); + cancel_delayed_work_sync(&priv->hp_ilimit_clear_work); + + cs42l43_clear_jack(priv); + + return pm_runtime_force_suspend(dev); +} + +static int cs42l43_codec_resume(struct device *dev) +{ + struct cs42l43_codec *priv = dev_get_drvdata(dev); + int ret, i; + + ret = pm_runtime_force_resume(dev); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) + cs42l43_enable_irq(priv, cs42l43_irqs[i].irq); + + for (i = 0; i < ARRAY_SIZE(priv->shutter_irqs); i++) + if (priv->shutter_irqs[i]) + cs42l43_enable_irq(priv, priv->shutter_irqs[i]); return 0; } static const struct dev_pm_ops cs42l43_codec_pm_ops = { RUNTIME_PM_OPS(NULL, cs42l43_codec_runtime_resume, NULL) - SYSTEM_SLEEP_PM_OPS(cs42l43_codec_runtime_force_suspend, pm_runtime_force_resume) + SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend, cs42l43_codec_resume) }; static const struct platform_device_id cs42l43_codec_id_table[] = { diff --git a/sound/soc/codecs/cs42l43.h b/sound/soc/codecs/cs42l43.h index 3ea36362b11a..b2fa2cd1d99f 100644 --- a/sound/soc/codecs/cs42l43.h +++ b/sound/soc/codecs/cs42l43.h @@ -44,6 +44,8 @@ struct cs42l43_codec { struct device *dev; struct cs42l43 *core; struct snd_soc_component *component; + struct irq_domain *dom; + unsigned int shutter_irqs[4]; struct clk *mclk; @@ -130,6 +132,7 @@ static inline int cs42l43_sdw_add_peripheral(struct snd_pcm_substream *substream int cs42l43_set_jack(struct snd_soc_component *component, struct snd_soc_jack *jack, void *d); void cs42l43_bias_sense_timeout(struct work_struct *work); +void cs42l43_clear_jack(struct cs42l43_codec *priv); void cs42l43_tip_sense_work(struct work_struct *work); irqreturn_t cs42l43_bias_detect_clamp(int irq, void *data); irqreturn_t cs42l43_button_press(int irq, void *data); diff --git a/sound/soc/codecs/cs48l32-tables.c b/sound/soc/codecs/cs48l32-tables.c index 59eaa9a5029f..8ff3652a010e 100644 --- a/sound/soc/codecs/cs48l32-tables.c +++ b/sound/soc/codecs/cs48l32-tables.c @@ -533,8 +533,6 @@ static const struct regmap_config cs48l32_regmap = { int cs48l32_create_regmap(struct spi_device *spi, struct cs48l32 *cs48l32) { cs48l32->regmap = devm_regmap_init_spi(spi, &cs48l32_regmap); - if (IS_ERR(cs48l32->regmap)) - return PTR_ERR(cs48l32->regmap); - return 0; + return PTR_ERR_OR_ZERO(cs48l32->regmap); } diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index a4496cc26902..ae89260ca215 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -2247,10 +2247,8 @@ static int da7213_runtime_resume(struct device *dev) return regcache_sync(da7213->regmap); } -static const struct dev_pm_ops da7213_pm = { - RUNTIME_PM_OPS(da7213_runtime_suspend, da7213_runtime_resume, NULL) - SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) -}; +static DEFINE_RUNTIME_DEV_PM_OPS(da7213_pm, da7213_runtime_suspend, + da7213_runtime_resume, NULL); static const struct i2c_device_id da7213_i2c_id[] = { { "da7213" }, diff --git a/sound/soc/codecs/es8323.c b/sound/soc/codecs/es8323.c index a9822998199f..eb85b71e87f3 100644 --- a/sound/soc/codecs/es8323.c +++ b/sound/soc/codecs/es8323.c @@ -182,13 +182,13 @@ static const struct snd_kcontrol_new es8323_mono_adc_mux_controls = /* Left Mixer */ static const struct snd_kcontrol_new es8323_left_mixer_controls[] = { - SOC_DAPM_SINGLE("Left Playback Switch", SND_SOC_NOPM, 7, 1, 1), + SOC_DAPM_SINGLE("Left Playback Switch", ES8323_DACCONTROL17, 7, 1, 0), SOC_DAPM_SINGLE("Left Bypass Switch", ES8323_DACCONTROL17, 6, 1, 0), }; /* Right Mixer */ static const struct snd_kcontrol_new es8323_right_mixer_controls[] = { - SOC_DAPM_SINGLE("Right Playback Switch", SND_SOC_NOPM, 6, 1, 1), + SOC_DAPM_SINGLE("Right Playback Switch", ES8323_DACCONTROL20, 7, 1, 0), SOC_DAPM_SINGLE("Right Bypass Switch", ES8323_DACCONTROL20, 6, 1, 0), }; @@ -211,8 +211,8 @@ static const struct snd_soc_dapm_widget es8323_dapm_widgets[] = { SND_SOC_DAPM_ADC("Right ADC", "Right Capture", SND_SOC_NOPM, 4, 1), SND_SOC_DAPM_ADC("Left ADC", "Left Capture", SND_SOC_NOPM, 5, 1), - SND_SOC_DAPM_DAC("Right DAC", "Right Playback", SND_SOC_NOPM, 6, 1), - SND_SOC_DAPM_DAC("Left DAC", "Left Playback", SND_SOC_NOPM, 7, 1), + SND_SOC_DAPM_DAC("Right DAC", "Right Playback", ES8323_DACPOWER, 6, 1), + SND_SOC_DAPM_DAC("Left DAC", "Left Playback", ES8323_DACPOWER, 7, 1), SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0, &es8323_left_mixer_controls[0], @@ -223,10 +223,10 @@ static const struct snd_soc_dapm_widget es8323_dapm_widgets[] = { SND_SOC_DAPM_PGA("Right ADC Power", SND_SOC_NOPM, 6, 1, NULL, 0), SND_SOC_DAPM_PGA("Left ADC Power", SND_SOC_NOPM, 7, 1, NULL, 0), - SND_SOC_DAPM_PGA("Right Out 2", SND_SOC_NOPM, 2, 0, NULL, 0), - SND_SOC_DAPM_PGA("Left Out 2", SND_SOC_NOPM, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Out 1", SND_SOC_NOPM, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("Left Out 1", SND_SOC_NOPM, 5, 0, NULL, 0), + SND_SOC_DAPM_PGA("Right Out 2", ES8323_DACPOWER, 2, 0, NULL, 0), + SND_SOC_DAPM_PGA("Left Out 2", ES8323_DACPOWER, 3, 0, NULL, 0), + SND_SOC_DAPM_PGA("Right Out 1", ES8323_DACPOWER, 4, 0, NULL, 0), + SND_SOC_DAPM_PGA("Left Out 1", ES8323_DACPOWER, 5, 0, NULL, 0), SND_SOC_DAPM_PGA("LAMP", ES8323_ADCCONTROL1, 4, 0, NULL, 0), SND_SOC_DAPM_PGA("RAMP", ES8323_ADCCONTROL1, 0, 0, NULL, 0), @@ -632,7 +632,6 @@ static int es8323_probe(struct snd_soc_component *component) snd_soc_component_write(component, ES8323_CONTROL2, 0x60); snd_soc_component_write(component, ES8323_CHIPPOWER, 0x00); - snd_soc_component_write(component, ES8323_DACCONTROL17, 0xB8); return 0; } diff --git a/sound/soc/codecs/fs-amp-lib.c b/sound/soc/codecs/fs-amp-lib.c new file mode 100644 index 000000000000..c8f56617e370 --- /dev/null +++ b/sound/soc/codecs/fs-amp-lib.c @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// fs-amp-lib.c --- Common library for FourSemi Audio Amplifiers +// +// Copyright (C) 2016-2025 Shanghai FourSemi Semiconductor Co.,Ltd. + +#include <linux/crc16.h> +#include <linux/device.h> +#include <linux/firmware.h> +#include <linux/module.h> +#include <linux/slab.h> + +#include "fs-amp-lib.h" + +static int fs_get_scene_count(struct fs_amp_lib *amp_lib) +{ + const struct fs_fwm_table *table; + int count; + + if (!amp_lib || !amp_lib->dev) + return -EINVAL; + + table = amp_lib->table[FS_INDEX_SCENE]; + if (!table) + return -EFAULT; + + count = table->size / sizeof(struct fs_scene_index); + if (count < 1 || count > FS_SCENE_COUNT_MAX) { + dev_err(amp_lib->dev, "Invalid scene count: %d\n", count); + return -ERANGE; + } + + return count; +} + +static void fs_get_fwm_string(struct fs_amp_lib *amp_lib, + int offset, const char **pstr) +{ + const struct fs_fwm_table *table; + + if (!amp_lib || !amp_lib->dev || !pstr) + return; + + table = amp_lib->table[FS_INDEX_STRING]; + if (table && offset > 0 && offset < table->size + sizeof(*table)) + *pstr = (char *)table + offset; + else + *pstr = NULL; +} + +static void fs_get_scene_reg(struct fs_amp_lib *amp_lib, + int offset, struct fs_amp_scene *scene) +{ + const struct fs_fwm_table *table; + + if (!amp_lib || !amp_lib->dev || !scene) + return; + + table = amp_lib->table[FS_INDEX_REG]; + if (table && offset > 0 && offset < table->size + sizeof(*table)) + scene->reg = (struct fs_reg_table *)((char *)table + offset); + else + scene->reg = NULL; +} + +static void fs_get_scene_model(struct fs_amp_lib *amp_lib, + int offset, struct fs_amp_scene *scene) +{ + const struct fs_fwm_table *table; + const char *ptr; + + if (!amp_lib || !amp_lib->dev || !scene) + return; + + table = amp_lib->table[FS_INDEX_MODEL]; + ptr = (char *)table; + if (table && offset > 0 && offset < table->size + sizeof(*table)) + scene->model = (struct fs_file_table *)(ptr + offset); + else + scene->model = NULL; +} + +static void fs_get_scene_effect(struct fs_amp_lib *amp_lib, + int offset, struct fs_amp_scene *scene) +{ + const struct fs_fwm_table *table; + const char *ptr; + + if (!amp_lib || !amp_lib->dev || !scene) + return; + + table = amp_lib->table[FS_INDEX_EFFECT]; + ptr = (char *)table; + if (table && offset > 0 && offset < table->size + sizeof(*table)) + scene->effect = (struct fs_file_table *)(ptr + offset); + else + scene->effect = NULL; +} + +static int fs_parse_scene_tables(struct fs_amp_lib *amp_lib) +{ + const struct fs_scene_index *scene_index; + const struct fs_fwm_table *table; + struct fs_amp_scene *scene; + int idx, count; + + if (!amp_lib || !amp_lib->dev) + return -EINVAL; + + count = fs_get_scene_count(amp_lib); + if (count <= 0) + return -EFAULT; + + scene = devm_kcalloc(amp_lib->dev, count, sizeof(*scene), GFP_KERNEL); + if (!scene) + return -ENOMEM; + + amp_lib->scene_count = count; + amp_lib->scene = scene; + + table = amp_lib->table[FS_INDEX_SCENE]; + scene_index = (struct fs_scene_index *)table->buf; + + for (idx = 0; idx < count; idx++) { + fs_get_fwm_string(amp_lib, scene_index->name, &scene->name); + if (!scene->name) + scene->name = devm_kasprintf(amp_lib->dev, + GFP_KERNEL, "S%d", idx); + dev_dbg(amp_lib->dev, "scene.%d name: %s\n", idx, scene->name); + fs_get_scene_reg(amp_lib, scene_index->reg, scene); + fs_get_scene_model(amp_lib, scene_index->model, scene); + fs_get_scene_effect(amp_lib, scene_index->effect, scene); + scene++; + scene_index++; + } + + return 0; +} + +static int fs_parse_all_tables(struct fs_amp_lib *amp_lib) +{ + const struct fs_fwm_table *table; + const struct fs_fwm_index *index; + const char *ptr; + int idx, count; + int ret; + + if (!amp_lib || !amp_lib->dev || !amp_lib->hdr) + return -EINVAL; + + /* Parse all fwm tables */ + table = (struct fs_fwm_table *)amp_lib->hdr->params; + index = (struct fs_fwm_index *)table->buf; + count = table->size / sizeof(*index); + + for (idx = 0; idx < count; idx++, index++) { + if (index->type >= FS_INDEX_MAX) + return -ERANGE; + ptr = (char *)table + (int)index->offset; + amp_lib->table[index->type] = (struct fs_fwm_table *)ptr; + } + + /* Parse all scene tables */ + ret = fs_parse_scene_tables(amp_lib); + if (ret) + dev_err(amp_lib->dev, "Failed to parse scene: %d\n", ret); + + return ret; +} + +static int fs_verify_firmware(struct fs_amp_lib *amp_lib) +{ + const struct fs_fwm_header *hdr; + int crcsum; + + if (!amp_lib || !amp_lib->dev || !amp_lib->hdr) + return -EINVAL; + + hdr = amp_lib->hdr; + + /* Verify the crcsum code */ + crcsum = crc16(0x0000, (const char *)&hdr->crc_size, hdr->crc_size); + if (crcsum != hdr->crc16) { + dev_err(amp_lib->dev, "Failed to checksum: %x-%x\n", + crcsum, hdr->crc16); + return -EFAULT; + } + + /* Verify the devid(chip_type) */ + if (amp_lib->devid != LO_U16(hdr->chip_type)) { + dev_err(amp_lib->dev, "DEVID dismatch: %04X#%04X\n", + amp_lib->devid, hdr->chip_type); + return -EINVAL; + } + + return 0; +} + +static void fs_print_firmware_info(struct fs_amp_lib *amp_lib) +{ + const struct fs_fwm_header *hdr; + const char *pro_name = NULL; + const char *dev_name = NULL; + + if (!amp_lib || !amp_lib->dev || !amp_lib->hdr) + return; + + hdr = amp_lib->hdr; + + fs_get_fwm_string(amp_lib, hdr->project, &pro_name); + fs_get_fwm_string(amp_lib, hdr->device, &dev_name); + + dev_info(amp_lib->dev, "Project: %s Device: %s\n", + pro_name ? pro_name : "null", + dev_name ? dev_name : "null"); + + dev_info(amp_lib->dev, "Date: %04d%02d%02d-%02d%02d\n", + hdr->date.year, hdr->date.month, hdr->date.day, + hdr->date.hour, hdr->date.minute); +} + +int fs_amp_load_firmware(struct fs_amp_lib *amp_lib, const char *name) +{ + const struct firmware *cont; + struct fs_fwm_header *hdr; + int ret; + + if (!amp_lib || !amp_lib->dev || !name) + return -EINVAL; + + ret = request_firmware(&cont, name, amp_lib->dev); + if (ret) { + dev_err(amp_lib->dev, "Failed to request %s: %d\n", name, ret); + return ret; + } + + dev_info(amp_lib->dev, "Loading %s - size: %zu\n", name, cont->size); + + hdr = devm_kmemdup(amp_lib->dev, cont->data, cont->size, GFP_KERNEL); + release_firmware(cont); + if (!hdr) + return -ENOMEM; + + amp_lib->hdr = hdr; + ret = fs_verify_firmware(amp_lib); + if (ret) { + amp_lib->hdr = NULL; + return ret; + } + + ret = fs_parse_all_tables(amp_lib); + if (ret) { + amp_lib->hdr = NULL; + return ret; + } + + fs_print_firmware_info(amp_lib); + + return 0; +} +EXPORT_SYMBOL_GPL(fs_amp_load_firmware); + +MODULE_AUTHOR("Nick Li <nick.li@foursemi.com>"); +MODULE_DESCRIPTION("FourSemi audio amplifier library"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/fs-amp-lib.h b/sound/soc/codecs/fs-amp-lib.h new file mode 100644 index 000000000000..4a77c7b383cd --- /dev/null +++ b/sound/soc/codecs/fs-amp-lib.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * fs-amp-lib.h --- Common library for FourSemi Audio Amplifiers + * + * Copyright (C) 2016-2025 Shanghai FourSemi Semiconductor Co.,Ltd. + */ + +#ifndef __FS_AMP_LIB_H__ +#define __FS_AMP_LIB_H__ + +#define HI_U16(a) (((a) >> 8) & 0xFF) +#define LO_U16(a) ((a) & 0xFF) +#define FS_TABLE_NAME_LEN (4) +#define FS_SCENE_COUNT_MAX (16) +#define FS_CMD_DELAY_MS_MAX (100) /* 100ms */ + +#define FS_CMD_DELAY (0xFF) +#define FS_CMD_BURST (0xFE) +#define FS_CMD_UPDATE (0xFD) + +#define FS_SOC_ENUM_EXT(xname, xhandler_info, xhandler_get, xhandler_put) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = xhandler_info, \ + .get = xhandler_get, .put = xhandler_put \ +} + +enum fs_index_type { + FS_INDEX_INFO = 0, + FS_INDEX_STCOEF, + FS_INDEX_SCENE, + FS_INDEX_MODEL, + FS_INDEX_REG, + FS_INDEX_EFFECT, + FS_INDEX_STRING, + FS_INDEX_WOOFER, + FS_INDEX_MAX, +}; + +#pragma pack(push, 1) + +struct fs_reg_val { + u8 reg; + u16 val; +}; + +struct fs_reg_bits { + u8 cmd; /* FS_CMD_UPDATE */ + u8 reg; + u16 val; + u16 mask; +}; + +struct fs_cmd_pkg { + union { + u8 cmd; + struct fs_reg_val regv; + struct fs_reg_bits regb; + }; +}; + +struct fs_fwm_index { + /* Index type */ + u16 type; + /* Offset address starting from the end of header */ + u16 offset; +}; + +struct fs_fwm_table { + char name[FS_TABLE_NAME_LEN]; + u16 size; /* size of buf */ + u8 buf[]; +}; + +struct fs_scene_index { + /* Offset address(scene name) in string table */ + u16 name; + /* Offset address(scene reg) in register table */ + u16 reg; + /* Offset address(scene model) in model table */ + u16 model; + /* Offset address(scene effect) in effect table */ + u16 effect; +}; + +struct fs_reg_table { + u16 size; /* size of buf */ + u8 buf[]; +}; + +struct fs_file_table { + u16 name; + u16 size; /* size of buf */ + u8 buf[]; +}; + +struct fs_fwm_date { + u32 year:12; + u32 month:4; + u32 day:5; + u32 hour:5; + u32 minute:6; +}; + +struct fs_fwm_header { + u16 version; + u16 project; /* Offset address(project name) in string table */ + u16 device; /* Offset address(device name) in string table */ + struct fs_fwm_date date; + u16 crc16; + u16 crc_size; /* Starting position for CRC checking */ + u16 chip_type; + u16 addr; /* 7-bit i2c address */ + u16 spkid; + u16 rsvd[6]; + u8 params[]; +}; + +#pragma pack(pop) + +struct fs_i2s_srate { + u32 srate; /* Sample rate */ + u16 i2ssr; /* Value of Bit field[I2SSR] */ +}; + +struct fs_pll_div { + unsigned int bclk; /* Rate of bit clock */ + u16 pll1; + u16 pll2; + u16 pll3; +}; + +struct fs_amp_scene { + const char *name; + const struct fs_reg_table *reg; + const struct fs_file_table *model; + const struct fs_file_table *effect; +}; + +struct fs_amp_lib { + const struct fs_fwm_header *hdr; + const struct fs_fwm_table *table[FS_INDEX_MAX]; + struct fs_amp_scene *scene; + struct device *dev; + int scene_count; + u16 devid; +}; + +int fs_amp_load_firmware(struct fs_amp_lib *amp_lib, const char *name); + +#endif // __FS_AMP_LIB_H__ diff --git a/sound/soc/codecs/fs210x.c b/sound/soc/codecs/fs210x.c new file mode 100644 index 000000000000..e2f85714972d --- /dev/null +++ b/sound/soc/codecs/fs210x.c @@ -0,0 +1,1586 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// fs210x.c -- Driver for the FS2104/5S Audio Amplifier +// +// Copyright (C) 2016-2025 Shanghai FourSemi Semiconductor Co.,Ltd. + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/workqueue.h> +#include <sound/soc.h> +#include <sound/tlv.h> + +#include "fs210x.h" +#include "fs-amp-lib.h" + +#define FS210X_DEFAULT_FWM_NAME "fs210x_fwm.bin" +#define FS210X_DEFAULT_DAI_NAME "fs210x-aif" +#define FS2105S_DEVICE_ID 0x20 /* FS2105S */ +#define FS210X_DEVICE_ID 0x45 /* FS2104 */ +#define FS210X_REG_MAX 0xF8 +#define FS210X_INIT_SCENE 0 +#define FS210X_DEFAULT_SCENE 1 +#define FS210X_START_DELAY_MS 5 +#define FS210X_FAULT_CHECK_INTERVAL_MS 2000 +#define FS2105S_RATES (SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_88200 | \ + SNDRV_PCM_RATE_96000) +#define FS210X_RATES (SNDRV_PCM_RATE_16000 | FS2105S_RATES) +#define FS210X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | \ + SNDRV_PCM_FMTBIT_S32_LE) +#define FS210X_NUM_SUPPLIES ARRAY_SIZE(fs210x_supply_names) + +static const char *const fs210x_supply_names[] = { + "pvdd", + "dvdd", +}; + +struct fs210x_platform_data { + const char *fwm_name; +}; + +struct fs210x_priv { + struct i2c_client *i2c; + struct device *dev; + struct regmap *regmap; + struct fs210x_platform_data pdata; + struct regulator_bulk_data supplies[FS210X_NUM_SUPPLIES]; + struct gpio_desc *gpio_sdz; + struct delayed_work start_work; + struct delayed_work fault_check_work; + struct fs_amp_lib amp_lib; + const struct fs_amp_scene *cur_scene; + struct clk *clk_bclk; + /* + * @lock: Mutex ensuring exclusive access for critical device operations + * + * This lock serializes access between the following actions: + * - Device initialization procedures(probe) + * - Enable/disable device(DAPM event) + * - Suspend/resume device(PM) + * - Runtime scene switching(control) + * - Scheduling/execution of delayed works items(delayed works) + */ + struct mutex lock; + unsigned int check_interval_ms; + unsigned int bclk; + unsigned int srate; + int scene_id; + u16 devid; + bool is_inited; + bool is_suspended; + bool is_bclk_on; + bool is_playing; +}; + +static const unsigned int fs2105s_rates[] = { + 32000, 44100, 48000, 88200, 96000 +}; + +static const struct snd_pcm_hw_constraint_list fs2105s_constraints = { + .count = ARRAY_SIZE(fs2105s_rates), + .list = fs2105s_rates, +}; + +static const unsigned int fs210x_rates[] = { + 16000, 32000, 44100, 48000, 88200, 96000 +}; + +static const struct snd_pcm_hw_constraint_list fs210x_constraints = { + .count = ARRAY_SIZE(fs210x_rates), + .list = fs210x_rates, +}; + +static const struct fs_pll_div fs210x_pll_div[] = { + /* bclk, pll1, pll2, pll3 */ + { 512000, 0x006C, 0x0120, 0x0001 }, + { 768000, 0x016C, 0x00C0, 0x0001 }, + { 1024000, 0x016C, 0x0090, 0x0001 }, + { 1536000, 0x016C, 0x0060, 0x0001 }, + { 2048000, 0x016C, 0x0090, 0x0002 }, + { 2304000, 0x016C, 0x0080, 0x0002 }, + { 3072000, 0x016C, 0x0090, 0x0003 }, + { 4096000, 0x016C, 0x0090, 0x0004 }, + { 4608000, 0x016C, 0x0080, 0x0004 }, + { 6144000, 0x016C, 0x0090, 0x0006 }, + { 8192000, 0x016C, 0x0090, 0x0008 }, + { 9216000, 0x016C, 0x0090, 0x0009 }, + { 12288000, 0x016C, 0x0090, 0x000C }, + { 16384000, 0x016C, 0x0090, 0x0010 }, + { 18432000, 0x016C, 0x0090, 0x0012 }, + { 24576000, 0x016C, 0x0090, 0x0018 }, + { 1411200, 0x016C, 0x0060, 0x0001 }, + { 2116800, 0x016C, 0x0080, 0x0002 }, + { 2822400, 0x016C, 0x0090, 0x0003 }, + { 4233600, 0x016C, 0x0080, 0x0004 }, + { 5644800, 0x016C, 0x0090, 0x0006 }, + { 8467200, 0x016C, 0x0090, 0x0009 }, + { 11289600, 0x016C, 0x0090, 0x000C }, + { 16934400, 0x016C, 0x0090, 0x0012 }, + { 22579200, 0x016C, 0x0090, 0x0018 }, + { 2000000, 0x017C, 0x0093, 0x0002 }, +}; + +static int fs210x_bclk_set(struct fs210x_priv *fs210x, bool on) +{ + int ret = 0; + + if (!fs210x || !fs210x->dev) + return -EINVAL; + + if ((fs210x->is_bclk_on ^ on) == 0) + return 0; + + if (on) { + clk_set_rate(fs210x->clk_bclk, fs210x->bclk); + ret = clk_prepare_enable(fs210x->clk_bclk); + fs210x->is_bclk_on = true; + fsleep(2000); /* >= 2ms */ + } else { + clk_disable_unprepare(fs210x->clk_bclk); + fs210x->is_bclk_on = false; + } + + return ret; +} + +static int fs210x_reg_write(struct fs210x_priv *fs210x, + u8 reg, u16 val) +{ + int ret; + + ret = regmap_write(fs210x->regmap, reg, val); + if (ret) { + dev_err(fs210x->dev, "Failed to write %02Xh: %d\n", reg, ret); + return ret; + } + + return 0; +} + +static int fs210x_reg_read(struct fs210x_priv *fs210x, + u8 reg, u16 *pval) +{ + unsigned int val; + int ret; + + ret = regmap_read(fs210x->regmap, reg, &val); + if (ret) { + dev_err(fs210x->dev, "Failed to read %02Xh: %d\n", reg, ret); + return ret; + } + + *pval = (u16)val; + + return 0; +} + +static int fs210x_reg_update_bits(struct fs210x_priv *fs210x, + u8 reg, u16 mask, u16 val) +{ + int ret; + + ret = regmap_update_bits(fs210x->regmap, reg, mask, val); + if (ret) { + dev_err(fs210x->dev, "Failed to update %02Xh: %d\n", reg, ret); + return ret; + } + + return 0; +} + +static int fs210x_reg_bulk_write(struct fs210x_priv *fs210x, + u8 reg, const void *val, u32 size) +{ + int ret; + + ret = regmap_bulk_write(fs210x->regmap, reg, val, size / 2); + if (ret) { + dev_err(fs210x->dev, "Failed to bulk write %02Xh: %d\n", + reg, ret); + return ret; + } + + return 0; +} + +static inline int fs210x_write_reg_val(struct fs210x_priv *fs210x, + const struct fs_reg_val *regv) +{ + return fs210x_reg_write(fs210x, regv->reg, regv->val); +} + +static inline int fs210x_write_reg_bits(struct fs210x_priv *fs210x, + const struct fs_reg_bits *regu) +{ + return fs210x_reg_update_bits(fs210x, + regu->reg, + regu->mask, + regu->val); +} + +static inline int fs210x_set_cmd_pkg(struct fs210x_priv *fs210x, + const struct fs_cmd_pkg *pkg, + unsigned int *offset) +{ + int delay_us; + + if (pkg->cmd >= 0x00 && pkg->cmd <= FS210X_REG_MAX) { + *offset = sizeof(pkg->regv); + return fs210x_write_reg_val(fs210x, &pkg->regv); + } else if (pkg->cmd == FS_CMD_UPDATE) { + *offset = sizeof(pkg->regb); + return fs210x_write_reg_bits(fs210x, &pkg->regb); + } else if (pkg->cmd == FS_CMD_DELAY) { + if (pkg->regv.val > FS_CMD_DELAY_MS_MAX) + return -EOPNOTSUPP; + delay_us = pkg->regv.val * 1000; /* ms -> us */ + fsleep(delay_us); + *offset = sizeof(pkg->regv); + return 0; + } + + dev_err(fs210x->dev, "Invalid pkg cmd: %d\n", pkg->cmd); + + return -EOPNOTSUPP; +} + +static int fs210x_reg_write_table(struct fs210x_priv *fs210x, + const struct fs_reg_table *reg) +{ + const struct fs_cmd_pkg *pkg; + unsigned int index, offset; + int ret; + + if (!fs210x || !fs210x->dev) + return -EINVAL; + + if (!reg || reg->size == 0) + return -EFAULT; + + for (index = 0; index < reg->size; index += offset) { + pkg = (struct fs_cmd_pkg *)(reg->buf + index); + ret = fs210x_set_cmd_pkg(fs210x, pkg, &offset); + if (ret) { + dev_err(fs210x->dev, "Failed to set cmd pkg: %02X-%d\n", + pkg->cmd, ret); + return ret; + } + } + + if (index != reg->size) { + dev_err(fs210x->dev, "Invalid reg table size: %d-%d\n", + index, reg->size); + return -EFAULT; + } + + return 0; +} + +static int fs210x_dev_play(struct fs210x_priv *fs210x) +{ + int ret; + + if (!fs210x->is_inited) + return -EFAULT; + + if (fs210x->is_playing) + return 0; + + ret = fs210x_reg_write(fs210x, FS210X_11H_SYSCTRL, + FS210X_11H_DPS_PLAY); + if (!ret) + fs210x->is_playing = true; + + fsleep(10000); /* >= 10ms */ + + return ret; +} + +static int fs210x_dev_stop(struct fs210x_priv *fs210x) +{ + int ret; + + if (!fs210x->is_inited) + return -EFAULT; + + if (!fs210x->is_playing) + return 0; + + ret = fs210x_reg_write(fs210x, FS210X_11H_SYSCTRL, + FS210X_11H_DPS_PWDN); + fs210x->is_playing = false; + + fsleep(30000); /* >= 30ms */ + + return ret; +} + +static int fs210x_set_reg_table(struct fs210x_priv *fs210x, + const struct fs_amp_scene *scene) +{ + const struct fs_amp_scene *cur_scene; + const struct fs_reg_table *reg; + + if (!fs210x || !fs210x->dev || !scene) + return -EINVAL; + + cur_scene = fs210x->cur_scene; + if (!scene->reg || cur_scene == scene) { + dev_dbg(fs210x->dev, "Skip writing reg table\n"); + return 0; + } + + reg = scene->reg; + dev_dbg(fs210x->dev, "reg table size: %d\n", reg->size); + + return fs210x_reg_write_table(fs210x, reg); +} + +static int fs210x_set_woofer_table(struct fs210x_priv *fs210x) +{ + const struct fs_file_table *woofer; + const struct fs_fwm_table *table; + int ret; + + if (!fs210x || !fs210x->dev) + return -EINVAL; + + /* NOTE: fs2105s has woofer ram only */ + if (fs210x->devid != FS2105S_DEVICE_ID) + return 0; + + table = fs210x->amp_lib.table[FS_INDEX_WOOFER]; + if (!table) { + dev_dbg(fs210x->dev, "Skip writing woofer table\n"); + return 0; + } + + woofer = (struct fs_file_table *)table->buf; + dev_dbg(fs210x->dev, "woofer table size: %d\n", woofer->size); + /* Unit of woofer data is u32(4 bytes) */ + if (woofer->size == 0 || (woofer->size & 0x3)) { + dev_err(fs210x->dev, "Invalid woofer size: %d\n", + woofer->size); + return -EINVAL; + } + + ret = fs210x_reg_write(fs210x, FS210X_46H_DACEQA, + FS2105S_46H_CAM_BURST_W); + ret |= fs210x_reg_bulk_write(fs210x, FS210X_42H_DACEQWL, + woofer->buf, woofer->size); + + return ret; +} + +static int fs210x_set_effect_table(struct fs210x_priv *fs210x, + const struct fs_amp_scene *scene) +{ + const struct fs_amp_scene *cur_scene; + const struct fs_file_table *effect; + int half_size; + int ret; + + if (!fs210x || !fs210x->dev || !scene) + return -EINVAL; + + cur_scene = fs210x->cur_scene; + if (!scene->effect || cur_scene == scene) { + dev_dbg(fs210x->dev, "Skip writing effect table\n"); + return 0; + } + + effect = scene->effect; + dev_dbg(fs210x->dev, "effect table size: %d\n", effect->size); + + /* Unit of effect data is u32(4 bytes), 2 channels */ + if (effect->size == 0 || (effect->size & 0x7)) { + dev_err(fs210x->dev, "Invalid effect size: %d\n", + effect->size); + return -EINVAL; + } + + half_size = effect->size / 2; + + /* Left channel */ + ret = fs210x_reg_write(fs210x, FS210X_46H_DACEQA, + FS210X_46H_CAM_BURST_L); + ret |= fs210x_reg_bulk_write(fs210x, FS210X_42H_DACEQWL, + effect->buf, half_size); + if (ret) + return ret; + + /* Right channel */ + ret = fs210x_reg_write(fs210x, FS210X_46H_DACEQA, + FS210X_46H_CAM_BURST_R); + ret |= fs210x_reg_bulk_write(fs210x, FS210X_42H_DACEQWL, + effect->buf + half_size, half_size); + + return ret; +} + +static int fs210x_access_dsp_ram(struct fs210x_priv *fs210x, bool enable) +{ + int ret; + + if (!fs210x || !fs210x->dev) + return -EINVAL; + + if (enable) { + ret = fs210x_reg_write(fs210x, FS210X_11H_SYSCTRL, + FS210X_11H_DPS_HIZ); + ret |= fs210x_reg_write(fs210x, FS210X_0BH_ACCKEY, + FS210X_0BH_ACCKEY_ON); + } else { + ret = fs210x_reg_write(fs210x, FS210X_0BH_ACCKEY, + FS210X_0BH_ACCKEY_OFF); + ret |= fs210x_reg_write(fs210x, FS210X_11H_SYSCTRL, + FS210X_11H_DPS_PWDN); + } + + fsleep(10000); /* >= 10ms */ + + return ret; +} + +static int fs210x_write_dsp_effect(struct fs210x_priv *fs210x, + const struct fs_amp_scene *scene, + int scene_id) +{ + int ret; + + if (!fs210x || !scene) + return -EINVAL; + + ret = fs210x_access_dsp_ram(fs210x, true); + if (ret) { + dev_err(fs210x->dev, "Failed to access dsp: %d\n", ret); + goto tag_exit; + } + + ret = fs210x_set_effect_table(fs210x, scene); + if (ret) { + dev_err(fs210x->dev, "Failed to set effect: %d\n", ret); + goto tag_exit; + } + + if (scene_id == FS210X_INIT_SCENE) + ret = fs210x_set_woofer_table(fs210x); + +tag_exit: + fs210x_reg_write(fs210x, FS210X_46H_DACEQA, + FS210X_46H_CAM_CLEAR); + fs210x_access_dsp_ram(fs210x, false); + + return ret; +} + +static int fs210x_check_scene(struct fs210x_priv *fs210x, + int scene_id, bool *skip_set) +{ + struct fs_amp_lib *amp_lib; + + if (!fs210x || !skip_set) + return -EINVAL; + + amp_lib = &fs210x->amp_lib; + if (amp_lib->scene_count == 0 || !amp_lib->scene) { + dev_err(fs210x->dev, "There's no scene data\n"); + return -EINVAL; + } + + if (scene_id < 0 || scene_id >= amp_lib->scene_count) { + dev_err(fs210x->dev, "Invalid scene_id: %d\n", scene_id); + return -EINVAL; + } + + if (fs210x->scene_id == scene_id) { + dev_dbg(fs210x->dev, "Skip to set same scene\n"); + return 0; + } + + *skip_set = false; + + return 0; +} + +static int fs210x_set_scene(struct fs210x_priv *fs210x, int scene_id) +{ + const struct fs_amp_scene *scene; + bool skip_set = true; + bool is_playing; + int ret; + + if (!fs210x || !fs210x->dev) + return -EINVAL; + + ret = fs210x_check_scene(fs210x, scene_id, &skip_set); + if (ret || skip_set) + return ret; + + scene = fs210x->amp_lib.scene + scene_id; + dev_info(fs210x->dev, "Switch scene.%d: %s\n", + scene_id, scene->name); + + is_playing = fs210x->is_playing; + if (is_playing) + fs210x_dev_stop(fs210x); + + ret = fs210x_set_reg_table(fs210x, scene); + if (ret) { + dev_err(fs210x->dev, "Failed to set reg: %d\n", ret); + return ret; + } + + ret = fs210x_write_dsp_effect(fs210x, scene, scene_id); + if (ret) { + dev_err(fs210x->dev, "Failed to write ram: %d\n", ret); + return ret; + } + + fs210x->cur_scene = scene; + fs210x->scene_id = scene_id; + + if (is_playing) + fs210x_dev_play(fs210x); + + return 0; +} + +static int fs210x_init_chip(struct fs210x_priv *fs210x) +{ + int scene_id; + int ret; + + regcache_cache_bypass(fs210x->regmap, true); + + if (!fs210x->gpio_sdz) { + /* Gpio is not found, i2c reset */ + ret = fs210x_reg_write(fs210x, FS210X_10H_PWRCTRL, + FS210X_10H_I2C_RESET); + if (ret) + goto tag_power_down; + } else { + /* gpio reset, deactivate */ + gpiod_set_value_cansleep(fs210x->gpio_sdz, 0); + } + + fsleep(10000); /* >= 10ms */ + + /* Backup scene id */ + scene_id = fs210x->scene_id; + fs210x->scene_id = -1; + + /* Init registers/RAM by init scene */ + ret = fs210x_set_scene(fs210x, FS210X_INIT_SCENE); + if (ret) + goto tag_power_down; + + /* + * If the firmware has effect scene(s), + * we load effect scene by default scene or scene_id + */ + if (fs210x->amp_lib.scene_count > 1) { + if (scene_id < FS210X_DEFAULT_SCENE) + scene_id = FS210X_DEFAULT_SCENE; + ret = fs210x_set_scene(fs210x, scene_id); + if (ret) + goto tag_power_down; + } + +tag_power_down: + /* Power down the device */ + ret |= fs210x_reg_write(fs210x, FS210X_11H_SYSCTRL, + FS210X_11H_DPS_PWDN); + fsleep(10000); /* >= 10ms */ + + regcache_cache_bypass(fs210x->regmap, false); + if (!ret) { + regcache_mark_dirty(fs210x->regmap); + regcache_sync(fs210x->regmap); + fs210x->is_inited = true; + } + + return ret; +} + +static int fs210x_set_i2s_params(struct fs210x_priv *fs210x) +{ + const struct fs_i2s_srate params[] = { + { 16000, 0x3 }, + { 32000, 0x7 }, + { 44100, 0x8 }, + { 48000, 0x9 }, + { 88200, 0xA }, + { 96000, 0xB }, + }; + u16 val; + int i, ret; + + for (i = 0; i < ARRAY_SIZE(params); i++) { + if (params[i].srate != fs210x->srate) + continue; + val = params[i].i2ssr << FS210X_17H_I2SSR_SHIFT; + ret = fs210x_reg_update_bits(fs210x, + FS210X_17H_I2SCTRL, + FS210X_17H_I2SSR_MASK, + val); + return ret; + } + + dev_err(fs210x->dev, "Invalid sample rate: %d\n", fs210x->srate); + + return -EINVAL; +} + +static int fs210x_get_pll_div(struct fs210x_priv *fs210x, + const struct fs_pll_div **pll_div) +{ + int i; + + if (!fs210x || !pll_div) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(fs210x_pll_div); i++) { + if (fs210x_pll_div[i].bclk != fs210x->bclk) + continue; + *pll_div = fs210x_pll_div + i; + return 0; + } + + dev_err(fs210x->dev, "No PLL table for bclk: %d\n", fs210x->bclk); + + return -EFAULT; +} + +static int fs210x_set_hw_params(struct fs210x_priv *fs210x) +{ + const struct fs_pll_div *pll_div; + int ret; + + ret = fs210x_set_i2s_params(fs210x); + if (ret) { + dev_err(fs210x->dev, "Failed to set i2s params: %d\n", ret); + return ret; + } + + /* Set pll params */ + ret = fs210x_get_pll_div(fs210x, &pll_div); + if (ret) + return ret; + + ret = fs210x_reg_write(fs210x, FS210X_A1H_PLLCTRL1, pll_div->pll1); + ret |= fs210x_reg_write(fs210x, FS210X_A2H_PLLCTRL2, pll_div->pll2); + ret |= fs210x_reg_write(fs210x, FS210X_A3H_PLLCTRL3, pll_div->pll3); + + return ret; +} + +static int fs210x_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + const struct snd_pcm_hw_constraint_list *list; + struct fs210x_priv *fs210x; + int ret; + + fs210x = snd_soc_component_get_drvdata(dai->component); + if (!fs210x) { + pr_err("dai_startup: fs210x is null\n"); + return -EINVAL; + } + + if (!substream->runtime) + return 0; + + ret = snd_pcm_hw_constraint_mask64(substream->runtime, + SNDRV_PCM_HW_PARAM_FORMAT, + FS210X_FORMATS); + if (ret < 0) { + dev_err(fs210x->dev, + "Failed to set hw param format: %d\n", ret); + return ret; + } + + if (fs210x->devid == FS2105S_DEVICE_ID) + list = &fs2105s_constraints; + else + list = &fs210x_constraints; + + ret = snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + list); + if (ret < 0) { + dev_err(fs210x->dev, + "Failed to set hw param rate: %d\n", ret); + return ret; + } + + return 0; +} + +static int fs210x_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct fs210x_priv *fs210x; + + fs210x = snd_soc_component_get_drvdata(dai->component); + + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: + /* Only supports consumer mode */ + break; + default: + dev_err(fs210x->dev, "Only supports consumer mode\n"); + return -EINVAL; + } + + return 0; +} + +static int fs210x_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct fs210x_priv *fs210x; + int chn_num; + int ret; + + if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) + return 0; + + fs210x = snd_soc_component_get_drvdata(dai->component); + + fs210x->srate = params_rate(params); + fs210x->bclk = snd_soc_params_to_bclk(params); + chn_num = params_channels(params); + if (chn_num == 1) /* mono */ + fs210x->bclk *= 2; /* I2S bus has 2 channels */ + + /* The FS2105S can't support 16kHz sample rate. */ + if (fs210x->devid == FS2105S_DEVICE_ID && fs210x->srate == 16000) + return -EOPNOTSUPP; + + mutex_lock(&fs210x->lock); + ret = fs210x_set_hw_params(fs210x); + mutex_unlock(&fs210x->lock); + if (ret) + dev_err(fs210x->dev, "Failed to set hw params: %d\n", ret); + + return ret; +} + +static int fs210x_dai_mute(struct snd_soc_dai *dai, int mute, int stream) +{ + struct fs210x_priv *fs210x; + unsigned long delay; + + if (stream != SNDRV_PCM_STREAM_PLAYBACK) + return 0; + + fs210x = snd_soc_component_get_drvdata(dai->component); + + mutex_lock(&fs210x->lock); + + if (!fs210x->is_inited || fs210x->is_suspended) { + mutex_unlock(&fs210x->lock); + return 0; + } + + mutex_unlock(&fs210x->lock); + + if (mute) { + cancel_delayed_work_sync(&fs210x->fault_check_work); + cancel_delayed_work_sync(&fs210x->start_work); + } else { + delay = msecs_to_jiffies(fs210x->check_interval_ms); + schedule_delayed_work(&fs210x->fault_check_work, delay); + } + + return 0; +} + +static int fs210x_dai_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct fs210x_priv *fs210x; + + fs210x = snd_soc_component_get_drvdata(dai->component); + + mutex_lock(&fs210x->lock); + + if (!fs210x->is_inited || fs210x->is_suspended || fs210x->is_playing) { + mutex_unlock(&fs210x->lock); + return 0; + } + + mutex_unlock(&fs210x->lock); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + /* + * According to the power up/down sequence of FS210x, + * it requests the I2S clock has been present + * and stable(>= 2ms) before playing. + */ + schedule_delayed_work(&fs210x->start_work, + msecs_to_jiffies(FS210X_START_DELAY_MS)); + break; + + default: + break; + } + + return 0; +} + +static void fs210x_start_work(struct work_struct *work) +{ + struct fs210x_priv *fs210x; + int ret; + + fs210x = container_of(work, struct fs210x_priv, start_work.work); + + mutex_lock(&fs210x->lock); + + ret = fs210x_dev_play(fs210x); + if (ret) + dev_err(fs210x->dev, "Failed to start playing: %d\n", ret); + + mutex_unlock(&fs210x->lock); +} + +static void fs210x_fault_check_work(struct work_struct *work) +{ + struct fs210x_priv *fs210x; + u16 status; + int ret; + + fs210x = container_of(work, struct fs210x_priv, fault_check_work.work); + + mutex_lock(&fs210x->lock); + + if (!fs210x->is_inited || fs210x->is_suspended || !fs210x->is_playing) { + mutex_unlock(&fs210x->lock); + return; + } + + ret = fs210x_reg_read(fs210x, FS210X_05H_ANASTAT, &status); + mutex_unlock(&fs210x->lock); + if (ret) + return; + + if (!(status & FS210X_05H_PVDD_MASK)) + dev_err(fs210x->dev, "PVDD fault\n"); + if (status & FS210X_05H_OCDL_MASK) + dev_err(fs210x->dev, "OC detected\n"); + if (status & FS210X_05H_UVDL_MASK) + dev_err(fs210x->dev, "UV detected\n"); + if (status & FS210X_05H_OVDL_MASK) + dev_err(fs210x->dev, "OV detected\n"); + if (status & FS210X_05H_OTPDL_MASK) + dev_err(fs210x->dev, "OT detected\n"); + if (status & FS210X_05H_OCRDL_MASK) + dev_err(fs210x->dev, "OCR detected\n"); + if (status & FS210X_05H_OCLDL_MASK) + dev_err(fs210x->dev, "OCL detected\n"); + if (status & FS210X_05H_DCRDL_MASK) + dev_err(fs210x->dev, "DCR detected\n"); + if (status & FS210X_05H_DCLDL_MASK) + dev_err(fs210x->dev, "DCL detected\n"); + if (status & FS210X_05H_SRDL_MASK) + dev_err(fs210x->dev, "SR detected\n"); + if (status & FS210X_05H_OTWDL_MASK) + dev_err(fs210x->dev, "OTW detected\n"); + if (!(status & FS210X_05H_AMPS_MASK)) + dev_dbg(fs210x->dev, "Amplifier unready\n"); + if (!(status & FS210X_05H_PLLS_MASK)) + dev_err(fs210x->dev, "PLL unlock\n"); + if (!(status & FS210X_05H_ANAS_MASK)) + dev_err(fs210x->dev, "Analog power fault\n"); + + schedule_delayed_work(&fs210x->fault_check_work, + msecs_to_jiffies(fs210x->check_interval_ms)); +} + +static int fs210x_get_drvdata_from_kctrl(struct snd_kcontrol *kctrl, + struct fs210x_priv **fs210x) +{ + struct snd_soc_component *cmpnt; + + if (!kctrl) { + pr_err("fs210x: kcontrol is null\n"); + return -EINVAL; + } + + cmpnt = snd_soc_kcontrol_component(kctrl); + if (!cmpnt) { + pr_err("fs210x: component is null\n"); + return -EINVAL; + } + + *fs210x = snd_soc_component_get_drvdata(cmpnt); + + return 0; +} + +static int fs210x_effect_scene_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + const struct fs_amp_scene *scene; + struct fs210x_priv *fs210x; + const char *name = "N/A"; + int idx, count; + int ret; + + ret = fs210x_get_drvdata_from_kctrl(kcontrol, &fs210x); + if (ret || !fs210x->dev) { + pr_err("scene_effect_info: fs210x is null\n"); + return -EINVAL; + } + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + + count = fs210x->amp_lib.scene_count - 1; /* Skip init scene */ + if (count < 1) { + uinfo->value.enumerated.items = 0; + return 0; + } + + uinfo->value.enumerated.items = count; + if (uinfo->value.enumerated.item >= count) + uinfo->value.enumerated.item = count - 1; + + idx = uinfo->value.enumerated.item; + scene = fs210x->amp_lib.scene + idx + 1; + if (scene->name) + name = scene->name; + + strscpy(uinfo->value.enumerated.name, name, strlen(name) + 1); + + return 0; +} + +static int fs210x_effect_scene_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct fs210x_priv *fs210x; + int index; + int ret; + + ret = fs210x_get_drvdata_from_kctrl(kcontrol, &fs210x); + if (ret || !fs210x->dev) { + pr_err("scene_effect_get: fs210x is null\n"); + return -EINVAL; + } + + /* The id of effect scene is from 1 to N. */ + if (fs210x->scene_id < 1) + return -EINVAL; + + mutex_lock(&fs210x->lock); + /* + * FS210x has scene(s) as below: + * init scene: id = 0 + * effect scene(s): id = 1~N (optional) + * effect_index = scene_id - 1 + */ + index = fs210x->scene_id - 1; + ucontrol->value.integer.value[0] = index; + mutex_unlock(&fs210x->lock); + + return 0; +} + +static int fs210x_effect_scene_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct fs210x_priv *fs210x; + int scene_id, scene_count; + bool is_changed = false; + int ret; + + ret = fs210x_get_drvdata_from_kctrl(kcontrol, &fs210x); + if (ret || !fs210x->dev) { + pr_err("scene_effect_put: fs210x is null\n"); + return -EINVAL; + } + + mutex_lock(&fs210x->lock); + + /* + * FS210x has scene(s) as below: + * init scene: id = 0 (It's set in fs210x_init_chip() only) + * effect scene(s): id = 1~N (optional) + * scene_id = effect_index + 1. + */ + scene_id = ucontrol->value.integer.value[0] + 1; + scene_count = fs210x->amp_lib.scene_count - 1; /* Skip init scene */ + if (scene_id < 1 || scene_id > scene_count) { + mutex_unlock(&fs210x->lock); + return -ERANGE; + } + + if (scene_id != fs210x->scene_id) + is_changed = true; + + if (fs210x->is_suspended) { + fs210x->scene_id = scene_id; + mutex_unlock(&fs210x->lock); + return is_changed; + } + + ret = fs210x_set_scene(fs210x, scene_id); + if (ret) + dev_err(fs210x->dev, "Failed to set scene: %d\n", ret); + + mutex_unlock(&fs210x->lock); + + if (!ret && is_changed) + return 1; + + return ret; +} + +static int fs210x_playback_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kc, int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct fs210x_priv *fs210x = snd_soc_component_get_drvdata(cmpnt); + int ret = 0; + + mutex_lock(&fs210x->lock); + + if (fs210x->is_suspended) { + mutex_unlock(&fs210x->lock); + return 0; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* + * If there is no bclk for us to set the clock output, + * we will enable the device(start_work) in dai trigger. + */ + if (!fs210x->clk_bclk) + break; + fs210x_bclk_set(fs210x, true); + ret = fs210x_dev_play(fs210x); + break; + case SND_SOC_DAPM_POST_PMD: + ret = fs210x_dev_stop(fs210x); + fs210x_bclk_set(fs210x, false); + break; + default: + break; + } + + mutex_unlock(&fs210x->lock); + + return ret; +} + +static const struct snd_soc_dai_ops fs210x_dai_ops = { + .startup = fs210x_dai_startup, + .set_fmt = fs210x_dai_set_fmt, + .hw_params = fs210x_dai_hw_params, + .mute_stream = fs210x_dai_mute, + .trigger = fs210x_dai_trigger, +}; + +static const struct snd_soc_dai_driver fs210x_dai = { + .name = FS210X_DEFAULT_DAI_NAME, + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = FS210X_RATES, + .formats = FS210X_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = FS210X_RATES, + .formats = FS210X_FORMATS, + }, + .ops = &fs210x_dai_ops, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, +}; + +static const DECLARE_TLV_DB_SCALE(fs2105s_vol_tlv, -9709, 19, 1); +static const DECLARE_TLV_DB_SCALE(fs210x_vol_tlv, -13357, 19, 1); + +static const struct snd_kcontrol_new fs2105s_vol_control[] = { + SOC_DOUBLE_R_TLV("PCM Playback Volume", + FS210X_39H_LVOLCTRL, FS210X_3AH_RVOLCTRL, + 7, 0x1FF, 0, fs2105s_vol_tlv), +}; + +static const struct snd_kcontrol_new fs210x_vol_control[] = { + SOC_DOUBLE_R_TLV("PCM Playback Volume", + FS210X_39H_LVOLCTRL, FS210X_3AH_RVOLCTRL, + 6, 0x2BF, 0, fs210x_vol_tlv), +}; + +static const struct snd_kcontrol_new fs210x_controls[] = { + SOC_DOUBLE("DAC Mute Switch", FS210X_30H_DACCTRL, 4, 8, 1, 0), + SOC_DOUBLE("DAC Fade Switch", FS210X_30H_DACCTRL, 5, 9, 1, 0), +}; + +static const struct snd_kcontrol_new fs210x_scene_control[] = { + FS_SOC_ENUM_EXT("Effect Scene", + fs210x_effect_scene_info, + fs210x_effect_scene_get, + fs210x_effect_scene_put), +}; + +static const struct snd_soc_dapm_widget fs210x_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN_E("AIF IN", "Playback", 0, SND_SOC_NOPM, 0, 0, + fs210x_playback_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_AIF_OUT("AIF OUT", "Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_OUTPUT("OUTL"), + SND_SOC_DAPM_OUTPUT("OUTR"), + SND_SOC_DAPM_INPUT("SDO"), +}; + +static const struct snd_soc_dapm_route fs210x_dapm_routes[] = { + { "OUTL", NULL, "AIF IN" }, + { "OUTR", NULL, "AIF IN" }, + { "AIF OUT", NULL, "SDO" }, +}; + +static int fs210x_add_mixer_controls(struct fs210x_priv *fs210x, + struct snd_soc_component *cmpnt) +{ + const struct snd_kcontrol_new *kctrl; + int count; + int ret; + + if (!fs210x || !cmpnt) + return -EINVAL; + + if (fs210x->devid == FS2105S_DEVICE_ID) { + kctrl = fs2105s_vol_control; + count = ARRAY_SIZE(fs2105s_vol_control); + } else { + kctrl = fs210x_vol_control; + count = ARRAY_SIZE(fs210x_vol_control); + } + + ret = snd_soc_add_component_controls(cmpnt, kctrl, count); + if (ret) + return ret; + + /* + * If the firmware has no scene or only init scene, + * we skip adding this mixer control. + */ + if (fs210x->amp_lib.scene_count < 2) + return 0; + + kctrl = fs210x_scene_control; + count = ARRAY_SIZE(fs210x_scene_control); + + return snd_soc_add_component_controls(cmpnt, kctrl, count); +} + +static int fs210x_probe(struct snd_soc_component *cmpnt) +{ + struct fs210x_priv *fs210x; + int ret; + + fs210x = snd_soc_component_get_drvdata(cmpnt); + if (!fs210x || !fs210x->dev) + return -EINVAL; + + fs210x->amp_lib.dev = fs210x->dev; + fs210x->amp_lib.devid = fs210x->devid; + + ret = fs_amp_load_firmware(&fs210x->amp_lib, fs210x->pdata.fwm_name); + if (ret) + return ret; + + ret = fs210x_add_mixer_controls(fs210x, cmpnt); + if (ret) + return ret; + + mutex_lock(&fs210x->lock); + ret = fs210x_init_chip(fs210x); + mutex_unlock(&fs210x->lock); + + return ret; +} + +static void fs210x_remove(struct snd_soc_component *cmpnt) +{ + struct fs210x_priv *fs210x; + + fs210x = snd_soc_component_get_drvdata(cmpnt); + if (!fs210x || !fs210x->dev) + return; + + cancel_delayed_work_sync(&fs210x->start_work); + cancel_delayed_work_sync(&fs210x->fault_check_work); +} + +#ifdef CONFIG_PM +static int fs210x_suspend(struct snd_soc_component *cmpnt) +{ + struct fs210x_priv *fs210x; + int ret; + + fs210x = snd_soc_component_get_drvdata(cmpnt); + if (!fs210x || !fs210x->dev) + return -EINVAL; + + regcache_cache_only(fs210x->regmap, true); + + mutex_lock(&fs210x->lock); + fs210x->cur_scene = NULL; + fs210x->is_inited = false; + fs210x->is_playing = false; + fs210x->is_suspended = true; + + gpiod_set_value_cansleep(fs210x->gpio_sdz, 1); /* Active */ + fsleep(30000); /* >= 30ms */ + mutex_unlock(&fs210x->lock); + + cancel_delayed_work_sync(&fs210x->start_work); + cancel_delayed_work_sync(&fs210x->fault_check_work); + + ret = regulator_bulk_disable(FS210X_NUM_SUPPLIES, fs210x->supplies); + if (ret) { + dev_err(fs210x->dev, "Failed to suspend: %d\n", ret); + return ret; + } + + return 0; +} + +static int fs210x_resume(struct snd_soc_component *cmpnt) +{ + struct fs210x_priv *fs210x; + int ret; + + fs210x = snd_soc_component_get_drvdata(cmpnt); + if (!fs210x || !fs210x->dev) + return -EINVAL; + + ret = regulator_bulk_enable(FS210X_NUM_SUPPLIES, fs210x->supplies); + if (ret) { + dev_err(fs210x->dev, "Failed to enable supplies: %d\n", ret); + return ret; + } + + mutex_lock(&fs210x->lock); + + fs210x->is_suspended = false; + ret = fs210x_init_chip(fs210x); + + mutex_unlock(&fs210x->lock); + + return ret; +} +#else +#define fs210x_suspend NULL +#define fs210x_resume NULL +#endif // CONFIG_PM + +static bool fs210x_volatile_registers(struct device *dev, unsigned int reg) +{ + switch (reg) { + case FS210X_00H_STATUS ... FS210X_0FH_I2CADDR: + case FS210X_ABH_INTSTAT: + case FS210X_ACH_INTSTATR: + return true; + default: + return false; + } +} + +static const struct snd_soc_component_driver fs210x_soc_component_dev = { + .probe = fs210x_probe, + .remove = fs210x_remove, + .suspend = fs210x_suspend, + .resume = fs210x_resume, + .controls = fs210x_controls, + .num_controls = ARRAY_SIZE(fs210x_controls), + .dapm_widgets = fs210x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(fs210x_dapm_widgets), + .dapm_routes = fs210x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(fs210x_dapm_routes), +}; + +static const struct regmap_config fs210x_regmap = { + .reg_bits = 8, + .val_bits = 16, + .max_register = FS210X_REG_MAX, + .val_format_endian = REGMAP_ENDIAN_BIG, + .cache_type = REGCACHE_MAPLE, + .volatile_reg = fs210x_volatile_registers, +}; + +static int fs210x_detect_device(struct fs210x_priv *fs210x) +{ + u16 devid; + int ret; + + ret = fs210x_reg_read(fs210x, FS210X_03H_DEVID, &devid); + if (ret) + return ret; + + fs210x->devid = HI_U16(devid); + + switch (fs210x->devid) { + case FS210X_DEVICE_ID: + dev_info(fs210x->dev, "FS2104 detected\n"); + break; + case FS2105S_DEVICE_ID: + dev_info(fs210x->dev, "FS2105S detected\n"); + break; + default: + dev_err(fs210x->dev, "DEVID: 0x%04X dismatch\n", devid); + return -ENODEV; + } + + return 0; +} + +static int fs210x_parse_dts(struct fs210x_priv *fs210x, + struct fs210x_platform_data *pdata) +{ + struct device_node *node = fs210x->dev->of_node; + int i, ret; + + if (!node) + return 0; + + ret = of_property_read_string(node, "firmware-name", &pdata->fwm_name); + if (ret) + pdata->fwm_name = FS210X_DEFAULT_FWM_NAME; + + fs210x->gpio_sdz = devm_gpiod_get_optional(fs210x->dev, + "reset", GPIOD_OUT_HIGH); + if (IS_ERR(fs210x->gpio_sdz)) + return dev_err_probe(fs210x->dev, PTR_ERR(fs210x->gpio_sdz), + "Failed to get reset-gpios\n"); + + for (i = 0; i < FS210X_NUM_SUPPLIES; i++) + fs210x->supplies[i].supply = fs210x_supply_names[i]; + + ret = devm_regulator_bulk_get(fs210x->dev, + ARRAY_SIZE(fs210x->supplies), + fs210x->supplies); + if (ret) + return dev_err_probe(fs210x->dev, ret, + "Failed to get supplies\n"); + + return 0; +} + +static void fs210x_deinit(struct fs210x_priv *fs210x) +{ + gpiod_set_value_cansleep(fs210x->gpio_sdz, 1); /* Active */ + fsleep(10000); /* >= 10ms */ + + regulator_bulk_disable(FS210X_NUM_SUPPLIES, fs210x->supplies); +} + +static int fs210x_init(struct fs210x_priv *fs210x) +{ + int ret; + + ret = fs210x_parse_dts(fs210x, &fs210x->pdata); + if (ret) + return ret; + + fs210x->clk_bclk = devm_clk_get_optional(fs210x->dev, "bclk"); + if (IS_ERR(fs210x->clk_bclk)) + return dev_err_probe(fs210x->dev, PTR_ERR(fs210x->clk_bclk), + "Failed to get bclk\n"); + + ret = regulator_bulk_enable(FS210X_NUM_SUPPLIES, fs210x->supplies); + if (ret) + return dev_err_probe(fs210x->dev, ret, + "Failed to enable supplies\n"); + + /* Make sure the SDZ pin is pulled down enough time. */ + fsleep(10000); /* >= 10ms */ + gpiod_set_value_cansleep(fs210x->gpio_sdz, 0); /* Deactivate */ + fsleep(10000); /* >= 10ms */ + + ret = fs210x_detect_device(fs210x); + if (ret) { + fs210x_deinit(fs210x); + return ret; + } + + fs210x->scene_id = -1; /* Invalid scene */ + fs210x->cur_scene = NULL; + fs210x->is_playing = false; + fs210x->is_inited = false; + fs210x->is_suspended = false; + fs210x->check_interval_ms = FS210X_FAULT_CHECK_INTERVAL_MS; + + INIT_DELAYED_WORK(&fs210x->fault_check_work, fs210x_fault_check_work); + INIT_DELAYED_WORK(&fs210x->start_work, fs210x_start_work); + mutex_init(&fs210x->lock); + + return 0; +} + +static int fs210x_register_snd_component(struct fs210x_priv *fs210x) +{ + struct snd_soc_dai_driver *dai_drv; + static int instance_id; + int ret; + + dai_drv = devm_kmemdup(fs210x->dev, &fs210x_dai, + sizeof(fs210x_dai), GFP_KERNEL); + if (!dai_drv) + return -ENOMEM; + + dai_drv->name = devm_kasprintf(fs210x->dev, + GFP_KERNEL, "%s-%d", + dai_drv->name, instance_id); + if (!dai_drv->name) + return -ENOMEM; + + instance_id++; + + if (fs210x->devid == FS2105S_DEVICE_ID) { + dai_drv->playback.rates = FS2105S_RATES; + dai_drv->capture.rates = FS2105S_RATES; + } + + ret = snd_soc_register_component(fs210x->dev, + &fs210x_soc_component_dev, + dai_drv, 1); + return ret; +} + +static ssize_t check_interval_ms_show(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct fs210x_priv *fs210x = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%d\n", fs210x->check_interval_ms); +} + +static ssize_t check_interval_ms_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct fs210x_priv *fs210x = dev_get_drvdata(dev); + int ret; + + ret = kstrtouint(buf, 10, &fs210x->check_interval_ms); + if (ret) + return -EINVAL; + + return (ssize_t)count; +} + +static DEVICE_ATTR_RW(check_interval_ms); + +static struct attribute *fs210x_attrs[] = { + &dev_attr_check_interval_ms.attr, + NULL, +}; + +static struct attribute_group fs210x_attr_group = { + .attrs = fs210x_attrs, +}; + +static int fs210x_i2c_probe(struct i2c_client *client) +{ + struct fs210x_priv *fs210x; + int ret; + + fs210x = devm_kzalloc(&client->dev, sizeof(*fs210x), GFP_KERNEL); + if (!fs210x) + return -ENOMEM; + + fs210x->i2c = client; + fs210x->dev = &client->dev; + i2c_set_clientdata(client, fs210x); + + fs210x->regmap = devm_regmap_init_i2c(client, &fs210x_regmap); + if (IS_ERR(fs210x->regmap)) + return dev_err_probe(fs210x->dev, PTR_ERR(fs210x->regmap), + "Failed to get regmap\n"); + + ret = fs210x_init(fs210x); + if (ret) + return ret; + + ret = devm_device_add_group(fs210x->dev, &fs210x_attr_group); + if (ret) { + fs210x_deinit(fs210x); + return dev_err_probe(fs210x->dev, ret, + "Failed to create sysfs group\n"); + } + + ret = fs210x_register_snd_component(fs210x); + if (ret) { + fs210x_deinit(fs210x); + return dev_err_probe(fs210x->dev, ret, + "Failed to register component\n"); + } + + return 0; +} + +static void fs210x_i2c_remove(struct i2c_client *client) +{ + struct fs210x_priv *fs210x = i2c_get_clientdata(client); + + snd_soc_unregister_component(fs210x->dev); + fs210x_deinit(fs210x); +} + +static const struct i2c_device_id fs210x_i2c_id[] = { + { "fs2104" }, + { "fs2105s" }, + {} +}; +MODULE_DEVICE_TABLE(i2c, fs210x_i2c_id); + +static const struct of_device_id fs210x_of_match[] = { + { .compatible = "foursemi,fs2105s", }, + {}, +}; +MODULE_DEVICE_TABLE(of, fs210x_of_match); + +static struct i2c_driver fs210x_i2c_driver = { + .driver = { + .name = "fs210x", + .of_match_table = fs210x_of_match, + }, + .id_table = fs210x_i2c_id, + .probe = fs210x_i2c_probe, + .remove = fs210x_i2c_remove, +}; + +module_i2c_driver(fs210x_i2c_driver); + +MODULE_AUTHOR("Nick Li <nick.li@foursemi.com>"); +MODULE_DESCRIPTION("FS2104/5S Audio Amplifier Driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/fs210x.h b/sound/soc/codecs/fs210x.h new file mode 100644 index 000000000000..78e1760332ca --- /dev/null +++ b/sound/soc/codecs/fs210x.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * fs210x.h -- Driver for the FS2104/5S Audio Amplifier + * + * Copyright (C) 2016-2025 Shanghai FourSemi Semiconductor Co.,Ltd. + */ + +#ifndef __FS210X_H__ +#define __FS210X_H__ + +#define FS210X_00H_STATUS 0x00 +#define FS210X_03H_DEVID 0x03 +#define FS210X_05H_ANASTAT 0x05 +#define FS210X_06H_DIGSTAT 0x06 +#define FS210X_0BH_ACCKEY 0x0B +#define FS210X_0FH_I2CADDR 0x0F +#define FS210X_10H_PWRCTRL 0x10 +#define FS210X_11H_SYSCTRL 0x11 +#define FS210X_17H_I2SCTRL 0x17 +#define FS210X_30H_DACCTRL 0x30 +#define FS210X_39H_LVOLCTRL 0x39 +#define FS210X_3AH_RVOLCTRL 0x3A +#define FS210X_42H_DACEQWL 0x42 +#define FS210X_46H_DACEQA 0x46 +#define FS210X_A1H_PLLCTRL1 0xA1 +#define FS210X_A2H_PLLCTRL2 0xA2 +#define FS210X_A3H_PLLCTRL3 0xA3 +#define FS210X_ABH_INTSTAT 0xAB +#define FS210X_ACH_INTSTATR 0xAC + +#define FS210X_05H_PVDD_SHIFT 14 +#define FS210X_05H_PVDD_MASK BIT(14) +#define FS210X_05H_OCDL_SHIFT 13 +#define FS210X_05H_OCDL_MASK BIT(13) +#define FS210X_05H_UVDL_SHIFT 12 +#define FS210X_05H_UVDL_MASK BIT(12) +#define FS210X_05H_OVDL_SHIFT 11 +#define FS210X_05H_OVDL_MASK BIT(11) +#define FS210X_05H_OTPDL_SHIFT 10 +#define FS210X_05H_OTPDL_MASK BIT(10) +#define FS210X_05H_OCRDL_SHIFT 9 +#define FS210X_05H_OCRDL_MASK BIT(9) +#define FS210X_05H_OCLDL_SHIFT 8 +#define FS210X_05H_OCLDL_MASK BIT(8) +#define FS210X_05H_DCRDL_SHIFT 7 +#define FS210X_05H_DCRDL_MASK BIT(7) +#define FS210X_05H_DCLDL_SHIFT 6 +#define FS210X_05H_DCLDL_MASK BIT(6) +#define FS210X_05H_SRDL_SHIFT 5 +#define FS210X_05H_SRDL_MASK BIT(5) +#define FS210X_05H_OTWDL_SHIFT 4 +#define FS210X_05H_OTWDL_MASK BIT(4) +#define FS210X_05H_AMPS_SHIFT 3 +#define FS210X_05H_AMPS_MASK BIT(3) +#define FS210X_05H_PLLS_SHIFT 1 +#define FS210X_05H_PLLS_MASK BIT(1) +#define FS210X_05H_ANAS_SHIFT 0 +#define FS210X_05H_ANAS_MASK BIT(0) +#define FS210X_17H_I2SSR_SHIFT 12 +#define FS210X_17H_I2SSR_MASK GENMASK(15, 12) +#define FS210X_30H_RMUTE_SHIFT 8 +#define FS210X_30H_LMUTE_SHIFT 4 + +#define FS210X_0BH_ACCKEY_ON 0x0091 +#define FS210X_0BH_ACCKEY_OFF 0x0000 +#define FS210X_10H_I2C_RESET 0x0002 +#define FS210X_11H_DPS_HIZ 0x0100 +#define FS210X_11H_DPS_PWDN 0x0000 +#define FS210X_11H_DPS_PLAY 0x0300 +#define FS210X_46H_CAM_BURST_L 0x8000 +#define FS210X_46H_CAM_BURST_R 0x8200 +#define FS2105S_46H_CAM_BURST_W 0x8400 +#define FS210X_46H_CAM_CLEAR 0x0000 + +#endif /* __FS210X_H__ */ diff --git a/sound/soc/codecs/lpass-macro-common.h b/sound/soc/codecs/lpass-macro-common.h index fb4b96cb2b23..10ad682019fa 100644 --- a/sound/soc/codecs/lpass-macro-common.h +++ b/sound/soc/codecs/lpass-macro-common.h @@ -29,6 +29,7 @@ enum lpass_codec_version { LPASS_CODEC_VERSION_2_6, LPASS_CODEC_VERSION_2_7, LPASS_CODEC_VERSION_2_8, + LPASS_CODEC_VERSION_2_9, }; struct lpass_macro { diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index a49551f3fb29..2e1b77973a3e 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -1485,6 +1485,8 @@ static void va_macro_set_lpass_codec_version(struct va_macro *va) version = LPASS_CODEC_VERSION_2_7; if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x80 || core_id_2 == 0x81)) version = LPASS_CODEC_VERSION_2_8; + if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x90 || core_id_2 == 0x91)) + version = LPASS_CODEC_VERSION_2_9; if (version == LPASS_CODEC_VERSION_UNKNOWN) dev_warn(va->dev, "Unknown Codec version, ID: %02x / %02x / %02x\n", diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index d7eec9fdaf9c..38faa9074ca3 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -2698,6 +2698,7 @@ static int wsa_macro_component_probe(struct snd_soc_component *comp) case LPASS_CODEC_VERSION_2_6: case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: + case LPASS_CODEC_VERSION_2_9: widgets = wsa_macro_dapm_widgets_v2_5; num_widgets = ARRAY_SIZE(wsa_macro_dapm_widgets_v2_5); break; @@ -2846,6 +2847,7 @@ static int wsa_macro_probe(struct platform_device *pdev) case LPASS_CODEC_VERSION_2_6: case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: + case LPASS_CODEC_VERSION_2_9: wsa->reg_layout = &wsa_codec_v2_5; def_count = ARRAY_SIZE(wsa_defaults) + ARRAY_SIZE(wsa_defaults_v2_5); reg_defaults = kmalloc_array(def_count, sizeof(*reg_defaults), diff --git a/sound/soc/codecs/pcm1754.c b/sound/soc/codecs/pcm1754.c new file mode 100644 index 000000000000..b68a528000be --- /dev/null +++ b/sound/soc/codecs/pcm1754.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * PCM1754 DAC ASoC codec driver + * + * Copyright (c) 2022 Alvin Å ipraga <alsi@bang-olufsen.dk> + * Copyright (c) 2025 Stefan Kerkmann <s.kerkmann@pengutronix.de> + */ + +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> + +#include <sound/pcm_params.h> +#include <sound/soc.h> + +struct pcm1754_priv { + unsigned int format; + struct gpio_desc *gpiod_mute; + struct gpio_desc *gpiod_format; +}; + +static int pcm1754_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int format) +{ + struct snd_soc_component *component = codec_dai->component; + struct pcm1754_priv *priv = snd_soc_component_get_drvdata(component); + + priv->format = format; + + return 0; +} + +static int pcm1754_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *codec_dai) +{ + struct snd_soc_component *component = codec_dai->component; + struct pcm1754_priv *priv = snd_soc_component_get_drvdata(component); + int format; + + switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_RIGHT_J: + switch (params_width(params)) { + case 16: + format = 1; + break; + default: + return -EINVAL; + } + break; + case SND_SOC_DAIFMT_I2S: + switch (params_width(params)) { + case 16: + fallthrough; + case 24: + format = 0; + break; + default: + return -EINVAL; + } + break; + default: + dev_err(component->dev, "Invalid DAI format\n"); + return -EINVAL; + } + + gpiod_set_value_cansleep(priv->gpiod_format, format); + + return 0; +} + +static int pcm1754_mute_stream(struct snd_soc_dai *dai, int mute, int stream) +{ + struct pcm1754_priv *priv = snd_soc_component_get_drvdata(dai->component); + + gpiod_set_value_cansleep(priv->gpiod_mute, mute); + + return 0; +} + +static const struct snd_soc_dai_ops pcm1754_dai_ops = { + .set_fmt = pcm1754_set_dai_fmt, + .hw_params = pcm1754_hw_params, + .mute_stream = pcm1754_mute_stream, +}; + +static const struct snd_soc_dai_driver pcm1754_dai = { + .name = "pcm1754", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 5000, + .rate_max = 200000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE + }, + .ops = &pcm1754_dai_ops, +}; + +static const struct snd_soc_dapm_widget pcm1754_dapm_widgets[] = { + SND_SOC_DAPM_REGULATOR_SUPPLY("VCC", 0, 0), + + SND_SOC_DAPM_DAC("DAC1", "Channel 1 Playback", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC2", "Channel 2 Playback", SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_OUTPUT("VOUTL"), + SND_SOC_DAPM_OUTPUT("VOUTR"), +}; + +static const struct snd_soc_dapm_route pcm1754_dapm_routes[] = { + { "DAC1", NULL, "Playback" }, + { "DAC2", NULL, "Playback" }, + + { "DAC1", NULL, "VCC" }, + { "DAC2", NULL, "VCC" }, + + { "VOUTL", NULL, "DAC1" }, + { "VOUTR", NULL, "DAC2" }, +}; + +static const struct snd_soc_component_driver soc_component_dev_pcm1754 = { + .dapm_widgets = pcm1754_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm1754_dapm_widgets), + .dapm_routes = pcm1754_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm1754_dapm_routes), +}; + +static int pcm1754_probe(struct platform_device *pdev) +{ + struct pcm1754_priv *priv; + struct device *dev = &pdev->dev; + struct snd_soc_dai_driver *dai_drv; + int ret; + + dai_drv = devm_kmemdup(dev, &pcm1754_dai, sizeof(*dai_drv), GFP_KERNEL); + if (!dai_drv) + return -ENOMEM; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->gpiod_mute = devm_gpiod_get_optional(dev, "mute", GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpiod_mute)) + return dev_err_probe(dev, PTR_ERR(priv->gpiod_mute), + "failed to get mute gpio"); + + priv->gpiod_format = devm_gpiod_get_optional(dev, "format", GPIOD_OUT_LOW); + if (IS_ERR(priv->gpiod_format)) + return dev_err_probe(dev, PTR_ERR(priv->gpiod_format), + "failed to get format gpio"); + + dev_set_drvdata(dev, priv); + + ret = devm_snd_soc_register_component( + &pdev->dev, &soc_component_dev_pcm1754, dai_drv, 1); + if (ret) + return dev_err_probe(dev, ret, "failed to register"); + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id pcm1754_of_match[] = { + { .compatible = "ti,pcm1754" }, + { } +}; +MODULE_DEVICE_TABLE(of, pcm1754_of_match); +#endif + +static struct platform_driver pcm1754_codec_driver = { + .driver = { + .name = "pcm1754-codec", + .of_match_table = of_match_ptr(pcm1754_of_match), + }, + .probe = pcm1754_probe, +}; + +module_platform_driver(pcm1754_codec_driver); + +MODULE_DESCRIPTION("ASoC PCM1754 driver"); +MODULE_AUTHOR("Alvin Å ipraga <alsi@bang-olufsen.dk>"); +MODULE_AUTHOR("Stefan Kerkmann <s.kerkmann@pengutronix.de>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/pcm6240.c b/sound/soc/codecs/pcm6240.c index 75af12231d1d..08cc52b374a9 100644 --- a/sound/soc/codecs/pcm6240.c +++ b/sound/soc/codecs/pcm6240.c @@ -1353,8 +1353,8 @@ static int pcmdev_gain_ctrl_add(struct pcmdevice_priv *pcm_dev, return 0; } - pcmdev_controls = devm_kzalloc(pcm_dev->dev, - nr_chn * sizeof(struct snd_kcontrol_new), GFP_KERNEL); + pcmdev_controls = devm_kcalloc(pcm_dev->dev, nr_chn, + sizeof(struct snd_kcontrol_new), GFP_KERNEL); if (!pcmdev_controls) return -ENOMEM; diff --git a/sound/soc/codecs/pm4125-sdw.c b/sound/soc/codecs/pm4125-sdw.c new file mode 100644 index 000000000000..4ed09fbe3f54 --- /dev/null +++ b/sound/soc/codecs/pm4125-sdw.c @@ -0,0 +1,545 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved. +// Copyright, 2025 Linaro Ltd + +#include <linux/component.h> +#include <linux/device.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_registers.h> +#include <linux/soundwire/sdw_type.h> +#include <sound/soc-dapm.h> +#include <sound/soc.h> +#include "pm4125.h" + +static struct pm4125_sdw_ch_info pm4125_sdw_rx_ch_info[] = { + WCD_SDW_CH(PM4125_HPH_L, PM4125_HPH_PORT, BIT(0)), + WCD_SDW_CH(PM4125_HPH_R, PM4125_HPH_PORT, BIT(1)), +}; + +static struct pm4125_sdw_ch_info pm4125_sdw_tx_ch_info[] = { + WCD_SDW_CH(PM4125_ADC1, PM4125_ADC_1_2_DMIC1L_BCS_PORT, BIT(0)), + WCD_SDW_CH(PM4125_ADC2, PM4125_ADC_1_2_DMIC1L_BCS_PORT, BIT(1)), +}; + +static struct sdw_dpn_prop pm4125_dpn_prop[PM4125_MAX_SWR_PORTS] = { + { + .num = 1, + .type = SDW_DPN_SIMPLE, + .min_ch = 1, + .max_ch = 8, + .simple_ch_prep_sm = true, + }, { + .num = 2, + .type = SDW_DPN_SIMPLE, + .min_ch = 1, + .max_ch = 4, + .simple_ch_prep_sm = true, + } +}; + +struct device *pm4125_sdw_device_get(struct device_node *np) +{ + return bus_find_device_by_of_node(&sdw_bus_type, np); +} +EXPORT_SYMBOL_GPL(pm4125_sdw_device_get); + +int pm4125_sdw_hw_params(struct pm4125_sdw_priv *priv, struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct sdw_port_config port_config[PM4125_MAX_SWR_PORTS]; + unsigned long ch_mask; + int i, j; + + priv->sconfig.ch_count = 1; + priv->active_ports = 0; + for (i = 0; i < PM4125_MAX_SWR_PORTS; i++) { + ch_mask = priv->port_config[i].ch_mask; + if (!ch_mask) + continue; + + for_each_set_bit(j, &ch_mask, 4) + priv->sconfig.ch_count++; + + port_config[priv->active_ports] = priv->port_config[i]; + priv->active_ports++; + } + + priv->sconfig.bps = 1; + priv->sconfig.frame_rate = params_rate(params); + priv->sconfig.direction = priv->is_tx ? SDW_DATA_DIR_TX : SDW_DATA_DIR_RX; + priv->sconfig.type = SDW_STREAM_PCM; + + return sdw_stream_add_slave(priv->sdev, &priv->sconfig, &port_config[0], priv->active_ports, + priv->sruntime); +} +EXPORT_SYMBOL_GPL(pm4125_sdw_hw_params); + +static int pm4125_update_status(struct sdw_slave *slave, enum sdw_slave_status status) +{ + struct pm4125_sdw_priv *priv = dev_get_drvdata(&slave->dev); + + if (priv->regmap && status == SDW_SLAVE_ATTACHED) { + /* Write out any cached changes that happened between probe and attach */ + regcache_cache_only(priv->regmap, false); + return regcache_sync(priv->regmap); + } + + return 0; +} + +/* + * Handle Soundwire out-of-band interrupt event by triggering the first irq of the slave_irq + * irq domain, which then will be handled by the regmap_irq threaded irq. + * Looping is to ensure no interrupts were missed in the process. + */ +static int pm4125_interrupt_callback(struct sdw_slave *slave, struct sdw_slave_intr_status *status) +{ + struct pm4125_sdw_priv *priv = dev_get_drvdata(&slave->dev); + struct irq_domain *slave_irq = priv->slave_irq; + u32 sts1, sts2, sts3; + + do { + handle_nested_irq(irq_find_mapping(slave_irq, 0)); + regmap_read(priv->regmap, PM4125_DIG_SWR_INTR_STATUS_0, &sts1); + regmap_read(priv->regmap, PM4125_DIG_SWR_INTR_STATUS_1, &sts2); + regmap_read(priv->regmap, PM4125_DIG_SWR_INTR_STATUS_2, &sts3); + + } while (sts1 || sts2 || sts3); + + return IRQ_HANDLED; +} + +static const struct reg_default pm4125_defaults[] = { + { PM4125_ANA_MICBIAS_MICB_1_2_EN, 0x01 }, + { PM4125_ANA_MICBIAS_MICB_3_EN, 0x00 }, + { PM4125_ANA_MICBIAS_LDO_1_SETTING, 0x21 }, + { PM4125_ANA_MICBIAS_LDO_1_CTRL, 0x01 }, + { PM4125_ANA_TX_AMIC1, 0x00 }, + { PM4125_ANA_TX_AMIC2, 0x00 }, + { PM4125_ANA_MBHC_MECH, 0x39 }, + { PM4125_ANA_MBHC_ELECT, 0x08 }, + { PM4125_ANA_MBHC_ZDET, 0x10 }, + { PM4125_ANA_MBHC_RESULT_1, 0x00 }, + { PM4125_ANA_MBHC_RESULT_2, 0x00 }, + { PM4125_ANA_MBHC_RESULT_3, 0x00 }, + { PM4125_ANA_MBHC_BTN0_ZDET_VREF1, 0x00 }, + { PM4125_ANA_MBHC_BTN1_ZDET_VREF2, 0x10 }, + { PM4125_ANA_MBHC_BTN2_ZDET_VREF3, 0x20 }, + { PM4125_ANA_MBHC_BTN3_ZDET_DBG_400, 0x30 }, + { PM4125_ANA_MBHC_BTN4_ZDET_DBG_1400, 0x40 }, + { PM4125_ANA_MBHC_MICB2_RAMP, 0x00 }, + { PM4125_ANA_MBHC_CTL_1, 0x02 }, + { PM4125_ANA_MBHC_CTL_2, 0x05 }, + { PM4125_ANA_MBHC_PLUG_DETECT_CTL, 0xE9 }, + { PM4125_ANA_MBHC_ZDET_ANA_CTL, 0x0F }, + { PM4125_ANA_MBHC_ZDET_RAMP_CTL, 0x00 }, + { PM4125_ANA_MBHC_FSM_STATUS, 0x00 }, + { PM4125_ANA_MBHC_ADC_RESULT, 0x00 }, + { PM4125_ANA_MBHC_CTL_CLK, 0x30 }, + { PM4125_ANA_MBHC_ZDET_CALIB_RESULT, 0x00 }, + { PM4125_ANA_NCP_EN, 0x00 }, + { PM4125_ANA_NCP_VCTRL, 0xA7 }, + { PM4125_ANA_HPHPA_CNP_CTL_1, 0x54 }, + { PM4125_ANA_HPHPA_CNP_CTL_2, 0x2B }, + { PM4125_ANA_HPHPA_PA_STATUS, 0x00 }, + { PM4125_ANA_HPHPA_FSM_CLK, 0x12 }, + { PM4125_ANA_HPHPA_L_GAIN, 0x00 }, + { PM4125_ANA_HPHPA_R_GAIN, 0x00 }, + { PM4125_SWR_HPHPA_HD2, 0x1B }, + { PM4125_ANA_HPHPA_SPARE_CTL, 0x02 }, + { PM4125_ANA_SURGE_EN, 0x38 }, + { PM4125_ANA_COMBOPA_CTL, 0x35 }, + { PM4125_ANA_COMBOPA_CTL_4, 0x84 }, + { PM4125_ANA_COMBOPA_CTL_5, 0x05 }, + { PM4125_ANA_RXLDO_CTL, 0x86 }, + { PM4125_ANA_MBIAS_EN, 0x00 }, + { PM4125_DIG_SWR_CHIP_ID0, 0x00 }, + { PM4125_DIG_SWR_CHIP_ID1, 0x00 }, + { PM4125_DIG_SWR_CHIP_ID2, 0x0C }, + { PM4125_DIG_SWR_CHIP_ID3, 0x01 }, + { PM4125_DIG_SWR_SWR_TX_CLK_RATE, 0x00 }, + { PM4125_DIG_SWR_CDC_RST_CTL, 0x03 }, + { PM4125_DIG_SWR_TOP_CLK_CFG, 0x00 }, + { PM4125_DIG_SWR_CDC_RX_CLK_CTL, 0x00 }, + { PM4125_DIG_SWR_CDC_TX_CLK_CTL, 0x33 }, + { PM4125_DIG_SWR_SWR_RST_EN, 0x00 }, + { PM4125_DIG_SWR_CDC_RX_RST, 0x00 }, + { PM4125_DIG_SWR_CDC_RX0_CTL, 0xFC }, + { PM4125_DIG_SWR_CDC_RX1_CTL, 0xFC }, + { PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1, 0x00 }, + { PM4125_DIG_SWR_CDC_COMP_CTL_0, 0x00 }, + { PM4125_DIG_SWR_CDC_RX_DELAY_CTL, 0x66 }, + { PM4125_DIG_SWR_CDC_RX_GAIN_0, 0x55 }, + { PM4125_DIG_SWR_CDC_RX_GAIN_1, 0xA9 }, + { PM4125_DIG_SWR_CDC_RX_GAIN_CTL, 0x00 }, + { PM4125_DIG_SWR_CDC_TX0_CTL, 0x68 }, + { PM4125_DIG_SWR_CDC_TX1_CTL, 0x68 }, + { PM4125_DIG_SWR_CDC_TX_RST, 0x00 }, + { PM4125_DIG_SWR_CDC_REQ0_CTL, 0x01 }, + { PM4125_DIG_SWR_CDC_REQ1_CTL, 0x01 }, + { PM4125_DIG_SWR_CDC_RST, 0x00 }, + { PM4125_DIG_SWR_CDC_AMIC_CTL, 0x02 }, + { PM4125_DIG_SWR_CDC_DMIC_CTL, 0x00 }, + { PM4125_DIG_SWR_CDC_DMIC1_CTL, 0x00 }, + { PM4125_DIG_SWR_CDC_DMIC1_RATE, 0x01 }, + { PM4125_DIG_SWR_PDM_WD_CTL0, 0x00 }, + { PM4125_DIG_SWR_PDM_WD_CTL1, 0x00 }, + { PM4125_DIG_SWR_INTR_MODE, 0x00 }, + { PM4125_DIG_SWR_INTR_MASK_0, 0xFF }, + { PM4125_DIG_SWR_INTR_MASK_1, 0x7F }, + { PM4125_DIG_SWR_INTR_MASK_2, 0x0C }, + { PM4125_DIG_SWR_INTR_STATUS_0, 0x00 }, + { PM4125_DIG_SWR_INTR_STATUS_1, 0x00 }, + { PM4125_DIG_SWR_INTR_STATUS_2, 0x00 }, + { PM4125_DIG_SWR_INTR_CLEAR_0, 0x00 }, + { PM4125_DIG_SWR_INTR_CLEAR_1, 0x00 }, + { PM4125_DIG_SWR_INTR_CLEAR_2, 0x00 }, + { PM4125_DIG_SWR_INTR_LEVEL_0, 0x00 }, + { PM4125_DIG_SWR_INTR_LEVEL_1, 0x2A }, + { PM4125_DIG_SWR_INTR_LEVEL_2, 0x00 }, + { PM4125_DIG_SWR_CDC_CONN_RX0_CTL, 0x00 }, + { PM4125_DIG_SWR_CDC_CONN_RX1_CTL, 0x00 }, + { PM4125_DIG_SWR_LOOP_BACK_MODE, 0x00 }, + { PM4125_DIG_SWR_DRIVE_STRENGTH_0, 0x00 }, + { PM4125_DIG_SWR_DIG_DEBUG_CTL, 0x00 }, + { PM4125_DIG_SWR_DIG_DEBUG_EN, 0x00 }, + { PM4125_DIG_SWR_DEM_BYPASS_DATA0, 0x55 }, + { PM4125_DIG_SWR_DEM_BYPASS_DATA1, 0x55 }, + { PM4125_DIG_SWR_DEM_BYPASS_DATA2, 0x55 }, + { PM4125_DIG_SWR_DEM_BYPASS_DATA3, 0x01 }, +}; + +static bool pm4125_rdwr_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PM4125_ANA_MICBIAS_MICB_1_2_EN: + case PM4125_ANA_MICBIAS_MICB_3_EN: + case PM4125_ANA_MICBIAS_LDO_1_SETTING: + case PM4125_ANA_MICBIAS_LDO_1_CTRL: + case PM4125_ANA_TX_AMIC1: + case PM4125_ANA_TX_AMIC2: + case PM4125_ANA_MBHC_MECH: + case PM4125_ANA_MBHC_ELECT: + case PM4125_ANA_MBHC_ZDET: + case PM4125_ANA_MBHC_BTN0_ZDET_VREF1: + case PM4125_ANA_MBHC_BTN1_ZDET_VREF2: + case PM4125_ANA_MBHC_BTN2_ZDET_VREF3: + case PM4125_ANA_MBHC_BTN3_ZDET_DBG_400: + case PM4125_ANA_MBHC_BTN4_ZDET_DBG_1400: + case PM4125_ANA_MBHC_MICB2_RAMP: + case PM4125_ANA_MBHC_CTL_1: + case PM4125_ANA_MBHC_CTL_2: + case PM4125_ANA_MBHC_PLUG_DETECT_CTL: + case PM4125_ANA_MBHC_ZDET_ANA_CTL: + case PM4125_ANA_MBHC_ZDET_RAMP_CTL: + case PM4125_ANA_MBHC_CTL_CLK: + case PM4125_ANA_NCP_EN: + case PM4125_ANA_NCP_VCTRL: + case PM4125_ANA_HPHPA_CNP_CTL_1: + case PM4125_ANA_HPHPA_CNP_CTL_2: + case PM4125_ANA_HPHPA_FSM_CLK: + case PM4125_ANA_HPHPA_L_GAIN: + case PM4125_ANA_HPHPA_R_GAIN: + case PM4125_ANA_HPHPA_SPARE_CTL: + case PM4125_SWR_HPHPA_HD2: + case PM4125_ANA_SURGE_EN: + case PM4125_ANA_COMBOPA_CTL: + case PM4125_ANA_COMBOPA_CTL_4: + case PM4125_ANA_COMBOPA_CTL_5: + case PM4125_ANA_RXLDO_CTL: + case PM4125_ANA_MBIAS_EN: + case PM4125_DIG_SWR_SWR_TX_CLK_RATE: + case PM4125_DIG_SWR_CDC_RST_CTL: + case PM4125_DIG_SWR_TOP_CLK_CFG: + case PM4125_DIG_SWR_CDC_RX_CLK_CTL: + case PM4125_DIG_SWR_CDC_TX_CLK_CTL: + case PM4125_DIG_SWR_SWR_RST_EN: + case PM4125_DIG_SWR_CDC_RX_RST: + case PM4125_DIG_SWR_CDC_RX0_CTL: + case PM4125_DIG_SWR_CDC_RX1_CTL: + case PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1: + case PM4125_DIG_SWR_CDC_COMP_CTL_0: + case PM4125_DIG_SWR_CDC_RX_DELAY_CTL: + case PM4125_DIG_SWR_CDC_RX_GAIN_0: + case PM4125_DIG_SWR_CDC_RX_GAIN_1: + case PM4125_DIG_SWR_CDC_RX_GAIN_CTL: + case PM4125_DIG_SWR_CDC_TX0_CTL: + case PM4125_DIG_SWR_CDC_TX1_CTL: + case PM4125_DIG_SWR_CDC_TX_RST: + case PM4125_DIG_SWR_CDC_REQ0_CTL: + case PM4125_DIG_SWR_CDC_REQ1_CTL: + case PM4125_DIG_SWR_CDC_RST: + case PM4125_DIG_SWR_CDC_AMIC_CTL: + case PM4125_DIG_SWR_CDC_DMIC_CTL: + case PM4125_DIG_SWR_CDC_DMIC1_CTL: + case PM4125_DIG_SWR_CDC_DMIC1_RATE: + case PM4125_DIG_SWR_PDM_WD_CTL0: + case PM4125_DIG_SWR_PDM_WD_CTL1: + case PM4125_DIG_SWR_INTR_MODE: + case PM4125_DIG_SWR_INTR_MASK_0: + case PM4125_DIG_SWR_INTR_MASK_1: + case PM4125_DIG_SWR_INTR_MASK_2: + case PM4125_DIG_SWR_INTR_CLEAR_0: + case PM4125_DIG_SWR_INTR_CLEAR_1: + case PM4125_DIG_SWR_INTR_CLEAR_2: + case PM4125_DIG_SWR_INTR_LEVEL_0: + case PM4125_DIG_SWR_INTR_LEVEL_1: + case PM4125_DIG_SWR_INTR_LEVEL_2: + case PM4125_DIG_SWR_CDC_CONN_RX0_CTL: + case PM4125_DIG_SWR_CDC_CONN_RX1_CTL: + case PM4125_DIG_SWR_LOOP_BACK_MODE: + case PM4125_DIG_SWR_DRIVE_STRENGTH_0: + case PM4125_DIG_SWR_DIG_DEBUG_CTL: + case PM4125_DIG_SWR_DIG_DEBUG_EN: + case PM4125_DIG_SWR_DEM_BYPASS_DATA0: + case PM4125_DIG_SWR_DEM_BYPASS_DATA1: + case PM4125_DIG_SWR_DEM_BYPASS_DATA2: + case PM4125_DIG_SWR_DEM_BYPASS_DATA3: + return true; + } + + return false; +} + +static bool pm4125_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PM4125_ANA_MBHC_RESULT_1: + case PM4125_ANA_MBHC_RESULT_2: + case PM4125_ANA_MBHC_RESULT_3: + case PM4125_ANA_MBHC_FSM_STATUS: + case PM4125_ANA_MBHC_ADC_RESULT: + case PM4125_ANA_MBHC_ZDET_CALIB_RESULT: + case PM4125_ANA_HPHPA_PA_STATUS: + case PM4125_DIG_SWR_CHIP_ID0: + case PM4125_DIG_SWR_CHIP_ID1: + case PM4125_DIG_SWR_CHIP_ID2: + case PM4125_DIG_SWR_CHIP_ID3: + case PM4125_DIG_SWR_INTR_STATUS_0: + case PM4125_DIG_SWR_INTR_STATUS_1: + case PM4125_DIG_SWR_INTR_STATUS_2: + return true; + } + return pm4125_rdwr_register(dev, reg); +} + +static bool pm4125_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PM4125_ANA_MBHC_RESULT_1: + case PM4125_ANA_MBHC_RESULT_2: + case PM4125_ANA_MBHC_RESULT_3: + case PM4125_ANA_MBHC_FSM_STATUS: + case PM4125_ANA_MBHC_ADC_RESULT: + case PM4125_ANA_MBHC_ZDET_CALIB_RESULT: + case PM4125_ANA_HPHPA_PA_STATUS: + case PM4125_DIG_SWR_CHIP_ID0: + case PM4125_DIG_SWR_CHIP_ID1: + case PM4125_DIG_SWR_CHIP_ID2: + case PM4125_DIG_SWR_CHIP_ID3: + case PM4125_DIG_SWR_INTR_STATUS_0: + case PM4125_DIG_SWR_INTR_STATUS_1: + case PM4125_DIG_SWR_INTR_STATUS_2: + return true; + } + + return false; +} + +static const struct regmap_config pm4125_regmap_config = { + .name = "pm4125_csr", + .reg_bits = 32, + .val_bits = 8, + .cache_type = REGCACHE_MAPLE, + .reg_defaults = pm4125_defaults, + .num_reg_defaults = ARRAY_SIZE(pm4125_defaults), + .max_register = PM4125_MAX_REGISTER, + .readable_reg = pm4125_readable_register, + .writeable_reg = pm4125_rdwr_register, + .volatile_reg = pm4125_volatile_register, +}; + +static const struct sdw_slave_ops pm4125_slave_ops = { + .update_status = pm4125_update_status, + .interrupt_callback = pm4125_interrupt_callback, +}; + +static int pm4125_sdw_component_bind(struct device *dev, struct device *master, void *data) +{ + pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + return 0; +} + +static void pm4125_sdw_component_unbind(struct device *dev, struct device *master, void *data) +{ + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_dont_use_autosuspend(dev); +} + +static const struct component_ops pm4125_sdw_component_ops = { + .bind = pm4125_sdw_component_bind, + .unbind = pm4125_sdw_component_unbind, +}; + +static int pm4125_probe(struct sdw_slave *pdev, const struct sdw_device_id *id) +{ + struct device *dev = &pdev->dev; + struct pm4125_sdw_priv *priv; + u8 master_ch_mask[PM4125_MAX_SWR_CH_IDS]; + int master_ch_mask_size = 0; + int ret, i; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* Port map index starts at 0, however the data port for this codec starts at index 1 */ + if (of_property_present(dev->of_node, "qcom,tx-port-mapping")) { + priv->is_tx = true; + ret = of_property_read_u32_array(dev->of_node, "qcom,tx-port-mapping", + &pdev->m_port_map[1], PM4125_MAX_TX_SWR_PORTS); + } else { + ret = of_property_read_u32_array(dev->of_node, "qcom,rx-port-mapping", + &pdev->m_port_map[1], PM4125_MAX_SWR_PORTS); + } + + if (ret < 0) + dev_info(dev, "Error getting static port mapping for %s (%d)\n", + priv->is_tx ? "TX" : "RX", ret); + + priv->sdev = pdev; + dev_set_drvdata(dev, priv); + + pdev->prop.scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | + SDW_SCP_INT1_BUS_CLASH | + SDW_SCP_INT1_PARITY; + pdev->prop.lane_control_support = true; + pdev->prop.simple_clk_stop_capable = true; + + memset(master_ch_mask, 0, PM4125_MAX_SWR_CH_IDS); + + if (priv->is_tx) { + master_ch_mask_size = of_property_count_u8_elems(dev->of_node, + "qcom,tx-channel-mapping"); + + if (master_ch_mask_size) + ret = of_property_read_u8_array(dev->of_node, "qcom,tx-channel-mapping", + master_ch_mask, master_ch_mask_size); + } else { + master_ch_mask_size = of_property_count_u8_elems(dev->of_node, + "qcom,rx-channel-mapping"); + + if (master_ch_mask_size) + ret = of_property_read_u8_array(dev->of_node, "qcom,rx-channel-mapping", + master_ch_mask, master_ch_mask_size); + } + + if (ret < 0) + dev_info(dev, "Static channel mapping not specified using device channel maps\n"); + + if (priv->is_tx) { + pdev->prop.source_ports = GENMASK(PM4125_MAX_TX_SWR_PORTS, 0); + pdev->prop.src_dpn_prop = pm4125_dpn_prop; + priv->ch_info = &pm4125_sdw_tx_ch_info[0]; + + for (i = 0; i < master_ch_mask_size; i++) + priv->ch_info[i].master_ch_mask = PM4125_SWRM_CH_MASK(master_ch_mask[i]); + + pdev->prop.wake_capable = true; + + priv->regmap = devm_regmap_init_sdw(pdev, &pm4125_regmap_config); + if (IS_ERR(priv->regmap)) + return dev_err_probe(dev, PTR_ERR(priv->regmap), "regmap init failed\n"); + + /* Start in cache-only until device is enumerated */ + regcache_cache_only(priv->regmap, true); + } else { + pdev->prop.sink_ports = GENMASK(PM4125_MAX_SWR_PORTS - 1, 0); + pdev->prop.sink_dpn_prop = pm4125_dpn_prop; + priv->ch_info = &pm4125_sdw_rx_ch_info[0]; + + for (i = 0; i < master_ch_mask_size; i++) + priv->ch_info[i].master_ch_mask = PM4125_SWRM_CH_MASK(master_ch_mask[i]); + } + + ret = component_add(dev, &pm4125_sdw_component_ops); + if (ret) + return ret; + + /* Set suspended until aggregate device is bind */ + pm_runtime_set_suspended(dev); + + return 0; +} + +static int pm4125_remove(struct sdw_slave *pdev) +{ + struct device *dev = &pdev->dev; + + component_del(dev, &pm4125_sdw_component_ops); + + return 0; +} + +static const struct sdw_device_id pm4125_slave_id[] = { + SDW_SLAVE_ENTRY(0x0217, 0x10c, 0), /* Soundwire pm4125 RX/TX Device ID */ + { } +}; +MODULE_DEVICE_TABLE(sdw, pm4125_slave_id); + +static int __maybe_unused pm4125_sdw_runtime_suspend(struct device *dev) +{ + struct pm4125_sdw_priv *priv = dev_get_drvdata(dev); + + if (priv->regmap) { + regcache_cache_only(priv->regmap, true); + regcache_mark_dirty(priv->regmap); + } + + return 0; +} + +static int __maybe_unused pm4125_sdw_runtime_resume(struct device *dev) +{ + struct pm4125_sdw_priv *priv = dev_get_drvdata(dev); + + if (priv->regmap) { + regcache_cache_only(priv->regmap, false); + regcache_sync(priv->regmap); + } + + return 0; +} + +static const struct dev_pm_ops pm4125_sdw_pm_ops = { + SET_RUNTIME_PM_OPS(pm4125_sdw_runtime_suspend, pm4125_sdw_runtime_resume, NULL) +}; + +static struct sdw_driver pm4125_codec_driver = { + .probe = pm4125_probe, + .remove = pm4125_remove, + .ops = &pm4125_slave_ops, + .id_table = pm4125_slave_id, + .driver = { + .name = "pm4125-codec", + .pm = &pm4125_sdw_pm_ops, + } +}; +module_sdw_driver(pm4125_codec_driver); + +MODULE_DESCRIPTION("PM4125 SDW codec driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/pm4125.c b/sound/soc/codecs/pm4125.c new file mode 100644 index 000000000000..706fc668ffe2 --- /dev/null +++ b/sound/soc/codecs/pm4125.c @@ -0,0 +1,1780 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved. +// Copyright (c) 2025, Linaro Ltd + +#include <linux/component.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h> +#include <sound/jack.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> +#include <sound/tlv.h> + +#include "pm4125.h" +#include "wcd-mbhc-v2.h" + +#define WCD_MBHC_HS_V_MAX 1600 +#define PM4125_MBHC_MAX_BUTTONS 8 + +#define PM4125_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\ + SNDRV_PCM_RATE_384000) + +/* Fractional Rates */ +#define PM4125_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800) + +#define PM4125_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + +/* Registers in SPMI addr space */ +#define PM4125_CODEC_RESET_REG 0xF3DB +#define PM4125_CODEC_OFF 0x1 +#define PM4125_CODEC_ON 0x0 +#define PM4125_CODEC_FOUNDRY_ID_REG 0x7 + +enum { + HPH_COMP_DELAY, + HPH_PA_DELAY, + AMIC2_BCS_ENABLE, +}; + +enum { + AIF1_PB = 0, + AIF1_CAP, + NUM_CODEC_DAIS, +}; + +struct pm4125_priv { + struct sdw_slave *tx_sdw_dev; + struct pm4125_sdw_priv *sdw_priv[NUM_CODEC_DAIS]; + struct device *txdev; + struct device *rxdev; + struct device_node *rxnode; + struct device_node *txnode; + struct regmap *regmap; + struct regmap *spmi_regmap; + /* mbhc module */ + struct wcd_mbhc *wcd_mbhc; + struct wcd_mbhc_config mbhc_cfg; + struct wcd_mbhc_intr intr_ids; + struct irq_domain *virq; + const struct regmap_irq_chip *pm4125_regmap_irq_chip; + struct regmap_irq_chip_data *irq_chip; + struct snd_soc_jack *jack; + unsigned long status_mask; + s32 micb_ref[PM4125_MAX_MICBIAS]; + s32 pullup_ref[PM4125_MAX_MICBIAS]; + u32 micb1_mv; + u32 micb2_mv; + u32 micb3_mv; + + int hphr_pdm_wd_int; + int hphl_pdm_wd_int; + bool comp1_enable; + bool comp2_enable; + + atomic_t gloal_mbias_cnt; +}; + +static const char * const pm4125_power_supplies[] = { + "vdd-io", "vdd-cp", "vdd-mic-bias", "vdd-pa-vpos", +}; + +static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1); +static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1); + +static const struct wcd_mbhc_field pm4125_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = { + WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, PM4125_ANA_MBHC_MECH, 0x80), + WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, PM4125_ANA_MBHC_MECH, 0x40), + WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, PM4125_ANA_MBHC_MECH, 0x20), + WCD_MBHC_FIELD(WCD_MBHC_MIC_CLAMP_CTL, PM4125_ANA_MBHC_PLUG_DETECT_CTL, 0x30), + WCD_MBHC_FIELD(WCD_MBHC_ELECT_DETECTION_TYPE, PM4125_ANA_MBHC_ELECT, 0x08), + WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, PM4125_ANA_MBHC_PLUG_DETECT_CTL, 0x1F), + WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, PM4125_ANA_MBHC_MECH, 0x04), + WCD_MBHC_FIELD(WCD_MBHC_HPHL_PLUG_TYPE, PM4125_ANA_MBHC_MECH, 0x10), + WCD_MBHC_FIELD(WCD_MBHC_GND_PLUG_TYPE, PM4125_ANA_MBHC_MECH, 0x08), + WCD_MBHC_FIELD(WCD_MBHC_SW_HPH_LP_100K_TO_GND, PM4125_ANA_MBHC_MECH, 0x01), + WCD_MBHC_FIELD(WCD_MBHC_ELECT_SCHMT_ISRC, PM4125_ANA_MBHC_ELECT, 0x06), + WCD_MBHC_FIELD(WCD_MBHC_FSM_EN, PM4125_ANA_MBHC_ELECT, 0x80), + WCD_MBHC_FIELD(WCD_MBHC_INSREM_DBNC, PM4125_ANA_MBHC_PLUG_DETECT_CTL, 0x0F), + WCD_MBHC_FIELD(WCD_MBHC_BTN_DBNC, PM4125_ANA_MBHC_CTL_1, 0x03), + WCD_MBHC_FIELD(WCD_MBHC_HS_VREF, PM4125_ANA_MBHC_CTL_2, 0x03), + WCD_MBHC_FIELD(WCD_MBHC_HS_COMP_RESULT, PM4125_ANA_MBHC_RESULT_3, 0x08), + WCD_MBHC_FIELD(WCD_MBHC_IN2P_CLAMP_STATE, PM4125_ANA_MBHC_RESULT_3, 0x10), + WCD_MBHC_FIELD(WCD_MBHC_MIC_SCHMT_RESULT, PM4125_ANA_MBHC_RESULT_3, 0x20), + WCD_MBHC_FIELD(WCD_MBHC_HPHL_SCHMT_RESULT, PM4125_ANA_MBHC_RESULT_3, 0x80), + WCD_MBHC_FIELD(WCD_MBHC_HPHR_SCHMT_RESULT, PM4125_ANA_MBHC_RESULT_3, 0x40), + WCD_MBHC_FIELD(WCD_MBHC_BTN_RESULT, PM4125_ANA_MBHC_RESULT_3, 0x07), + WCD_MBHC_FIELD(WCD_MBHC_BTN_ISRC_CTL, PM4125_ANA_MBHC_ELECT, 0x70), + WCD_MBHC_FIELD(WCD_MBHC_ELECT_RESULT, PM4125_ANA_MBHC_RESULT_3, 0xFF), + WCD_MBHC_FIELD(WCD_MBHC_MICB_CTRL, PM4125_ANA_MICBIAS_MICB_1_2_EN, 0xC0), + WCD_MBHC_FIELD(WCD_MBHC_HPHR_PA_EN, PM4125_ANA_HPHPA_CNP_CTL_2, 0x40), + WCD_MBHC_FIELD(WCD_MBHC_HPHL_PA_EN, PM4125_ANA_HPHPA_CNP_CTL_2, 0x80), + WCD_MBHC_FIELD(WCD_MBHC_HPH_PA_EN, PM4125_ANA_HPHPA_CNP_CTL_2, 0xC0), + WCD_MBHC_FIELD(WCD_MBHC_SWCH_LEVEL_REMOVE, PM4125_ANA_MBHC_RESULT_3, 0x10), + WCD_MBHC_FIELD(WCD_MBHC_FSM_STATUS, PM4125_ANA_MBHC_FSM_STATUS, 0x01), + WCD_MBHC_FIELD(WCD_MBHC_MUX_CTL, PM4125_ANA_MBHC_CTL_2, 0x70), + WCD_MBHC_FIELD(WCD_MBHC_MOISTURE_STATUS, PM4125_ANA_MBHC_FSM_STATUS, 0x20), + WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_DET_EN, PM4125_ANA_HPHPA_CNP_CTL_2, 0x01), + WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_DET_EN, PM4125_ANA_HPHPA_CNP_CTL_2, 0x01), + WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_STATUS, PM4125_DIG_SWR_INTR_STATUS_0, 0x80), + WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_STATUS, PM4125_DIG_SWR_INTR_STATUS_0, 0x20), + WCD_MBHC_FIELD(WCD_MBHC_ADC_EN, PM4125_ANA_MBHC_CTL_1, 0x08), + WCD_MBHC_FIELD(WCD_MBHC_ADC_COMPLETE, PM4125_ANA_MBHC_FSM_STATUS, 0x40), + WCD_MBHC_FIELD(WCD_MBHC_ADC_TIMEOUT, PM4125_ANA_MBHC_FSM_STATUS, 0x80), + WCD_MBHC_FIELD(WCD_MBHC_ADC_RESULT, PM4125_ANA_MBHC_ADC_RESULT, 0xFF), + WCD_MBHC_FIELD(WCD_MBHC_MICB2_VOUT, PM4125_ANA_MICBIAS_LDO_1_SETTING, 0x3F), + WCD_MBHC_FIELD(WCD_MBHC_ADC_MODE, PM4125_ANA_MBHC_CTL_1, 0x10), + WCD_MBHC_FIELD(WCD_MBHC_DETECTION_DONE, PM4125_ANA_MBHC_CTL_1, 0x04), + WCD_MBHC_FIELD(WCD_MBHC_ELECT_ISRC_EN, PM4125_ANA_MBHC_ZDET, 0x02), +}; + +static const struct regmap_irq pm4125_irqs[PM4125_NUM_IRQS] = { + REGMAP_IRQ_REG(PM4125_IRQ_MBHC_BUTTON_PRESS_DET, 0, BIT(0)), + REGMAP_IRQ_REG(PM4125_IRQ_MBHC_BUTTON_RELEASE_DET, 0, BIT(1)), + REGMAP_IRQ_REG(PM4125_IRQ_MBHC_ELECT_INS_REM_DET, 0, BIT(2)), + REGMAP_IRQ_REG(PM4125_IRQ_MBHC_ELECT_INS_REM_LEG_DET, 0, BIT(3)), + REGMAP_IRQ_REG(PM4125_IRQ_MBHC_SW_DET, 0, BIT(4)), + REGMAP_IRQ_REG(PM4125_IRQ_HPHR_OCP_INT, 0, BIT(5)), + REGMAP_IRQ_REG(PM4125_IRQ_HPHR_CNP_INT, 0, BIT(6)), + REGMAP_IRQ_REG(PM4125_IRQ_HPHL_OCP_INT, 0, BIT(7)), + REGMAP_IRQ_REG(PM4125_IRQ_HPHL_CNP_INT, 1, BIT(0)), + REGMAP_IRQ_REG(PM4125_IRQ_EAR_CNP_INT, 1, BIT(1)), + REGMAP_IRQ_REG(PM4125_IRQ_EAR_SCD_INT, 1, BIT(2)), + REGMAP_IRQ_REG(PM4125_IRQ_AUX_CNP_INT, 1, BIT(3)), + REGMAP_IRQ_REG(PM4125_IRQ_AUX_SCD_INT, 1, BIT(4)), + REGMAP_IRQ_REG(PM4125_IRQ_HPHL_PDM_WD_INT, 1, BIT(5)), + REGMAP_IRQ_REG(PM4125_IRQ_HPHR_PDM_WD_INT, 1, BIT(6)), + REGMAP_IRQ_REG(PM4125_IRQ_AUX_PDM_WD_INT, 1, BIT(7)), + REGMAP_IRQ_REG(PM4125_IRQ_LDORT_SCD_INT, 2, BIT(0)), + REGMAP_IRQ_REG(PM4125_IRQ_MBHC_MOISTURE_INT, 2, BIT(1)), + REGMAP_IRQ_REG(PM4125_IRQ_HPHL_SURGE_DET_INT, 2, BIT(2)), + REGMAP_IRQ_REG(PM4125_IRQ_HPHR_SURGE_DET_INT, 2, BIT(3)), +}; + +static int pm4125_handle_post_irq(void *data) +{ + struct pm4125_priv *pm4125 = (struct pm4125_priv *)data; + + regmap_write(pm4125->regmap, PM4125_DIG_SWR_INTR_CLEAR_0, 0); + regmap_write(pm4125->regmap, PM4125_DIG_SWR_INTR_CLEAR_1, 0); + regmap_write(pm4125->regmap, PM4125_DIG_SWR_INTR_CLEAR_2, 0); + + return IRQ_HANDLED; +} + +static const u32 pm4125_config_regs[] = { + PM4125_DIG_SWR_INTR_LEVEL_0, +}; + +static struct regmap_irq_chip pm4125_regmap_irq_chip = { + .name = "pm4125", + .irqs = pm4125_irqs, + .num_irqs = ARRAY_SIZE(pm4125_irqs), + .num_regs = 3, + .status_base = PM4125_DIG_SWR_INTR_STATUS_0, + .mask_base = PM4125_DIG_SWR_INTR_MASK_0, + .ack_base = PM4125_DIG_SWR_INTR_CLEAR_0, + .use_ack = 1, + .clear_ack = 1, + .config_base = pm4125_config_regs, + .num_config_bases = ARRAY_SIZE(pm4125_config_regs), + .num_config_regs = 1, + .runtime_pm = true, + .handle_post_irq = pm4125_handle_post_irq, +}; + +static void pm4125_reset(struct pm4125_priv *pm4125) +{ + regmap_write(pm4125->spmi_regmap, PM4125_CODEC_RESET_REG, PM4125_CODEC_OFF); + usleep_range(20, 30); + regmap_write(pm4125->spmi_regmap, PM4125_CODEC_RESET_REG, PM4125_CODEC_ON); + usleep_range(5000, 5010); +} + +static void pm4125_io_init(struct regmap *regmap) +{ + /* Disable HPH OCP */ + regmap_update_bits(regmap, PM4125_ANA_HPHPA_CNP_CTL_2, + PM4125_ANA_HPHPA_CNP_OCP_EN_L_MASK | PM4125_ANA_HPHPA_CNP_OCP_EN_R_MASK, + PM4125_ANA_HPHPA_CNP_OCP_DISABLE); + + /* Enable surge protection */ + regmap_update_bits(regmap, PM4125_ANA_SURGE_EN, PM4125_ANA_SURGE_PROTECTION_HPHL_MASK, + FIELD_PREP(PM4125_ANA_SURGE_PROTECTION_HPHL_MASK, + PM4125_ANA_SURGE_PROTECTION_ENABLE)); + regmap_update_bits(regmap, PM4125_ANA_SURGE_EN, PM4125_ANA_SURGE_PROTECTION_HPHR_MASK, + FIELD_PREP(PM4125_ANA_SURGE_PROTECTION_HPHR_MASK, + PM4125_ANA_SURGE_PROTECTION_ENABLE)); + + /* Disable mic bias 2 pull down */ + regmap_update_bits(regmap, PM4125_ANA_MICBIAS_MICB_1_2_EN, + PM4125_ANA_MICBIAS_MICB2_PULL_DN_MASK, + FIELD_PREP(PM4125_ANA_MICBIAS_MICB2_PULL_DN_MASK, + PM4125_ANA_MICBIAS_MICB_PULL_DISABLE)); +} + +static int pm4125_global_mbias_disable(struct snd_soc_component *component) +{ + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + + if (atomic_dec_and_test(&pm4125->gloal_mbias_cnt)) { + + snd_soc_component_write_field(component, PM4125_ANA_MBIAS_EN, + PM4125_ANA_MBIAS_EN_V2I_MASK, + PM4125_ANA_MBIAS_EN_DISABLE); + snd_soc_component_write_field(component, PM4125_ANA_MBIAS_EN, + PM4125_ANA_MBIAS_EN_GLOBAL_MASK, + PM4125_ANA_MBIAS_EN_DISABLE); + } + + return 0; +} + +static int pm4125_global_mbias_enable(struct snd_soc_component *component) +{ + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + + if (atomic_inc_return(&pm4125->gloal_mbias_cnt) == 1) { + snd_soc_component_write_field(component, PM4125_ANA_MBIAS_EN, + PM4125_ANA_MBIAS_EN_GLOBAL_MASK, + PM4125_ANA_MBIAS_EN_ENABLE); + snd_soc_component_write_field(component, PM4125_ANA_MBIAS_EN, + PM4125_ANA_MBIAS_EN_V2I_MASK, + PM4125_ANA_MBIAS_EN_ENABLE); + usleep_range(1000, 1100); + } + + return 0; +} + +static int pm4125_rx_clk_enable(struct snd_soc_component *component) +{ + pm4125_global_mbias_enable(component); + + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL, + PM4125_DIG_SWR_ANA_RX_CLK_EN_MASK, + PM4125_DIG_SWR_RX_CLK_ENABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL, + PM4125_DIG_SWR_ANA_RX_DIV2_CLK_EN_MASK, + PM4125_DIG_SWR_RX_CLK_ENABLE); + usleep_range(5000, 5100); + + snd_soc_component_write_field(component, PM4125_ANA_HPHPA_FSM_CLK, + PM4125_ANA_HPHPA_FSM_DIV_RATIO_MASK, + PM4125_ANA_HPHPA_FSM_DIV_RATIO_68); + snd_soc_component_write_field(component, PM4125_ANA_HPHPA_FSM_CLK, + PM4125_ANA_HPHPA_FSM_CLK_DIV_EN_MASK, + PM4125_ANA_HPHPA_FSM_CLK_DIV_ENABLE); + snd_soc_component_update_bits(component, PM4125_ANA_NCP_VCTRL, 0x07, 0x06); + snd_soc_component_write_field(component, PM4125_ANA_NCP_EN, + PM4125_ANA_NCP_ENABLE_MASK, + PM4125_ANA_NCP_ENABLE); + usleep_range(500, 510); + + return 0; +} + +static int pm4125_rx_clk_disable(struct snd_soc_component *component) +{ + + snd_soc_component_write_field(component, PM4125_ANA_HPHPA_FSM_CLK, + PM4125_ANA_HPHPA_FSM_CLK_DIV_EN_MASK, + PM4125_ANA_HPHPA_FSM_CLK_DIV_DISABLE); + snd_soc_component_write_field(component, PM4125_ANA_HPHPA_FSM_CLK, + PM4125_ANA_HPHPA_FSM_DIV_RATIO_MASK, + 0x00); + snd_soc_component_write_field(component, PM4125_ANA_NCP_EN, + PM4125_ANA_NCP_ENABLE_MASK, + PM4125_ANA_NCP_DISABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL, + PM4125_DIG_SWR_ANA_RX_DIV2_CLK_EN_MASK, + PM4125_DIG_SWR_RX_CLK_DISABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL, + PM4125_DIG_SWR_ANA_RX_CLK_EN_MASK, + PM4125_DIG_SWR_RX_CLK_DISABLE); + + pm4125_global_mbias_disable(component); + + return 0; +} + + +static int pm4125_codec_enable_rxclk(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + pm4125_rx_clk_enable(component); + break; + case SND_SOC_DAPM_POST_PMD: + pm4125_rx_clk_disable(component); + break; + } + + return 0; +} + +static int pm4125_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_write_field(component, PM4125_ANA_HPHPA_CNP_CTL_1, + PM4125_ANA_HPHPA_CNP_CTL_1_EN_MASK, + PM4125_ANA_HPHPA_CNP_CTL_1_EN); + snd_soc_component_write_field(component, PM4125_SWR_HPHPA_HD2, + PM4125_SWR_HPHPA_HD2_LEFT_MASK, + PM4125_SWR_HPHPA_HD2_ENABLE); + break; + case SND_SOC_DAPM_POST_PMU: + if (pm4125->comp1_enable) { + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_COMP_CTL_0, + PM4125_DIG_SWR_COMP_HPHL_EN_MASK, + PM4125_DIG_SWR_COMP_ENABLE); + + if (pm4125->comp2_enable) + snd_soc_component_write_field(component, + PM4125_DIG_SWR_CDC_COMP_CTL_0, + PM4125_DIG_SWR_COMP_HPHR_EN_MASK, + PM4125_DIG_SWR_COMP_ENABLE); + /* + * 5ms sleep is required after COMP is enabled as per + * HW requirement + */ + usleep_range(5000, 5100); + } else { + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_COMP_CTL_0, + PM4125_DIG_SWR_COMP_HPHL_EN_MASK, + PM4125_DIG_SWR_COMP_DISABLE); + } + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX0_CTL, + PM4125_DIG_SWR_DSM_DITHER_EN_MASK, + PM4125_DIG_SWR_DSM_DITHER_DISABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_GAIN_CTL, + PM4125_DIG_SWR_RX0_EN_MASK, + PM4125_DIG_SWR_RX_INPUT_ENABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL, + PM4125_DIG_SWR_RX0_CLK_EN_MASK, + PM4125_DIG_SWR_RX_CLK_ENABLE); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL, + PM4125_DIG_SWR_RX0_CLK_EN_MASK, + PM4125_DIG_SWR_RX_CLK_DISABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_GAIN_CTL, + PM4125_DIG_SWR_RX0_EN_MASK, + PM4125_DIG_SWR_RX_INPUT_DISABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX0_CTL, + PM4125_DIG_SWR_DSM_DITHER_EN_MASK, + PM4125_DIG_SWR_DSM_DITHER_ENABLE); + if (pm4125->comp1_enable) + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_COMP_CTL_0, + PM4125_DIG_SWR_COMP_HPHL_EN_MASK, + PM4125_DIG_SWR_COMP_DISABLE); + break; + } + + return 0; +} + +static int pm4125_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_write_field(component, PM4125_ANA_HPHPA_CNP_CTL_1, + PM4125_ANA_HPHPA_CNP_CTL_1_EN_MASK, + PM4125_ANA_HPHPA_CNP_CTL_1_EN); + snd_soc_component_write_field(component, PM4125_SWR_HPHPA_HD2, + PM4125_SWR_HPHPA_HD2_RIGHT_MASK, + PM4125_SWR_HPHPA_HD2_ENABLE); + break; + case SND_SOC_DAPM_POST_PMU: + if (pm4125->comp2_enable) { + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_COMP_CTL_0, + PM4125_DIG_SWR_COMP_HPHR_EN_MASK, + PM4125_DIG_SWR_COMP_ENABLE); + if (pm4125->comp1_enable) + snd_soc_component_write_field(component, + PM4125_DIG_SWR_CDC_COMP_CTL_0, + PM4125_DIG_SWR_COMP_HPHL_EN_MASK, + PM4125_DIG_SWR_COMP_ENABLE); + /* + * 5ms sleep is required after COMP is enabled + * as per HW requirement + */ + usleep_range(5000, 5100); + } else { + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_COMP_CTL_0, + PM4125_DIG_SWR_COMP_HPHR_EN_MASK, + PM4125_DIG_SWR_COMP_DISABLE); + } + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX1_CTL, + PM4125_DIG_SWR_DSM_DITHER_EN_MASK, + PM4125_DIG_SWR_DSM_DITHER_DISABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_GAIN_CTL, + PM4125_DIG_SWR_RX1_EN_MASK, + PM4125_DIG_SWR_RX_INPUT_ENABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL, + PM4125_DIG_SWR_RX1_CLK_EN_MASK, + PM4125_DIG_SWR_RX_CLK_ENABLE); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL, + PM4125_DIG_SWR_RX1_CLK_EN_MASK, + PM4125_DIG_SWR_RX_CLK_DISABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_GAIN_CTL, + PM4125_DIG_SWR_RX1_EN_MASK, + PM4125_DIG_SWR_RX_INPUT_DISABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX1_CTL, + PM4125_DIG_SWR_DSM_DITHER_EN_MASK, + PM4125_DIG_SWR_DSM_DITHER_ENABLE); + if (pm4125->comp2_enable) + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_COMP_CTL_0, + PM4125_DIG_SWR_COMP_HPHR_EN_MASK, + PM4125_DIG_SWR_COMP_DISABLE); + break; + } + + return 0; +} + +static int pm4125_codec_ear_lo_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX0_CTL, + PM4125_DIG_SWR_DSM_DITHER_EN_MASK, + PM4125_DIG_SWR_DSM_DITHER_DISABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL, + PM4125_DIG_SWR_RX0_CLK_EN_MASK, + PM4125_DIG_SWR_RX_CLK_ENABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_GAIN_CTL, + PM4125_DIG_SWR_RX0_EN_MASK, + PM4125_DIG_SWR_RX_INPUT_ENABLE); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_CLK_CTL, + PM4125_DIG_SWR_RX0_CLK_EN_MASK, + PM4125_DIG_SWR_RX_CLK_DISABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX_GAIN_CTL, + PM4125_DIG_SWR_RX0_EN_MASK, + PM4125_DIG_SWR_RX_INPUT_DISABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_RX0_CTL, + PM4125_DIG_SWR_DSM_DITHER_EN_MASK, + PM4125_DIG_SWR_DSM_DITHER_ENABLE); + break; + } + + return 0; +} + + +static int pm4125_codec_enable_hphl_wdt_irq(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + usleep_range(5000, 5100); + enable_irq(pm4125->hphl_pdm_wd_int); + break; + case SND_SOC_DAPM_PRE_PMD: + disable_irq_nosync(pm4125->hphl_pdm_wd_int); + break; + } + + return 0; +} + +static int pm4125_codec_enable_hphr_wdt_irq(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + usleep_range(5000, 5100); + enable_irq(pm4125->hphr_pdm_wd_int); + break; + case SND_SOC_DAPM_PRE_PMD: + disable_irq_nosync(pm4125->hphr_pdm_wd_int); + break; + } + + return 0; +} + +static int pm4125_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + usleep_range(200, 210); + snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL1, + PM4125_WDT_ENABLE_MASK, + (PM4125_WDT_ENABLE_RX1_M | PM4125_WDT_ENABLE_RX1_L)); + break; + case SND_SOC_DAPM_POST_PMD: + usleep_range(5000, 5100); + snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL1, + PM4125_WDT_ENABLE_MASK, 0x00); + break; + } + + return 0; +} + +static int pm4125_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + usleep_range(200, 210); + snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL0, + PM4125_WDT_ENABLE_MASK, + (PM4125_WDT_ENABLE_RX0_M | PM4125_WDT_ENABLE_RX0_L)); + break; + case SND_SOC_DAPM_POST_PMD: + usleep_range(5000, 5100); + snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL0, + PM4125_WDT_ENABLE_MASK, 0x00); + break; + } + + return 0; +} + +static int pm4125_codec_enable_lo_pa(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL_5, 0x04, 0x00); + usleep_range(1000, 1010); + snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL_4, 0x0F, 0x0F); + usleep_range(1000, 1010); + snd_soc_component_write_field(component, PM4125_ANA_COMBOPA_CTL, + PM4125_ANA_COMBO_PA_SELECT_MASK, + PM4125_ANA_COMBO_PA_SELECT_LO); + snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL0, + PM4125_WDT_ENABLE_MASK, + (PM4125_WDT_ENABLE_RX0_M | PM4125_WDT_ENABLE_RX0_L)); + break; + case SND_SOC_DAPM_POST_PMU: + usleep_range(5000, 5010); + snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL_4, 0x0F, 0x04); + break; + case SND_SOC_DAPM_POST_PMD: + usleep_range(2000, 2010); + snd_soc_component_write_field(component, PM4125_ANA_COMBOPA_CTL, + PM4125_ANA_COMBO_PA_SELECT_MASK, + PM4125_ANA_COMBO_PA_SELECT_EAR); + usleep_range(5000, 5100); + snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL0, + PM4125_WDT_ENABLE_MASK, 0x00); + break; + } + + return 0; +} + +static int pm4125_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL_5, 0x04, 0x00); + usleep_range(1000, 1010); + snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL_4, 0x0F, 0x0F); + usleep_range(1000, 1010); + snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL, + PM4125_ANA_COMBO_PA_SELECT_MASK, + PM4125_ANA_COMBO_PA_SELECT_EAR); + snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL0, + PM4125_WDT_ENABLE_MASK, + (PM4125_WDT_ENABLE_RX0_M | PM4125_WDT_ENABLE_RX0_L)); + break; + case SND_SOC_DAPM_POST_PMU: + usleep_range(5000, 5010); + snd_soc_component_update_bits(component, PM4125_ANA_COMBOPA_CTL_4, 0x0F, 0x04); + break; + case SND_SOC_DAPM_POST_PMD: + usleep_range(5000, 5010); + snd_soc_component_write_field(component, PM4125_DIG_SWR_PDM_WD_CTL0, + PM4125_WDT_ENABLE_MASK, 0x00); + break; + } + + return 0; +} + +static int pm4125_get_micb_vout_ctl_val(struct device *dev, u32 micb_mv) +{ + if (micb_mv < 1600 || micb_mv > 2850) { + dev_err(dev, "%s: unsupported micbias voltage (%u mV)\n", __func__, micb_mv); + return -EINVAL; + } + + return (micb_mv - 1600) / 50; +} + +static int pm4125_codec_enable_adc(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Enable BCS for Headset mic */ + if (w->shift == 1 && + !(snd_soc_component_read(component, PM4125_ANA_TX_AMIC2) & 0x10)) { + set_bit(AMIC2_BCS_ENABLE, &pm4125->status_mask); + } + pm4125_global_mbias_enable(component); + if (w->shift) + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1, + PM4125_DIG_SWR_TX_ANA_TXD1_MODE_MASK, + PM4125_DIG_SWR_TXD_MODE_NORMAL); + else + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1, + PM4125_DIG_SWR_TX_ANA_TXD0_MODE_MASK, + PM4125_DIG_SWR_TXD_MODE_NORMAL); + break; + case SND_SOC_DAPM_POST_PMD: + if (w->shift == 1 && test_bit(AMIC2_BCS_ENABLE, &pm4125->status_mask)) + clear_bit(AMIC2_BCS_ENABLE, &pm4125->status_mask); + + if (w->shift) + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1, + PM4125_DIG_SWR_TX_ANA_TXD1_MODE_MASK, + 0x00); + else + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1, + PM4125_DIG_SWR_TX_ANA_TXD0_MODE_MASK, + 0x00); + pm4125_global_mbias_disable(component); + break; + }; + + return 0; +} + +static int pm4125_codec_enable_dmic(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + u16 dmic_clk_reg = w->reg; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_AMIC_CTL, + PM4125_DIG_SWR_AMIC_SELECT_MASK, + PM4125_DIG_SWR_AMIC_SELECT_DMIC1); + snd_soc_component_update_bits(component, dmic_clk_reg, + PM4125_DIG_SWR_DMIC1_CLK_EN_MASK, + PM4125_DIG_SWR_DMIC1_CLK_ENABLE); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_update_bits(component, dmic_clk_reg, + PM4125_DIG_SWR_DMIC1_CLK_EN_MASK, + PM4125_DIG_SWR_DMIC1_CLK_DISABLE); + snd_soc_component_write_field(component, PM4125_DIG_SWR_CDC_AMIC_CTL, + PM4125_DIG_SWR_AMIC_SELECT_MASK, + PM4125_DIG_SWR_AMIC_SELECT_AMIC3); + break; + } + + return 0; +} + +static int pm4125_micbias_control(struct snd_soc_component *component, int micb_num, int req, + bool is_dapm) +{ + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + int micb_index = micb_num - 1; + u16 micb_reg; + u8 pullup_mask = 0, enable_mask = 0; + + if ((micb_index < 0) || (micb_index > PM4125_MAX_MICBIAS - 1)) { + dev_err(component->dev, "%s: Invalid micbias index, micb_ind:%d\n", + __func__, micb_index); + return -EINVAL; + } + switch (micb_num) { + case MIC_BIAS_1: + micb_reg = PM4125_ANA_MICBIAS_MICB_1_2_EN; + pullup_mask = PM4125_ANA_MICBIAS_MICB1_PULL_UP_MASK; + enable_mask = 0x40; + break; + case MIC_BIAS_2: + micb_reg = PM4125_ANA_MICBIAS_MICB_1_2_EN; + pullup_mask = PM4125_ANA_MICBIAS_MICB2_PULL_UP_MASK; + enable_mask = 0x04; + break; + case MIC_BIAS_3: + micb_reg = PM4125_ANA_MICBIAS_MICB_3_EN; + pullup_mask = 0x02; + break; + default: + dev_err(component->dev, "%s: Invalid micbias number: %d\n", + __func__, micb_num); + return -EINVAL; + }; + + switch (req) { + case MICB_PULLUP_ENABLE: + pm4125->pullup_ref[micb_index]++; + if ((pm4125->pullup_ref[micb_index] == 1) && + (pm4125->micb_ref[micb_index] == 0)) + snd_soc_component_update_bits(component, micb_reg, + pullup_mask, pullup_mask); + break; + case MICB_PULLUP_DISABLE: + if (pm4125->pullup_ref[micb_index] > 0) + pm4125->pullup_ref[micb_index]--; + if ((pm4125->pullup_ref[micb_index] == 0) && + (pm4125->micb_ref[micb_index] == 0)) + snd_soc_component_update_bits(component, micb_reg, + pullup_mask, 0x00); + break; + case MICB_ENABLE: + pm4125->micb_ref[micb_index]++; + if (pm4125->micb_ref[micb_index] == 1) { + pm4125_global_mbias_enable(component); + snd_soc_component_update_bits(component, micb_reg, + enable_mask, enable_mask); + } + break; + case MICB_DISABLE: + if (pm4125->micb_ref[micb_index] > 0) + pm4125->micb_ref[micb_index]--; + if ((pm4125->micb_ref[micb_index] == 0) && + (pm4125->pullup_ref[micb_index] > 0)) { + snd_soc_component_update_bits(component, micb_reg, + pullup_mask, pullup_mask); + snd_soc_component_update_bits(component, micb_reg, + enable_mask, 0x00); + pm4125_global_mbias_disable(component); + } else if ((pm4125->micb_ref[micb_index] == 0) && + (pm4125->pullup_ref[micb_index] == 0)) { + snd_soc_component_update_bits(component, micb_reg, + enable_mask, 0x00); + pm4125_global_mbias_disable(component); + } + break; + }; + + return 0; +} + +static int pm4125_codec_enable_micbias(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + int micb_num = w->shift; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (micb_num == MIC_BIAS_3) + pm4125_micbias_control(component, micb_num, MICB_PULLUP_ENABLE, true); + else + pm4125_micbias_control(component, micb_num, MICB_ENABLE, true); + break; + case SND_SOC_DAPM_POST_PMU: + usleep_range(1000, 1100); + break; + case SND_SOC_DAPM_POST_PMD: + if (micb_num == MIC_BIAS_3) + pm4125_micbias_control(component, micb_num, MICB_PULLUP_DISABLE, true); + else + pm4125_micbias_control(component, micb_num, MICB_DISABLE, true); + break; + } + + return 0; +} + +static int pm4125_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + int micb_num = w->shift; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + pm4125_micbias_control(component, micb_num, MICB_PULLUP_ENABLE, true); + break; + case SND_SOC_DAPM_POST_PMU: + usleep_range(1000, 1100); + break; + case SND_SOC_DAPM_POST_PMD: + pm4125_micbias_control(component, micb_num, MICB_PULLUP_DISABLE, true); + break; + } + + return 0; +} + +static int pm4125_connect_port(struct pm4125_sdw_priv *sdw_priv, u8 port_idx, u8 ch_id, bool enable) +{ + struct sdw_port_config *port_config = &sdw_priv->port_config[port_idx - 1]; + const struct pm4125_sdw_ch_info *ch_info = &sdw_priv->ch_info[ch_id]; + struct sdw_slave *sdev = sdw_priv->sdev; + u8 port_num = ch_info->port_num; + u8 ch_mask = ch_info->ch_mask; + u8 mstr_port_num, mstr_ch_mask; + + port_config->num = port_num; + + mstr_port_num = sdev->m_port_map[port_num]; + mstr_ch_mask = ch_info->master_ch_mask; + + if (enable) { + port_config->ch_mask |= ch_mask; + sdw_priv->master_channel_map[mstr_port_num] |= mstr_ch_mask; + } else { + port_config->ch_mask &= ~ch_mask; + sdw_priv->master_channel_map[mstr_port_num] &= ~mstr_ch_mask; + } + + return 0; +} + +static int pm4125_get_compander(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + struct soc_mixer_control *mc; + bool hphr; + + mc = (struct soc_mixer_control *)(kcontrol->private_value); + hphr = mc->shift; + + ucontrol->value.integer.value[0] = hphr ? pm4125->comp2_enable : pm4125->comp1_enable; + return 0; +} + +static int pm4125_set_compander(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + struct pm4125_sdw_priv *sdw_priv = pm4125->sdw_priv[AIF1_PB]; + int value = ucontrol->value.integer.value[0]; + struct soc_mixer_control *mc; + int portidx; + bool hphr; + + mc = (struct soc_mixer_control *)(kcontrol->private_value); + hphr = mc->shift; + + if (hphr) { + if (value == pm4125->comp2_enable) + return 0; + + pm4125->comp2_enable = value; + } else { + if (value == pm4125->comp1_enable) + return 0; + + pm4125->comp1_enable = value; + } + + portidx = sdw_priv->ch_info[mc->reg].port_num; + + pm4125_connect_port(sdw_priv, portidx, mc->reg, value ? true : false); + + return 1; +} + +static int pm4125_get_swr_port(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(comp); + struct pm4125_sdw_priv *sdw_priv; + int dai_id = mixer->shift; + int ch_idx = mixer->reg; + int portidx; + + sdw_priv = pm4125->sdw_priv[dai_id]; + portidx = sdw_priv->ch_info[ch_idx].port_num; + + ucontrol->value.integer.value[0] = sdw_priv->port_enable[portidx]; + + return 0; +} + +static int pm4125_set_swr_port(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(comp); + struct pm4125_sdw_priv *sdw_priv; + int dai_id = mixer->shift; + int ch_idx = mixer->reg; + int portidx; + bool enable; + + sdw_priv = pm4125->sdw_priv[dai_id]; + + portidx = sdw_priv->ch_info[ch_idx].port_num; + + enable = ucontrol->value.integer.value[0]; + + if (enable == sdw_priv->port_enable[portidx]) { + pm4125_connect_port(sdw_priv, portidx, ch_idx, enable); + return 0; + } + + sdw_priv->port_enable[portidx] = enable; + pm4125_connect_port(sdw_priv, portidx, ch_idx, enable); + + return 1; +} + +static void pm4125_mbhc_bias_control(struct snd_soc_component *component, bool enable) +{ + snd_soc_component_write_field(component, PM4125_ANA_MBHC_ELECT, + PM4125_ANA_MBHC_ELECT_BIAS_EN_MASK, + enable ? PM4125_ANA_MBHC_ELECT_BIAS_ENABLE : + PM4125_ANA_MBHC_ELECT_BIAS_DISABLE); +} + +static void pm4125_mbhc_program_btn_thr(struct snd_soc_component *component, + int *btn_low, int *btn_high, + int num_btn, bool is_micbias) +{ + int i, vth; + + if (num_btn > WCD_MBHC_DEF_BUTTONS) { + dev_err(component->dev, "%s: invalid number of buttons: %d\n", + __func__, num_btn); + return; + } + + for (i = 0; i < num_btn; i++) { + vth = ((btn_high[i] * 2) / 25) & 0x3F; + snd_soc_component_write_field(component, PM4125_ANA_MBHC_BTN0_ZDET_VREF1 + i, + PM4125_ANA_MBHC_BTN0_THRESHOLD_MASK, vth << 2); + } +} + +static const struct wcd_mbhc_cb mbhc_cb = { + .mbhc_bias = pm4125_mbhc_bias_control, + .set_btn_thr = pm4125_mbhc_program_btn_thr, +}; + +static int pm4125_mbhc_init(struct snd_soc_component *component) +{ + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + struct wcd_mbhc_intr *intr_ids = &pm4125->intr_ids; + + intr_ids->mbhc_sw_intr = regmap_irq_get_virq(pm4125->irq_chip, PM4125_IRQ_MBHC_SW_DET); + + intr_ids->mbhc_btn_press_intr = regmap_irq_get_virq(pm4125->irq_chip, + PM4125_IRQ_MBHC_BUTTON_PRESS_DET); + + intr_ids->mbhc_btn_release_intr = regmap_irq_get_virq(pm4125->irq_chip, + PM4125_IRQ_MBHC_BUTTON_RELEASE_DET); + + intr_ids->mbhc_hs_ins_intr = regmap_irq_get_virq(pm4125->irq_chip, + PM4125_IRQ_MBHC_ELECT_INS_REM_LEG_DET); + + intr_ids->mbhc_hs_rem_intr = regmap_irq_get_virq(pm4125->irq_chip, + PM4125_IRQ_MBHC_ELECT_INS_REM_DET); + + intr_ids->hph_left_ocp = regmap_irq_get_virq(pm4125->irq_chip, PM4125_IRQ_HPHL_OCP_INT); + + intr_ids->hph_right_ocp = regmap_irq_get_virq(pm4125->irq_chip, PM4125_IRQ_HPHR_OCP_INT); + + pm4125->wcd_mbhc = wcd_mbhc_init(component, &mbhc_cb, intr_ids, pm4125_mbhc_fields, false); + if (IS_ERR(pm4125->wcd_mbhc)) + return PTR_ERR(pm4125->wcd_mbhc); + + return 0; +} + +static void pm4125_mbhc_deinit(struct snd_soc_component *component) +{ + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + + wcd_mbhc_deinit(pm4125->wcd_mbhc); +} + +static const struct snd_kcontrol_new pm4125_snd_controls[] = { + SOC_SINGLE_EXT("HPHL_COMP Switch", PM4125_COMP_L, 0, 1, 0, + pm4125_get_compander, pm4125_set_compander), + SOC_SINGLE_EXT("HPHR_COMP Switch", PM4125_COMP_R, 1, 1, 0, + pm4125_get_compander, pm4125_set_compander), + + SOC_SINGLE_TLV("HPHL Volume", PM4125_ANA_HPHPA_L_GAIN, 0, 20, 1, + line_gain), + SOC_SINGLE_TLV("HPHR Volume", PM4125_ANA_HPHPA_R_GAIN, 0, 20, 1, + line_gain), + SOC_SINGLE_TLV("ADC1 Volume", PM4125_ANA_TX_AMIC1, 0, 8, 0, + analog_gain), + SOC_SINGLE_TLV("ADC2 Volume", PM4125_ANA_TX_AMIC2, 0, 8, 0, + analog_gain), + + SOC_SINGLE_EXT("HPHL Switch", PM4125_HPH_L, 0, 1, 0, + pm4125_get_swr_port, pm4125_set_swr_port), + SOC_SINGLE_EXT("HPHR Switch", PM4125_HPH_R, 0, 1, 0, + pm4125_get_swr_port, pm4125_set_swr_port), + + SOC_SINGLE_EXT("ADC1 Switch", PM4125_ADC1, 1, 1, 0, + pm4125_get_swr_port, pm4125_set_swr_port), + SOC_SINGLE_EXT("ADC2 Switch", PM4125_ADC2, 1, 1, 0, + pm4125_get_swr_port, pm4125_set_swr_port), +}; + +static const struct snd_kcontrol_new adc1_switch[] = { + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) +}; + +static const struct snd_kcontrol_new adc2_switch[] = { + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) +}; + +static const struct snd_kcontrol_new dmic1_switch[] = { + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) +}; + +static const struct snd_kcontrol_new dmic2_switch[] = { + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) +}; + +static const struct snd_kcontrol_new ear_rdac_switch[] = { + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) +}; + +static const struct snd_kcontrol_new lo_rdac_switch[] = { + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) +}; + +static const struct snd_kcontrol_new hphl_rdac_switch[] = { + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) +}; + +static const struct snd_kcontrol_new hphr_rdac_switch[] = { + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) +}; + +static const char * const adc2_mux_text[] = { + "INP2", "INP3" +}; + +static const struct soc_enum adc2_enum = SOC_ENUM_SINGLE(PM4125_ANA_TX_AMIC2, 4, + ARRAY_SIZE(adc2_mux_text), adc2_mux_text); + +static const struct snd_kcontrol_new tx_adc2_mux = SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum); + +static const struct snd_soc_dapm_widget pm4125_dapm_widgets[] = { + /* Input widgets */ + SND_SOC_DAPM_INPUT("AMIC1"), + SND_SOC_DAPM_INPUT("AMIC2"), + SND_SOC_DAPM_INPUT("AMIC3"), + SND_SOC_DAPM_INPUT("IN1_HPHL"), + SND_SOC_DAPM_INPUT("IN2_HPHR"), + + /* TX widgets */ + SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0, pm4125_codec_enable_adc, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_ADC_E("ADC2", NULL, SND_SOC_NOPM, 1, 0, pm4125_codec_enable_adc, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0, &tx_adc2_mux), + + /* TX mixers */ + SND_SOC_DAPM_MIXER("ADC1_MIXER", SND_SOC_NOPM, 0, 0, adc1_switch, ARRAY_SIZE(adc1_switch)), + SND_SOC_DAPM_MIXER("ADC2_MIXER", SND_SOC_NOPM, 1, 0, adc2_switch, ARRAY_SIZE(adc2_switch)), + + /* MIC_BIAS widgets */ + SND_SOC_DAPM_SUPPLY("MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0, pm4125_codec_enable_micbias, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0, pm4125_codec_enable_micbias, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0, pm4125_codec_enable_micbias, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY("PA_VPOS", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* RX widgets */ + SND_SOC_DAPM_PGA_E("EAR PGA", PM4125_ANA_COMBOPA_CTL, 7, 0, NULL, 0, + pm4125_codec_enable_ear_pa, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("LO PGA", PM4125_ANA_COMBOPA_CTL, 7, 0, NULL, 0, + pm4125_codec_enable_lo_pa, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("HPHL PGA", PM4125_ANA_HPHPA_CNP_CTL_2, 7, 0, NULL, 0, + pm4125_codec_enable_hphl_pa, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("HPHR PGA", PM4125_ANA_HPHPA_CNP_CTL_2, 6, 0, NULL, 0, + pm4125_codec_enable_hphr_pa, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_DAC_E("RDAC1", NULL, SND_SOC_NOPM, 0, 0, pm4125_codec_hphl_dac_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_DAC_E("RDAC2", NULL, SND_SOC_NOPM, 0, 0, pm4125_codec_hphr_dac_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_DAC_E("RDAC3", NULL, SND_SOC_NOPM, 0, 0, pm4125_codec_ear_lo_dac_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + + SND_SOC_DAPM_SUPPLY("HPHL_WDT_IRQ", SND_SOC_NOPM, 0, 0, pm4125_codec_enable_hphl_wdt_irq, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY("HPHR_WDT_IRQ", SND_SOC_NOPM, 0, 0, pm4125_codec_enable_hphr_wdt_irq, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY("RXCLK", SND_SOC_NOPM, 0, 0, pm4125_codec_enable_rxclk, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MIXER_E("RX1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0), + SND_SOC_DAPM_MIXER_E("RX2", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0), + + /* RX mixer widgets */ + SND_SOC_DAPM_MIXER("EAR_RDAC", SND_SOC_NOPM, 0, 0, ear_rdac_switch, + ARRAY_SIZE(ear_rdac_switch)), + SND_SOC_DAPM_MIXER("LO_RDAC", SND_SOC_NOPM, 0, 0, lo_rdac_switch, + ARRAY_SIZE(lo_rdac_switch)), + SND_SOC_DAPM_MIXER("HPHL_RDAC", SND_SOC_NOPM, 0, 0, hphl_rdac_switch, + ARRAY_SIZE(hphl_rdac_switch)), + SND_SOC_DAPM_MIXER("HPHR_RDAC", SND_SOC_NOPM, 0, 0, hphr_rdac_switch, + ARRAY_SIZE(hphr_rdac_switch)), + + /* TX output widgets */ + SND_SOC_DAPM_OUTPUT("ADC1_OUTPUT"), + SND_SOC_DAPM_OUTPUT("ADC2_OUTPUT"), + + /* RX output widgets */ + SND_SOC_DAPM_OUTPUT("EAR"), + SND_SOC_DAPM_OUTPUT("LO"), + SND_SOC_DAPM_OUTPUT("HPHL"), + SND_SOC_DAPM_OUTPUT("HPHR"), + + /* MIC_BIAS pull up widgets */ + SND_SOC_DAPM_SUPPLY("VA MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0, + pm4125_codec_enable_micbias_pullup, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("VA MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0, + pm4125_codec_enable_micbias_pullup, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("VA MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0, + pm4125_codec_enable_micbias_pullup, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + /* TX widgets */ + SND_SOC_DAPM_ADC_E("DMIC1", NULL, PM4125_DIG_SWR_CDC_DMIC1_CTL, 0, 0, + pm4125_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_ADC_E("DMIC2", NULL, PM4125_DIG_SWR_CDC_DMIC1_CTL, 1, 0, + pm4125_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* TX mixer widgets */ + SND_SOC_DAPM_MIXER("DMIC1_MIXER", SND_SOC_NOPM, 0, 0, dmic1_switch, + ARRAY_SIZE(dmic1_switch)), + SND_SOC_DAPM_MIXER("DMIC2_MIXER", SND_SOC_NOPM, 1, 0, dmic2_switch, + ARRAY_SIZE(dmic2_switch)), + + /* Output widgets */ + SND_SOC_DAPM_OUTPUT("DMIC1_OUTPUT"), + SND_SOC_DAPM_OUTPUT("DMIC2_OUTPUT"), +}; + +static const struct snd_soc_dapm_route pm4125_audio_map[] = { + { "ADC1_OUTPUT", NULL, "ADC1_MIXER" }, + { "ADC1_MIXER", "Switch", "ADC1" }, + { "ADC1", NULL, "AMIC1" }, + + { "ADC2_OUTPUT", NULL, "ADC2_MIXER" }, + { "ADC2_MIXER", "Switch", "ADC2" }, + { "ADC2", NULL, "ADC2 MUX" }, + { "ADC2 MUX", "INP3", "AMIC3" }, + { "ADC2 MUX", "INP2", "AMIC2" }, + + { "IN1_HPHL", NULL, "PA_VPOS" }, + { "RX1", NULL, "IN1_HPHL" }, + { "RX1", NULL, "RXCLK" }, + { "RX1", NULL, "HPHL_WDT_IRQ" }, + { "RDAC1", NULL, "RX1" }, + { "HPHL_RDAC", "Switch", "RDAC1" }, + { "HPHL PGA", NULL, "HPHL_RDAC" }, + { "HPHL", NULL, "HPHL PGA" }, + + { "IN2_HPHR", NULL, "PA_VPOS" }, + { "RX2", NULL, "IN2_HPHR" }, + { "RX2", NULL, "RXCLK" }, + { "RX2", NULL, "HPHR_WDT_IRQ" }, + { "RDAC2", NULL, "RX2" }, + { "HPHR_RDAC", "Switch", "RDAC2" }, + { "HPHR PGA", NULL, "HPHR_RDAC" }, + { "HPHR", NULL, "HPHR PGA" }, + + { "RDAC3", NULL, "RX1" }, + { "EAR_RDAC", "Switch", "RDAC3" }, + { "EAR PGA", NULL, "EAR_RDAC" }, + { "EAR", NULL, "EAR PGA" }, + + { "LO_RDAC", "Switch", "RDAC3" }, + { "LO PGA", NULL, "LO_RDAC" }, + { "LO", NULL, "LO PGA" }, + + { "DMIC1_OUTPUT", NULL, "DMIC1_MIXER" }, + { "DMIC1_MIXER", "Switch", "DMIC1" }, + + { "DMIC2_OUTPUT", NULL, "DMIC2_MIXER" }, + { "DMIC2_MIXER", "Switch", "DMIC2" }, +}; + +static int pm4125_set_micbias_data(struct device *dev, struct pm4125_priv *pm4125) +{ + int vout_ctl; + + /* Set micbias voltage */ + vout_ctl = pm4125_get_micb_vout_ctl_val(dev, pm4125->micb1_mv); + if (vout_ctl < 0) + return -EINVAL; + + regmap_update_bits(pm4125->regmap, PM4125_ANA_MICBIAS_LDO_1_SETTING, + PM4125_ANA_MICBIAS_MICB_OUT_VAL_MASK, vout_ctl << 3); + return 0; +} + +static irqreturn_t pm4125_wd_handle_irq(int irq, void *data) +{ + /* + * HPHR/HPHL Watchdog interrupt threaded handler + * Watchdog interrupts are expected to be enabled when switching on the HPHL/R + * in order to make sure the interrupts are acked by the regmap_irq handler + * io allow PDM sync. We could leave those interrupts masked but we would + * not haveany valid way to enable/disable them without violating irq layers. + * + * The HPHR/HPHL Watchdog interrupts are handled by regmap_irq, so requesting + * a threaded handler is the safest way to be able to ack those interrupts + * without colliding with the regmap_irq setup. + */ + return IRQ_HANDLED; +} + +static const struct irq_chip pm4125_codec_irq_chip = { + .name = "pm4125_codec", +}; + +static int pm4125_codec_irq_chip_map(struct irq_domain *irqd, unsigned int virq, + irq_hw_number_t hw) +{ + irq_set_chip_and_handler(virq, &pm4125_codec_irq_chip, handle_simple_irq); + irq_set_nested_thread(virq, 1); + irq_set_noprobe(virq); + + return 0; +} + +static const struct irq_domain_ops pm4125_domain_ops = { + .map = pm4125_codec_irq_chip_map, +}; + +static int pm4125_irq_init(struct pm4125_priv *pm4125, struct device *dev) +{ + pm4125->virq = irq_domain_add_linear(NULL, 1, &pm4125_domain_ops, NULL); + if (!(pm4125->virq)) { + dev_err(dev, "%s: Failed to add IRQ domain\n", __func__); + return -EINVAL; + } + + pm4125_regmap_irq_chip.irq_drv_data = pm4125; + + return devm_regmap_add_irq_chip(dev, pm4125->regmap, irq_create_mapping(pm4125->virq, 0), + IRQF_ONESHOT, 0, &pm4125_regmap_irq_chip, + &pm4125->irq_chip); +} + +static int pm4125_soc_codec_probe(struct snd_soc_component *component) +{ + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + struct sdw_slave *tx_sdw_dev = pm4125->tx_sdw_dev; + struct device *dev = component->dev; + unsigned long time_left; + int i, ret; + + time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete, + msecs_to_jiffies(5000)); + if (!time_left) { + dev_err(dev, "soundwire device init timeout\n"); + return -ETIMEDOUT; + } + + snd_soc_component_init_regmap(component, pm4125->regmap); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + return ret; + + pm4125_io_init(pm4125->regmap); + + /* Set all interrupts as edge triggered */ + for (i = 0; i < pm4125_regmap_irq_chip.num_regs; i++) + regmap_write(pm4125->regmap, (PM4125_DIG_SWR_INTR_LEVEL_0 + i), 0); + + pm_runtime_put(dev); + + pm4125->hphr_pdm_wd_int = regmap_irq_get_virq(pm4125->irq_chip, PM4125_IRQ_HPHR_PDM_WD_INT); + pm4125->hphl_pdm_wd_int = regmap_irq_get_virq(pm4125->irq_chip, PM4125_IRQ_HPHL_PDM_WD_INT); + + /* Request for watchdog interrupts */ + ret = devm_request_threaded_irq(dev, pm4125->hphr_pdm_wd_int, NULL, pm4125_wd_handle_irq, + IRQF_ONESHOT | IRQF_TRIGGER_RISING, + "HPHR PDM WDOG INT", pm4125); + if (ret) + dev_err(dev, "Failed to request HPHR wdt interrupt: %d\n", ret); + + ret = devm_request_threaded_irq(dev, pm4125->hphl_pdm_wd_int, NULL, pm4125_wd_handle_irq, + IRQF_ONESHOT | IRQF_TRIGGER_RISING, + "HPHL PDM WDOG INT", pm4125); + if (ret) + dev_err(dev, "Failed to request HPHL wdt interrupt: %d\n", ret); + + disable_irq_nosync(pm4125->hphr_pdm_wd_int); + disable_irq_nosync(pm4125->hphl_pdm_wd_int); + + ret = pm4125_mbhc_init(component); + if (ret) + dev_err(component->dev, "mbhc initialization failed\n"); + + return ret; +} + +static void pm4125_soc_codec_remove(struct snd_soc_component *component) +{ + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + + pm4125_mbhc_deinit(component); + free_irq(pm4125->hphl_pdm_wd_int, pm4125); + free_irq(pm4125->hphr_pdm_wd_int, pm4125); +} + +static int pm4125_codec_set_jack(struct snd_soc_component *comp, struct snd_soc_jack *jack, + void *data) +{ + struct pm4125_priv *pm4125 = dev_get_drvdata(comp->dev); + int ret = 0; + + if (jack) + ret = wcd_mbhc_start(pm4125->wcd_mbhc, &pm4125->mbhc_cfg, jack); + else + wcd_mbhc_stop(pm4125->wcd_mbhc); + + return ret; +} + +static const struct snd_soc_component_driver soc_codec_dev_pm4125 = { + .name = "pm4125_codec", + .probe = pm4125_soc_codec_probe, + .remove = pm4125_soc_codec_remove, + .controls = pm4125_snd_controls, + .num_controls = ARRAY_SIZE(pm4125_snd_controls), + .dapm_widgets = pm4125_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pm4125_dapm_widgets), + .dapm_routes = pm4125_audio_map, + .num_dapm_routes = ARRAY_SIZE(pm4125_audio_map), + .set_jack = pm4125_codec_set_jack, + .endianness = 1, +}; + +static void pm4125_dt_parse_micbias_info(struct device *dev, struct pm4125_priv *priv) +{ + struct device_node *np = dev->of_node; + u32 prop_val = 0; + int ret; + + ret = of_property_read_u32(np, "qcom,micbias1-microvolt", &prop_val); + if (!ret) + priv->micb1_mv = prop_val / 1000; + else + dev_warn(dev, "Micbias1 DT property not found\n"); + + ret = of_property_read_u32(np, "qcom,micbias2-microvolt", &prop_val); + if (!ret) + priv->micb2_mv = prop_val / 1000; + else + dev_warn(dev, "Micbias2 DT property not found\n"); + + ret = of_property_read_u32(np, "qcom,micbias3-microvolt", &prop_val); + if (!ret) + priv->micb3_mv = prop_val / 1000; + else + dev_warn(dev, "Micbias3 DT property not found\n"); +} + +static int pm4125_codec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct pm4125_priv *pm4125 = dev_get_drvdata(dai->dev); + struct pm4125_sdw_priv *sdw_priv = pm4125->sdw_priv[dai->id]; + + return pm4125_sdw_hw_params(sdw_priv, substream, params, dai); +} + +static int pm4125_codec_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + struct pm4125_priv *pm4125 = dev_get_drvdata(dai->dev); + struct pm4125_sdw_priv *sdw_priv = pm4125->sdw_priv[dai->id]; + + return sdw_stream_remove_slave(sdw_priv->sdev, sdw_priv->sruntime); +} + +static int pm4125_codec_set_sdw_stream(struct snd_soc_dai *dai, void *stream, int direction) +{ + struct pm4125_priv *pm4125 = dev_get_drvdata(dai->dev); + struct pm4125_sdw_priv *sdw_priv = pm4125->sdw_priv[dai->id]; + + sdw_priv->sruntime = stream; + + return 0; +} + +static int pm4125_get_channel_map(const struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot) +{ + struct pm4125_priv *pm4125 = dev_get_drvdata(dai->dev); + struct pm4125_sdw_priv *sdw_priv = pm4125->sdw_priv[dai->id]; + int i; + + switch (dai->id) { + case AIF1_PB: + if (!rx_slot || !rx_num) { + dev_err(dai->dev, "Invalid rx_slot %p or rx_num %p\n", rx_slot, rx_num); + return -EINVAL; + } + + for (i = 0; i < SDW_MAX_PORTS; i++) + rx_slot[i] = sdw_priv->master_channel_map[i]; + + *rx_num = i; + break; + case AIF1_CAP: + if (!tx_slot || !tx_num) { + dev_err(dai->dev, "Invalid tx_slot %p or tx_num %p\n", tx_slot, tx_num); + return -EINVAL; + } + + for (i = 0; i < SDW_MAX_PORTS; i++) + tx_slot[i] = sdw_priv->master_channel_map[i]; + + *tx_num = i; + break; + default: + break; + } + + return 0; +} + +static const struct snd_soc_dai_ops pm4125_sdw_dai_ops = { + .hw_params = pm4125_codec_hw_params, + .hw_free = pm4125_codec_free, + .set_stream = pm4125_codec_set_sdw_stream, + .get_channel_map = pm4125_get_channel_map, +}; + +static struct snd_soc_dai_driver pm4125_dais[] = { + [0] = { + .name = "pm4125-sdw-rx", + .playback = { + .stream_name = "PM4125 AIF Playback", + .rates = PM4125_RATES | PM4125_FRAC_RATES, + .formats = PM4125_FORMATS, + .rate_min = 8000, + .rate_max = 384000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &pm4125_sdw_dai_ops, + }, + [1] = { + .name = "pm4125-sdw-tx", + .capture = { + .stream_name = "PM4125 AIF Capture", + .rates = PM4125_RATES, + .formats = PM4125_FORMATS, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &pm4125_sdw_dai_ops, + }, +}; + +static int pm4125_bind(struct device *dev) +{ + struct pm4125_priv *pm4125 = dev_get_drvdata(dev); + struct device_link *devlink; + int ret; + + /* Give the soundwire subdevices some more time to settle */ + usleep_range(15000, 15010); + + ret = component_bind_all(dev, pm4125); + if (ret) { + dev_err(dev, "Slave bind failed, ret = %d\n", ret); + return ret; + } + + pm4125->rxdev = pm4125_sdw_device_get(pm4125->rxnode); + if (!pm4125->rxdev) { + dev_err(dev, "could not find rxslave with matching of node\n"); + ret = -EINVAL; + goto error_unbind_all; + } + + pm4125->sdw_priv[AIF1_PB] = dev_get_drvdata(pm4125->rxdev); + pm4125->sdw_priv[AIF1_PB]->pm4125 = pm4125; + + pm4125->txdev = pm4125_sdw_device_get(pm4125->txnode); + if (!pm4125->txdev) { + dev_err(dev, "could not find txslave with matching of node\n"); + ret = -EINVAL; + goto error_unbind_all; + } + + pm4125->sdw_priv[AIF1_CAP] = dev_get_drvdata(pm4125->txdev); + pm4125->sdw_priv[AIF1_CAP]->pm4125 = pm4125; + + pm4125->tx_sdw_dev = dev_to_sdw_dev(pm4125->txdev); + if (!pm4125->tx_sdw_dev) { + dev_err(dev, "could not get txslave with matching of dev\n"); + ret = -EINVAL; + goto error_unbind_all; + } + + /* + * As TX is the main CSR reg interface, which should not be suspended first. + * expicilty add the dependency link + */ + devlink = device_link_add(pm4125->rxdev, pm4125->txdev, + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); + if (!devlink) { + dev_err(dev, "Could not devlink TX and RX\n"); + ret = -EINVAL; + goto error_unbind_all; + } + + devlink = device_link_add(dev, pm4125->txdev, + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); + if (!devlink) { + dev_err(dev, "Could not devlink PM4125 and TX\n"); + ret = -EINVAL; + goto link_remove_rx_tx; + } + + devlink = device_link_add(dev, pm4125->rxdev, + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); + if (!devlink) { + dev_err(dev, "Could not devlink PM4125 and RX\n"); + ret = -EINVAL; + goto link_remove_dev_tx; + } + + pm4125->regmap = dev_get_regmap(&pm4125->tx_sdw_dev->dev, NULL); + if (!pm4125->regmap) { + dev_err(dev, "could not get TX device regmap\n"); + ret = -EINVAL; + goto link_remove_dev_rx; + } + + ret = pm4125_irq_init(pm4125, dev); + if (ret) { + dev_err(dev, "IRQ init failed: %d\n", ret); + goto link_remove_dev_rx; + } + + pm4125->sdw_priv[AIF1_PB]->slave_irq = pm4125->virq; + pm4125->sdw_priv[AIF1_CAP]->slave_irq = pm4125->virq; + + ret = pm4125_set_micbias_data(dev, pm4125); + if (ret < 0) { + dev_err(dev, "Bad micbias pdata\n"); + goto link_remove_dev_rx; + } + + ret = snd_soc_register_component(dev, &soc_codec_dev_pm4125, + pm4125_dais, ARRAY_SIZE(pm4125_dais)); + if (!ret) + return ret; + + dev_err(dev, "Codec registration failed\n"); + +link_remove_dev_rx: + device_link_remove(dev, pm4125->rxdev); +link_remove_dev_tx: + device_link_remove(dev, pm4125->txdev); +link_remove_rx_tx: + device_link_remove(pm4125->rxdev, pm4125->txdev); +error_unbind_all: + component_unbind_all(dev, pm4125); + return ret; +} + +static void pm4125_unbind(struct device *dev) +{ + struct pm4125_priv *pm4125 = dev_get_drvdata(dev); + + snd_soc_unregister_component(dev); + device_link_remove(dev, pm4125->txdev); + device_link_remove(dev, pm4125->rxdev); + device_link_remove(pm4125->rxdev, pm4125->txdev); + component_unbind_all(dev, pm4125); +} + +static const struct component_master_ops pm4125_comp_ops = { + .bind = pm4125_bind, + .unbind = pm4125_unbind, +}; + +static int pm4125_add_slave_components(struct pm4125_priv *pm4125, struct device *dev, + struct component_match **matchptr) +{ + struct device_node *np = dev->of_node; + + pm4125->rxnode = of_parse_phandle(np, "qcom,rx-device", 0); + if (!pm4125->rxnode) + return dev_err_probe(dev, -ENODEV, "Couldn't parse phandle to qcom,rx-device\n"); + component_match_add_release(dev, matchptr, component_release_of, component_compare_of, + pm4125->rxnode); + + pm4125->txnode = of_parse_phandle(np, "qcom,tx-device", 0); + if (!pm4125->txnode) + return dev_err_probe(dev, -ENODEV, "Couldn't parse phandle to qcom,tx-device\n"); + component_match_add_release(dev, matchptr, component_release_of, component_compare_of, + pm4125->txnode); + + return 0; +} + +static int pm4125_probe(struct platform_device *pdev) +{ + struct component_match *match = NULL; + struct device *dev = &pdev->dev; + struct pm4125_priv *pm4125; + struct wcd_mbhc_config *cfg; + int ret; + + pm4125 = devm_kzalloc(dev, sizeof(*pm4125), GFP_KERNEL); + if (!pm4125) + return -ENOMEM; + + dev_set_drvdata(dev, pm4125); + + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(pm4125_power_supplies), + pm4125_power_supplies); + if (ret) + return dev_err_probe(dev, ret, "Failed to get and enable supplies\n"); + + pm4125->spmi_regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!pm4125->spmi_regmap) + return -ENXIO; + + pm4125_reset(pm4125); + + pm4125_dt_parse_micbias_info(dev, pm4125); + atomic_set(&pm4125->gloal_mbias_cnt, 0); + + cfg = &pm4125->mbhc_cfg; + cfg->mbhc_micbias = MIC_BIAS_2; + cfg->anc_micbias = MIC_BIAS_2; + cfg->v_hs_max = WCD_MBHC_HS_V_MAX; + cfg->num_btn = PM4125_MBHC_MAX_BUTTONS; + cfg->micb_mv = pm4125->micb2_mv; + cfg->linein_th = 5000; + cfg->hs_thr = 1700; + cfg->hph_thr = 50; + + wcd_dt_parse_mbhc_data(dev, &pm4125->mbhc_cfg); + + ret = pm4125_add_slave_components(pm4125, dev, &match); + if (ret) + return ret; + + ret = component_master_add_with_match(dev, &pm4125_comp_ops, match); + if (ret) + return ret; + + pm_runtime_set_autosuspend_delay(dev, 1000); + pm_runtime_use_autosuspend(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_idle(dev); + + return 0; +} + +static void pm4125_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + component_master_del(&pdev->dev, &pm4125_comp_ops); + + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_dont_use_autosuspend(dev); +} + +static const struct of_device_id pm4125_of_match[] = { + { .compatible = "qcom,pm4125-codec" }, + { } +}; +MODULE_DEVICE_TABLE(of, pm4125_of_match); + +static struct platform_driver pm4125_codec_driver = { + .probe = pm4125_probe, + .remove = pm4125_remove, + .driver = { + .name = "pm4125_codec", + .of_match_table = pm4125_of_match, + .suppress_bind_attrs = true, + }, +}; + +module_platform_driver(pm4125_codec_driver); +MODULE_DESCRIPTION("PM4125 audio codec driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/pm4125.h b/sound/soc/codecs/pm4125.h new file mode 100644 index 000000000000..3520c711b744 --- /dev/null +++ b/sound/soc/codecs/pm4125.h @@ -0,0 +1,307 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _PM4125_REGISTERS_H +#define _PM4125_REGISTERS_H + +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_type.h> + +#define PM4125_ANA_BASE_ADDR 0x3000 +#define PM4125_DIG_BASE_ADDR 0x3400 + +#define PM4125_ANA_MICBIAS_MICB_1_2_EN (PM4125_ANA_BASE_ADDR+0x040) +#define PM4125_ANA_MICBIAS_MICB1_PULL_UP_MASK BIT(5) +#define PM4125_ANA_MICBIAS_MICB2_PULL_UP_MASK BIT(1) +#define PM4125_ANA_MICBIAS_MICB2_PULL_DN_MASK BIT(0) +#define PM4125_ANA_MICBIAS_MICB_PULL_ENABLE 1 +#define PM4125_ANA_MICBIAS_MICB_PULL_DISABLE 0 +#define PM4125_ANA_MICBIAS_MICB_3_EN (PM4125_ANA_BASE_ADDR+0x041) +#define PM4125_ANA_MICBIAS_LDO_1_SETTING (PM4125_ANA_BASE_ADDR+0x042) +#define PM4125_ANA_MICBIAS_MICB_OUT_VAL_MASK GENMASK(7, 3) +#define PM4125_ANA_MICBIAS_LDO_1_CTRL (PM4125_ANA_BASE_ADDR+0x043) +#define PM4125_ANA_TX_AMIC1 (PM4125_ANA_BASE_ADDR+0x047) +#define PM4125_ANA_TX_AMIC2 (PM4125_ANA_BASE_ADDR+0x048) +#define PM4125_ANA_MBHC_MECH (PM4125_ANA_BASE_ADDR+0x05A) +#define PM4125_ANA_MBHC_ELECT (PM4125_ANA_BASE_ADDR+0x05B) +#define PM4125_ANA_MBHC_ELECT_BIAS_EN_MASK BIT(0) +#define PM4125_ANA_MBHC_ELECT_BIAS_ENABLE 1 +#define PM4125_ANA_MBHC_ELECT_BIAS_DISABLE 0 +#define PM4125_ANA_MBHC_ZDET (PM4125_ANA_BASE_ADDR+0x05C) +#define PM4125_ANA_MBHC_RESULT_1 (PM4125_ANA_BASE_ADDR+0x05D) +#define PM4125_ANA_MBHC_RESULT_2 (PM4125_ANA_BASE_ADDR+0x05E) +#define PM4125_ANA_MBHC_RESULT_3 (PM4125_ANA_BASE_ADDR+0x05F) +#define PM4125_ANA_MBHC_BTN0_ZDET_VREF1 (PM4125_ANA_BASE_ADDR+0x060) +#define PM4125_ANA_MBHC_BTN0_THRESHOLD_MASK GENMASK(7, 2) +#define PM4125_ANA_MBHC_BTN1_ZDET_VREF2 (PM4125_ANA_BASE_ADDR+0x061) +#define PM4125_ANA_MBHC_BTN2_ZDET_VREF3 (PM4125_ANA_BASE_ADDR+0x062) +#define PM4125_ANA_MBHC_BTN3_ZDET_DBG_400 (PM4125_ANA_BASE_ADDR+0x063) +#define PM4125_ANA_MBHC_BTN4_ZDET_DBG_1400 (PM4125_ANA_BASE_ADDR+0x064) +#define PM4125_ANA_MBHC_MICB2_RAMP (PM4125_ANA_BASE_ADDR+0x065) +#define PM4125_ANA_MBHC_CTL_1 (PM4125_ANA_BASE_ADDR+0x066) +#define PM4125_ANA_MBHC_CTL_2 (PM4125_ANA_BASE_ADDR+0x067) +#define PM4125_ANA_MBHC_PLUG_DETECT_CTL (PM4125_ANA_BASE_ADDR+0x068) +#define PM4125_ANA_MBHC_ZDET_ANA_CTL (PM4125_ANA_BASE_ADDR+0x069) +#define PM4125_ANA_MBHC_ZDET_RAMP_CTL (PM4125_ANA_BASE_ADDR+0x06A) +#define PM4125_ANA_MBHC_FSM_STATUS (PM4125_ANA_BASE_ADDR+0x06B) +#define PM4125_ANA_MBHC_ADC_RESULT (PM4125_ANA_BASE_ADDR+0x06C) +#define PM4125_ANA_MBHC_CTL_CLK (PM4125_ANA_BASE_ADDR+0x06D) +#define PM4125_ANA_MBHC_ZDET_CALIB_RESULT (PM4125_ANA_BASE_ADDR+0x072) +#define PM4125_ANA_NCP_EN (PM4125_ANA_BASE_ADDR+0x077) +#define PM4125_ANA_NCP_ENABLE_MASK BIT(0) +#define PM4125_ANA_NCP_ENABLE 1 +#define PM4125_ANA_NCP_DISABLE 0 +#define PM4125_ANA_NCP_VCTRL (PM4125_ANA_BASE_ADDR+0x07C) +#define PM4125_ANA_HPHPA_CNP_CTL_1 (PM4125_ANA_BASE_ADDR+0x083) +#define PM4125_ANA_HPHPA_CNP_CTL_1_EN_MASK BIT(1) +#define PM4125_ANA_HPHPA_CNP_CTL_1_EN 1 +#define PM4125_ANA_HPHPA_CNP_CTL_2 (PM4125_ANA_BASE_ADDR+0x084) +#define PM4125_ANA_HPHPA_CNP_OCP_EN_L_MASK BIT(1) +#define PM4125_ANA_HPHPA_CNP_OCP_EN_R_MASK BIT(0) +#define PM4125_ANA_HPHPA_CNP_OCP_ENABLE 1 +#define PM4125_ANA_HPHPA_CNP_OCP_DISABLE 0 +#define PM4125_ANA_HPHPA_PA_STATUS (PM4125_ANA_BASE_ADDR+0x087) +#define PM4125_ANA_HPHPA_FSM_CLK (PM4125_ANA_BASE_ADDR+0x088) +#define PM4125_ANA_HPHPA_FSM_CLK_DIV_EN_MASK BIT(7) +#define PM4125_ANA_HPHPA_FSM_CLK_DIV_ENABLE 1 +#define PM4125_ANA_HPHPA_FSM_CLK_DIV_DISABLE 0 +#define PM4125_ANA_HPHPA_FSM_DIV_RATIO_MASK GENMASK(6, 0) +#define PM4125_ANA_HPHPA_FSM_DIV_RATIO_68 (0x11) +#define PM4125_ANA_HPHPA_L_GAIN (PM4125_ANA_BASE_ADDR+0x08B) +#define PM4125_ANA_HPHPA_R_GAIN (PM4125_ANA_BASE_ADDR+0x08C) +#define PM4125_ANA_HPHPA_SPARE_CTL (PM4125_ANA_BASE_ADDR+0x08E) +#define PM4125_SWR_HPHPA_HD2 (PM4125_ANA_BASE_ADDR+0x090) +#define PM4125_SWR_HPHPA_HD2_LEFT_MASK GENMASK(5, 3) +#define PM4125_SWR_HPHPA_HD2_RIGHT_MASK GENMASK(2, 0) +#define PM4125_SWR_HPHPA_HD2_ENABLE (BIT(2) | BIT(1) | BIT(0)) +#define PM4125_ANA_SURGE_EN (PM4125_ANA_BASE_ADDR+0x097) +#define PM4125_ANA_SURGE_PROTECTION_HPHL_MASK BIT(7) +#define PM4125_ANA_SURGE_PROTECTION_HPHR_MASK BIT(6) +#define PM4125_ANA_SURGE_PROTECTION_ENABLE 1 +#define PM4125_ANA_SURGE_PROTECTION_DISABLE 0 +#define PM4125_ANA_COMBOPA_CTL (PM4125_ANA_BASE_ADDR+0x09B) +#define PM4125_ANA_COMBO_PA_SELECT_MASK BIT(6) +#define PM4125_ANA_COMBO_PA_SELECT_EAR 0 +#define PM4125_ANA_COMBO_PA_SELECT_LO 1 +#define PM4125_ANA_COMBOPA_CTL_4 (PM4125_ANA_BASE_ADDR+0x09F) +#define PM4125_ANA_COMBOPA_CTL_5 (PM4125_ANA_BASE_ADDR+0x0A0) +#define PM4125_ANA_RXLDO_CTL (PM4125_ANA_BASE_ADDR+0x0B2) +#define PM4125_ANA_MBIAS_EN (PM4125_ANA_BASE_ADDR+0x0B4) +#define PM4125_ANA_MBIAS_EN_GLOBAL_MASK BIT(5) +#define PM4125_ANA_MBIAS_EN_V2I_MASK BIT(4) +#define PM4125_ANA_MBIAS_EN_ENABLE 1 +#define PM4125_ANA_MBIAS_EN_DISABLE 0 + +#define PM4125_DIG_SWR_CHIP_ID0 (PM4125_DIG_BASE_ADDR+0x001) +#define PM4125_DIG_SWR_CHIP_ID1 (PM4125_DIG_BASE_ADDR+0x002) +#define PM4125_DIG_SWR_CHIP_ID2 (PM4125_DIG_BASE_ADDR+0x003) +#define PM4125_DIG_SWR_CHIP_ID3 (PM4125_DIG_BASE_ADDR+0x004) +#define PM4125_DIG_SWR_SWR_TX_CLK_RATE (PM4125_DIG_BASE_ADDR+0x040) +#define PM4125_DIG_SWR_CDC_RST_CTL (PM4125_DIG_BASE_ADDR+0x041) +#define PM4125_DIG_SWR_TOP_CLK_CFG (PM4125_DIG_BASE_ADDR+0x042) +#define PM4125_DIG_SWR_CDC_RX_CLK_CTL (PM4125_DIG_BASE_ADDR+0x043) +#define PM4125_DIG_SWR_ANA_RX_DIV2_CLK_EN_MASK BIT(5) +#define PM4125_DIG_SWR_ANA_RX_CLK_EN_MASK BIT(4) +#define PM4125_DIG_SWR_RX1_CLK_EN_MASK BIT(1) +#define PM4125_DIG_SWR_RX0_CLK_EN_MASK BIT(0) +#define PM4125_DIG_SWR_RX_CLK_ENABLE 1 +#define PM4125_DIG_SWR_RX_CLK_DISABLE 0 +#define PM4125_DIG_SWR_CDC_TX_CLK_CTL (PM4125_DIG_BASE_ADDR+0x044) +#define PM4125_DIG_SWR_SWR_RST_EN (PM4125_DIG_BASE_ADDR+0x045) +#define PM4125_DIG_SWR_CDC_RX_RST (PM4125_DIG_BASE_ADDR+0x047) +#define PM4125_DIG_SWR_CDC_RX0_CTL (PM4125_DIG_BASE_ADDR+0x048) +#define PM4125_DIG_SWR_DSM_DITHER_EN_MASK BIT(7) +#define PM4125_DIG_SWR_DSM_DITHER_DISABLE 0 +#define PM4125_DIG_SWR_DSM_DITHER_ENABLE 1 +#define PM4125_DIG_SWR_CDC_RX1_CTL (PM4125_DIG_BASE_ADDR+0x049) +#define PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1 (PM4125_DIG_BASE_ADDR+0x04B) +#define PM4125_DIG_SWR_TX_ANA_TXD1_MODE_MASK GENMASK(7, 4) +#define PM4125_DIG_SWR_TX_ANA_TXD0_MODE_MASK GENMASK(3, 0) +#define PM4125_DIG_SWR_TXD_MODE_ULPI (0x9) +#define PM4125_DIG_SWR_TXD_MODE_NORMAL (0x3) +#define PM4125_DIG_SWR_CDC_COMP_CTL_0 (PM4125_DIG_BASE_ADDR+0x04F) +#define PM4125_DIG_SWR_COMP_HPHL_EN_MASK BIT(1) +#define PM4125_DIG_SWR_COMP_HPHR_EN_MASK BIT(0) +#define PM4125_DIG_SWR_COMP_ENABLE 1 +#define PM4125_DIG_SWR_COMP_DISABLE 0 +#define PM4125_DIG_SWR_CDC_RX_DELAY_CTL (PM4125_DIG_BASE_ADDR+0x052) +#define PM4125_DIG_SWR_CDC_RX_GAIN_0 (PM4125_DIG_BASE_ADDR+0x053) +#define PM4125_DIG_SWR_CDC_RX_GAIN_1 (PM4125_DIG_BASE_ADDR+0x054) +#define PM4125_DIG_SWR_CDC_RX_GAIN_CTL (PM4125_DIG_BASE_ADDR+0x057) +#define PM4125_DIG_SWR_RX1_EN_MASK BIT(3) +#define PM4125_DIG_SWR_RX0_EN_MASK BIT(2) +#define PM4125_DIG_SWR_RX_INPUT_DISABLE 0 +#define PM4125_DIG_SWR_RX_INPUT_ENABLE 1 +#define PM4125_DIG_SWR_CDC_TX0_CTL (PM4125_DIG_BASE_ADDR+0x060) +#define PM4125_DIG_SWR_CDC_TX1_CTL (PM4125_DIG_BASE_ADDR+0x061) +#define PM4125_DIG_SWR_CDC_TX_RST (PM4125_DIG_BASE_ADDR+0x063) +#define PM4125_DIG_SWR_CDC_REQ0_CTL (PM4125_DIG_BASE_ADDR+0x064) +#define PM4125_DIG_SWR_CDC_REQ1_CTL (PM4125_DIG_BASE_ADDR+0x065) +#define PM4125_DIG_SWR_CDC_RST (PM4125_DIG_BASE_ADDR+0x067) +#define PM4125_DIG_SWR_CDC_AMIC_CTL (PM4125_DIG_BASE_ADDR+0x06A) +#define PM4125_DIG_SWR_AMIC_SELECT_MASK BIT(1) +#define PM4125_DIG_SWR_AMIC_SELECT_DMIC1 0 +#define PM4125_DIG_SWR_AMIC_SELECT_AMIC3 1 +#define PM4125_DIG_SWR_CDC_DMIC_CTL (PM4125_DIG_BASE_ADDR+0x06B) +#define PM4125_DIG_SWR_CDC_DMIC1_CTL (PM4125_DIG_BASE_ADDR+0x06C) +#define PM4125_DIG_SWR_DMIC1_CLK_EN_MASK BIT(3) +#define PM4125_DIG_SWR_DMIC1_CLK_ENABLE 1 +#define PM4125_DIG_SWR_DMIC1_CLK_DISABLE 0 +#define PM4125_DIG_SWR_CDC_DMIC1_RATE (PM4125_DIG_BASE_ADDR+0x06D) +#define PM4125_DIG_SWR_PDM_WD_CTL0 (PM4125_DIG_BASE_ADDR+0x070) +#define PM4125_WDT_ENABLE_MASK GENMASK(1, 0) +#define PM4125_WDT_ENABLE_RX0_L BIT(0) +#define PM4125_WDT_ENABLE_RX0_M BIT(1) +#define PM4125_DIG_SWR_PDM_WD_CTL1 (PM4125_DIG_BASE_ADDR+0x071) +#define PM4125_WDT_ENABLE_RX1_L BIT(0) +#define PM4125_WDT_ENABLE_RX1_M BIT(1) +#define PM4125_DIG_SWR_INTR_MODE (PM4125_DIG_BASE_ADDR+0x080) +#define PM4125_DIG_SWR_INTR_MASK_0 (PM4125_DIG_BASE_ADDR+0x081) +#define PM4125_DIG_SWR_INTR_MASK_1 (PM4125_DIG_BASE_ADDR+0x082) +#define PM4125_DIG_SWR_INTR_MASK_2 (PM4125_DIG_BASE_ADDR+0x083) +#define PM4125_DIG_SWR_INTR_STATUS_0 (PM4125_DIG_BASE_ADDR+0x084) +#define PM4125_DIG_SWR_INTR_STATUS_1 (PM4125_DIG_BASE_ADDR+0x085) +#define PM4125_DIG_SWR_INTR_STATUS_2 (PM4125_DIG_BASE_ADDR+0x086) +#define PM4125_DIG_SWR_INTR_CLEAR_0 (PM4125_DIG_BASE_ADDR+0x087) +#define PM4125_DIG_SWR_INTR_CLEAR_1 (PM4125_DIG_BASE_ADDR+0x088) +#define PM4125_DIG_SWR_INTR_CLEAR_2 (PM4125_DIG_BASE_ADDR+0x089) +#define PM4125_DIG_SWR_INTR_LEVEL_0 (PM4125_DIG_BASE_ADDR+0x08A) +#define PM4125_DIG_SWR_INTR_LEVEL_1 (PM4125_DIG_BASE_ADDR+0x08B) +#define PM4125_DIG_SWR_INTR_LEVEL_2 (PM4125_DIG_BASE_ADDR+0x08C) +#define PM4125_DIG_SWR_CDC_CONN_RX0_CTL (PM4125_DIG_BASE_ADDR+0x093) +#define PM4125_DIG_SWR_CDC_CONN_RX1_CTL (PM4125_DIG_BASE_ADDR+0x094) +#define PM4125_DIG_SWR_LOOP_BACK_MODE (PM4125_DIG_BASE_ADDR+0x097) +#define PM4125_DIG_SWR_DRIVE_STRENGTH_0 (PM4125_DIG_BASE_ADDR+0x0A0) +#define PM4125_DIG_SWR_DIG_DEBUG_CTL (PM4125_DIG_BASE_ADDR+0x0AB) +#define PM4125_DIG_SWR_DIG_DEBUG_EN (PM4125_DIG_BASE_ADDR+0x0AC) +#define PM4125_DIG_SWR_DEM_BYPASS_DATA0 (PM4125_DIG_BASE_ADDR+0x0B0) +#define PM4125_DIG_SWR_DEM_BYPASS_DATA1 (PM4125_DIG_BASE_ADDR+0x0B1) +#define PM4125_DIG_SWR_DEM_BYPASS_DATA2 (PM4125_DIG_BASE_ADDR+0x0B2) +#define PM4125_DIG_SWR_DEM_BYPASS_DATA3 (PM4125_DIG_BASE_ADDR+0x0B3) + +#define PM4125_ANALOG_REGISTERS_MAX_SIZE (PM4125_ANA_BASE_ADDR+0x0B5) +#define PM4125_DIGITAL_REGISTERS_MAX_SIZE (PM4125_DIG_BASE_ADDR+0x0B4) +#define PM4125_ANALOG_MAX_REGISTER (PM4125_ANALOG_REGISTERS_MAX_SIZE - 1) +#define PM4125_DIGITAL_MAX_REGISTER (PM4125_DIGITAL_REGISTERS_MAX_SIZE - 1) +#define PM4125_MAX_REGISTER PM4125_DIGITAL_MAX_REGISTER + +#define PM4125_MAX_MICBIAS 3 +#define PM4125_MAX_SWR_CH_IDS 15 +#define PM4125_SWRM_CH_MASK(ch_idx) BIT(ch_idx - 1) + +enum pm4125_tx_sdw_ports { + PM4125_ADC_1_2_DMIC1L_BCS_PORT = 1, + PM4125_DMIC_1L_1R_ADC1_BCS_PORT, + PM4125_MAX_TX_SWR_PORTS = PM4125_DMIC_1L_1R_ADC1_BCS_PORT, +}; + +enum pm4125_rx_sdw_ports { + PM4125_HPH_PORT = 1, + PM4125_COMP_PORT, + PM4125_MAX_SWR_PORTS = PM4125_COMP_PORT, +}; + +struct pm4125_sdw_ch_info { + int port_num; + unsigned int ch_mask; + unsigned int master_ch_mask; +}; + +#define WCD_SDW_CH(id, pn, cmask) \ + [id] = { \ + .port_num = pn, \ + .ch_mask = cmask, \ + .master_ch_mask = cmask, \ + } + +struct pm4125_priv; +struct pm4125_sdw_priv { + struct sdw_slave *sdev; + struct sdw_stream_config sconfig; + struct sdw_stream_runtime *sruntime; + struct sdw_port_config port_config[PM4125_MAX_SWR_PORTS]; + struct pm4125_sdw_ch_info *ch_info; + bool port_enable[PM4125_MAX_SWR_CH_IDS]; + unsigned int master_channel_map[SDW_MAX_PORTS]; + int active_ports; + int num_ports; + bool is_tx; + struct pm4125_priv *pm4125; + struct irq_domain *slave_irq; + struct regmap *regmap; +}; + +#if IS_ENABLED(CONFIG_SND_SOC_PM4125_SDW) +int pm4125_sdw_free(struct pm4125_sdw_priv *pm4125, struct snd_pcm_substream *substream, + struct snd_soc_dai *dai); +int pm4125_sdw_set_sdw_stream(struct pm4125_sdw_priv *pm4125, struct snd_soc_dai *dai, void *stream, + int direction); +int pm4125_sdw_hw_params(struct pm4125_sdw_priv *pm4125, struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai); + +struct device *pm4125_sdw_device_get(struct device_node *np); + +#else +static inline int pm4125_sdw_free(struct pm4125_sdw_priv *pm4125, + struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + return -EOPNOTSUPP; +} + +static inline int pm4125_sdw_set_sdw_stream(struct pm4125_sdw_priv *pm4125, + struct snd_soc_dai *dai, void *stream, int direction) +{ + return -EOPNOTSUPP; +} + +static inline int pm4125_sdw_hw_params(struct pm4125_sdw_priv *pm4125, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + return -EOPNOTSUPP; +} +#endif + +enum { + /* INTR_CTRL_INT_MASK_0 */ + PM4125_IRQ_MBHC_BUTTON_PRESS_DET = 0, + PM4125_IRQ_MBHC_BUTTON_RELEASE_DET, + PM4125_IRQ_MBHC_ELECT_INS_REM_DET, + PM4125_IRQ_MBHC_ELECT_INS_REM_LEG_DET, + PM4125_IRQ_MBHC_SW_DET, + PM4125_IRQ_HPHR_OCP_INT, + PM4125_IRQ_HPHR_CNP_INT, + PM4125_IRQ_HPHL_OCP_INT, + + /* INTR_CTRL_INT_MASK_1 */ + PM4125_IRQ_HPHL_CNP_INT, + PM4125_IRQ_EAR_CNP_INT, + PM4125_IRQ_EAR_SCD_INT, + PM4125_IRQ_AUX_CNP_INT, + PM4125_IRQ_AUX_SCD_INT, + PM4125_IRQ_HPHL_PDM_WD_INT, + PM4125_IRQ_HPHR_PDM_WD_INT, + PM4125_IRQ_AUX_PDM_WD_INT, + + /* INTR_CTRL_INT_MASK_2 */ + PM4125_IRQ_LDORT_SCD_INT, + PM4125_IRQ_MBHC_MOISTURE_INT, + PM4125_IRQ_HPHL_SURGE_DET_INT, + PM4125_IRQ_HPHR_SURGE_DET_INT, + PM4125_NUM_IRQS, +}; + +enum pm4125_tx_sdw_channels { + PM4125_ADC1, + PM4125_ADC2, +}; + +enum pm4125_rx_sdw_channels { + PM4125_HPH_L, + PM4125_HPH_R, + PM4125_COMP_L, + PM4125_COMP_R, +}; + +#endif /* _PM4125_REGISTERS_H */ diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c index dcddc28e8856..e3f9b03df3aa 100644 --- a/sound/soc/codecs/rt1320-sdw.c +++ b/sound/soc/codecs/rt1320-sdw.c @@ -256,6 +256,161 @@ static const struct reg_sequence rt1320_vc_blind_write[] = { { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, }; +static const struct reg_sequence rt1321_blind_write[] = { + { 0x0000c003, 0xf0 }, + { 0x0000c01b, 0xfc }, + { 0x0000c5c3, 0xf2 }, + { 0x0000c5c2, 0x00 }, + { 0x0000c5c1, 0x10 }, + { 0x0000c5c0, 0x04 }, + { 0x0000c5c7, 0x03 }, + { 0x0000c5c6, 0x10 }, + { 0x0000c526, 0x47 }, + { 0x0000c5c4, 0x12 }, + { 0x0000c5c5, 0x60 }, + { 0x0000c520, 0x10 }, + { 0x0000c521, 0x32 }, + { 0x0000c5c7, 0x00 }, + { 0x0000c5c8, 0x03 }, + { 0x0000c5d3, 0x08 }, + { 0x0000c5d2, 0x0a }, + { 0x0000c5d1, 0x49 }, + { 0x0000c5d0, 0x0f }, + { 0x0000c580, 0x10 }, + { 0x0000c581, 0x32 }, + { 0x0000c582, 0x01 }, + { 0x0000cb00, 0x03 }, + { 0x0000cb02, 0x52 }, + { 0x0000cb04, 0x80 }, + { 0x0000cb0b, 0x01 }, + { 0x0000c682, 0x60 }, + { 0x0000c019, 0x10 }, + { 0x0000c5f0, 0x01 }, + { 0x0000c5f7, 0x22 }, + { 0x0000c5f6, 0x22 }, + { 0x0000c057, 0x51 }, + { 0x0000c054, 0x55 }, + { 0x0000c053, 0x55 }, + { 0x0000c052, 0x55 }, + { 0x0000c051, 0x01 }, + { 0x0000c050, 0x15 }, + { 0x0000c060, 0x99 }, + { 0x0000c030, 0x55 }, + { 0x0000c061, 0x55 }, + { 0x0000c063, 0x55 }, + { 0x0000c065, 0xa5 }, + { 0x0000c06b, 0x0a }, + { 0x0000ca05, 0xd6 }, + { 0x0000ca07, 0x07 }, + { 0x0000ca25, 0xd6 }, + { 0x0000ca27, 0x07 }, + { 0x0000cd00, 0x05 }, + { 0x0000c604, 0x40 }, + { 0x0000c609, 0x40 }, + { 0x0000c046, 0xf7 }, + { 0x0000c045, 0xff }, + { 0x0000c044, 0xff }, + { 0x0000c043, 0xff }, + { 0x0000c042, 0xff }, + { 0x0000c041, 0xff }, + { 0x0000c040, 0xff }, + { 0x0000c049, 0xff }, + { 0x0000c028, 0x3f }, + { 0x0000c020, 0x3f }, + { 0x0000c032, 0x13 }, + { 0x0000c033, 0x01 }, + { 0x0000cc10, 0x01 }, + { 0x0000dc20, 0x03 }, + { 0x0000de03, 0x05 }, + { 0x0000dc00, 0x00 }, + { 0x0000c700, 0xf0 }, + { 0x0000c701, 0x13 }, + { 0x0000c900, 0xc3 }, + { 0x0000c570, 0x08 }, + { 0x0000c086, 0x02 }, + { 0x0000c085, 0x7f }, + { 0x0000c084, 0x00 }, + { 0x0000c081, 0xff }, + { 0x0000f084, 0x0f }, + { 0x0000f083, 0xff }, + { 0x0000f082, 0xff }, + { 0x0000f081, 0xff }, + { 0x0000f080, 0xff }, + { 0x20003003, 0x3f }, + { 0x20005818, 0x81 }, + { 0x20009018, 0x81 }, + { 0x2000301c, 0x81 }, + { 0x0000c003, 0xc0 }, + { 0x0000c047, 0x80 }, + { 0x0000d541, 0x80 }, + { 0x0000d487, 0x0b }, + { 0x0000d487, 0x3b }, + { 0x0000d486, 0xc3 }, + { 0x0000d470, 0x89 }, + { 0x0000d471, 0x3a }, + { 0x0000d472, 0x1d }, + { 0x0000d478, 0xff }, + { 0x0000d479, 0x20 }, + { 0x0000d47a, 0x10 }, + { 0x0000d73c, 0xb7 }, + { 0x0000d73d, 0xd7 }, + { 0x0000d73e, 0x00 }, + { 0x0000d73f, 0x10 }, + { 0x3fc2dfc3, 0x00 }, + { 0x3fc2dfc2, 0x00 }, + { 0x3fc2dfc1, 0x00 }, + { 0x3fc2dfc0, 0x07 }, + { 0x3fc2dfc7, 0x00 }, + { 0x3fc2dfc6, 0x00 }, + { 0x3fc2dfc5, 0x00 }, + { 0x3fc2dfc4, 0x01 }, + { 0x3fc2df83, 0x00 }, + { 0x3fc2df82, 0x00 }, + { 0x3fc2df81, 0x00 }, + { 0x3fc2df80, 0x00 }, + { 0x0000d541, 0x40 }, + { 0x0000d486, 0x43 }, + { 0x1000db00, 0x03 }, + { 0x1000db01, 0x00 }, + { 0x1000db02, 0x10 }, + { 0x1000db03, 0x00 }, + { 0x1000db04, 0x00 }, + { 0x1000db05, 0x45 }, + { 0x1000db06, 0x12 }, + { 0x1000db07, 0x09 }, + { 0x1000db08, 0x00 }, + { 0x1000db09, 0x00 }, + { 0x1000db0a, 0x00 }, + { 0x1000db0b, 0x13 }, + { 0x1000db0c, 0x09 }, + { 0x1000db0d, 0x00 }, + { 0x1000db0e, 0x00 }, + { 0x1000db0f, 0x00 }, + { 0x0000d540, 0x21 }, + { 0x41000189, 0x00 }, + { 0x4100018a, 0x00 }, + { 0x41001988, 0x00 }, + { 0x41081400, 0x09 }, + { 0x40801508, 0x03 }, + { 0x40801588, 0x03 }, + { 0x40801809, 0x00 }, + { 0x4080180a, 0x00 }, + { 0x4080180b, 0x00 }, + { 0x4080180c, 0x00 }, + { 0x40801b09, 0x00 }, + { 0x40801b0a, 0x00 }, + { 0x40801b0b, 0x00 }, + { 0x40801b0c, 0x00 }, + { 0x0000d714, 0x17 }, + { 0x20009012, 0x00 }, + { 0x0000dd0b, 0x0d }, + { 0x0000dd0a, 0xff }, + { 0x0000dd09, 0x0d }, + { 0x0000dd08, 0xff }, + { 0x0000d172, 0x2a }, + { 0x41001988, 0x03 }, +}; + static const struct reg_default rt1320_reg_defaults[] = { { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, @@ -340,10 +495,19 @@ static bool rt1320_readable_register(struct device *dev, unsigned int reg) case 0xf717 ... 0xf719: case 0xf720 ... 0xf723: case 0x1000cd91 ... 0x1000cd96: + case RT1321_PATCH_MAIN_VER ... RT1321_PATCH_BETA_VER: case 0x1000f008: case 0x1000f021: + case 0x2000300f: + case 0x2000301c: + case 0x2000900f: + case 0x20009018: + case 0x3fc29d80 ... 0x3fc29d83: case 0x3fe2e000 ... 0x3fe2e003: case 0x3fc2ab80 ... 0x3fc2abd4: + case 0x3fc2bfc0 ... 0x3fc2bfc8: + case 0x3fc2d300 ... 0x3fc2d354: + case 0x3fc2dfc0 ... 0x3fc2dfc8: /* 0x40801508/0x40801809/0x4080180a/0x40801909/0x4080190a */ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_REQ_POWER_STATE, 0): case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_01): @@ -394,6 +558,7 @@ static bool rt1320_volatile_register(struct device *dev, unsigned int reg) case 0xc560: case 0xc5b5 ... 0xc5b7: case 0xc5fc ... 0xc5ff: + case 0xc680 ... 0xc683: case 0xc820: case 0xc900: case 0xc920: @@ -412,7 +577,7 @@ static bool rt1320_volatile_register(struct device *dev, unsigned int reg) case 0xd4e5 ... 0xd4e6: case 0xd4e8 ... 0xd4ff: case 0xd530: - case 0xd540: + case 0xd540 ... 0xd541: case 0xd543: case 0xdb58 ... 0xdb5f: case 0xdb60 ... 0xdb63: @@ -429,13 +594,20 @@ static bool rt1320_volatile_register(struct device *dev, unsigned int reg) case 0xf01e: case 0xf717 ... 0xf719: case 0xf720 ... 0xf723: - case 0x10000000 ... 0x10007fff: + case 0x10000000 ... 0x10008fff: case 0x1000c000 ... 0x1000dfff: case 0x1000f008: case 0x1000f021: + case 0x2000300f: + case 0x2000301c: + case 0x2000900f: + case 0x20009018: case 0x3fc2ab80 ... 0x3fc2abd4: + case 0x3fc2b780: case 0x3fc2bf80 ... 0x3fc2bf83: - case 0x3fc2bfc0 ... 0x3fc2bfc7: + case 0x3fc2bfc0 ... 0x3fc2bfc8: + case 0x3fc2d300 ... 0x3fc2d354: + case 0x3fc2dfc0 ... 0x3fc2dfc8: case 0x3fe2e000 ... 0x3fe2e003: case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0): @@ -560,7 +732,7 @@ static int rt1320_read_prop(struct sdw_slave *slave) static int rt1320_pde_transition_delay(struct rt1320_sdw_priv *rt1320, unsigned char func, unsigned char entity, unsigned char ps) { - unsigned int delay = 1000, val; + unsigned int delay = 2000, val; pm_runtime_mark_last_busy(&rt1320->sdw_slave->dev); @@ -591,24 +763,44 @@ static void rt1320_load_mcu_patch(struct rt1320_sdw_priv *rt1320) struct sdw_slave *slave = rt1320->sdw_slave; const struct firmware *patch; const char *filename; - unsigned int addr, val; + unsigned int addr, val, min_addr, max_addr; const unsigned char *ptr; int ret, i; - if (rt1320->version_id <= RT1320_VB) - filename = RT1320_VAB_MCU_PATCH; - else - filename = RT1320_VC_MCU_PATCH; + switch (rt1320->dev_id) { + case RT1320_DEV_ID: + if (rt1320->version_id <= RT1320_VB) + filename = RT1320_VAB_MCU_PATCH; + else + filename = RT1320_VC_MCU_PATCH; + min_addr = 0x10007000; + max_addr = 0x10007fff; + break; + case RT1321_DEV_ID: + filename = RT1321_VA_MCU_PATCH; + min_addr = 0x10008000; + max_addr = 0x10008fff; + break; + default: + dev_err(&slave->dev, "%s: Unknown device ID %d\n", __func__, rt1320->dev_id); + return; + } /* load the patch code here */ ret = request_firmware(&patch, filename, &slave->dev); if (ret) { dev_err(&slave->dev, "%s: Failed to load %s firmware", __func__, filename); regmap_write(rt1320->regmap, 0xc598, 0x00); - regmap_write(rt1320->regmap, 0x10007000, 0x67); - regmap_write(rt1320->regmap, 0x10007001, 0x80); - regmap_write(rt1320->regmap, 0x10007002, 0x00); - regmap_write(rt1320->regmap, 0x10007003, 0x00); + regmap_write(rt1320->regmap, min_addr, 0x67); + regmap_write(rt1320->regmap, min_addr + 0x1, 0x80); + regmap_write(rt1320->regmap, min_addr + 0x2, 0x00); + regmap_write(rt1320->regmap, min_addr + 0x3, 0x00); + if (rt1320->dev_id == RT1321_DEV_ID) { + regmap_write(rt1320->regmap, 0xd73c, 0x67); + regmap_write(rt1320->regmap, 0xd73d, 0x80); + regmap_write(rt1320->regmap, 0xd73e, 0x00); + regmap_write(rt1320->regmap, 0xd73f, 0x00); + } } else { ptr = (const unsigned char *)patch->data; if ((patch->size % 8) == 0) { @@ -618,7 +810,7 @@ static void rt1320_load_mcu_patch(struct rt1320_sdw_priv *rt1320) val = (ptr[i + 4] & 0xff) | (ptr[i + 5] & 0xff) << 8 | (ptr[i + 6] & 0xff) << 16 | (ptr[i + 7] & 0xff) << 24; - if (addr > 0x10007fff || addr < 0x10007000) { + if (addr > max_addr || addr < min_addr) { dev_err(&slave->dev, "%s: the address 0x%x is wrong", __func__, addr); goto _exit_; } @@ -688,6 +880,28 @@ static void rt1320_vc_preset(struct rt1320_sdw_priv *rt1320) } } +static void rt1321_preset(struct rt1320_sdw_priv *rt1320) +{ + unsigned int i, reg, val, delay; + + for (i = 0; i < ARRAY_SIZE(rt1321_blind_write); i++) { + reg = rt1321_blind_write[i].reg; + val = rt1321_blind_write[i].def; + delay = rt1321_blind_write[i].delay_us; + + if (reg == 0x3fc2dfc3) + rt1320_load_mcu_patch(rt1320); + + regmap_write(rt1320->regmap, reg, val); + + if (delay) + usleep_range(delay, delay + 1000); + + if (reg == SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0)) + rt1320_pde_transition_delay(rt1320, FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, val); + } +} + static int rt1320_io_init(struct device *dev, struct sdw_slave *slave) { struct rt1320_sdw_priv *rt1320 = dev_get_drvdata(dev); @@ -714,6 +928,9 @@ static int rt1320_io_init(struct device *dev, struct sdw_slave *slave) if (rt1320->version_id < 0) { regmap_read(rt1320->regmap, RT1320_DEV_VERSION_ID_1, &val); rt1320->version_id = val; + regmap_read(rt1320->regmap, RT1320_DEV_ID_0, &val); + regmap_read(rt1320->regmap, RT1320_DEV_ID_1, &tmp); + rt1320->dev_id = (val << 8) | tmp; } regmap_read(rt1320->regmap, @@ -722,16 +939,25 @@ static int rt1320_io_init(struct device *dev, struct sdw_slave *slave) /* initialization write */ if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION)) { - if (rt1320->version_id < RT1320_VC) - rt1320_vab_preset(rt1320); - else - rt1320_vc_preset(rt1320); + switch (rt1320->dev_id) { + case RT1320_DEV_ID: + if (rt1320->version_id < RT1320_VC) + rt1320_vab_preset(rt1320); + else + rt1320_vc_preset(rt1320); + break; + case RT1321_DEV_ID: + rt1321_preset(rt1320); + break; + default: + dev_err(dev, "%s: Unknown device ID %d\n", __func__, rt1320->dev_id); + } regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0), FUNCTION_NEEDS_INITIALIZATION); } - if (!rt1320->first_hw_init && rt1320->version_id == RT1320_VA) { + if (!rt1320->first_hw_init && rt1320->version_id == RT1320_VA && rt1320->dev_id == RT1320_DEV_ID) { regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0); regmap_read(rt1320->regmap, RT1320_HIFI_VER_0, &val); @@ -751,7 +977,7 @@ static int rt1320_io_init(struct device *dev, struct sdw_slave *slave) regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 3); } - dev_dbg(dev, "%s version_id=%d\n", __func__, rt1320->version_id); + dev_dbg(dev, "%s version_id=%d, dev_id=0x%x\n", __func__, rt1320->version_id, rt1320->dev_id); if (rt1320->first_hw_init) { regcache_cache_bypass(rt1320->regmap, false); @@ -894,12 +1120,20 @@ _dmic_vol_: /* check all channels */ for (i = 0; i < p->count; i++) { - if (i < 2) { + switch (rt1320->dev_id) { + case RT1320_DEV_ID: + if (i < 2) { + reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01); + regmap_read(rt1320->mbq_regmap, reg_base + i, ®value[i]); + } else { + reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01); + regmap_read(rt1320->mbq_regmap, reg_base + i - 2, ®value[i]); + } + break; + case RT1321_DEV_ID: reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01); regmap_read(rt1320->mbq_regmap, reg_base + i, ®value[i]); - } else { - reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01); - regmap_read(rt1320->mbq_regmap, reg_base + i - 2, ®value[i]); + break; } gain_val[i] = ucontrol->value.integer.value[i]; @@ -916,12 +1150,20 @@ _dmic_vol_: return 0; for (i = 0; i < p->count; i++) { - if (i < 2) { + switch (rt1320->dev_id) { + case RT1320_DEV_ID: + if (i < 2) { + reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01); + err = regmap_write(rt1320->mbq_regmap, reg_base + i, gain_val[i]); + } else { + reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01); + err = regmap_write(rt1320->mbq_regmap, reg_base + i - 2, gain_val[i]); + } + break; + case RT1321_DEV_ID: reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01); err = regmap_write(rt1320->mbq_regmap, reg_base + i, gain_val[i]); - } else { - reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01); - err = regmap_write(rt1320->mbq_regmap, reg_base + i - 2, gain_val[i]); + break; } if (err < 0) @@ -966,12 +1208,20 @@ _dmic_vol_: /* check all channels */ for (i = 0; i < p->count; i++) { - if (i < 2) { + switch (rt1320->dev_id) { + case RT1320_DEV_ID: + if (i < 2) { + reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01); + regmap_read(rt1320->mbq_regmap, reg_base + i, ®value); + } else { + reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01); + regmap_read(rt1320->mbq_regmap, reg_base + i - 2, ®value); + } + break; + case RT1321_DEV_ID: reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01); regmap_read(rt1320->mbq_regmap, reg_base + i, ®value); - } else { - reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01); - regmap_read(rt1320->mbq_regmap, reg_base + i - 2, ®value); + break; } ctl = p->max - (((0x1e00 - regvalue) & 0xffff) / interval_offset); @@ -989,14 +1239,26 @@ static int rt1320_set_fu_capture_ctl(struct rt1320_sdw_priv *rt1320) for (i = 0; i < ARRAY_SIZE(rt1320->fu_mixer_mute); i++) { ch_mute = (rt1320->fu_dapm_mute || rt1320->fu_mixer_mute[i]) ? 0x01 : 0x00; - if (i < 2) + switch (rt1320->dev_id) { + case RT1320_DEV_ID: + if (i < 2) + err = regmap_write(rt1320->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, + RT1320_SDCA_CTL_FU_MUTE, CH_01) + i, ch_mute); + else + err = regmap_write(rt1320->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, + RT1320_SDCA_CTL_FU_MUTE, CH_01) + i - 2, ch_mute); + break; + case RT1321_DEV_ID: err = regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_01) + i, ch_mute); - else - err = regmap_write(rt1320->regmap, - SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, - RT1320_SDCA_CTL_FU_MUTE, CH_01) + i - 2, ch_mute); + break; + default: + dev_err(&rt1320->sdw_slave->dev, "%s: Unknown device ID %d\n", __func__, rt1320->dev_id); + return -EINVAL; + } if (err < 0) return err; } @@ -1217,10 +1479,20 @@ static int rt1320_sdw_hw_params(struct snd_pcm_substream *substream, if (dai->id == RT1320_AIF1) port_config.num = 4; else if (dai->id == RT1320_AIF2) { - dmic_port_config[0].ch_mask = BIT(0) | BIT(1); - dmic_port_config[0].num = 8; - dmic_port_config[1].ch_mask = BIT(0) | BIT(1); - dmic_port_config[1].num = 10; + switch (rt1320->dev_id) { + case RT1320_DEV_ID: + dmic_port_config[0].ch_mask = BIT(0) | BIT(1); + dmic_port_config[0].num = 8; + dmic_port_config[1].ch_mask = BIT(0) | BIT(1); + dmic_port_config[1].num = 10; + break; + case RT1321_DEV_ID: + dmic_port_config[0].ch_mask = BIT(0) | BIT(1); + dmic_port_config[0].num = 8; + break; + default: + return -EINVAL; + } } else return -EINVAL; } @@ -1228,10 +1500,21 @@ static int rt1320_sdw_hw_params(struct snd_pcm_substream *substream, if (dai->id == RT1320_AIF1) retval = sdw_stream_add_slave(rt1320->sdw_slave, &stream_config, &port_config, 1, sdw_stream); - else if (dai->id == RT1320_AIF2) - retval = sdw_stream_add_slave(rt1320->sdw_slave, &stream_config, + else if (dai->id == RT1320_AIF2) { + switch (rt1320->dev_id) { + case RT1320_DEV_ID: + retval = sdw_stream_add_slave(rt1320->sdw_slave, &stream_config, dmic_port_config, 2, sdw_stream); - else + break; + case RT1321_DEV_ID: + retval = sdw_stream_add_slave(rt1320->sdw_slave, &stream_config, + dmic_port_config, 1, sdw_stream); + break; + default: + dev_err(dai->dev, "%s: Unknown device ID %d\n", __func__, rt1320->dev_id); + return -EINVAL; + } + } else return -EINVAL; if (retval) { dev_err(dai->dev, "%s: Unable to configure port\n", __func__); @@ -1273,9 +1556,11 @@ static int rt1320_sdw_hw_params(struct snd_pcm_substream *substream, regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), sampling_rate); - regmap_write(rt1320->regmap, - SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), - sampling_rate); + + if (rt1320->dev_id == RT1320_DEV_ID) + regmap_write(rt1320->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), + sampling_rate); } return 0; @@ -1469,6 +1754,7 @@ static int rt1320_sdw_remove(struct sdw_slave *slave) static const struct sdw_device_id rt1320_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x1320, 0x3, 0x0, 0), SDW_SLAVE_ENTRY_EXT(0x025d, 0x1320, 0x3, 0x1, 0), + SDW_SLAVE_ENTRY_EXT(0x025d, 0x1321, 0x3, 0x1, 0), {}, }; MODULE_DEVICE_TABLE(sdw, rt1320_id); diff --git a/sound/soc/codecs/rt1320-sdw.h b/sound/soc/codecs/rt1320-sdw.h index 23b321aee6a9..a6d90e259dc9 100644 --- a/sound/soc/codecs/rt1320-sdw.h +++ b/sound/soc/codecs/rt1320-sdw.h @@ -14,8 +14,16 @@ #include <linux/soundwire/sdw_registers.h> #include <sound/soc.h> +#define RT1320_DEV_ID 0x6981 +#define RT1321_DEV_ID 0x7045 + /* imp-defined registers */ #define RT1320_DEV_VERSION_ID_1 0xc404 +#define RT1320_DEV_ID_1 0xc405 +#define RT1320_DEV_ID_0 0xc406 + +#define RT1321_PATCH_MAIN_VER 0x1000cffe +#define RT1321_PATCH_BETA_VER 0x1000cfff #define RT1320_KR0_STATUS_CNT 0x1000f008 #define RT1320_KR0_INT_READY 0x1000f021 @@ -86,6 +94,7 @@ enum rt1320_version_id { #define RT1320_VER_B_ID 0x07392238 #define RT1320_VAB_MCU_PATCH "realtek/rt1320/rt1320-patch-code-vab.bin" #define RT1320_VC_MCU_PATCH "realtek/rt1320/rt1320-patch-code-vc.bin" +#define RT1321_VA_MCU_PATCH "realtek/rt1320/rt1321-patch-code-va.bin" struct rt1320_sdw_priv { struct snd_soc_component *component; @@ -96,6 +105,7 @@ struct rt1320_sdw_priv { bool hw_init; bool first_hw_init; int version_id; + unsigned int dev_id; bool fu_dapm_mute; bool fu_mixer_mute[4]; }; diff --git a/sound/soc/codecs/rt721-sdca-sdw.c b/sound/soc/codecs/rt721-sdca-sdw.c index 582b47d69278..4d8a12b13015 100644 --- a/sound/soc/codecs/rt721-sdca-sdw.c +++ b/sound/soc/codecs/rt721-sdca-sdw.c @@ -63,15 +63,14 @@ static bool rt721_sdca_volatile_register(struct device *dev, unsigned int reg) static bool rt721_sdca_mbq_readable_register(struct device *dev, unsigned int reg) { switch (reg) { - case 0x0900007: + case 0x0900004 ... 0x0900009: case 0x0a00005: case 0x0c00005: case 0x0d00014: case 0x0310100: - case 0x2000001: - case 0x2000002: - case 0x2000003: + case 0x2000000 ... 0x2000003: case 0x2000013: + case 0x200002c: case 0x200003c: case 0x2000046: case 0x5810000: @@ -134,6 +133,8 @@ static bool rt721_sdca_mbq_volatile_register(struct device *dev, unsigned int re { switch (reg) { case 0x0310100: + case 0x0900005: + case 0x0900009: case 0x0a00005: case 0x0c00005: case 0x0d00014: @@ -141,6 +142,7 @@ static bool rt721_sdca_mbq_volatile_register(struct device *dev, unsigned int re case 0x200000d: case 0x2000019: case 0x2000020: + case 0x200002c: case 0x2000030: case 0x2000046: case 0x2000067: diff --git a/sound/soc/codecs/tas2781-comlib-i2c.c b/sound/soc/codecs/tas2781-comlib-i2c.c index c078bb0a8437..b3fd7350143b 100644 --- a/sound/soc/codecs/tas2781-comlib-i2c.c +++ b/sound/soc/codecs/tas2781-comlib-i2c.c @@ -320,6 +320,8 @@ void tasdevice_reset(struct tasdevice_priv *tas_dev) for (i = 0; i < tas_dev->ndev; i++) { ret = tasdevice_dev_write(tas_dev, i, TASDEVICE_REG_SWRESET, + tas_dev->chip_id >= TAS5825 ? + TAS5825_REG_SWRESET_RESET : TASDEVICE_REG_SWRESET_RESET); if (ret < 0) dev_err(tas_dev->dev, diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c index c9c1e608ddb7..78fd0a5dc6f2 100644 --- a/sound/soc/codecs/tas2781-fmwlib.c +++ b/sound/soc/codecs/tas2781-fmwlib.c @@ -91,7 +91,7 @@ struct blktyp_devidx_map { }; static const char deviceNumber[TASDEVICE_DSP_TAS_MAX_DEVICE] = { - 1, 2, 1, 2, 1, 1, 0, 2, 4, 3, 1, 2, 3, 4 + 1, 2, 1, 2, 1, 1, 0, 2, 4, 3, 1, 2, 3, 4, 1, 2 }; /* fixed m68k compiling issue: mapping table can save code field */ @@ -180,6 +180,16 @@ static struct tasdevice_config_info *tasdevice_add_config( dev_err(tas_priv->dev, "add conf: Out of boundary\n"); goto out; } + /* If in the RCA bin file are several profiles with the + * keyword "init", init_profile_id only store the last + * init profile id. + */ + if (strnstr(&config_data[config_offset], "init", 64)) { + tas_priv->rcabin.init_profile_id = + tas_priv->rcabin.ncfgs - 1; + dev_dbg(tas_priv->dev, "%s: init profile id = %d\n", + __func__, tas_priv->rcabin.init_profile_id); + } config_offset += 64; } @@ -283,6 +293,8 @@ int tasdevice_rca_parser(void *context, const struct firmware *fmw) int i; rca = &(tas_priv->rcabin); + /* Initialize to none */ + rca->init_profile_id = -1; fw_hdr = &(rca->fw_hdr); if (!fmw || !fmw->data) { dev_err(tas_priv->dev, "Failed to read %s\n", @@ -509,6 +521,56 @@ out: return offset; } +static int fw_parse_tas5825_program_data_kernel( + struct tasdevice_priv *tas_priv, struct tasdevice_fw *tas_fmw, + const struct firmware *fmw, int offset) +{ + struct tasdevice_prog *program; + unsigned int i; + + for (i = 0; i < tas_fmw->nr_programs; i++) { + program = &(tas_fmw->programs[i]); + if (offset + 72 > fmw->size) { + dev_err(tas_priv->dev, "%s: mpName error\n", __func__); + return -EINVAL; + } + /* Skip 65 unused byts*/ + offset += 65; + offset = fw_parse_data_kernel(tas_fmw, &(program->dev_data), + fmw, offset); + if (offset < 0) + return offset; + } + + return offset; +} + +static int fw_parse_tas5825_configuration_data_kernel( + struct tasdevice_priv *tas_priv, + struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset) +{ + const unsigned char *data = fmw->data; + struct tasdevice_config *config; + unsigned int i; + + for (i = 0; i < tas_fmw->nr_configurations; i++) { + config = &(tas_fmw->configs[i]); + if (offset + 80 > fmw->size) { + dev_err(tas_priv->dev, "%s: mpName error\n", __func__); + return -EINVAL; + } + memcpy(config->name, &data[offset], 64); + /* Skip extra 8 bytes*/ + offset += 72; + offset = fw_parse_data_kernel(tas_fmw, &(config->dev_data), + fmw, offset); + if (offset < 0) + return offset; + } + + return offset; +} + static int fw_parse_program_data_kernel( struct tasdevice_priv *tas_priv, struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset) @@ -1826,7 +1888,8 @@ static void dspbin_type_check(struct tasdevice_priv *tas_priv, else tas_priv->dspbin_typ = TASDEV_ALPHA; } - if (tas_priv->dspbin_typ != TASDEV_BASIC) + if ((tas_priv->dspbin_typ != TASDEV_BASIC) && + (ppcver < PPC3_VERSION_TAS5825_BASE)) tas_priv->fw_parse_fct_param_address = fw_parse_fct_param_address; } @@ -1837,7 +1900,17 @@ static int dspfw_default_callback(struct tasdevice_priv *tas_priv, int rc = 0; if (drv_ver == 0x100) { - if (ppcver >= PPC3_VERSION_BASE) { + if (ppcver >= PPC3_VERSION_TAS5825_BASE) { + tas_priv->fw_parse_variable_header = + fw_parse_variable_header_kernel; + tas_priv->fw_parse_program_data = + fw_parse_tas5825_program_data_kernel; + tas_priv->fw_parse_configuration_data = + fw_parse_tas5825_configuration_data_kernel; + tas_priv->tasdevice_load_block = + tasdevice_load_block_kernel; + dspbin_type_check(tas_priv, ppcver); + } else if (ppcver >= PPC3_VERSION_BASE) { tas_priv->fw_parse_variable_header = fw_parse_variable_header_kernel; tas_priv->fw_parse_program_data = diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c index 0e09d794516f..1539b70881d1 100644 --- a/sound/soc/codecs/tas2781-i2c.c +++ b/sound/soc/codecs/tas2781-i2c.c @@ -30,8 +30,10 @@ #include <sound/tas2781.h> #include <sound/tas2781-comlib-i2c.h> #include <sound/tlv.h> +#include <sound/tas2x20-tlv.h> #include <sound/tas2563-tlv.h> #include <sound/tas2781-tlv.h> +#include <sound/tas5825-tlv.h> #include <linux/unaligned.h> #define X2563_CL_STT_VAL(xreg, xval) \ @@ -98,16 +100,32 @@ static const struct bulk_reg_val tas2781_cali_start_reg[] = { }; static const struct i2c_device_id tasdevice_id[] = { + { "tas2020", TAS2020 }, + { "tas2118", TAS2118 }, + { "tas2120", TAS2120 }, + { "tas2320", TAS2320 }, { "tas2563", TAS2563 }, + { "tas2570", TAS2570 }, + { "tas2572", TAS2572 }, { "tas2781", TAS2781 }, + { "tas5825", TAS5825 }, + { "tas5827", TAS5827 }, {} }; MODULE_DEVICE_TABLE(i2c, tasdevice_id); #ifdef CONFIG_OF static const struct of_device_id tasdevice_of_match[] = { + { .compatible = "ti,tas2020" }, + { .compatible = "ti,tas2118" }, + { .compatible = "ti,tas2120" }, + { .compatible = "ti,tas2320" }, { .compatible = "ti,tas2563" }, + { .compatible = "ti,tas2570" }, + { .compatible = "ti,tas2572" }, { .compatible = "ti,tas2781" }, + { .compatible = "ti,tas5825" }, + { .compatible = "ti,tas5827" }, {}, }; MODULE_DEVICE_TABLE(of, tasdevice_of_match); @@ -797,7 +815,7 @@ static int tasdev_nop_get( return 0; } -static int tas2563_digital_gain_get( +static int tasdevice_digital_gain_get( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -823,15 +841,15 @@ static int tas2563_digital_gain_get( while (r > 1 + l) { mid = (l + r) / 2; - ar_mid = get_unaligned_be32(tas2563_dvc_table[mid]); + ar_mid = get_unaligned_be32(tas_dev->dvc_tlv_table[mid]); if (target < ar_mid) r = mid; else l = mid; } - ar_l = get_unaligned_be32(tas2563_dvc_table[l]); - ar_r = get_unaligned_be32(tas2563_dvc_table[r]); + ar_l = get_unaligned_be32(tas_dev->dvc_tlv_table[l]); + ar_r = get_unaligned_be32(tas_dev->dvc_tlv_table[r]); /* find out the member same as or closer to the current volume */ ucontrol->value.integer.value[0] = @@ -841,7 +859,7 @@ out: return 0; } -static int tas2563_digital_gain_put( +static int tasdevice_digital_gain_put( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -867,7 +885,7 @@ static int tas2563_digital_gain_put( } volrd = get_unaligned_be32(&data[0]); - volwr = get_unaligned_be32(tas2563_dvc_table[vol]); + volwr = get_unaligned_be32(tas_dev->dvc_tlv_table[vol]); if (volrd == volwr) { rc = 0; @@ -876,7 +894,7 @@ static int tas2563_digital_gain_put( for (i = 0; i < tas_dev->ndev; i++) { ret = tasdevice_dev_bulk_write(tas_dev, i, reg, - (unsigned char *)tas2563_dvc_table[vol], 4); + (unsigned char *)tas_dev->dvc_tlv_table[vol], 4); if (ret) { dev_err(tas_dev->dev, "%s, set digital vol error in dev %d\n", @@ -892,11 +910,6 @@ out: return rc; } -static const struct snd_kcontrol_new tasdevice_snd_controls[] = { - SOC_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0, - tasdev_force_fwload_get, tasdev_force_fwload_put), -}; - static const struct snd_kcontrol_new tasdevice_cali_controls[] = { SOC_SINGLE_EXT("Calibration Stop", SND_SOC_NOPM, 0, 1, 0, tasdev_nop_get, tasdev_calib_stop_put), @@ -907,6 +920,16 @@ static const struct snd_kcontrol_new tasdevice_cali_controls[] = { SND_SOC_BYTES_EXT("Amp XMA2 Data", 6, tasdev_XMA2_data_get, NULL), }; +static const struct snd_kcontrol_new tas2x20_snd_controls[] = { + SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS2X20_AMP_LEVEL, + 0, 0, 42, 1, tas2781_amp_getvol, + tas2781_amp_putvol, tas2x20_amp_tlv), + SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS2X20_DVC_LEVEL, + 0, 0, ARRAY_SIZE(tas2x20_dvc_table) - 1, 0, + tasdevice_digital_gain_get, tasdevice_digital_gain_put, + tas2x20_dvc_tlv), +}; + static const struct snd_kcontrol_new tas2781_snd_controls[] = { SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS2781_AMP_LEVEL, 1, 0, 20, 0, tas2781_amp_getvol, @@ -916,6 +939,15 @@ static const struct snd_kcontrol_new tas2781_snd_controls[] = { tas2781_digital_putvol, tas2781_dvc_tlv), }; +static const struct snd_kcontrol_new tas5825_snd_controls[] = { + SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS5825_AMP_LEVEL, + 0, 0, 31, 1, tas2781_amp_getvol, + tas2781_amp_putvol, tas5825_amp_tlv), + SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS5825_DVC_LEVEL, + 0, 0, 254, 1, tas2781_amp_getvol, + tas2781_amp_putvol, tas5825_dvc_tlv), +}; + static const struct snd_kcontrol_new tas2781_cali_controls[] = { SND_SOC_BYTES_EXT("Amp Latch Data", 3, tas2781_latch_reg_get, NULL), }; @@ -923,7 +955,7 @@ static const struct snd_kcontrol_new tas2781_cali_controls[] = { static const struct snd_kcontrol_new tas2563_snd_controls[] = { SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS2563_DVC_LVL, 0, 0, ARRAY_SIZE(tas2563_dvc_table) - 1, 0, - tas2563_digital_gain_get, tas2563_digital_gain_put, + tasdevice_digital_gain_get, tasdevice_digital_gain_put, tas2563_dvc_tlv), }; @@ -968,8 +1000,8 @@ static int tasdevice_info_chip_id(struct snd_kcontrol *kcontrol, { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; - uinfo->value.integer.min = TAS2563; - uinfo->value.integer.max = TAS2781; + uinfo->value.integer.min = TAS2020; + uinfo->value.integer.max = TAS_OTHERS; return 0; } @@ -1168,9 +1200,9 @@ static int tasdevice_active_num_put(struct snd_kcontrol *kcontrol, static int tasdevice_dsp_create_ctrls(struct tasdevice_priv *tas_priv) { struct snd_kcontrol_new *dsp_ctrls; - char *active_dev_num, *chip_id; + char *active_dev_num, *chip_id, *fw_load; char *conf_name, *prog_name; - int nr_controls = 4; + int nr_controls = 5; int mix_index = 0; /* Alloc kcontrol via devm_kzalloc, which don't manually @@ -1228,6 +1260,19 @@ static int tasdevice_dsp_create_ctrls(struct tasdevice_priv *tas_priv) dsp_ctrls[mix_index].get = tasdevice_get_chip_id; mix_index++; + fw_load = devm_kstrdup(tas_priv->dev, "Speaker Force Firmware Load", + GFP_KERNEL); + if (!fw_load) + return -ENOMEM; + + dsp_ctrls[mix_index].name = fw_load; + dsp_ctrls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER; + dsp_ctrls[mix_index].info = snd_soc_info_bool_ext; + dsp_ctrls[mix_index].put = tasdev_force_fwload_put; + dsp_ctrls[mix_index].get = tasdev_force_fwload_get; + dsp_ctrls[mix_index].private_value = 0UL; + mix_index++; + return snd_soc_add_component_controls(tas_priv->codec, dsp_ctrls, nr_controls < mix_index ? nr_controls : mix_index); } @@ -1587,6 +1632,16 @@ static void tasdevice_fw_ready(const struct firmware *fmw, * failing to load DSP firmware is NOT an error. */ tas_priv->fw_state = TASDEVICE_RCA_FW_OK; + /* There is no DSP firmware required for TAS2118/2X20/257X. */ + switch (tas_priv->chip_id) { + case TAS2020: + case TAS2118: + case TAS2120: + case TAS2320: + case TAS2570: + case TAS2572: + goto out; + } if (tas_priv->name_prefix) scnprintf(tas_priv->coef_binaryname, 64, "%s-%s_coef.bin", tas_priv->name_prefix, tas_priv->dev_name); @@ -1608,39 +1663,48 @@ static void tasdevice_fw_ready(const struct firmware *fmw, dev_err(tas_priv->dev, "dsp controls error\n"); goto out; } - - ret = tasdevice_create_cali_ctrls(tas_priv); - if (ret) { - dev_err(tas_priv->dev, "cali controls error\n"); - goto out; - } - tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK; - /* If calibrated data occurs error, dsp will still works with default - * calibrated data inside algo. - */ - for (i = 0; i < tas_priv->ndev; i++) { - if (tas_priv->name_prefix) - scnprintf(tas_priv->cal_binaryname[i], 64, - "%s-%s_cal_0x%02x.bin", tas_priv->name_prefix, - tas_priv->dev_name, - tas_priv->tasdevice[i].dev_addr); - else - scnprintf(tas_priv->cal_binaryname[i], 64, - "%s_cal_0x%02x.bin", tas_priv->dev_name, - tas_priv->tasdevice[i].dev_addr); - ret = tas2781_load_calibration(tas_priv, - tas_priv->cal_binaryname[i], i); - if (ret != 0) - dev_err(tas_priv->dev, - "%s: load %s error, default will effect\n", - __func__, tas_priv->cal_binaryname[i]); + /* There is no calibration required for TAS5825/TAS5827. */ + if (tas_priv->chip_id < TAS5825) { + ret = tasdevice_create_cali_ctrls(tas_priv); + if (ret) { + dev_err(tas_priv->dev, "cali controls error\n"); + goto out; + } + /* If calibrated data occurs error, dsp will still works + * with default calibrated data inside algo. + */ + for (i = 0; i < tas_priv->ndev; i++) { + if (tas_priv->name_prefix) + scnprintf(tas_priv->cal_binaryname[i], 64, + "%s-%s_cal_0x%02x.bin", + tas_priv->name_prefix, + tas_priv->dev_name, + tas_priv->tasdevice[i].dev_addr); + else + scnprintf(tas_priv->cal_binaryname[i], 64, + "%s_cal_0x%02x.bin", + tas_priv->dev_name, + tas_priv->tasdevice[i].dev_addr); + ret = tas2781_load_calibration(tas_priv, + tas_priv->cal_binaryname[i], i); + if (ret != 0) + dev_err(tas_priv->dev, + "%s: load %s error, keep default.\n", + __func__, tas_priv->cal_binaryname[i]); + } } tasdevice_prmg_load(tas_priv, 0); tas_priv->cur_prog = 0; + /* Init common setting for different audio profiles */ + if (tas_priv->rcabin.init_profile_id >= 0) + tasdevice_select_cfg_blk(tas_priv, + tas_priv->rcabin.init_profile_id, + TASDEVICE_BIN_BLK_PRE_POWER_UP); + #ifdef CONFIG_SND_SOC_TAS2781_ACOUST_I2C if (tas_priv->name_prefix) acoustic_debugfs_node = devm_kasprintf(tas_priv->dev, @@ -1653,8 +1717,14 @@ static void tasdevice_fw_ready(const struct firmware *fmw, #endif out: if (tas_priv->fw_state == TASDEVICE_RCA_FW_OK) { - /* If DSP FW fail, DSP kcontrol won't be created. */ - tasdevice_dsp_remove(tas_priv); + switch (tas_priv->chip_id) { + case TAS2563: + case TAS2781: + case TAS5825: + case TAS5827: + /* If DSP FW fail, DSP kcontrol won't be created. */ + tasdevice_dsp_remove(tas_priv); + } } mutex_unlock(&tas_priv->codec_lock); release_firmware(fmw); @@ -1798,13 +1868,30 @@ static int tasdevice_codec_probe(struct snd_soc_component *codec) int rc; switch (tas_priv->chip_id) { + case TAS2020: + case TAS2118: + case TAS2120: + case TAS2320: + case TAS2570: + case TAS2572: + p = (struct snd_kcontrol_new *)tas2x20_snd_controls; + size = ARRAY_SIZE(tas2x20_snd_controls); + tas_priv->dvc_tlv_table = tas2x20_dvc_table; + break; case TAS2781: p = (struct snd_kcontrol_new *)tas2781_snd_controls; size = ARRAY_SIZE(tas2781_snd_controls); break; + case TAS5825: + case TAS5827: + p = (struct snd_kcontrol_new *)tas5825_snd_controls; + size = ARRAY_SIZE(tas5825_snd_controls); + break; default: p = (struct snd_kcontrol_new *)tas2563_snd_controls; size = ARRAY_SIZE(tas2563_snd_controls); + tas_priv->dvc_tlv_table = tas2563_dvc_table; + break; } rc = snd_soc_add_component_controls(codec, p, size); @@ -1844,8 +1931,6 @@ static const struct snd_soc_component_driver soc_codec_driver_tasdevice = { .probe = tasdevice_codec_probe, .remove = tasdevice_codec_remove, - .controls = tasdevice_snd_controls, - .num_controls = ARRAY_SIZE(tasdevice_snd_controls), .dapm_widgets = tasdevice_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(tasdevice_dapm_widgets), .dapm_routes = tasdevice_audio_map, @@ -1961,7 +2046,16 @@ static void tasdevice_i2c_remove(struct i2c_client *client) #ifdef CONFIG_ACPI static const struct acpi_device_id tasdevice_acpi_match[] = { - { "TAS2781", TAS2781 }, + { "TXNW2020", TAS2020 }, + { "TXNW2118", TAS2118 }, + { "TXNW2120", TAS2120 }, + { "TXNW2320", TAS2320 }, + { "TXNW2563", TAS2563 }, + { "TXNW2570", TAS2570 }, + { "TXNW2572", TAS2572 }, + { "TXNW2781", TAS2781 }, + { "TXNW5825", TAS5825 }, + { "TXNW5827", TAS5827 }, {}, }; diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c new file mode 100644 index 000000000000..1fb4227b711e --- /dev/null +++ b/sound/soc/codecs/tas2783-sdw.c @@ -0,0 +1,1331 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// ALSA SoC Texas Instruments TAS2783 Audio Smart Amplifier +// +// Copyright (C) 2025 Texas Instruments Incorporated +// https://www.ti.com +// +// The TAS2783 driver implements a flexible and configurable +// algo coefficient setting for single TAS2783 chips. +// +// Author: Niranjan H Y <niranjanhy@ti.com> +// Author: Baojun Xu <baojun.xu@ti.com> +// Author: Kevin Lu <kevin-lu@ti.com> + +#include <linux/unaligned.h> +#include <linux/crc32.h> +#include <linux/efi.h> +#include <linux/err.h> +#include <linux/firmware.h> +#include <linux/init.h> +#include <linux/module.h> +#include <sound/pcm_params.h> +#include <linux/pm.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/wait.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_registers.h> +#include <linux/soundwire/sdw_type.h> +#include <sound/sdw.h> +#include <sound/soc.h> +#include <sound/tlv.h> +#include <sound/tas2781-tlv.h> + +#include "tas2783.h" + +#define TIMEOUT_FW_DL_MS (3000) +#define FW_DL_OFFSET 36 +#define FW_FL_HDR 12 +#define TAS2783_PROBE_TIMEOUT 5000 +#define TAS2783_CALI_GUID EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, \ + 0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92) + +static const u32 tas2783_cali_reg[] = { + TAS2783_CAL_R0, + TAS2783_CAL_INVR0, + TAS2783_CAL_R0LOW, + TAS2783_CAL_POWER, + TAS2783_CAL_TLIM, +}; + +struct bin_header_t { + u16 vendor_id; + u16 version; + u32 file_id; + u32 length; +}; + +struct calibration_data { + u32 is_valid; + unsigned long read_sz; + u8 data[TAS2783_CALIB_DATA_SZ]; +}; + +struct tas2783_prv { + struct snd_soc_component *component; + struct calibration_data cali_data; + struct sdw_slave *sdw_peripheral; + enum sdw_slave_status status; + /* calibration */ + struct mutex calib_lock; + /* pde and firmware download */ + struct mutex pde_lock; + struct regmap *regmap; + struct device *dev; + struct class *class; + struct attribute_group *cal_attr_groups; + struct tm tm; + u8 rca_binaryname[64]; + u8 dev_name[32]; + bool hw_init; + /* wq for firmware download */ + wait_queue_head_t fw_wait; + bool fw_dl_task_done; + bool fw_dl_success; +}; + +static const struct reg_default tas2783_reg_default[] = { + {TAS2783_AMP_LEVEL, 0x28}, + {TASDEV_REG_SDW(0, 0, 0x03), 0x28}, + {TASDEV_REG_SDW(0, 0, 0x04), 0x21}, + {TASDEV_REG_SDW(0, 0, 0x05), 0x41}, + {TASDEV_REG_SDW(0, 0, 0x06), 0x00}, + {TASDEV_REG_SDW(0, 0, 0x07), 0x20}, + {TASDEV_REG_SDW(0, 0, 0x08), 0x09}, + {TASDEV_REG_SDW(0, 0, 0x09), 0x02}, + {TASDEV_REG_SDW(0, 0, 0x0a), 0x0a}, + {TASDEV_REG_SDW(0, 0, 0x0c), 0x10}, + {TASDEV_REG_SDW(0, 0, 0x0d), 0x13}, + {TASDEV_REG_SDW(0, 0, 0x0e), 0xc2}, + {TASDEV_REG_SDW(0, 0, 0x0f), 0x40}, + {TASDEV_REG_SDW(0, 0, 0x10), 0x04}, + {TASDEV_REG_SDW(0, 0, 0x13), 0x13}, + {TASDEV_REG_SDW(0, 0, 0x14), 0x12}, + {TASDEV_REG_SDW(0, 0, 0x15), 0x00}, + {TASDEV_REG_SDW(0, 0, 0x16), 0x12}, + {TASDEV_REG_SDW(0, 0, 0x17), 0x80}, + {TAS2783_DVC_LVL, 0x00}, + {TASDEV_REG_SDW(0, 0, 0x1b), 0x61}, + {TASDEV_REG_SDW(0, 0, 0x1c), 0x36}, + {TASDEV_REG_SDW(0, 0, 0x1d), 0x00}, + {TASDEV_REG_SDW(0, 0, 0x1f), 0x01}, + {TASDEV_REG_SDW(0, 0, 0x20), 0x2e}, + {TASDEV_REG_SDW(0, 0, 0x21), 0x00}, + {TASDEV_REG_SDW(0, 0, 0x34), 0x06}, + {TASDEV_REG_SDW(0, 0, 0x35), 0xbd}, + {TASDEV_REG_SDW(0, 0, 0x36), 0xad}, + {TASDEV_REG_SDW(0, 0, 0x37), 0xa8}, + {TASDEV_REG_SDW(0, 0, 0x38), 0x00}, + {TASDEV_REG_SDW(0, 0, 0x3b), 0xfc}, + {TASDEV_REG_SDW(0, 0, 0x3d), 0xdd}, + {TASDEV_REG_SDW(0, 0, 0x40), 0xf6}, + {TASDEV_REG_SDW(0, 0, 0x41), 0x14}, + {TASDEV_REG_SDW(0, 0, 0x5c), 0x19}, + {TASDEV_REG_SDW(0, 0, 0x5d), 0x80}, + {TASDEV_REG_SDW(0, 0, 0x63), 0x48}, + {TASDEV_REG_SDW(0, 0, 0x65), 0x08}, + {TASDEV_REG_SDW(0, 0, 0x66), 0xb2}, + {TASDEV_REG_SDW(0, 0, 0x67), 0x00}, + {TASDEV_REG_SDW(0, 0, 0x6a), 0x12}, + {TASDEV_REG_SDW(0, 0, 0x6b), 0xfb}, + {TASDEV_REG_SDW(0, 0, 0x6c), 0x00}, + {TASDEV_REG_SDW(0, 0, 0x6d), 0x00}, + {TASDEV_REG_SDW(0, 0, 0x6e), 0x1a}, + {TASDEV_REG_SDW(0, 0, 0x6f), 0x00}, + {TASDEV_REG_SDW(0, 0, 0x70), 0x96}, + {TASDEV_REG_SDW(0, 0, 0x71), 0x02}, + {TASDEV_REG_SDW(0, 0, 0x73), 0x08}, + {TASDEV_REG_SDW(0, 0, 0x75), 0xe0}, + {TASDEV_REG_SDW(0, 0, 0x7a), 0x60}, + {TASDEV_REG_SDW(0, 0, 0x60), 0x21}, + {TASDEV_REG_SDW(0, 1, 0x02), 0x00}, + {TASDEV_REG_SDW(0, 1, 0x17), 0xc0}, + {TASDEV_REG_SDW(0, 1, 0x19), 0x60}, + {TASDEV_REG_SDW(0, 1, 0x35), 0x75}, + {TASDEV_REG_SDW(0, 1, 0x3d), 0x00}, + {TASDEV_REG_SDW(0, 1, 0x3e), 0x00}, + {TASDEV_REG_SDW(0, 1, 0x3f), 0x00}, + {TASDEV_REG_SDW(0, 1, 0x40), 0x00}, + {TASDEV_REG_SDW(0, 1, 0x41), 0x00}, + {TASDEV_REG_SDW(0, 1, 0x42), 0x00}, + {TASDEV_REG_SDW(0, 1, 0x43), 0x00}, + {TASDEV_REG_SDW(0, 1, 0x44), 0x00}, + {TASDEV_REG_SDW(0, 1, 0x45), 0x00}, + {TASDEV_REG_SDW(0, 1, 0x47), 0xab}, + {TASDEV_REG_SDW(0, 0xfd, 0x0d), 0x0d}, + {TASDEV_REG_SDW(0, 0xfd, 0x39), 0x00}, + {TASDEV_REG_SDW(0, 0xfd, 0x3e), 0x00}, + {TASDEV_REG_SDW(0, 0xfd, 0x45), 0x00}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS21, 0x02, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS21, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS24, 0x02, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS24, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS26, 0x02, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS26, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS28, 0x02, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS28, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS127, 0x02, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS127, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, 0x01, 1), 0x1}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, 0x02, 1), 0x9c00}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x01, 0), 0x1}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x01, 1), 0x1}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x0b, 1), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x01, 1), 0x1}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x01, 0), 0x1}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x0b, 1), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 0), 0x1}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 1), 0x1}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 2), 0x1}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 1), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 2), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x04, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x08, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x11, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x04, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x08, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x11, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x04, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x08, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x11, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x04, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x08, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x11, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x01, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x04, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x05, 0), 0x1}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x08, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x11, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x12, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x01, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x04, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x05, 0), 0x1}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x08, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x11, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x12, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 1), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 2), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 3), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 4), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 5), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 6), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 7), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x06, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT23, 0x04, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT23, 0x08, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x04, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x08, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x11, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x04, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x08, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x11, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x04, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x08, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x11, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x04, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x08, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x11, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 1), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 2), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 3), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 4), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 5), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 6), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 7), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 8), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 9), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xa), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xb), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xc), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xd), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xe), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xf), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 0x1, 0), 0x3}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 0x10, 0), 0x3}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x06, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x11, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x12, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x13, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x06, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x11, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x12, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x13, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x05, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x10, 0), 0x1}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x11, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x12, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_TG23, 0x10, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x01, 0), 0x1}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x06, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x07, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x08, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x09, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x0a, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x10, 0), 0x1}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x12, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x13, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x14, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x15, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x16, 0), 0x0}, + {SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_UDMPU23, 0x10, 0), 0x0}, +}; + +static const struct reg_sequence tas2783_init_seq[] = { + REG_SEQ0(SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x10, 0x00), 0x04), + REG_SEQ0(0x00800418, 0x00), + REG_SEQ0(0x00800419, 0x00), + REG_SEQ0(0x0080041a, 0x00), + REG_SEQ0(0x0080041b, 0x00), + REG_SEQ0(0x00800428, 0x40), + REG_SEQ0(0x00800429, 0x00), + REG_SEQ0(0x0080042a, 0x00), + REG_SEQ0(0x0080042b, 0x00), + REG_SEQ0(SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x1, 0x00), 0x00), + REG_SEQ0(0x0080005c, 0xD9), + REG_SEQ0(0x00800082, 0x20), + REG_SEQ0(0x008000a1, 0x00), + REG_SEQ0(0x00800097, 0xc8), + REG_SEQ0(0x00800099, 0x20), + REG_SEQ0(0x008000c7, 0xaa), + REG_SEQ0(0x008000b5, 0x74), + REG_SEQ0(0x00800082, 0x20), + REG_SEQ0(0x00807e8d, 0x0d), + REG_SEQ0(0x00807eb9, 0x53), + REG_SEQ0(0x00807ebe, 0x42), + REG_SEQ0(0x00807ec5, 0x37), + REG_SEQ0(0x00800066, 0x92), + REG_SEQ0(0x00800003, 0x28), + REG_SEQ0(0x00800004, 0x21), + REG_SEQ0(0x00800005, 0x41), + REG_SEQ0(0x00800006, 0x00), + REG_SEQ0(0x00800007, 0x20), + REG_SEQ0(0x0080000c, 0x10), + REG_SEQ0(0x00800013, 0x08), + REG_SEQ0(0x00800015, 0x00), + REG_SEQ0(0x00800017, 0x80), + REG_SEQ0(0x0080001a, 0x00), + REG_SEQ0(0x0080001b, 0x22), + REG_SEQ0(0x0080001c, 0x36), + REG_SEQ0(0x0080001d, 0x01), + REG_SEQ0(0x0080001f, 0x00), + REG_SEQ0(0x00800020, 0x2e), + REG_SEQ0(0x00800034, 0x06), + REG_SEQ0(0x00800035, 0xb9), + REG_SEQ0(0x00800036, 0xad), + REG_SEQ0(0x00800037, 0xa8), + REG_SEQ0(0x00800038, 0x00), + REG_SEQ0(0x0080003b, 0xfc), + REG_SEQ0(0x0080003d, 0xdd), + REG_SEQ0(0x00800040, 0xf6), + REG_SEQ0(0x00800041, 0x14), + REG_SEQ0(0x0080005c, 0x19), + REG_SEQ0(0x0080005d, 0x80), + REG_SEQ0(0x00800063, 0x48), + REG_SEQ0(0x00800065, 0x08), + REG_SEQ0(0x00800067, 0x00), + REG_SEQ0(0x0080006a, 0x12), + REG_SEQ0(0x0080006b, 0x7b), + REG_SEQ0(0x0080006c, 0x00), + REG_SEQ0(0x0080006d, 0x00), + REG_SEQ0(0x0080006e, 0x1a), + REG_SEQ0(0x0080006f, 0x00), + REG_SEQ0(0x00800070, 0x96), + REG_SEQ0(0x00800071, 0x02), + REG_SEQ0(0x00800073, 0x08), + REG_SEQ0(0x00800075, 0xe0), + REG_SEQ0(0x0080007a, 0x60), + REG_SEQ0(0x008000bd, 0x00), + REG_SEQ0(0x008000be, 0x00), + REG_SEQ0(0x008000bf, 0x00), + REG_SEQ0(0x008000c0, 0x00), + REG_SEQ0(0x008000c1, 0x00), + REG_SEQ0(0x008000c2, 0x00), + REG_SEQ0(0x008000c3, 0x00), + REG_SEQ0(0x008000c4, 0x00), + REG_SEQ0(0x008000c5, 0x00), + REG_SEQ0(0x00800008, 0x49), + REG_SEQ0(0x00800009, 0x02), + REG_SEQ0(0x0080000a, 0x1a), + REG_SEQ0(0x0080000d, 0x93), + REG_SEQ0(0x0080000e, 0x82), + REG_SEQ0(0x0080000f, 0x42), + REG_SEQ0(0x00800010, 0x84), + REG_SEQ0(0x00800014, 0x0a), + REG_SEQ0(0x00800016, 0x00), + REG_SEQ0(0x00800060, 0x21), +}; + +static int tas2783_sdca_mbq_size(struct device *dev, u32 reg) +{ + switch (reg) { + case 0x000 ... 0x080: /* Data port 0. */ + case 0x100 ... 0x140: /* Data port 1. */ + case 0x200 ... 0x240: /* Data port 2. */ + case 0x300 ... 0x340: /* Data port 3. */ + case 0x400 ... 0x440: /* Data port 4. */ + case 0x500 ... 0x540: /* Data port 5. */ + case 0x800000 ... 0x803fff: /* Page 0 ~ 127. */ + case 0x807e80 ... 0x807eff: /* Page 253. */ + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_UDMPU23, + TAS2783_SDCA_CTL_UDMPU_CLUSTER, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, TAS2783_SDCA_CTL_FU_MUTE, + TAS2783_DEVICE_CHANNEL_LEFT): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 0x1, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x04, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x11, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x12, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x11, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x11, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_TG23, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x01, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x08, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x0a, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x14, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x15, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x16, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x04, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x04, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x04, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT23, 0x04, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x04, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x04, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x04, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 1): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 2): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 3): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 4): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 5): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 6): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 7): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 8): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 9): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xa): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xb): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xc): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xd): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xe): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x12, 0xf): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS21, 0x02, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS21, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS24, 0x02, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS24, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS25, 0x02, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS25, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS127, 0x02, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS127, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS26, 0x02, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS26, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS28, 0x02, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_CS28, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x01, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x04, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x05, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x11, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 1): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 2): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x01, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x01, 1): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x01, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x01, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x04, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x05, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x11, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x01, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x01, 1): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x04, 0): + return 1; + + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x11, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x11, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x11, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x11, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x11, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x11, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x11, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 1): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 2): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 3): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 4): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 5): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 6): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x01, 7): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, 0x02, 1): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x0b, 1): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 1): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 2): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x0b, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x0b, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x0b, 1): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x07, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x09, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x12, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x12, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x12, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x13, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x12, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x13, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x11, 0): + return 2; + + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT21, 0x08, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT26, 0x08, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT28, 0x08, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_IT29, 0x08, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT23, 0x08, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT24, 0x08, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT25, 0x08, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT28, 0x08, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_OT127, 0x08, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MU26, 0x06, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU127, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU26, 0x10, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x06, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x12, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_XU22, 0x13, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU21, 0x08, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_MFPU26, 0x08, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_SAPU29, 0x05, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x06, 0): + case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU26, 0x06, 0): + return 4; + + default: + return 0; + } +} + +static bool tas2783_readable_register(struct device *dev, unsigned int reg) +{ + return tas2783_sdca_mbq_size(dev, reg) > 0; +} + +static bool tas2783_volatile_register(struct device *dev, u32 reg) +{ + switch (reg) { + case 0x000 ... 0x080: /* Data port 0. */ + case 0x100 ... 0x140: /* Data port 1. */ + case 0x200 ... 0x240: /* Data port 2. */ + case 0x300 ... 0x340: /* Data port 3. */ + case 0x400 ... 0x440: /* Data port 4. */ + case 0x500 ... 0x540: /* Data port 5. */ + case 0x800001: + return true; + + default: + return false; + } +} + +static const struct regmap_config tas_regmap = { + .reg_bits = 32, + .val_bits = 8, + .readable_reg = tas2783_readable_register, + .volatile_reg = tas2783_volatile_register, + .reg_defaults = tas2783_reg_default, + .num_reg_defaults = ARRAY_SIZE(tas2783_reg_default), + .max_register = 0x41008000 + TASDEV_REG_SDW(0xa1, 0x60, 0x7f), + .cache_type = REGCACHE_MAPLE, + .use_single_read = true, + .use_single_write = true, +}; + +static const struct regmap_sdw_mbq_cfg tas2783_mbq_cfg = { + .mbq_size = tas2783_sdca_mbq_size, +}; + +static s32 tas2783_digital_getvol(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return snd_soc_get_volsw(kcontrol, ucontrol); +} + +static s32 tas2783_digital_putvol(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return snd_soc_put_volsw(kcontrol, ucontrol); +} + +static s32 tas2783_amp_getvol(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return snd_soc_get_volsw(kcontrol, ucontrol); +} + +static s32 tas2783_amp_putvol(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return snd_soc_put_volsw(kcontrol, ucontrol); +} + +static const struct snd_kcontrol_new tas2783_snd_controls[] = { + SOC_SINGLE_RANGE_EXT_TLV("Amp Volume", TAS2783_AMP_LEVEL, + 1, 0, 20, 0, tas2783_amp_getvol, + tas2783_amp_putvol, tas2781_amp_tlv), + SOC_SINGLE_RANGE_EXT_TLV("Speaker Volume", TAS2783_DVC_LVL, + 0, 0, 200, 1, tas2783_digital_getvol, + tas2783_digital_putvol, tas2781_dvc_tlv), +}; + +static s32 tas2783_validate_calibdata(struct tas2783_prv *tas_dev, + u8 *data, u32 size) +{ + u32 ts, spk_count, size_calculated; + u32 crc_calculated, crc_read, i; + u32 *tmp_val; + struct tm tm; + + i = 0; + tmp_val = (u32 *)data; + if (tmp_val[i++] != 2783) { + dev_err(tas_dev->dev, "cal data magic number mismatch"); + return -EINVAL; + } + + spk_count = tmp_val[i++]; + if (spk_count > TAS2783_CALIB_MAX_SPK_COUNT) { + dev_err(tas_dev->dev, "cal data spk_count too large"); + return -EINVAL; + } + + ts = tmp_val[i++]; + time64_to_tm(ts, 0, &tm); + dev_dbg(tas_dev->dev, "cal data timestamp: %ld-%d-%d %d:%d:%d", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + + size_calculated = + (spk_count * TAS2783_CALIB_PARAMS * sizeof(u32)) + + TAS2783_CALIB_HDR_SZ + TAS2783_CALIB_CRC_SZ; + if (size_calculated > TAS2783_CALIB_DATA_SZ) { + dev_err(tas_dev->dev, "cali data sz too large"); + return -EINVAL; + } else if (size < size_calculated) { + dev_err(tas_dev->dev, "cali data size mismatch calc=%u vs %d\n", + size, size_calculated); + return -EINVAL; + } + + crc_calculated = crc32(~0, data, + size_calculated - TAS2783_CALIB_CRC_SZ) ^ ~0; + crc_read = tmp_val[(size_calculated - TAS2783_CALIB_CRC_SZ) / sizeof(u32)]; + if (crc_calculated != crc_read) { + dev_err(tas_dev->dev, + "calib data integrity check fail, 0x%08x vs 0x%08x\n", + crc_calculated, crc_read); + return -EINVAL; + } + + return 0; +} + +static void tas2783_set_calib_params_to_device(struct tas2783_prv *tas_dev, u32 *cali_data) +{ + u32 dev_count, offset, i, device_num; + u32 reg_value; + u8 buf[4]; + + dev_count = cali_data[1]; + offset = 3; + + for (device_num = 0; device_num < dev_count; device_num++) { + if (cali_data[offset] != tas_dev->sdw_peripheral->id.unique_id) { + offset += TAS2783_CALIB_PARAMS; + continue; + } + offset++; + + for (i = 0; i < ARRAY_SIZE(tas2783_cali_reg); i++) { + reg_value = cali_data[offset + i]; + buf[0] = reg_value >> 24; + buf[1] = reg_value >> 16; + buf[2] = reg_value >> 8; + buf[3] = reg_value & 0xff; + regmap_bulk_write(tas_dev->regmap, tas2783_cali_reg[i], + buf, sizeof(u32)); + } + break; + } + + if (device_num == dev_count) + dev_err(tas_dev->dev, "device not found\n"); + else + dev_dbg(tas_dev->dev, "calib data update done\n"); +} + +static s32 tas2783_update_calibdata(struct tas2783_prv *tas_dev) +{ + efi_guid_t efi_guid = TAS2783_CALI_GUID; + u32 attr, i, *tmp_val; + unsigned long size; + s32 ret; + efi_status_t status; + static efi_char16_t efi_names[][32] = { + L"SmartAmpCalibrationData", L"CALI_DATA"}; + + tmp_val = (u32 *)tas_dev->cali_data.data; + attr = 0; + i = 0; + + /* + * In some cases, the calibration is performed in Windows, + * and data was saved in UEFI. Linux can access it. + */ + for (i = 0; i < ARRAY_SIZE(efi_names); i++) { + size = 0; + status = efi.get_variable(efi_names[i], &efi_guid, &attr, + &size, NULL); + if (size > TAS2783_CALIB_DATA_SZ) { + dev_err(tas_dev->dev, "cali data too large\n"); + break; + } + + tas_dev->cali_data.read_sz = size; + if (status == EFI_BUFFER_TOO_SMALL) { + status = efi.get_variable(efi_names[i], &efi_guid, &attr, + &tas_dev->cali_data.read_sz, + tas_dev->cali_data.data); + dev_dbg(tas_dev->dev, "cali get %lu bytes result:%ld\n", + tas_dev->cali_data.read_sz, status); + } + if (status == EFI_SUCCESS) + break; + } + + if (status != EFI_SUCCESS) { + /* Failed got calibration data from EFI. */ + dev_dbg(tas_dev->dev, "No calibration data in UEFI."); + return 0; + } + + mutex_lock(&tas_dev->calib_lock); + ret = tas2783_validate_calibdata(tas_dev, tas_dev->cali_data.data, + tas_dev->cali_data.read_sz); + if (!ret) + tas2783_set_calib_params_to_device(tas_dev, tmp_val); + mutex_unlock(&tas_dev->calib_lock); + + return ret; +} + +static s32 read_header(const u8 *data, struct bin_header_t *hdr) +{ + hdr->vendor_id = get_unaligned_le16(&data[0]); + hdr->file_id = get_unaligned_le32(&data[2]); + hdr->version = get_unaligned_le16(&data[6]); + hdr->length = get_unaligned_le32(&data[8]); + return 12; +} + +static void tas2783_fw_ready(const struct firmware *fmw, void *context) +{ + struct tas2783_prv *tas_dev = + (struct tas2783_prv *)context; + const u8 *buf = NULL; + s32 offset = 0, img_sz, file_blk_size, ret; + struct bin_header_t hdr; + + if (!fmw || !fmw->data) { + /* No firmware binary, devices will work in ROM mode. */ + dev_err(tas_dev->dev, + "Failed to read %s, no side-effect on driver running\n", + tas_dev->rca_binaryname); + ret = -EINVAL; + goto out; + } + + mutex_lock(&tas_dev->pde_lock); + img_sz = fmw->size; + buf = fmw->data; + offset += FW_DL_OFFSET; + while (offset < (img_sz - FW_FL_HDR)) { + memset(&hdr, 0, sizeof(hdr)); + offset += read_header(&buf[offset], &hdr); + dev_dbg(tas_dev->dev, + "vndr=%d, file=%d, version=%d, len=%d, off=%d\n", + hdr.vendor_id, hdr.file_id, hdr.version, + hdr.length, offset); + /* size also includes the header */ + file_blk_size = hdr.length - FW_FL_HDR; + + switch (hdr.file_id) { + case 0: + ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral, + PRAM_ADDR_START, file_blk_size, + &buf[offset]); + if (ret < 0) + dev_err(tas_dev->dev, + "PRAM update failed: %d", ret); + break; + + case 1: + ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral, + YRAM_ADDR_START, file_blk_size, + &buf[offset]); + if (ret < 0) + dev_err(tas_dev->dev, + "YRAM update failed: %d", ret); + + break; + + default: + ret = -EINVAL; + dev_err(tas_dev->dev, "Unsupported file"); + break; + } + + if (ret == 0) + offset += file_blk_size; + else + break; + } + mutex_unlock(&tas_dev->pde_lock); + tas2783_update_calibdata(tas_dev); + +out: + if (!ret) + tas_dev->fw_dl_success = true; + tas_dev->fw_dl_task_done = true; + wake_up(&tas_dev->fw_wait); + if (fmw) + release_firmware(fmw); +} + +static inline s32 tas_clear_latch(struct tas2783_prv *priv) +{ + return regmap_update_bits(priv->regmap, + TASDEV_REG_SDW(0, 0, 0x5c), + 0x04, 0x04); +} + +static s32 tas_fu21_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, s32 event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct tas2783_prv *tas_dev = snd_soc_component_get_drvdata(component); + s32 mute; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + mute = 0; + break; + + case SND_SOC_DAPM_PRE_PMD: + mute = 1; + break; + } + + return sdw_write_no_pm(tas_dev->sdw_peripheral, + SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, + TAS2783_SDCA_CTL_FU_MUTE, 1), mute); +} + +static s32 tas_fu23_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, s32 event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct tas2783_prv *tas_dev = snd_soc_component_get_drvdata(component); + s32 mute; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + mute = 0; + break; + + case SND_SOC_DAPM_PRE_PMD: + mute = 1; + break; + } + + return sdw_write_no_pm(tas_dev->sdw_peripheral, + SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, + TAS2783_SDCA_CTL_FU_MUTE, 1), mute); +} + +static const struct snd_soc_dapm_widget tas_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("ASI", "ASI Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("ASI OUT", "ASI Capture", 0, SND_SOC_NOPM, + 0, 0), + SND_SOC_DAPM_DAC_E("FU21", NULL, SND_SOC_NOPM, 0, 0, tas_fu21_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_DAC_E("FU23", NULL, SND_SOC_NOPM, 0, 0, tas_fu23_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_OUTPUT("SPK"), + SND_SOC_DAPM_INPUT("DMIC"), +}; + +static const struct snd_soc_dapm_route tas_audio_map[] = { + {"FU21", NULL, "ASI"}, + {"SPK", NULL, "FU21"}, + {"FU23", NULL, "ASI"}, + {"SPK", NULL, "FU23"}, + {"ASI OUT", NULL, "DMIC"}, +}; + +static s32 tas_set_sdw_stream(struct snd_soc_dai *dai, + void *sdw_stream, s32 direction) +{ + if (!sdw_stream) + return 0; + + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); + + return 0; +} + +static void tas_sdw_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + snd_soc_dai_set_dma_data(dai, substream, NULL); +} + +static s32 tas_sdw_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct tas2783_prv *tas_dev = + snd_soc_component_get_drvdata(component); + struct sdw_stream_config stream_config = {0}; + struct sdw_port_config port_config = {0}; + struct sdw_stream_runtime *sdw_stream; + struct sdw_slave *sdw_peripheral = tas_dev->sdw_peripheral; + s32 ret, retry = 3; + + if (!tas_dev->fw_dl_success) { + dev_err(tas_dev->dev, "error playback without fw download"); + return -EINVAL; + } + + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + if (!sdw_stream) + return -EINVAL; + + ret = tas_clear_latch(tas_dev); + if (ret) + dev_err(tas_dev->dev, + "clear latch failed, err=%d", ret); + + mutex_lock(&tas_dev->pde_lock); + /* + * Sometimes, there is error returned during power on. + * So added retry logic to ensure power on so that + * port prepare succeeds + */ + do { + ret = regmap_write(tas_dev->regmap, + SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, + TAS2783_SDCA_CTL_REQ_POW_STATE, 0), + TAS2783_SDCA_POW_STATE_ON); + if (!ret) + break; + usleep_range(2000, 2200); + } while (retry--); + mutex_unlock(&tas_dev->pde_lock); + if (ret) + return ret; + + /* SoundWire specific configuration */ + snd_sdw_params_to_config(substream, params, + &stream_config, &port_config); + /* port 1 for playback */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + port_config.num = 1; + else + port_config.num = 2; + + ret = sdw_stream_add_slave(sdw_peripheral, + &stream_config, &port_config, 1, sdw_stream); + if (ret) + dev_err(dai->dev, "Unable to configure port\n"); + + return ret; +} + +static s32 tas_sdw_pcm_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + s32 ret; + struct snd_soc_component *component = dai->component; + struct tas2783_prv *tas_dev = + snd_soc_component_get_drvdata(component); + struct sdw_stream_runtime *sdw_stream = + snd_soc_dai_get_dma_data(dai, substream); + + sdw_stream_remove_slave(tas_dev->sdw_peripheral, sdw_stream); + + mutex_lock(&tas_dev->pde_lock); + ret = regmap_write(tas_dev->regmap, + SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23, + TAS2783_SDCA_CTL_REQ_POW_STATE, 0), + TAS2783_SDCA_POW_STATE_OFF); + mutex_unlock(&tas_dev->pde_lock); + + return ret; +} + +static const struct snd_soc_dai_ops tas_dai_ops = { + .hw_params = tas_sdw_hw_params, + .hw_free = tas_sdw_pcm_hw_free, + .set_stream = tas_set_sdw_stream, + .shutdown = tas_sdw_shutdown, +}; + +static struct snd_soc_dai_driver tas_dai_driver[] = { + { + .name = "tas2783-codec", + .id = 0, + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 4, + .rates = TAS2783_DEVICE_RATES, + .formats = TAS2783_DEVICE_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 4, + .rates = TAS2783_DEVICE_RATES, + .formats = TAS2783_DEVICE_FORMATS, + }, + .ops = &tas_dai_ops, + .symmetric_rate = 1, + }, +}; + +static s32 tas_component_probe(struct snd_soc_component *component) +{ + struct tas2783_prv *tas_dev = + snd_soc_component_get_drvdata(component); + + tas_dev->component = component; + tas25xx_register_misc(tas_dev->sdw_peripheral); + + return 0; +} + +static void tas_component_remove(struct snd_soc_component *codec) +{ + struct tas2783_prv *tas_dev = + snd_soc_component_get_drvdata(codec); + tas25xx_deregister_misc(); + tas_dev->component = NULL; +} + +static const struct snd_soc_component_driver soc_codec_driver_tasdevice = { + .probe = tas_component_probe, + .remove = tas_component_remove, + .controls = tas2783_snd_controls, + .num_controls = ARRAY_SIZE(tas2783_snd_controls), + .dapm_widgets = tas_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas_dapm_widgets), + .dapm_routes = tas_audio_map, + .num_dapm_routes = ARRAY_SIZE(tas_audio_map), + .idle_bias_on = 1, + .endianness = 1, +}; + +static s32 tas_init(struct tas2783_prv *tas_dev) +{ + s32 ret; + + dev_set_drvdata(tas_dev->dev, tas_dev); + ret = devm_snd_soc_register_component(tas_dev->dev, + &soc_codec_driver_tasdevice, + tas_dai_driver, + ARRAY_SIZE(tas_dai_driver)); + if (ret) { + dev_err(tas_dev->dev, "%s: codec register error:%d.\n", + __func__, ret); + return ret; + } + + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(tas_dev->dev, 3000); + pm_runtime_use_autosuspend(tas_dev->dev); + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(tas_dev->dev); + pm_runtime_enable(tas_dev->dev); + + return ret; +} + +static s32 tas_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + s32 nval; + s32 i, j; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + prop->scp_int1_mask = + SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; + + prop->paging_support = true; + + /* first we need to allocate memory for set bits in port lists */ + prop->source_ports = 0x04; /* BITMAP: 00000100 */ + prop->sink_ports = 0x2; /* BITMAP: 00000010 */ + + nval = hweight32(prop->source_ports); + prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->src_dpn_prop), GFP_KERNEL); + if (!prop->src_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->src_dpn_prop; + addr = prop->source_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = false; + dpn[i].ch_prep_timeout = 10; + i++; + } + + /* do this again for sink now */ + nval = hweight32(prop->sink_ports); + prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->sink_dpn_prop), GFP_KERNEL); + if (!prop->sink_dpn_prop) + return -ENOMEM; + + j = 0; + dpn = prop->sink_dpn_prop; + addr = prop->sink_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[j].num = bit; + dpn[j].type = SDW_DPN_FULL; + dpn[j].simple_ch_prep_sm = false; + dpn[j].ch_prep_timeout = 10; + j++; + } + + /* set the timeout values */ + prop->clk_stop_timeout = 200; + + return 0; +} + +static s32 tas2783_sdca_dev_suspend(struct device *dev) +{ + struct tas2783_prv *tas_dev = dev_get_drvdata(dev); + + if (!tas_dev->hw_init) + return 0; + + regcache_cache_only(tas_dev->regmap, true); + return 0; +} + +static s32 tas2783_sdca_dev_system_suspend(struct device *dev) +{ + return tas2783_sdca_dev_suspend(dev); +} + +static s32 tas2783_sdca_dev_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct tas2783_prv *tas_dev = dev_get_drvdata(dev); + unsigned long t; + + if (!slave->unattach_request) + goto regmap_sync; + + t = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(TAS2783_PROBE_TIMEOUT)); + if (!t) { + dev_err(&slave->dev, "resume: initialization timed out\n"); + sdw_show_ping_status(slave->bus, true); + return -ETIMEDOUT; + } + + slave->unattach_request = 0; + +regmap_sync: + regcache_cache_only(tas_dev->regmap, false); + regcache_sync(tas_dev->regmap); + return 0; +} + +static const struct dev_pm_ops tas2783_sdca_pm = { + SYSTEM_SLEEP_PM_OPS(tas2783_sdca_dev_system_suspend, tas2783_sdca_dev_resume) + RUNTIME_PM_OPS(tas2783_sdca_dev_suspend, tas2783_sdca_dev_resume, NULL) +}; + +static s32 tas_io_init(struct device *dev, struct sdw_slave *slave) +{ + struct tas2783_prv *tas_dev = dev_get_drvdata(dev); + s32 ret; + u8 unique_id = tas_dev->sdw_peripheral->id.unique_id; + + if (tas_dev->hw_init) + return 0; + + tas_dev->fw_dl_task_done = false; + tas_dev->fw_dl_success = false; + scnprintf(tas_dev->rca_binaryname, sizeof(tas_dev->rca_binaryname), + "tas2783-%01x.bin", unique_id); + + ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, + tas_dev->rca_binaryname, tas_dev->dev, + GFP_KERNEL, tas_dev, tas2783_fw_ready); + if (ret) { + dev_err(tas_dev->dev, + "firmware request failed for uid=%d, ret=%d\n", + unique_id, ret); + return ret; + } + + ret = wait_event_timeout(tas_dev->fw_wait, tas_dev->fw_dl_task_done, + msecs_to_jiffies(TIMEOUT_FW_DL_MS)); + if (!ret) { + dev_err(tas_dev->dev, "fw request, wait_event timeout\n"); + ret = -EAGAIN; + } else { + ret = regmap_multi_reg_write(tas_dev->regmap, tas2783_init_seq, + ARRAY_SIZE(tas2783_init_seq)); + tas_dev->hw_init = true; + } + + return ret; +} + +static s32 tas_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct tas2783_prv *tas_dev = dev_get_drvdata(&slave->dev); + struct device *dev = &slave->dev; + + dev_dbg(dev, "Peripheral status = %s", + status == SDW_SLAVE_UNATTACHED ? "unattached" : + status == SDW_SLAVE_ATTACHED ? "attached" : "alert"); + + tas_dev->status = status; + if (status == SDW_SLAVE_UNATTACHED) + tas_dev->hw_init = false; + + /* Perform initialization only if slave status + * is present and hw_init flag is false + */ + if (tas_dev->hw_init || tas_dev->status != SDW_SLAVE_ATTACHED) + return 0; + + /* updated the cache data to device */ + regcache_cache_only(tas_dev->regmap, false); + regcache_sync(tas_dev->regmap); + + /* perform I/O transfers required for Slave initialization */ + return tas_io_init(&slave->dev, slave); +} + +static const struct sdw_slave_ops tas_sdw_ops = { + .read_prop = tas_read_prop, + .update_status = tas_update_status, +}; + +static void tas_remove(struct tas2783_prv *tas_dev) +{ + snd_soc_unregister_component(tas_dev->dev); +} + +static s32 tas_sdw_probe(struct sdw_slave *peripheral, + const struct sdw_device_id *id) +{ + struct regmap *regmap; + struct device *dev = &peripheral->dev; + struct tas2783_prv *tas_dev; + + tas_dev = devm_kzalloc(dev, sizeof(*tas_dev), GFP_KERNEL); + if (!tas_dev) + return dev_err_probe(dev, -ENOMEM, + "Failed devm_kzalloc"); + + tas_dev->dev = dev; + tas_dev->sdw_peripheral = peripheral; + tas_dev->hw_init = false; + mutex_init(&tas_dev->calib_lock); + mutex_init(&tas_dev->pde_lock); + + init_waitqueue_head(&tas_dev->fw_wait); + dev_set_drvdata(dev, tas_dev); + regmap = devm_regmap_init_sdw_mbq_cfg(peripheral, + &tas_regmap, + &tas2783_mbq_cfg); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "Failed devm_regmap_init_sdw."); + + /* keep in cache until the device is fully initialized */ + regcache_cache_only(regmap, true); + tas_dev->regmap = regmap; + return tas_init(tas_dev); +} + +static s32 tas_sdw_remove(struct sdw_slave *peripheral) +{ + struct tas2783_prv *tas_dev = dev_get_drvdata(&peripheral->dev); + + pm_runtime_disable(tas_dev->dev); + tas_remove(tas_dev); + mutex_destroy(&tas_dev->calib_lock); + mutex_destroy(&tas_dev->pde_lock); + dev_set_drvdata(&peripheral->dev, NULL); + + return 0; +} + +static const struct sdw_device_id tas_sdw_id[] = { + /* chipid for the TAS2783 is 0x0000 */ + SDW_SLAVE_ENTRY(0x0102, 0x0000, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, tas_sdw_id); + +static struct sdw_driver tas_sdw_driver = { + .driver = { + .name = "slave-tas2783", + .pm = pm_ptr(&tas2783_sdca_pm), + }, + .probe = tas_sdw_probe, + .remove = tas_sdw_remove, + .ops = &tas_sdw_ops, + .id_table = tas_sdw_id, +}; +module_sdw_driver(tas_sdw_driver); + +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("ASoC TAS2783 SoundWire Driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tas2783.h b/sound/soc/codecs/tas2783.h new file mode 100644 index 000000000000..794333e0a350 --- /dev/null +++ b/sound/soc/codecs/tas2783.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * ALSA SoC Texas Instruments TAS2783 Audio Smart Amplifier + * + * Copyright (C) 2025 Texas Instruments Incorporated + * https://www.ti.com + * + * The TAS2783 driver implements a flexible and configurable + * algo coefficient setting for single TAS2783 chips. + * + * Author: Niranjan H Y <niranjanhy@ti.com> + * Author: Baojun Xu <baojun.xu@ti.com> + */ +#include <linux/workqueue.h> + +#ifndef __TAS2783_H__ +#define __TAS2783_H__ + +#define TAS2783_DEVICE_RATES (SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_96000 | \ + SNDRV_PCM_RATE_88200) +#define TAS2783_DEVICE_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +/* book, page, register */ +#define TASDEV_REG_SDW(book, page, reg) (((book) * 256 * 128) + \ + 0x800000 + ((page) * 128) + (reg)) + +/* Volume control */ +#define TAS2783_DVC_LVL TASDEV_REG_SDW(0x0, 0x00, 0x1A) +#define TAS2783_AMP_LEVEL TASDEV_REG_SDW(0x0, 0x00, 0x03) +#define TAS2783_AMP_LEVEL_MASK GENMASK(5, 1) + +#define PRAM_ADDR_START TASDEV_REG_SDW(0x8c, 0x01, 0x8) +#define PRAM_ADDR_END TASDEV_REG_SDW(0x8c, 0xff, 0x7f) +#define YRAM_ADDR_START TASDEV_REG_SDW(0x00, 0x02, 0x8) +#define YRAM_ADDR_END TASDEV_REG_SDW(0x00, 0x37, 0x7f) + +/* Calibration data */ +#define TAS2783_CAL_R0 TASDEV_REG_SDW(0, 0x16, 0x4C) +#define TAS2783_CAL_INVR0 TASDEV_REG_SDW(0, 0x16, 0x5C) +#define TAS2783_CAL_R0LOW TASDEV_REG_SDW(0, 0x16, 0x64) +#define TAS2783_CAL_POWER TASDEV_REG_SDW(0, 0x15, 0x44) +#define TAS2783_CAL_TLIM TASDEV_REG_SDW(0, 0x17, 0x58) + +/* TAS2783 SDCA Control - function number */ +#define FUNC_NUM_SMART_AMP 0x01 + +/* TAS2783 SDCA entity */ + +#define TAS2783_SDCA_ENT_FU21 0x01 +#define TAS2783_SDCA_ENT_FU23 0x02 +#define TAS2783_SDCA_ENT_FU26 0x03 +#define TAS2783_SDCA_ENT_XU22 0x04 +#define TAS2783_SDCA_ENT_CS24 0x05 +#define TAS2783_SDCA_ENT_CS21 0x06 +#define TAS2783_SDCA_ENT_CS25 0x07 +#define TAS2783_SDCA_ENT_CS26 0x08 +#define TAS2783_SDCA_ENT_CS28 0x09 +#define TAS2783_SDCA_ENT_PDE23 0x0C +#define TAS2783_SDCA_ENT_UDMPU23 0x0E +#define TAS2783_SDCA_ENT_SAPU29 0x0F +#define TAS2783_SDCA_ENT_PPU21 0x10 +#define TAS2783_SDCA_ENT_PPU26 0x11 +#define TAS2783_SDCA_ENT_TG23 0x12 +#define TAS2783_SDCA_ENT_IT21 0x13 +#define TAS2783_SDCA_ENT_IT29 0x14 +#define TAS2783_SDCA_ENT_IT26 0x15 +#define TAS2783_SDCA_ENT_IT28 0x16 +#define TAS2783_SDCA_ENT_OT24 0x17 +#define TAS2783_SDCA_ENT_OT23 0x18 +#define TAS2783_SDCA_ENT_OT25 0x19 +#define TAS2783_SDCA_ENT_OT28 0x1A +#define TAS2783_SDCA_ENT_MU26 0x1b +#define TAS2783_SDCA_ENT_OT127 0x1E +#define TAS2783_SDCA_ENT_FU127 0x1F +#define TAS2783_SDCA_ENT_CS127 0x20 +#define TAS2783_SDCA_ENT_MFPU21 0x22 +#define TAS2783_SDCA_ENT_MFPU26 0x23 + +/* TAS2783 SDCA control */ +#define TAS2783_SDCA_CTL_REQ_POW_STATE 0x01 +#define TAS2783_SDCA_CTL_FU_MUTE 0x01 +#define TAS2783_SDCA_CTL_UDMPU_CLUSTER 0x10 + +#define TAS2783_DEVICE_CHANNEL_LEFT 1 +#define TAS2783_DEVICE_CHANNEL_RIGHT 2 + +#define TAS2783_SDCA_POW_STATE_ON 0 +#define TAS2783_SDCA_POW_STATE_OFF 3 + +/* calibration data */ +#define TAS2783_CALIB_PARAMS 6 /* 5 + 1 unique id */ +#define TAS2783_CALIB_MAX_SPK_COUNT 8 +#define TAS2783_CALIB_HDR_SZ 12 +#define TAS2783_CALIB_CRC_SZ 4 +#define TAS2783_CALIB_DATA_SZ ((TAS2783_CALIB_HDR_SZ) + TAS2783_CALIB_CRC_SZ + \ + ((TAS2783_CALIB_PARAMS) * 4 * (TAS2783_CALIB_MAX_SPK_COUNT))) + +#if IS_ENABLED(CONFIG_SND_SOC_TAS2783_UTIL) +int32_t tas25xx_register_misc(struct sdw_slave *peripheral); +int32_t tas25xx_deregister_misc(void); +#else +static void tas25xx_register_misc(struct sdw_slave *peripheral) {} +static void tas25xx_deregister_misc(void) {} +#endif + +#endif /*__TAS2783_H__ */ diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 7399080f8580..715a07ab97b9 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -1277,8 +1277,8 @@ static int aic32x4_setup_regulators(struct device *dev, /* Check if the regulator requirements are fulfilled */ if (IS_ERR(aic32x4->supply_iov)) { - dev_err(dev, "Missing supply 'iov'\n"); - return PTR_ERR(aic32x4->supply_iov); + return dev_err_probe(dev, PTR_ERR(aic32x4->supply_iov), + "Missing supply 'iov'\n"); } if (IS_ERR(aic32x4->supply_ldo)) { @@ -1286,12 +1286,12 @@ static int aic32x4_setup_regulators(struct device *dev, return -EPROBE_DEFER; if (IS_ERR(aic32x4->supply_dv)) { - dev_err(dev, "Missing supply 'dv' or 'ldoin'\n"); - return PTR_ERR(aic32x4->supply_dv); + return dev_err_probe(dev, PTR_ERR(aic32x4->supply_dv), + "Missing supply 'dv' or 'ldoin'\n"); } if (IS_ERR(aic32x4->supply_av)) { - dev_err(dev, "Missing supply 'av' or 'ldoin'\n"); - return PTR_ERR(aic32x4->supply_av); + return dev_err_probe(dev, PTR_ERR(aic32x4->supply_av), + "Missing supply 'av' or 'ldoin'\n"); } } else { if (PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER) @@ -1383,10 +1383,8 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap, } ret = aic32x4_setup_regulators(dev, aic32x4); - if (ret) { - dev_err(dev, "Failed to setup regulators\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to setup regulators\n"); if (aic32x4->rstn_gpio) { ndelay(10); diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index f1649df19738..eea8ca285f8e 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -121,6 +121,16 @@ static const struct reg_default aic3x_reg[] = { { 108, 0x00 }, { 109, 0x00 }, }; +static const struct reg_sequence aic3007_class_d[] = { + /* Class-D speaker driver init; datasheet p. 46 */ + { AIC3X_PAGE_SELECT, 0x0D }, + { 0xD, 0x0D }, + { 0x8, 0x5C }, + { 0x8, 0x5D }, + { 0x8, 0x5C }, + { AIC3X_PAGE_SELECT, 0x00 }, +}; + static bool aic3x_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -1393,6 +1403,10 @@ static int aic3x_set_power(struct snd_soc_component *component, int power) gpiod_set_value(aic3x->gpio_reset, 0); } + if (aic3x->model == AIC3X_MODEL_3007) + regmap_multi_reg_write_bypassed(aic3x->regmap, aic3007_class_d, + ARRAY_SIZE(aic3007_class_d)); + /* Sync reg_cache with the hardware */ regcache_cache_only(aic3x->regmap, false); regcache_sync(aic3x->regmap); @@ -1723,17 +1737,6 @@ static void aic3x_configure_ocmv(struct device *dev, struct aic3x_priv *aic3x) } } - -static const struct reg_sequence aic3007_class_d[] = { - /* Class-D speaker driver init; datasheet p. 46 */ - { AIC3X_PAGE_SELECT, 0x0D }, - { 0xD, 0x0D }, - { 0x8, 0x5C }, - { 0x8, 0x5D }, - { 0x8, 0x5C }, - { AIC3X_PAGE_SELECT, 0x00 }, -}; - int aic3x_probe(struct device *dev, struct regmap *regmap, kernel_ulong_t driver_data) { struct aic3x_priv *aic3x; @@ -1823,13 +1826,6 @@ int aic3x_probe(struct device *dev, struct regmap *regmap, kernel_ulong_t driver aic3x_configure_ocmv(dev, aic3x); - if (aic3x->model == AIC3X_MODEL_3007) { - ret = regmap_register_patch(aic3x->regmap, aic3007_class_d, - ARRAY_SIZE(aic3007_class_d)); - if (ret != 0) - dev_err(dev, "Failed to init class D: %d\n", ret); - } - ret = devm_snd_soc_register_component(dev, &soc_component_dev_aic3x, &aic3x_dai, 1); if (ret) return ret; diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 423b9264a205..c495be1cf2ed 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -14,7 +14,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/interrupt.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> #include <sound/core.h> @@ -24,7 +24,6 @@ #include <sound/initval.h> #include <sound/tlv.h> -#include <sound/tlv320dac33-plat.h> #include "tlv320dac33.h" /* @@ -80,7 +79,7 @@ struct tlv320dac33_priv { struct snd_soc_component *component; struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; struct snd_pcm_substream *substream; - int power_gpio; + struct gpio_desc *reset_gpiod; int chip_power; int irq; unsigned int refclk; @@ -383,14 +382,26 @@ static int dac33_hard_power(struct snd_soc_component *component, int power) goto exit; } - if (dac33->power_gpio >= 0) - gpio_set_value(dac33->power_gpio, 1); + if (dac33->reset_gpiod) { + ret = gpiod_set_value(dac33->reset_gpiod, 1); + if (ret < 0) { + dev_err(&dac33->i2c->dev, + "Failed to set reset GPIO: %d\n", ret); + goto exit; + } + } dac33->chip_power = 1; } else { dac33_soft_power(component, 0); - if (dac33->power_gpio >= 0) - gpio_set_value(dac33->power_gpio, 0); + if (dac33->reset_gpiod) { + ret = gpiod_set_value(dac33->reset_gpiod, 0); + if (ret < 0) { + dev_err(&dac33->i2c->dev, + "Failed to set reset GPIO: %d\n", ret); + goto exit; + } + } ret = regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies); @@ -1462,16 +1473,9 @@ static struct snd_soc_dai_driver dac33_dai = { static int dac33_i2c_probe(struct i2c_client *client) { - struct tlv320dac33_platform_data *pdata; struct tlv320dac33_priv *dac33; int ret, i; - if (client->dev.platform_data == NULL) { - dev_err(&client->dev, "Platform data not set\n"); - return -ENODEV; - } - pdata = client->dev.platform_data; - dac33 = devm_kzalloc(&client->dev, sizeof(struct tlv320dac33_priv), GFP_KERNEL); if (dac33 == NULL) @@ -1488,26 +1492,22 @@ static int dac33_i2c_probe(struct i2c_client *client) i2c_set_clientdata(client, dac33); - dac33->power_gpio = pdata->power_gpio; - dac33->burst_bclkdiv = pdata->burst_bclkdiv; - dac33->keep_bclk = pdata->keep_bclk; - dac33->mode1_latency = pdata->mode1_latency; + if (!dac33->burst_bclkdiv) + dac33->burst_bclkdiv = 8; if (!dac33->mode1_latency) dac33->mode1_latency = 10000; /* 10ms */ dac33->irq = client->irq; /* Disable FIFO use by default */ dac33->fifo_mode = DAC33_FIFO_BYPASS; - /* Check if the reset GPIO number is valid and request it */ - if (dac33->power_gpio >= 0) { - ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset"); - if (ret < 0) { - dev_err(&client->dev, - "Failed to request reset GPIO (%d)\n", - dac33->power_gpio); - goto err_gpio; - } - gpio_direction_output(dac33->power_gpio, 0); + /* request optional reset GPIO */ + dac33->reset_gpiod = + devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(dac33->reset_gpiod)) { + ret = PTR_ERR(dac33->reset_gpiod); + dev_err_probe(&client->dev, ret, + "Failed to get reset GPIO\n"); + goto err; } for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++) @@ -1518,19 +1518,17 @@ static int dac33_i2c_probe(struct i2c_client *client) if (ret != 0) { dev_err(&client->dev, "Failed to request supplies: %d\n", ret); - goto err_get; + goto err; } ret = devm_snd_soc_register_component(&client->dev, &soc_component_dev_tlv320dac33, &dac33_dai, 1); if (ret < 0) - goto err_get; + goto err; return ret; -err_get: - if (dac33->power_gpio >= 0) - gpio_free(dac33->power_gpio); -err_gpio: + +err: return ret; } @@ -1540,9 +1538,6 @@ static void dac33_i2c_remove(struct i2c_client *client) if (unlikely(dac33->chip_power)) dac33_hard_power(dac33->component, 0); - - if (dac33->power_gpio >= 0) - gpio_free(dac33->power_gpio); } static const struct i2c_device_id tlv320dac33_i2c_id[] = { diff --git a/sound/soc/codecs/wcd-common.c b/sound/soc/codecs/wcd-common.c new file mode 100644 index 000000000000..9016e974582f --- /dev/null +++ b/sound/soc/codecs/wcd-common.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2025, Qualcomm Technologies, Inc. and/or its subsidiaries. + +#include <linux/export.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/of.h> +#include <linux/printk.h> +#include <linux/component.h> +#include <linux/pm_runtime.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_type.h> +#include <linux/regmap.h> + +#include "wcd-common.h" + +#define WCD_MIN_MICBIAS_MV 1000 +#define WCD_DEF_MICBIAS_MV 1800 +#define WCD_MAX_MICBIAS_MV 2850 + +#define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m) (0xE0 + 0x10 * (m)) + +int wcd_get_micb_vout_ctl_val(struct device *dev, u32 micb_mv) +{ + /* min micbias voltage is 1V and maximum is 2.85V */ + if (micb_mv < WCD_MIN_MICBIAS_MV || micb_mv > WCD_MAX_MICBIAS_MV) { + dev_err(dev, "Unsupported micbias voltage (%u mV)\n", micb_mv); + return -EINVAL; + } + + return (micb_mv - WCD_MIN_MICBIAS_MV) / 50; +} +EXPORT_SYMBOL_GPL(wcd_get_micb_vout_ctl_val); + +static int wcd_get_micbias_val(struct device *dev, int micb_num, u32 *micb_mv) +{ + char micbias[64]; + int mv; + + sprintf(micbias, "qcom,micbias%d-microvolt", micb_num); + + if (of_property_read_u32(dev->of_node, micbias, &mv)) { + dev_err(dev, "%s value not found, using default\n", micbias); + mv = WCD_DEF_MICBIAS_MV; + } else { + /* convert it to milli volts */ + mv = mv/1000; + } + if (micb_mv) + *micb_mv = mv; + + mv = wcd_get_micb_vout_ctl_val(dev, mv); + if (mv < 0) { + dev_err(dev, "Unsupported %s voltage (%d mV), falling back to default (%d mV)\n", + micbias, mv, WCD_DEF_MICBIAS_MV); + return wcd_get_micb_vout_ctl_val(dev, WCD_DEF_MICBIAS_MV); + } + + return mv; +} + +int wcd_dt_parse_micbias_info(struct wcd_common *common) +{ + int ret, i; + + for (i = 0; i < common->max_bias; i++) { + ret = wcd_get_micbias_val(common->dev, i + 1, &common->micb_mv[i]); + if (ret < 0) + return ret; + common->micb_vout[i] = ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(wcd_dt_parse_micbias_info); + +static int wcd_sdw_component_bind(struct device *dev, struct device *master, void *data) +{ + pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + return 0; +} + +static void wcd_sdw_component_unbind(struct device *dev, struct device *master, void *data) +{ + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_dont_use_autosuspend(dev); +} + +const struct component_ops wcd_sdw_component_ops = { + .bind = wcd_sdw_component_bind, + .unbind = wcd_sdw_component_unbind, +}; +EXPORT_SYMBOL_GPL(wcd_sdw_component_ops); + +int wcd_update_status(struct sdw_slave *slave, enum sdw_slave_status status) +{ + struct regmap *regmap = dev_get_regmap(&slave->dev, NULL); + + if (regmap && status == SDW_SLAVE_ATTACHED) { + /* Write out any cached changes that happened between probe and attach */ + regcache_cache_only(regmap, false); + return regcache_sync(regmap); + } + + return 0; +} +EXPORT_SYMBOL_GPL(wcd_update_status); + +int wcd_bus_config(struct sdw_slave *slave, struct sdw_bus_params *params) +{ + sdw_write(slave, SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(params->next_bank), 0x01); + + return 0; +} +EXPORT_SYMBOL_GPL(wcd_bus_config); + +int wcd_interrupt_callback(struct sdw_slave *slave, struct irq_domain *slave_irq, + unsigned int wcd_intr_status0, unsigned int wcd_intr_status1, + unsigned int wcd_intr_status2) +{ + struct regmap *regmap = dev_get_regmap(&slave->dev, NULL); + u32 sts1, sts2, sts3; + + do { + handle_nested_irq(irq_find_mapping(slave_irq, 0)); + regmap_read(regmap, wcd_intr_status0, &sts1); + regmap_read(regmap, wcd_intr_status1, &sts2); + regmap_read(regmap, wcd_intr_status2, &sts3); + + } while (sts1 || sts2 || sts3); + + return IRQ_HANDLED; +} +EXPORT_SYMBOL_GPL(wcd_interrupt_callback); + +MODULE_DESCRIPTION("Common Qualcomm WCD Codec helpers driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/wcd-common.h b/sound/soc/codecs/wcd-common.h new file mode 100644 index 000000000000..d5c156e641fc --- /dev/null +++ b/sound/soc/codecs/wcd-common.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2025, Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __WCD_COMMON_H__ +#define __WCD_COMMON_H__ + +struct device; +struct sdw_slave; +struct sdw_bus_params; +struct irq_domain; +enum sdw_slave_status; + +#define WCD_MAX_MICBIAS 4 + +struct wcd_sdw_ch_info { + int port_num; + unsigned int ch_mask; + unsigned int master_ch_mask; +}; + +#define WCD_SDW_CH(id, pn, cmask) \ + [id] = { \ + .port_num = pn, \ + .ch_mask = cmask, \ + .master_ch_mask = cmask, \ + } + +struct wcd_common { + struct device *dev; + int max_bias; + u32 micb_mv[WCD_MAX_MICBIAS]; + u32 micb_vout[WCD_MAX_MICBIAS]; +}; + +extern const struct component_ops wcd_sdw_component_ops; +int wcd_get_micb_vout_ctl_val(struct device *dev, u32 micb_mv); +int wcd_dt_parse_micbias_info(struct wcd_common *common); +int wcd_update_status(struct sdw_slave *slave, enum sdw_slave_status status); +int wcd_bus_config(struct sdw_slave *slave, struct sdw_bus_params *params); +int wcd_interrupt_callback(struct sdw_slave *slave, struct irq_domain *slave_irq, + unsigned int wcd_intr_status0, unsigned int wcd_intr_status1, + unsigned int wcd_intr_status2); + +#endif /* __WCD_COMMON_H__ */ diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 1bb7e1dc7e6b..3c22f7149af8 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -21,6 +21,7 @@ #include <sound/soc-dapm.h> #include <sound/tlv.h> #include "wcd-clsh-v2.h" +#include "wcd-common.h" #include "wcd-mbhc-v2.h" #include <dt-bindings/sound/qcom,wcd934x.h> @@ -116,9 +117,6 @@ #define WCD934X_DEC_PWR_LVL_DF 0x00 #define WCD934X_DEC_PWR_LVL_HYBRID WCD934X_DEC_PWR_LVL_DF -#define WCD934X_DEF_MICBIAS_MV 1800 -#define WCD934X_MAX_MICBIAS_MV 2850 - #define WCD_IIR_FILTER_SIZE (sizeof(u32) * BAND_MAX) #define WCD_IIR_FILTER_CTL(xname, iidx, bidx) \ @@ -530,6 +528,7 @@ struct wcd934x_codec { struct slim_device *sdev; struct slim_device *sidev; struct wcd_clsh_ctrl *clsh_ctrl; + struct wcd_common common; struct snd_soc_component *component; struct wcd934x_slim_ch rx_chs[WCD934X_RX_MAX]; struct wcd934x_slim_ch tx_chs[WCD934X_TX_MAX]; @@ -555,7 +554,6 @@ struct wcd934x_codec { struct mutex micb_lock; u32 micb_ref[WCD934X_MAX_MICBIAS]; u32 pullup_ref[WCD934X_MAX_MICBIAS]; - u32 micb2_mv; }; #define to_wcd934x_codec(_hw) container_of(_hw, struct wcd934x_codec, hw) @@ -2168,55 +2166,24 @@ static struct clk *wcd934x_register_mclk_output(struct wcd934x_codec *wcd) return NULL; } -static int wcd934x_get_micbias_val(struct device *dev, const char *micbias, - u32 *micb_mv) -{ - int mv; - - if (of_property_read_u32(dev->parent->of_node, micbias, &mv)) { - dev_err(dev, "%s value not found, using default\n", micbias); - mv = WCD934X_DEF_MICBIAS_MV; - } else { - /* convert it to milli volts */ - mv = mv/1000; - } - - if (mv < 1000 || mv > 2850) { - dev_err(dev, "%s value not in valid range, using default\n", - micbias); - mv = WCD934X_DEF_MICBIAS_MV; - } - - if (micb_mv) - *micb_mv = mv; - - return (mv - 1000) / 50; -} - static int wcd934x_init_dmic(struct snd_soc_component *comp) { - int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4; struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev); u32 def_dmic_rate, dmic_clk_drv; + int ret; - vout_ctl_1 = wcd934x_get_micbias_val(comp->dev, - "qcom,micbias1-microvolt", NULL); - vout_ctl_2 = wcd934x_get_micbias_val(comp->dev, - "qcom,micbias2-microvolt", - &wcd->micb2_mv); - vout_ctl_3 = wcd934x_get_micbias_val(comp->dev, - "qcom,micbias3-microvolt", NULL); - vout_ctl_4 = wcd934x_get_micbias_val(comp->dev, - "qcom,micbias4-microvolt", NULL); + ret = wcd_dt_parse_mbhc_data(comp->dev, &wcd->mbhc_cfg); + if (ret) + return ret; snd_soc_component_update_bits(comp, WCD934X_ANA_MICB1, - WCD934X_MICB_VAL_MASK, vout_ctl_1); + WCD934X_MICB_VAL_MASK, wcd->common.micb_vout[0]); snd_soc_component_update_bits(comp, WCD934X_ANA_MICB2, - WCD934X_MICB_VAL_MASK, vout_ctl_2); + WCD934X_MICB_VAL_MASK, wcd->common.micb_vout[1]); snd_soc_component_update_bits(comp, WCD934X_ANA_MICB3, - WCD934X_MICB_VAL_MASK, vout_ctl_3); + WCD934X_MICB_VAL_MASK, wcd->common.micb_vout[2]); snd_soc_component_update_bits(comp, WCD934X_ANA_MICB4, - WCD934X_MICB_VAL_MASK, vout_ctl_4); + WCD934X_MICB_VAL_MASK, wcd->common.micb_vout[3]); if (wcd->rate == WCD934X_MCLK_CLK_9P6MHZ) def_dmic_rate = WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ; @@ -2517,15 +2484,6 @@ static void wcd934x_mbhc_micb_ramp_control(struct snd_soc_component *component, } } -static int wcd934x_get_micb_vout_ctl_val(u32 micb_mv) -{ - /* min micbias voltage is 1V and maximum is 2.85V */ - if (micb_mv < 1000 || micb_mv > 2850) - return -EINVAL; - - return (micb_mv - 1000) / 50; -} - static int wcd934x_mbhc_micb_adjust_voltage(struct snd_soc_component *component, int req_volt, int micb_num) { @@ -2562,7 +2520,7 @@ static int wcd934x_mbhc_micb_adjust_voltage(struct snd_soc_component *component, cur_vout_ctl = snd_soc_component_read_field(component, micb_reg, WCD934X_MICB_VAL_MASK); - req_vout_ctl = wcd934x_get_micb_vout_ctl_val(req_volt); + req_vout_ctl = wcd_get_micb_vout_ctl_val(component->dev, req_volt); if (req_vout_ctl < 0) { ret = -EINVAL; goto exit; @@ -2610,10 +2568,10 @@ static int wcd934x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *compon * voltage needed to detect threshold microphone, then do * not change the micbias, just return. */ - if (wcd934x->micb2_mv >= WCD_MBHC_THR_HS_MICB_MV) + if (wcd934x->common.micb_mv[1] >= WCD_MBHC_THR_HS_MICB_MV) return 0; - micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd934x->micb2_mv; + micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd934x->common.micb_mv[1]; rc = wcd934x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2); @@ -3036,7 +2994,7 @@ static void wcd934x_mbhc_deinit(struct snd_soc_component *component) static int wcd934x_comp_probe(struct snd_soc_component *component) { struct wcd934x_codec *wcd = dev_get_drvdata(component->dev); - int i; + int i, ret; snd_soc_component_init_regmap(component, wcd->regmap); wcd->component = component; @@ -3054,7 +3012,12 @@ static int wcd934x_comp_probe(struct snd_soc_component *component) for (i = 0; i < NUM_CODEC_DAIS; i++) INIT_LIST_HEAD(&wcd->dai[i].slim_ch_list); - wcd934x_init_dmic(component); + + ret = wcd934x_init_dmic(component); + if (ret) { + dev_err(component->dev, "Failed to Initialize micbias\n"); + return ret; + } if (wcd934x_mbhc_init(component)) dev_err(component->dev, "Failed to Initialize MBHC\n"); @@ -5831,6 +5794,13 @@ static const struct snd_soc_component_driver wcd934x_component_drv = { .endianness = 1, }; +static void wcd934x_put_device_action(void *data) +{ + struct device *dev = data; + + put_device(dev); +} + static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd) { struct device *dev = &wcd->sdev->dev; @@ -5847,11 +5817,13 @@ static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd) return dev_err_probe(dev, -EINVAL, "Unable to get SLIM Interface device\n"); slim_get_logical_addr(wcd->sidev); - wcd->if_regmap = regmap_init_slimbus(wcd->sidev, + wcd->if_regmap = devm_regmap_init_slimbus(wcd->sidev, &wcd934x_ifc_regmap_config); - if (IS_ERR(wcd->if_regmap)) + if (IS_ERR(wcd->if_regmap)) { + put_device(&wcd->sidev->dev); return dev_err_probe(dev, PTR_ERR(wcd->if_regmap), "Failed to allocate ifc register map\n"); + } of_property_read_u32(dev->parent->of_node, "qcom,dmic-sample-rate", &wcd->dmic_sample_rate); @@ -5860,14 +5832,13 @@ static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd) cfg->anc_micbias = MIC_BIAS_2; cfg->v_hs_max = WCD_MBHC_HS_V_MAX; cfg->num_btn = WCD934X_MBHC_MAX_BUTTONS; - cfg->micb_mv = wcd->micb2_mv; + cfg->micb_mv = wcd->common.micb_mv[1]; cfg->linein_th = 5000; cfg->hs_thr = 1700; cfg->hph_thr = 50; wcd_dt_parse_mbhc_data(dev, cfg); - return 0; } @@ -5888,11 +5859,17 @@ static int wcd934x_codec_probe(struct platform_device *pdev) wcd->sdev = to_slim_device(data->dev); mutex_init(&wcd->sysclk_mutex); mutex_init(&wcd->micb_lock); + wcd->common.dev = dev->parent; + wcd->common.max_bias = 4; ret = wcd934x_codec_parse_data(wcd); if (ret) return ret; + ret = devm_add_action_or_reset(dev, wcd934x_put_device_action, &wcd->sidev->dev); + if (ret) + return ret; + /* set default rate 9P6MHz */ regmap_update_bits(wcd->regmap, WCD934X_CODEC_RPM_CLK_MCLK_CFG, WCD934X_CODEC_RPM_CLK_MCLK_CFG_MCLK_MASK, diff --git a/sound/soc/codecs/wcd937x-sdw.c b/sound/soc/codecs/wcd937x-sdw.c index 1bfe7383b311..1878d67e3fa1 100644 --- a/sound/soc/codecs/wcd937x-sdw.c +++ b/sound/soc/codecs/wcd937x-sdw.c @@ -19,7 +19,7 @@ #include <sound/soc.h> #include "wcd937x.h" -static struct wcd937x_sdw_ch_info wcd937x_sdw_rx_ch_info[] = { +static struct wcd_sdw_ch_info wcd937x_sdw_rx_ch_info[] = { WCD_SDW_CH(WCD937X_HPH_L, WCD937X_HPH_PORT, BIT(0)), WCD_SDW_CH(WCD937X_HPH_R, WCD937X_HPH_PORT, BIT(1)), WCD_SDW_CH(WCD937X_CLSH, WCD937X_CLSH_PORT, BIT(0)), @@ -30,7 +30,7 @@ static struct wcd937x_sdw_ch_info wcd937x_sdw_rx_ch_info[] = { WCD_SDW_CH(WCD937X_DSD_R, WCD937X_DSD_PORT, BIT(1)), }; -static struct wcd937x_sdw_ch_info wcd937x_sdw_tx_ch_info[] = { +static struct wcd_sdw_ch_info wcd937x_sdw_tx_ch_info[] = { WCD_SDW_CH(WCD937X_ADC1, WCD937X_ADC_1_PORT, BIT(0)), WCD_SDW_CH(WCD937X_ADC2, WCD937X_ADC_2_3_PORT, BIT(0)), WCD_SDW_CH(WCD937X_ADC3, WCD937X_ADC_2_3_PORT, BIT(0)), @@ -78,12 +78,6 @@ static struct sdw_dpn_prop wcd937x_dpn_prop[WCD937X_MAX_SWR_PORTS] = { } }; -struct device *wcd937x_sdw_device_get(struct device_node *np) -{ - return bus_find_device_by_of_node(&sdw_bus_type, np); -} -EXPORT_SYMBOL_GPL(wcd937x_sdw_device_get); - int wcd937x_sdw_hw_params(struct wcd937x_sdw_priv *wcd, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, @@ -118,19 +112,6 @@ int wcd937x_sdw_hw_params(struct wcd937x_sdw_priv *wcd, } EXPORT_SYMBOL_GPL(wcd937x_sdw_hw_params); -static int wcd9370_update_status(struct sdw_slave *slave, enum sdw_slave_status status) -{ - struct wcd937x_sdw_priv *wcd = dev_get_drvdata(&slave->dev); - - if (wcd->regmap && status == SDW_SLAVE_ATTACHED) { - /* Write out any cached changes that happened between probe and attach */ - regcache_cache_only(wcd->regmap, false); - return regcache_sync(wcd->regmap); - } - - return 0; -} - /* * Handle Soundwire out-of-band interrupt event by triggering * the first irq of the slave_irq irq domain, which then will @@ -141,18 +122,9 @@ static int wcd9370_interrupt_callback(struct sdw_slave *slave, struct sdw_slave_intr_status *status) { struct wcd937x_sdw_priv *wcd = dev_get_drvdata(&slave->dev); - struct irq_domain *slave_irq = wcd->slave_irq; - u32 sts1, sts2, sts3; - - do { - handle_nested_irq(irq_find_mapping(slave_irq, 0)); - regmap_read(wcd->regmap, WCD937X_DIGITAL_INTR_STATUS_0, &sts1); - regmap_read(wcd->regmap, WCD937X_DIGITAL_INTR_STATUS_1, &sts2); - regmap_read(wcd->regmap, WCD937X_DIGITAL_INTR_STATUS_2, &sts3); - } while (sts1 || sts2 || sts3); - - return IRQ_HANDLED; + return wcd_interrupt_callback(slave, wcd->slave_irq, WCD937X_DIGITAL_INTR_STATUS_0, + WCD937X_DIGITAL_INTR_STATUS_1, WCD937X_DIGITAL_INTR_STATUS_2); } static const struct reg_default wcd937x_defaults[] = { @@ -985,35 +957,10 @@ static const struct regmap_config wcd937x_regmap_config = { }; static const struct sdw_slave_ops wcd9370_slave_ops = { - .update_status = wcd9370_update_status, + .update_status = wcd_update_status, .interrupt_callback = wcd9370_interrupt_callback, }; -static int wcd937x_sdw_component_bind(struct device *dev, - struct device *master, void *data) -{ - pm_runtime_set_autosuspend_delay(dev, 3000); - pm_runtime_use_autosuspend(dev); - pm_runtime_mark_last_busy(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - - return 0; -} - -static void wcd937x_sdw_component_unbind(struct device *dev, - struct device *master, void *data) -{ - pm_runtime_disable(dev); - pm_runtime_set_suspended(dev); - pm_runtime_dont_use_autosuspend(dev); -} - -static const struct component_ops wcd937x_sdw_component_ops = { - .bind = wcd937x_sdw_component_bind, - .unbind = wcd937x_sdw_component_unbind, -}; - static int wcd9370_probe(struct sdw_slave *pdev, const struct sdw_device_id *id) { @@ -1099,7 +1046,7 @@ static int wcd9370_probe(struct sdw_slave *pdev, } - ret = component_add(dev, &wcd937x_sdw_component_ops); + ret = component_add(dev, &wcd_sdw_component_ops); if (ret) return ret; @@ -1113,7 +1060,7 @@ static int wcd9370_remove(struct sdw_slave *pdev) { struct device *dev = &pdev->dev; - component_del(dev, &wcd937x_sdw_component_ops); + component_del(dev, &wcd_sdw_component_ops); return 0; } diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c index 3b0a8cc314e0..421ec7a2d6bd 100644 --- a/sound/soc/codecs/wcd937x.c +++ b/sound/soc/codecs/wcd937x.c @@ -21,6 +21,7 @@ #include <sound/tlv.h> #include "wcd-clsh-v2.h" +#include "wcd-common.h" #include "wcd-mbhc-v2.h" #include "wcd937x.h" @@ -85,6 +86,7 @@ struct wcd937x_priv { struct wcd_mbhc_config mbhc_cfg; struct wcd_mbhc_intr intr_ids; struct wcd_clsh_ctrl *clsh_info; + struct wcd_common common; struct irq_domain *virq; struct regmap_irq_chip_data *irq_chip; struct snd_soc_jack *jack; @@ -93,9 +95,6 @@ struct wcd937x_priv { s32 pullup_ref[WCD937X_MAX_MICBIAS]; u32 hph_mode; int ear_rx_path; - u32 micb1_mv; - u32 micb2_mv; - u32 micb3_mv; int hphr_pdm_wd_int; int hphl_pdm_wd_int; int aux_pdm_wd_int; @@ -872,15 +871,6 @@ static int wcd937x_enable_rx3(struct snd_soc_dapm_widget *w, return 0; } -static int wcd937x_get_micb_vout_ctl_val(u32 micb_mv) -{ - if (micb_mv < 1000 || micb_mv > 2850) { - pr_err("Unsupported micbias voltage (%u mV)\n", micb_mv); - return -EINVAL; - } - - return (micb_mv - 1000) / 50; -} static int wcd937x_tx_swr_ctrl(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) @@ -1193,7 +1183,7 @@ static int wcd937x_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w, static int wcd937x_connect_port(struct wcd937x_sdw_priv *wcd, u8 port_idx, u8 ch_id, bool enable) { struct sdw_port_config *port_config = &wcd->port_config[port_idx - 1]; - const struct wcd937x_sdw_ch_info *ch_info = &wcd->ch_info[ch_id]; + const struct wcd_sdw_ch_info *ch_info = &wcd->ch_info[ch_id]; u8 port_num = ch_info->port_num; u8 ch_mask = ch_info->ch_mask; u8 mstr_port_num, mstr_ch_mask; @@ -1481,7 +1471,7 @@ static int wcd937x_mbhc_micb_adjust_voltage(struct snd_soc_component *component, cur_vout_ctl = snd_soc_component_read_field(component, micb_reg, WCD937X_MICB_VOUT_MASK); - req_vout_ctl = wcd937x_get_micb_vout_ctl_val(req_volt); + req_vout_ctl = wcd_get_micb_vout_ctl_val(component->dev, req_volt); if (req_vout_ctl < 0) { ret = -EINVAL; goto exit; @@ -1529,10 +1519,10 @@ static int wcd937x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *compon * voltage needed to detect threshold microphone, then do * not change the micbias, just return. */ - if (wcd937x->micb2_mv >= WCD_MBHC_THR_HS_MICB_MV) + if (wcd937x->common.micb_mv[2] >= WCD_MBHC_THR_HS_MICB_MV) return 0; - micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd937x->micb2_mv; + micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd937x->common.micb_mv[2]; return wcd937x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2); } @@ -2046,9 +2036,9 @@ static const struct snd_kcontrol_new wcd937x_snd_controls[] = { SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum, wcd937x_rx_hph_mode_get, wcd937x_rx_hph_mode_put), - SOC_SINGLE_EXT("HPHL_COMP Switch", SND_SOC_NOPM, 0, 1, 0, + SOC_SINGLE_EXT("HPHL_COMP Switch", WCD937X_COMP_L, 0, 1, 0, wcd937x_get_compander, wcd937x_set_compander), - SOC_SINGLE_EXT("HPHR_COMP Switch", SND_SOC_NOPM, 1, 1, 0, + SOC_SINGLE_EXT("HPHR_COMP Switch", WCD937X_COMP_R, 1, 1, 0, wcd937x_get_compander, wcd937x_set_compander), SOC_SINGLE_TLV("HPHL Volume", WCD937X_HPH_L_EN, 0, 20, 1, line_gain), @@ -2436,22 +2426,14 @@ static const struct snd_soc_dapm_route wcd9375_audio_map[] = { { "DMIC6_MIXER", "Switch", "DMIC6" }, }; -static int wcd937x_set_micbias_data(struct wcd937x_priv *wcd937x) +static void wcd937x_set_micbias_data(struct device *dev, struct wcd937x_priv *wcd937x) { - int vout_ctl[3]; - - /* Set micbias voltage */ - vout_ctl[0] = wcd937x_get_micb_vout_ctl_val(wcd937x->micb1_mv); - vout_ctl[1] = wcd937x_get_micb_vout_ctl_val(wcd937x->micb2_mv); - vout_ctl[2] = wcd937x_get_micb_vout_ctl_val(wcd937x->micb3_mv); - if ((vout_ctl[0] | vout_ctl[1] | vout_ctl[2]) < 0) - return -EINVAL; - - regmap_update_bits(wcd937x->regmap, WCD937X_ANA_MICB1, WCD937X_ANA_MICB_VOUT, vout_ctl[0]); - regmap_update_bits(wcd937x->regmap, WCD937X_ANA_MICB2, WCD937X_ANA_MICB_VOUT, vout_ctl[1]); - regmap_update_bits(wcd937x->regmap, WCD937X_ANA_MICB3, WCD937X_ANA_MICB_VOUT, vout_ctl[2]); - - return 0; + regmap_update_bits(wcd937x->regmap, WCD937X_ANA_MICB1, WCD937X_ANA_MICB_VOUT, + wcd937x->common.micb_vout[0]); + regmap_update_bits(wcd937x->regmap, WCD937X_ANA_MICB2, WCD937X_ANA_MICB_VOUT, + wcd937x->common.micb_vout[1]); + regmap_update_bits(wcd937x->regmap, WCD937X_ANA_MICB3, WCD937X_ANA_MICB_VOUT, + wcd937x->common.micb_vout[2]); } static irqreturn_t wcd937x_wd_handle_irq(int irq, void *data) @@ -2630,31 +2612,6 @@ static const struct snd_soc_component_driver soc_codec_dev_wcd937x = { .endianness = 1, }; -static void wcd937x_dt_parse_micbias_info(struct device *dev, struct wcd937x_priv *wcd) -{ - struct device_node *np = dev->of_node; - u32 prop_val = 0; - int ret = 0; - - ret = of_property_read_u32(np, "qcom,micbias1-microvolt", &prop_val); - if (!ret) - wcd->micb1_mv = prop_val / 1000; - else - dev_warn(dev, "Micbias1 DT property not found\n"); - - ret = of_property_read_u32(np, "qcom,micbias2-microvolt", &prop_val); - if (!ret) - wcd->micb2_mv = prop_val / 1000; - else - dev_warn(dev, "Micbias2 DT property not found\n"); - - ret = of_property_read_u32(np, "qcom,micbias3-microvolt", &prop_val); - if (!ret) - wcd->micb3_mv = prop_val / 1000; - else - dev_warn(dev, "Micbias3 DT property not found\n"); -} - static bool wcd937x_swap_gnd_mic(struct snd_soc_component *component) { int value; @@ -2788,7 +2745,7 @@ static int wcd937x_bind(struct device *dev) return ret; } - wcd937x->rxdev = wcd937x_sdw_device_get(wcd937x->rxnode); + wcd937x->rxdev = of_sdw_find_device_by_node(wcd937x->rxnode); if (!wcd937x->rxdev) { dev_err(dev, "could not find slave with matching of node\n"); return -EINVAL; @@ -2797,7 +2754,7 @@ static int wcd937x_bind(struct device *dev) wcd937x->sdw_priv[AIF1_PB] = dev_get_drvdata(wcd937x->rxdev); wcd937x->sdw_priv[AIF1_PB]->wcd937x = wcd937x; - wcd937x->txdev = wcd937x_sdw_device_get(wcd937x->txnode); + wcd937x->txdev = of_sdw_find_device_by_node(wcd937x->txnode); if (!wcd937x->txdev) { dev_err(dev, "could not find txslave with matching of node\n"); return -EINVAL; @@ -2833,7 +2790,7 @@ static int wcd937x_bind(struct device *dev) return -EINVAL; } - wcd937x->regmap = dev_get_regmap(&wcd937x->tx_sdw_dev->dev, NULL); + wcd937x->regmap = wcd937x->sdw_priv[AIF1_CAP]->regmap; if (!wcd937x->regmap) { dev_err(dev, "could not get TX device regmap\n"); return -EINVAL; @@ -2848,11 +2805,7 @@ static int wcd937x_bind(struct device *dev) wcd937x->sdw_priv[AIF1_PB]->slave_irq = wcd937x->virq; wcd937x->sdw_priv[AIF1_CAP]->slave_irq = wcd937x->virq; - ret = wcd937x_set_micbias_data(wcd937x); - if (ret < 0) { - dev_err(dev, "Bad micbias pdata\n"); - return ret; - } + wcd937x_set_micbias_data(dev, wcd937x); ret = snd_soc_register_component(dev, &soc_codec_dev_wcd937x, wcd937x_dais, ARRAY_SIZE(wcd937x_dais)); @@ -2920,6 +2873,8 @@ static int wcd937x_probe(struct platform_device *pdev) dev_set_drvdata(dev, wcd937x); mutex_init(&wcd937x->micb_lock); + wcd937x->common.dev = dev; + wcd937x->common.max_bias = 3; wcd937x->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(wcd937x->reset_gpio)) @@ -2939,13 +2894,15 @@ static int wcd937x_probe(struct platform_device *pdev) if (ret) return dev_err_probe(dev, ret, "Failed to get and enable supplies\n"); - wcd937x_dt_parse_micbias_info(dev, wcd937x); + ret = wcd_dt_parse_micbias_info(&wcd937x->common); + if (ret) + return dev_err_probe(dev, ret, "Failed to get micbias\n"); cfg->mbhc_micbias = MIC_BIAS_2; cfg->anc_micbias = MIC_BIAS_2; cfg->v_hs_max = WCD_MBHC_HS_V_MAX; cfg->num_btn = WCD937X_MBHC_MAX_BUTTONS; - cfg->micb_mv = wcd937x->micb2_mv; + cfg->micb_mv = wcd937x->common.micb_mv[2]; cfg->linein_th = 5000; cfg->hs_thr = 1700; cfg->hph_thr = 50; diff --git a/sound/soc/codecs/wcd937x.h b/sound/soc/codecs/wcd937x.h index 3ab21bb5846e..3d0ba3cc0ee6 100644 --- a/sound/soc/codecs/wcd937x.h +++ b/sound/soc/codecs/wcd937x.h @@ -7,6 +7,7 @@ #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include "wcd-common.h" #define WCD937X_BASE_ADDRESS 0x3000 #define WCD937X_ANA_BIAS 0x3001 @@ -507,26 +508,13 @@ enum wcd937x_rx_sdw_ports { WCD937X_MAX_SWR_PORTS = WCD937X_DSD_PORT, }; -struct wcd937x_sdw_ch_info { - int port_num; - unsigned int ch_mask; - unsigned int master_ch_mask; -}; - -#define WCD_SDW_CH(id, pn, cmask) \ - [id] = { \ - .port_num = pn, \ - .ch_mask = cmask, \ - .master_ch_mask = cmask, \ - } - struct wcd937x_priv; struct wcd937x_sdw_priv { struct sdw_slave *sdev; struct sdw_stream_config sconfig; struct sdw_stream_runtime *sruntime; struct sdw_port_config port_config[WCD937X_MAX_SWR_PORTS]; - struct wcd937x_sdw_ch_info *ch_info; + struct wcd_sdw_ch_info *ch_info; bool port_enable[WCD937X_MAX_SWR_CH_IDS]; unsigned int master_channel_map[SDW_MAX_PORTS]; int active_ports; @@ -549,24 +537,22 @@ int wcd937x_sdw_hw_params(struct wcd937x_sdw_priv *wcd, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai); -struct device *wcd937x_sdw_device_get(struct device_node *np); - #else -int wcd937x_sdw_free(struct wcd937x_sdw_priv *wcd, +static inline int wcd937x_sdw_free(struct wcd937x_sdw_priv *wcd, struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { return -EOPNOTSUPP; } -int wcd937x_sdw_set_sdw_stream(struct wcd937x_sdw_priv *wcd, +static inline int wcd937x_sdw_set_sdw_stream(struct wcd937x_sdw_priv *wcd, struct snd_soc_dai *dai, void *stream, int direction) { return -EOPNOTSUPP; } -int wcd937x_sdw_hw_params(struct wcd937x_sdw_priv *wcd, +static inline int wcd937x_sdw_hw_params(struct wcd937x_sdw_priv *wcd, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) diff --git a/sound/soc/codecs/wcd938x-sdw.c b/sound/soc/codecs/wcd938x-sdw.c index e822cc145250..add907cb2706 100644 --- a/sound/soc/codecs/wcd938x-sdw.c +++ b/sound/soc/codecs/wcd938x-sdw.c @@ -18,10 +18,9 @@ #include <sound/soc.h> #include <sound/soc-dapm.h> #include "wcd938x.h" +#include "wcd-common.h" -#define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m) (0xE0 + 0x10 * (m)) - -static const struct wcd938x_sdw_ch_info wcd938x_sdw_rx_ch_info[] = { +static const struct wcd_sdw_ch_info wcd938x_sdw_rx_ch_info[] = { WCD_SDW_CH(WCD938X_HPH_L, WCD938X_HPH_PORT, BIT(0)), WCD_SDW_CH(WCD938X_HPH_R, WCD938X_HPH_PORT, BIT(1)), WCD_SDW_CH(WCD938X_CLSH, WCD938X_CLSH_PORT, BIT(0)), @@ -32,7 +31,7 @@ static const struct wcd938x_sdw_ch_info wcd938x_sdw_rx_ch_info[] = { WCD_SDW_CH(WCD938X_DSD_R, WCD938X_DSD_PORT, BIT(1)), }; -static const struct wcd938x_sdw_ch_info wcd938x_sdw_tx_ch_info[] = { +static const struct wcd_sdw_ch_info wcd938x_sdw_tx_ch_info[] = { WCD_SDW_CH(WCD938X_ADC1, WCD938X_ADC_1_2_PORT, BIT(0)), WCD_SDW_CH(WCD938X_ADC2, WCD938X_ADC_1_2_PORT, BIT(1)), WCD_SDW_CH(WCD938X_ADC3, WCD938X_ADC_3_4_PORT, BIT(0)), @@ -82,23 +81,6 @@ static struct sdw_dpn_prop wcd938x_dpn_prop[WCD938X_MAX_SWR_PORTS] = { } }; -struct device *wcd938x_sdw_device_get(struct device_node *np) -{ - return bus_find_device_by_of_node(&sdw_bus_type, np); - -} -EXPORT_SYMBOL_GPL(wcd938x_sdw_device_get); - -int wcd938x_swr_get_current_bank(struct sdw_slave *sdev) -{ - int bank; - - bank = sdw_read(sdev, SDW_SCP_CTRL); - - return ((bank & 0x40) ? 1 : 0); -} -EXPORT_SYMBOL_GPL(wcd938x_swr_get_current_bank); - int wcd938x_sdw_hw_params(struct wcd938x_sdw_priv *wcd, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, @@ -158,44 +140,13 @@ int wcd938x_sdw_set_sdw_stream(struct wcd938x_sdw_priv *wcd, } EXPORT_SYMBOL_GPL(wcd938x_sdw_set_sdw_stream); -static int wcd9380_update_status(struct sdw_slave *slave, - enum sdw_slave_status status) -{ - struct wcd938x_sdw_priv *wcd = dev_get_drvdata(&slave->dev); - - if (wcd->regmap && (status == SDW_SLAVE_ATTACHED)) { - /* Write out any cached changes that happened between probe and attach */ - regcache_cache_only(wcd->regmap, false); - return regcache_sync(wcd->regmap); - } - - return 0; -} - -static int wcd9380_bus_config(struct sdw_slave *slave, - struct sdw_bus_params *params) -{ - sdw_write(slave, SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(params->next_bank), 0x01); - - return 0; -} - static int wcd9380_interrupt_callback(struct sdw_slave *slave, struct sdw_slave_intr_status *status) { struct wcd938x_sdw_priv *wcd = dev_get_drvdata(&slave->dev); - struct irq_domain *slave_irq = wcd->slave_irq; - u32 sts1, sts2, sts3; - - do { - handle_nested_irq(irq_find_mapping(slave_irq, 0)); - regmap_read(wcd->regmap, WCD938X_DIGITAL_INTR_STATUS_0, &sts1); - regmap_read(wcd->regmap, WCD938X_DIGITAL_INTR_STATUS_1, &sts2); - regmap_read(wcd->regmap, WCD938X_DIGITAL_INTR_STATUS_2, &sts3); - } while (sts1 || sts2 || sts3); - - return IRQ_HANDLED; + return wcd_interrupt_callback(slave, wcd->slave_irq, WCD938X_DIGITAL_INTR_STATUS_0, + WCD938X_DIGITAL_INTR_STATUS_1, WCD938X_DIGITAL_INTR_STATUS_2); } static const struct reg_default wcd938x_defaults[] = { @@ -1193,25 +1144,9 @@ static const struct regmap_config wcd938x_regmap_config = { }; static const struct sdw_slave_ops wcd9380_slave_ops = { - .update_status = wcd9380_update_status, + .update_status = wcd_update_status, .interrupt_callback = wcd9380_interrupt_callback, - .bus_config = wcd9380_bus_config, -}; - -static int wcd938x_sdw_component_bind(struct device *dev, - struct device *master, void *data) -{ - return 0; -} - -static void wcd938x_sdw_component_unbind(struct device *dev, - struct device *master, void *data) -{ -} - -static const struct component_ops wcd938x_sdw_component_ops = { - .bind = wcd938x_sdw_component_bind, - .unbind = wcd938x_sdw_component_unbind, + .bus_config = wcd_bus_config, }; static int wcd9380_probe(struct sdw_slave *pdev, @@ -1278,7 +1213,7 @@ static int wcd9380_probe(struct sdw_slave *pdev, pm_runtime_set_active(dev); pm_runtime_enable(dev); - ret = component_add(dev, &wcd938x_sdw_component_ops); + ret = component_add(dev, &wcd_sdw_component_ops); if (ret) goto err_disable_rpm; @@ -1296,7 +1231,7 @@ static int wcd9380_remove(struct sdw_slave *pdev) { struct device *dev = &pdev->dev; - component_del(dev, &wcd938x_sdw_component_ops); + component_del(dev, &wcd_sdw_component_ops); pm_runtime_disable(dev); pm_runtime_set_suspended(dev); diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index 711f373ece24..e1a4783b984c 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -22,6 +22,7 @@ #include <linux/regulator/consumer.h> #include "wcd-clsh-v2.h" +#include "wcd-common.h" #include "wcd-mbhc-v2.h" #include "wcd938x.h" @@ -155,6 +156,7 @@ struct wcd938x_priv { struct wcd_mbhc_config mbhc_cfg; struct wcd_mbhc_intr intr_ids; struct wcd_clsh_ctrl *clsh_info; + struct wcd_common common; struct irq_domain *virq; struct regmap_irq_chip_data *irq_chip; struct snd_soc_jack *jack; @@ -169,10 +171,6 @@ struct wcd938x_priv { struct gpio_desc *us_euro_gpio; struct mux_control *us_euro_mux; unsigned int mux_state; - u32 micb1_mv; - u32 micb2_mv; - u32 micb3_mv; - u32 micb4_mv; int hphr_pdm_wd_int; int hphl_pdm_wd_int; int aux_pdm_wd_int; @@ -396,7 +394,7 @@ static int wcd938x_io_init(struct wcd938x_priv *wcd938x) } -static int wcd938x_sdw_connect_port(const struct wcd938x_sdw_ch_info *ch_info, +static int wcd938x_sdw_connect_port(const struct wcd_sdw_ch_info *ch_info, struct sdw_port_config *port_config, u8 enable) { @@ -1094,8 +1092,7 @@ static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w, int bank; int rate; - bank = (wcd938x_swr_get_current_bank(wcd938x->sdw_priv[AIF1_CAP]->sdev)) ? 0 : 1; - bank = bank ? 0 : 1; + bank = sdw_slave_get_current_bank(wcd938x->sdw_priv[AIF1_CAP]->sdev); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -1975,15 +1972,6 @@ static void wcd938x_mbhc_micb_ramp_control(struct snd_soc_component *component, } } -static int wcd938x_get_micb_vout_ctl_val(u32 micb_mv) -{ - /* min micbias voltage is 1V and maximum is 2.85V */ - if (micb_mv < 1000 || micb_mv > 2850) - return -EINVAL; - - return (micb_mv - 1000) / 50; -} - static int wcd938x_mbhc_micb_adjust_voltage(struct snd_soc_component *component, int req_volt, int micb_num) { @@ -2020,7 +2008,7 @@ static int wcd938x_mbhc_micb_adjust_voltage(struct snd_soc_component *component, cur_vout_ctl = snd_soc_component_read_field(component, micb_reg, WCD938X_MICB_VOUT_MASK); - req_vout_ctl = wcd938x_get_micb_vout_ctl_val(req_volt); + req_vout_ctl = wcd_get_micb_vout_ctl_val(component->dev, req_volt); if (req_vout_ctl < 0) { ret = -EINVAL; goto exit; @@ -2068,10 +2056,10 @@ static int wcd938x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *compon * voltage needed to detect threshold microphone, then do * not change the micbias, just return. */ - if (wcd938x->micb2_mv >= WCD_MBHC_THR_HS_MICB_MV) + if (wcd938x->common.micb_mv[2] >= WCD_MBHC_THR_HS_MICB_MV) return 0; - micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd938x->micb2_mv; + micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd938x->common.micb_mv[2]; return wcd938x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2); } @@ -2976,28 +2964,16 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = { {"EAR", NULL, "EAR PGA"}, }; -static int wcd938x_set_micbias_data(struct wcd938x_priv *wcd938x) +static void wcd938x_set_micbias_data(struct device *dev, struct wcd938x_priv *wcd938x) { - int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4; - - /* set micbias voltage */ - vout_ctl_1 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb1_mv); - vout_ctl_2 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb2_mv); - vout_ctl_3 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb3_mv); - vout_ctl_4 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb4_mv); - if (vout_ctl_1 < 0 || vout_ctl_2 < 0 || vout_ctl_3 < 0 || vout_ctl_4 < 0) - return -EINVAL; - regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB1, - WCD938X_MICB_VOUT_MASK, vout_ctl_1); + WCD938X_MICB_VOUT_MASK, wcd938x->common.micb_vout[0]); regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB2, - WCD938X_MICB_VOUT_MASK, vout_ctl_2); + WCD938X_MICB_VOUT_MASK, wcd938x->common.micb_vout[1]); regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB3, - WCD938X_MICB_VOUT_MASK, vout_ctl_3); + WCD938X_MICB_VOUT_MASK, wcd938x->common.micb_vout[2]); regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB4, - WCD938X_MICB_VOUT_MASK, vout_ctl_4); - - return 0; + WCD938X_MICB_VOUT_MASK, wcd938x->common.micb_vout[3]); } static irqreturn_t wcd938x_wd_handle_irq(int irq, void *data) @@ -3201,37 +3177,6 @@ static const struct snd_soc_component_driver soc_codec_dev_wcd938x = { .endianness = 1, }; -static void wcd938x_dt_parse_micbias_info(struct device *dev, struct wcd938x_priv *wcd) -{ - struct device_node *np = dev->of_node; - u32 prop_val = 0; - int rc = 0; - - rc = of_property_read_u32(np, "qcom,micbias1-microvolt", &prop_val); - if (!rc) - wcd->micb1_mv = prop_val/1000; - else - dev_info(dev, "%s: Micbias1 DT property not found\n", __func__); - - rc = of_property_read_u32(np, "qcom,micbias2-microvolt", &prop_val); - if (!rc) - wcd->micb2_mv = prop_val/1000; - else - dev_info(dev, "%s: Micbias2 DT property not found\n", __func__); - - rc = of_property_read_u32(np, "qcom,micbias3-microvolt", &prop_val); - if (!rc) - wcd->micb3_mv = prop_val/1000; - else - dev_info(dev, "%s: Micbias3 DT property not found\n", __func__); - - rc = of_property_read_u32(np, "qcom,micbias4-microvolt", &prop_val); - if (!rc) - wcd->micb4_mv = prop_val/1000; - else - dev_info(dev, "%s: Micbias4 DT property not found\n", __func__); -} - static bool wcd938x_swap_gnd_mic(struct snd_soc_component *component) { struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); @@ -3296,13 +3241,15 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device if (ret) return dev_err_probe(dev, ret, "Failed to get and enable supplies\n"); - wcd938x_dt_parse_micbias_info(dev, wcd938x); + ret = wcd_dt_parse_micbias_info(&wcd938x->common); + if (ret) + return dev_err_probe(dev, ret, "Failed to get and enable supplies\n"); cfg->mbhc_micbias = MIC_BIAS_2; cfg->anc_micbias = MIC_BIAS_2; cfg->v_hs_max = WCD_MBHC_HS_V_MAX; cfg->num_btn = WCD938X_MBHC_MAX_BUTTONS; - cfg->micb_mv = wcd938x->micb2_mv; + cfg->micb_mv = wcd938x->common.micb_mv[2]; cfg->linein_th = 5000; cfg->hs_thr = 1700; cfg->hph_thr = 50; @@ -3400,7 +3347,7 @@ static int wcd938x_bind(struct device *dev) return ret; } - wcd938x->rxdev = wcd938x_sdw_device_get(wcd938x->rxnode); + wcd938x->rxdev = of_sdw_find_device_by_node(wcd938x->rxnode); if (!wcd938x->rxdev) { dev_err(dev, "could not find slave with matching of node\n"); ret = -EINVAL; @@ -3409,7 +3356,7 @@ static int wcd938x_bind(struct device *dev) wcd938x->sdw_priv[AIF1_PB] = dev_get_drvdata(wcd938x->rxdev); wcd938x->sdw_priv[AIF1_PB]->wcd938x = wcd938x; - wcd938x->txdev = wcd938x_sdw_device_get(wcd938x->txnode); + wcd938x->txdev = of_sdw_find_device_by_node(wcd938x->txnode); if (!wcd938x->txdev) { dev_err(dev, "could not find txslave with matching of node\n"); ret = -EINVAL; @@ -3442,7 +3389,7 @@ static int wcd938x_bind(struct device *dev) goto err_remove_tx_link; } - wcd938x->regmap = dev_get_regmap(&wcd938x->tx_sdw_dev->dev, NULL); + wcd938x->regmap = wcd938x->sdw_priv[AIF1_CAP]->regmap; if (!wcd938x->regmap) { dev_err(dev, "could not get TX device regmap\n"); ret = -EINVAL; @@ -3458,11 +3405,7 @@ static int wcd938x_bind(struct device *dev) wcd938x->sdw_priv[AIF1_PB]->slave_irq = wcd938x->virq; wcd938x->sdw_priv[AIF1_CAP]->slave_irq = wcd938x->virq; - ret = wcd938x_set_micbias_data(wcd938x); - if (ret < 0) { - dev_err(dev, "%s: bad micbias pdata\n", __func__); - goto err_remove_rx_link; - } + wcd938x_set_micbias_data(dev, wcd938x); ret = snd_soc_register_component(dev, &soc_codec_dev_wcd938x, wcd938x_dais, ARRAY_SIZE(wcd938x_dais)); @@ -3551,6 +3494,8 @@ static int wcd938x_probe(struct platform_device *pdev) dev_set_drvdata(dev, wcd938x); mutex_init(&wcd938x->micb_lock); + wcd938x->common.dev = dev; + wcd938x->common.max_bias = 4; ret = wcd938x_populate_dt_data(wcd938x, dev); if (ret) diff --git a/sound/soc/codecs/wcd938x.h b/sound/soc/codecs/wcd938x.h index fb6a0e4ef337..c18610466d7d 100644 --- a/sound/soc/codecs/wcd938x.h +++ b/sound/soc/codecs/wcd938x.h @@ -587,17 +587,6 @@ #define WCD938X_MAX_SWR_CH_IDS 15 -struct wcd938x_sdw_ch_info { - int port_num; - unsigned int ch_mask; -}; - -#define WCD_SDW_CH(id, pn, cmask) \ - [id] = { \ - .port_num = pn, \ - .ch_mask = cmask, \ - } - enum wcd938x_tx_sdw_ports { WCD938X_ADC_1_2_PORT = 1, WCD938X_ADC_3_4_PORT, @@ -649,7 +638,7 @@ struct wcd938x_sdw_priv { struct sdw_stream_config sconfig; struct sdw_stream_runtime *sruntime; struct sdw_port_config port_config[WCD938X_MAX_SWR_PORTS]; - const struct wcd938x_sdw_ch_info *ch_info; + const struct wcd_sdw_ch_info *ch_info; bool port_enable[WCD938X_MAX_SWR_CH_IDS]; int active_ports; bool is_tx; @@ -669,10 +658,6 @@ int wcd938x_sdw_hw_params(struct wcd938x_sdw_priv *wcd, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai); - -struct device *wcd938x_sdw_device_get(struct device_node *np); -int wcd938x_swr_get_current_bank(struct sdw_slave *sdev); - #else static inline int wcd938x_sdw_free(struct wcd938x_sdw_priv *wcd, @@ -697,14 +682,5 @@ static inline int wcd938x_sdw_hw_params(struct wcd938x_sdw_priv *wcd, return -EOPNOTSUPP; } -static inline struct device *wcd938x_sdw_device_get(struct device_node *np) -{ - return NULL; -} - -static inline int wcd938x_swr_get_current_bank(struct sdw_slave *sdev) -{ - return 0; -} #endif /* CONFIG_SND_SOC_WCD938X_SDW */ #endif /* __WCD938X_H__ */ diff --git a/sound/soc/codecs/wcd939x-sdw.c b/sound/soc/codecs/wcd939x-sdw.c index f7a9323a9fea..d369100a2457 100644 --- a/sound/soc/codecs/wcd939x-sdw.c +++ b/sound/soc/codecs/wcd939x-sdw.c @@ -20,10 +20,9 @@ #include <sound/soc.h> #include <sound/soc-dapm.h> #include "wcd939x.h" +#include "wcd-common.h" -#define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m) (0xE0 + 0x10 * (m)) - -static const struct wcd939x_sdw_ch_info wcd939x_sdw_rx_ch_info[] = { +static const struct wcd_sdw_ch_info wcd939x_sdw_rx_ch_info[] = { WCD_SDW_CH(WCD939X_HPH_L, WCD939X_HPH_PORT, BIT(0)), WCD_SDW_CH(WCD939X_HPH_R, WCD939X_HPH_PORT, BIT(1)), WCD_SDW_CH(WCD939X_CLSH, WCD939X_CLSH_PORT, BIT(0)), @@ -36,7 +35,7 @@ static const struct wcd939x_sdw_ch_info wcd939x_sdw_rx_ch_info[] = { WCD_SDW_CH(WCD939X_HIFI_PCM_R, WCD939X_HIFI_PCM_PORT, BIT(1)), }; -static const struct wcd939x_sdw_ch_info wcd939x_sdw_tx_ch_info[] = { +static const struct wcd_sdw_ch_info wcd939x_sdw_tx_ch_info[] = { WCD_SDW_CH(WCD939X_ADC1, WCD939X_ADC_1_4_PORT, BIT(0)), WCD_SDW_CH(WCD939X_ADC2, WCD939X_ADC_1_4_PORT, BIT(1)), WCD_SDW_CH(WCD939X_ADC3, WCD939X_ADC_1_4_PORT, BIT(2)), @@ -128,19 +127,6 @@ static struct sdw_dpn_prop wcd939x_tx_dpn_prop[WCD939X_MAX_TX_SWR_PORTS] = { } }; -struct device *wcd939x_sdw_device_get(struct device_node *np) -{ - return bus_find_device_by_of_node(&sdw_bus_type, np); -} -EXPORT_SYMBOL_GPL(wcd939x_sdw_device_get); - -unsigned int wcd939x_swr_get_current_bank(struct sdw_slave *sdev) -{ - return FIELD_GET(SDW_SCP_STAT_CURR_BANK, - sdw_read(sdev, SDW_SCP_CTRL)); -} -EXPORT_SYMBOL_GPL(wcd939x_swr_get_current_bank); - int wcd939x_sdw_hw_params(struct wcd939x_sdw_priv *wcd, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, @@ -199,38 +185,6 @@ int wcd939x_sdw_set_sdw_stream(struct wcd939x_sdw_priv *wcd, } EXPORT_SYMBOL_GPL(wcd939x_sdw_set_sdw_stream); -struct regmap *wcd939x_swr_get_regmap(struct wcd939x_sdw_priv *wcd) -{ - if (wcd->regmap) - return wcd->regmap; - - return ERR_PTR(-EINVAL); -} -EXPORT_SYMBOL_GPL(wcd939x_swr_get_regmap); - -static int wcd9390_update_status(struct sdw_slave *slave, - enum sdw_slave_status status) -{ - struct wcd939x_sdw_priv *wcd = dev_get_drvdata(&slave->dev); - - if (wcd->regmap && status == SDW_SLAVE_ATTACHED) { - /* Write out any cached changes that happened between probe and attach */ - regcache_cache_only(wcd->regmap, false); - return regcache_sync(wcd->regmap); - } - - return 0; -} - -static int wcd9390_bus_config(struct sdw_slave *slave, - struct sdw_bus_params *params) -{ - sdw_write(slave, SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(params->next_bank), - 0x01); - - return 0; -} - /* * Handle Soundwire out-of-band interrupt event by triggering * the first irq of the slave_irq irq domain, which then will @@ -241,18 +195,9 @@ static int wcd9390_interrupt_callback(struct sdw_slave *slave, struct sdw_slave_intr_status *status) { struct wcd939x_sdw_priv *wcd = dev_get_drvdata(&slave->dev); - struct irq_domain *slave_irq = wcd->slave_irq; - u32 sts1, sts2, sts3; - - do { - handle_nested_irq(irq_find_mapping(slave_irq, 0)); - regmap_read(wcd->regmap, WCD939X_DIGITAL_INTR_STATUS_0, &sts1); - regmap_read(wcd->regmap, WCD939X_DIGITAL_INTR_STATUS_1, &sts2); - regmap_read(wcd->regmap, WCD939X_DIGITAL_INTR_STATUS_2, &sts3); - - } while (sts1 || sts2 || sts3); - return IRQ_HANDLED; + return wcd_interrupt_callback(slave, wcd->slave_irq, WCD939X_DIGITAL_INTR_STATUS_0, + WCD939X_DIGITAL_INTR_STATUS_1, WCD939X_DIGITAL_INTR_STATUS_2); } static const struct reg_default wcd939x_defaults[] = { @@ -1385,34 +1330,9 @@ static const struct regmap_config wcd939x_regmap_config = { }; static const struct sdw_slave_ops wcd9390_slave_ops = { - .update_status = wcd9390_update_status, + .update_status = wcd_update_status, .interrupt_callback = wcd9390_interrupt_callback, - .bus_config = wcd9390_bus_config, -}; - -static int wcd939x_sdw_component_bind(struct device *dev, struct device *master, - void *data) -{ - pm_runtime_set_autosuspend_delay(dev, 3000); - pm_runtime_use_autosuspend(dev); - pm_runtime_mark_last_busy(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - - return 0; -} - -static void wcd939x_sdw_component_unbind(struct device *dev, - struct device *master, void *data) -{ - pm_runtime_disable(dev); - pm_runtime_set_suspended(dev); - pm_runtime_dont_use_autosuspend(dev); -} - -static const struct component_ops wcd939x_sdw_component_ops = { - .bind = wcd939x_sdw_component_bind, - .unbind = wcd939x_sdw_component_unbind, + .bus_config = wcd_bus_config, }; static int wcd9390_probe(struct sdw_slave *pdev, const struct sdw_device_id *id) @@ -1478,7 +1398,7 @@ static int wcd9390_probe(struct sdw_slave *pdev, const struct sdw_device_id *id) regcache_cache_only(wcd->regmap, true); } - ret = component_add(dev, &wcd939x_sdw_component_ops); + ret = component_add(dev, &wcd_sdw_component_ops); if (ret) return ret; @@ -1493,7 +1413,7 @@ static int wcd9390_remove(struct sdw_slave *pdev) struct device *dev = &pdev->dev; struct wcd939x_sdw_priv *wcd = dev_get_drvdata(dev); - component_del(dev, &wcd939x_sdw_component_ops); + component_del(dev, &wcd_sdw_component_ops); if (wcd->regmap) regmap_exit(wcd->regmap); diff --git a/sound/soc/codecs/wcd939x.c b/sound/soc/codecs/wcd939x.c index 64f082e474c1..e74e6f013131 100644 --- a/sound/soc/codecs/wcd939x.c +++ b/sound/soc/codecs/wcd939x.c @@ -28,6 +28,7 @@ #include <linux/usb/typec_altmode.h> #include "wcd-clsh-v2.h" +#include "wcd-common.h" #include "wcd-mbhc-v2.h" #include "wcd939x.h" @@ -191,6 +192,7 @@ struct wcd939x_priv { struct wcd_mbhc_config mbhc_cfg; struct wcd_mbhc_intr intr_ids; struct wcd_clsh_ctrl *clsh_info; + struct wcd_common common; struct irq_domain *virq; struct regmap_irq_chip_data *irq_chip; struct snd_soc_jack *jack; @@ -201,10 +203,6 @@ struct wcd939x_priv { u32 tx_mode[TX_ADC_MAX]; int variant; struct gpio_desc *reset_gpio; - u32 micb1_mv; - u32 micb2_mv; - u32 micb3_mv; - u32 micb4_mv; int hphr_pdm_wd_int; int hphl_pdm_wd_int; int ear_pdm_wd_int; @@ -415,7 +413,7 @@ static int wcd939x_io_init(struct snd_soc_component *component) return 0; } -static int wcd939x_sdw_connect_port(const struct wcd939x_sdw_ch_info *ch_info, +static int wcd939x_sdw_connect_port(const struct wcd_sdw_ch_info *ch_info, struct sdw_port_config *port_config, u8 enable) { @@ -1017,7 +1015,7 @@ static int wcd939x_tx_swr_ctrl(struct snd_soc_dapm_widget *w, int bank; int rate; - bank = wcd939x_swr_get_current_bank(wcd939x->sdw_priv[AIF1_CAP]->sdev); + bank = sdw_slave_get_current_bank(wcd939x->sdw_priv[AIF1_CAP]->sdev); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -1919,17 +1917,6 @@ static void wcd939x_mbhc_micb_ramp_control(struct snd_soc_component *component, } } -static int wcd939x_get_micb_vout_ctl_val(u32 micb_mv) -{ - /* min micbias voltage is 1V and maximum is 2.85V */ - if (micb_mv < 1000 || micb_mv > 2850) { - pr_err("%s: unsupported micbias voltage\n", __func__); - return -EINVAL; - } - - return (micb_mv - 1000) / 50; -} - static int wcd939x_mbhc_micb_adjust_voltage(struct snd_soc_component *component, int req_volt, int micb_num) { @@ -1969,7 +1956,7 @@ static int wcd939x_mbhc_micb_adjust_voltage(struct snd_soc_component *component, cur_vout_ctl = snd_soc_component_read_field(component, micb_reg, WCD939X_MICB_VOUT_CTL); - req_vout_ctl = wcd939x_get_micb_vout_ctl_val(req_volt); + req_vout_ctl = wcd_get_micb_vout_ctl_val(component->dev, req_volt); if (req_vout_ctl < 0) { ret = req_vout_ctl; goto exit; @@ -2021,10 +2008,10 @@ static int wcd939x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *compon * voltage needed to detect threshold microphone, then do * not change the micbias, just return. */ - if (wcd939x->micb2_mv >= WCD_MBHC_THR_HS_MICB_MV) + if (wcd939x->common.micb_mv[1] >= WCD_MBHC_THR_HS_MICB_MV) return 0; - micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd939x->micb2_mv; + micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd939x->common.micb_mv[1]; return wcd939x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2); } @@ -2895,28 +2882,16 @@ static const struct snd_soc_dapm_route wcd939x_audio_map[] = { {"EAR", NULL, "EAR PGA"}, }; -static int wcd939x_set_micbias_data(struct wcd939x_priv *wcd939x) +static void wcd939x_set_micbias_data(struct device *dev, struct wcd939x_priv *wcd939x) { - int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4; - - /* set micbias voltage */ - vout_ctl_1 = wcd939x_get_micb_vout_ctl_val(wcd939x->micb1_mv); - vout_ctl_2 = wcd939x_get_micb_vout_ctl_val(wcd939x->micb2_mv); - vout_ctl_3 = wcd939x_get_micb_vout_ctl_val(wcd939x->micb3_mv); - vout_ctl_4 = wcd939x_get_micb_vout_ctl_val(wcd939x->micb4_mv); - if (vout_ctl_1 < 0 || vout_ctl_2 < 0 || vout_ctl_3 < 0 || vout_ctl_4 < 0) - return -EINVAL; - regmap_update_bits(wcd939x->regmap, WCD939X_ANA_MICB1, - WCD939X_MICB_VOUT_CTL, vout_ctl_1); + WCD939X_MICB_VOUT_CTL, wcd939x->common.micb_vout[0]); regmap_update_bits(wcd939x->regmap, WCD939X_ANA_MICB2, - WCD939X_MICB_VOUT_CTL, vout_ctl_2); + WCD939X_MICB_VOUT_CTL, wcd939x->common.micb_vout[1]); regmap_update_bits(wcd939x->regmap, WCD939X_ANA_MICB3, - WCD939X_MICB_VOUT_CTL, vout_ctl_3); + WCD939X_MICB_VOUT_CTL, wcd939x->common.micb_vout[2]); regmap_update_bits(wcd939x->regmap, WCD939X_ANA_MICB4, - WCD939X_MICB_VOUT_CTL, vout_ctl_4); - - return 0; + WCD939X_MICB_VOUT_CTL, wcd939x->common.micb_vout[3]); } static irqreturn_t wcd939x_wd_handle_irq(int irq, void *data) @@ -3186,37 +3161,6 @@ static int wcd939x_typec_mux_set(struct typec_mux_dev *mux, } #endif /* CONFIG_TYPEC */ -static void wcd939x_dt_parse_micbias_info(struct device *dev, struct wcd939x_priv *wcd) -{ - struct device_node *np = dev->of_node; - u32 prop_val = 0; - int rc = 0; - - rc = of_property_read_u32(np, "qcom,micbias1-microvolt", &prop_val); - if (!rc) - wcd->micb1_mv = prop_val / 1000; - else - dev_info(dev, "%s: Micbias1 DT property not found\n", __func__); - - rc = of_property_read_u32(np, "qcom,micbias2-microvolt", &prop_val); - if (!rc) - wcd->micb2_mv = prop_val / 1000; - else - dev_info(dev, "%s: Micbias2 DT property not found\n", __func__); - - rc = of_property_read_u32(np, "qcom,micbias3-microvolt", &prop_val); - if (!rc) - wcd->micb3_mv = prop_val / 1000; - else - dev_info(dev, "%s: Micbias3 DT property not found\n", __func__); - - rc = of_property_read_u32(np, "qcom,micbias4-microvolt", &prop_val); - if (!rc) - wcd->micb4_mv = prop_val / 1000; - else - dev_info(dev, "%s: Micbias4 DT property not found\n", __func__); -} - #if IS_ENABLED(CONFIG_TYPEC) static bool wcd939x_swap_gnd_mic(struct snd_soc_component *component) { @@ -3252,13 +3196,15 @@ static int wcd939x_populate_dt_data(struct wcd939x_priv *wcd939x, struct device if (ret) return dev_err_probe(dev, ret, "Failed to get and enable supplies\n"); - wcd939x_dt_parse_micbias_info(dev, wcd939x); + ret = wcd_dt_parse_micbias_info(&wcd939x->common); + if (ret) + return dev_err_probe(dev, ret, "Failed to get micbias\n"); cfg->mbhc_micbias = MIC_BIAS_2; cfg->anc_micbias = MIC_BIAS_2; cfg->v_hs_max = WCD_MBHC_HS_V_MAX; cfg->num_btn = WCD939X_MBHC_MAX_BUTTONS; - cfg->micb_mv = wcd939x->micb2_mv; + cfg->micb_mv = wcd939x->common.micb_mv[1]; cfg->linein_th = 5000; cfg->hs_thr = 1700; cfg->hph_thr = 50; @@ -3383,7 +3329,7 @@ static int wcd939x_bind(struct device *dev) goto err_put_typec_switch; } - wcd939x->rxdev = wcd939x_sdw_device_get(wcd939x->rxnode); + wcd939x->rxdev = of_sdw_find_device_by_node(wcd939x->rxnode); if (!wcd939x->rxdev) { dev_err(dev, "could not find slave with matching of node\n"); ret = -EINVAL; @@ -3392,7 +3338,7 @@ static int wcd939x_bind(struct device *dev) wcd939x->sdw_priv[AIF1_PB] = dev_get_drvdata(wcd939x->rxdev); wcd939x->sdw_priv[AIF1_PB]->wcd939x = wcd939x; - wcd939x->txdev = wcd939x_sdw_device_get(wcd939x->txnode); + wcd939x->txdev = of_sdw_find_device_by_node(wcd939x->txnode); if (!wcd939x->txdev) { dev_err(dev, "could not find txslave with matching of node\n"); ret = -EINVAL; @@ -3428,10 +3374,10 @@ static int wcd939x_bind(struct device *dev) } /* Get regmap from TX SoundWire device */ - wcd939x->regmap = wcd939x_swr_get_regmap(wcd939x->sdw_priv[AIF1_CAP]); - if (IS_ERR(wcd939x->regmap)) { + wcd939x->regmap = wcd939x->sdw_priv[AIF1_CAP]->regmap; + if (!wcd939x->regmap) { dev_err(dev, "could not get TX device regmap\n"); - ret = PTR_ERR(wcd939x->regmap); + ret = -ENODEV; goto err_remove_rx_link; } @@ -3444,11 +3390,7 @@ static int wcd939x_bind(struct device *dev) wcd939x->sdw_priv[AIF1_PB]->slave_irq = wcd939x->virq; wcd939x->sdw_priv[AIF1_CAP]->slave_irq = wcd939x->virq; - ret = wcd939x_set_micbias_data(wcd939x); - if (ret < 0) { - dev_err(dev, "%s: bad micbias pdata\n", __func__); - goto err_remove_rx_link; - } + wcd939x_set_micbias_data(dev, wcd939x); /* Check WCD9395 version */ regmap_read(wcd939x->regmap, WCD939X_DIGITAL_CHIP_ID1, &id1); @@ -3613,6 +3555,8 @@ static int wcd939x_probe(struct platform_device *pdev) dev_set_drvdata(dev, wcd939x); mutex_init(&wcd939x->micb_lock); + wcd939x->common.dev = dev; + wcd939x->common.max_bias = 4; ret = wcd939x_populate_dt_data(wcd939x, dev); if (ret) { diff --git a/sound/soc/codecs/wcd939x.h b/sound/soc/codecs/wcd939x.h index 3204fb10b58d..6bd2366587a8 100644 --- a/sound/soc/codecs/wcd939x.h +++ b/sound/soc/codecs/wcd939x.h @@ -844,17 +844,6 @@ #define WCD939X_MAX_SWR_CH_IDS (15) -struct wcd939x_sdw_ch_info { - int port_num; - unsigned int ch_mask; -}; - -#define WCD_SDW_CH(id, pn, cmask) \ - [id] = { \ - .port_num = pn, \ - .ch_mask = cmask, \ - } - enum wcd939x_tx_sdw_ports { WCD939X_ADC_1_4_PORT = 1, WCD939X_ADC_DMIC_1_2_PORT, @@ -909,7 +898,7 @@ struct wcd939x_sdw_priv { struct sdw_stream_config sconfig; struct sdw_stream_runtime *sruntime; struct sdw_port_config port_config[WCD939X_MAX_SWR_PORTS]; - const struct wcd939x_sdw_ch_info *ch_info; + const struct wcd_sdw_ch_info *ch_info; bool port_enable[WCD939X_MAX_SWR_CH_IDS]; int active_ports; bool is_tx; @@ -929,11 +918,6 @@ int wcd939x_sdw_hw_params(struct wcd939x_sdw_priv *wcd, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai); - -struct device *wcd939x_sdw_device_get(struct device_node *np); -unsigned int wcd939x_swr_get_current_bank(struct sdw_slave *sdev); - -struct regmap *wcd939x_swr_get_regmap(struct wcd939x_sdw_priv *wcd); #else static inline int wcd939x_sdw_free(struct wcd939x_sdw_priv *wcd, @@ -958,20 +942,6 @@ static inline int wcd939x_sdw_hw_params(struct wcd939x_sdw_priv *wcd, return -EOPNOTSUPP; } -static inline struct device *wcd939x_sdw_device_get(struct device_node *np) -{ - return NULL; -} - -static inline unsigned int wcd939x_swr_get_current_bank(struct sdw_slave *sdev) -{ - return 0; -} - -struct regmap *wcd939x_swr_get_regmap(struct wcd939x_sdw_priv *wcd) -{ - return PTR_ERR(-EINVAL); -} #endif /* CONFIG_SND_SOC_WCD939X_SDW */ #endif /* __WCD939X_H__ */ diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c deleted file mode 100644 index 737ca82cf976..000000000000 --- a/sound/soc/codecs/wl1273.c +++ /dev/null @@ -1,500 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * ALSA SoC WL1273 codec driver - * - * Author: Matti Aaltonen, <matti.j.aaltonen@nokia.com> - * - * Copyright: (C) 2010, 2011 Nokia Corporation - */ - -#include <linux/mfd/wl1273-core.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/soc.h> -#include <sound/initval.h> - -#include "wl1273.h" - -enum wl1273_mode { WL1273_MODE_BT, WL1273_MODE_FM_RX, WL1273_MODE_FM_TX }; - -/* codec private data */ -struct wl1273_priv { - enum wl1273_mode mode; - struct wl1273_core *core; - unsigned int channels; -}; - -static int snd_wl1273_fm_set_i2s_mode(struct wl1273_core *core, - int rate, int width) -{ - struct device *dev = &core->client->dev; - int r = 0; - u16 mode; - - dev_dbg(dev, "rate: %d\n", rate); - dev_dbg(dev, "width: %d\n", width); - - mutex_lock(&core->lock); - - mode = core->i2s_mode & ~WL1273_IS2_WIDTH & ~WL1273_IS2_RATE; - - switch (rate) { - case 48000: - mode |= WL1273_IS2_RATE_48K; - break; - case 44100: - mode |= WL1273_IS2_RATE_44_1K; - break; - case 32000: - mode |= WL1273_IS2_RATE_32K; - break; - case 22050: - mode |= WL1273_IS2_RATE_22_05K; - break; - case 16000: - mode |= WL1273_IS2_RATE_16K; - break; - case 12000: - mode |= WL1273_IS2_RATE_12K; - break; - case 11025: - mode |= WL1273_IS2_RATE_11_025; - break; - case 8000: - mode |= WL1273_IS2_RATE_8K; - break; - default: - dev_err(dev, "Sampling rate: %d not supported\n", rate); - r = -EINVAL; - goto out; - } - - switch (width) { - case 16: - mode |= WL1273_IS2_WIDTH_32; - break; - case 20: - mode |= WL1273_IS2_WIDTH_40; - break; - case 24: - mode |= WL1273_IS2_WIDTH_48; - break; - case 25: - mode |= WL1273_IS2_WIDTH_50; - break; - case 30: - mode |= WL1273_IS2_WIDTH_60; - break; - case 32: - mode |= WL1273_IS2_WIDTH_64; - break; - case 40: - mode |= WL1273_IS2_WIDTH_80; - break; - case 48: - mode |= WL1273_IS2_WIDTH_96; - break; - case 64: - mode |= WL1273_IS2_WIDTH_128; - break; - default: - dev_err(dev, "Data width: %d not supported\n", width); - r = -EINVAL; - goto out; - } - - dev_dbg(dev, "WL1273_I2S_DEF_MODE: 0x%04x\n", WL1273_I2S_DEF_MODE); - dev_dbg(dev, "core->i2s_mode: 0x%04x\n", core->i2s_mode); - dev_dbg(dev, "mode: 0x%04x\n", mode); - - if (core->i2s_mode != mode) { - r = core->write(core, WL1273_I2S_MODE_CONFIG_SET, mode); - if (r) - goto out; - - core->i2s_mode = mode; - r = core->write(core, WL1273_AUDIO_ENABLE, - WL1273_AUDIO_ENABLE_I2S); - if (r) - goto out; - } -out: - mutex_unlock(&core->lock); - - return r; -} - -static int snd_wl1273_fm_set_channel_number(struct wl1273_core *core, - int channel_number) -{ - struct device *dev = &core->client->dev; - int r = 0; - - dev_dbg(dev, "%s\n", __func__); - - mutex_lock(&core->lock); - - if (core->channel_number == channel_number) - goto out; - - if (channel_number == 1 && core->mode == WL1273_MODE_RX) - r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_MONO); - else if (channel_number == 1 && core->mode == WL1273_MODE_TX) - r = core->write(core, WL1273_MONO_SET, WL1273_TX_MONO); - else if (channel_number == 2 && core->mode == WL1273_MODE_RX) - r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_STEREO); - else if (channel_number == 2 && core->mode == WL1273_MODE_TX) - r = core->write(core, WL1273_MONO_SET, WL1273_TX_STEREO); - else - r = -EINVAL; -out: - mutex_unlock(&core->lock); - - return r; -} - -static int snd_wl1273_get_audio_route(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); - struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component); - - ucontrol->value.enumerated.item[0] = wl1273->mode; - - return 0; -} - -/* - * TODO: Implement the audio routing in the driver. Now this control - * only indicates the setting that has been done elsewhere (in the user - * space). - */ -static const char * const wl1273_audio_route[] = { "Bt", "FmRx", "FmTx" }; - -static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); - struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component); - - if (wl1273->mode == ucontrol->value.enumerated.item[0]) - return 0; - - /* Do not allow changes while stream is running */ - if (snd_soc_component_active(component)) - return -EPERM; - - if (ucontrol->value.enumerated.item[0] >= ARRAY_SIZE(wl1273_audio_route)) - return -EINVAL; - - wl1273->mode = ucontrol->value.enumerated.item[0]; - - return 1; -} - -static SOC_ENUM_SINGLE_EXT_DECL(wl1273_enum, wl1273_audio_route); - -static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); - struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component); - - dev_dbg(component->dev, "%s: enter.\n", __func__); - - ucontrol->value.enumerated.item[0] = wl1273->core->audio_mode; - - return 0; -} - -static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); - struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component); - int val, r = 0; - - dev_dbg(component->dev, "%s: enter.\n", __func__); - - val = ucontrol->value.enumerated.item[0]; - if (wl1273->core->audio_mode == val) - return 0; - - r = wl1273->core->set_audio(wl1273->core, val); - if (r < 0) - return r; - - return 1; -} - -static const char * const wl1273_audio_strings[] = { "Digital", "Analog" }; - -static SOC_ENUM_SINGLE_EXT_DECL(wl1273_audio_enum, wl1273_audio_strings); - -static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); - struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component); - - dev_dbg(component->dev, "%s: enter.\n", __func__); - - ucontrol->value.integer.value[0] = wl1273->core->volume; - - return 0; -} - -static int snd_wl1273_fm_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); - struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component); - int r; - - dev_dbg(component->dev, "%s: enter.\n", __func__); - - r = wl1273->core->set_volume(wl1273->core, - ucontrol->value.integer.value[0]); - if (r) - return r; - - return 1; -} - -static const struct snd_kcontrol_new wl1273_controls[] = { - SOC_ENUM_EXT("Codec Mode", wl1273_enum, - snd_wl1273_get_audio_route, snd_wl1273_set_audio_route), - SOC_ENUM_EXT("Audio Switch", wl1273_audio_enum, - snd_wl1273_fm_audio_get, snd_wl1273_fm_audio_put), - SOC_SINGLE_EXT("Volume", 0, 0, WL1273_MAX_VOLUME, 0, - snd_wl1273_fm_volume_get, snd_wl1273_fm_volume_put), -}; - -static const struct snd_soc_dapm_widget wl1273_dapm_widgets[] = { - SND_SOC_DAPM_INPUT("RX"), - - SND_SOC_DAPM_OUTPUT("TX"), -}; - -static const struct snd_soc_dapm_route wl1273_dapm_routes[] = { - { "Capture", NULL, "RX" }, - - { "TX", NULL, "Playback" }, -}; - -static int wl1273_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_component *component = dai->component; - struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component); - - switch (wl1273->mode) { - case WL1273_MODE_BT: - snd_pcm_hw_constraint_single(substream->runtime, - SNDRV_PCM_HW_PARAM_RATE, 8000); - snd_pcm_hw_constraint_single(substream->runtime, - SNDRV_PCM_HW_PARAM_CHANNELS, 1); - break; - case WL1273_MODE_FM_RX: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - pr_err("Cannot play in RX mode.\n"); - return -EINVAL; - } - break; - case WL1273_MODE_FM_TX: - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - pr_err("Cannot capture in TX mode.\n"); - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - return 0; -} - -static int wl1273_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(dai->component); - struct wl1273_core *core = wl1273->core; - unsigned int rate, width, r; - - if (params_width(params) != 16) { - dev_err(dai->dev, "%d bits/sample not supported\n", - params_width(params)); - return -EINVAL; - } - - rate = params_rate(params); - width = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min; - - if (wl1273->mode == WL1273_MODE_BT) { - if (rate != 8000) { - pr_err("Rate %d not supported.\n", params_rate(params)); - return -EINVAL; - } - - if (params_channels(params) != 1) { - pr_err("Only mono supported.\n"); - return -EINVAL; - } - - return 0; - } - - if (wl1273->mode == WL1273_MODE_FM_TX && - substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - pr_err("Only playback supported with TX.\n"); - return -EINVAL; - } - - if (wl1273->mode == WL1273_MODE_FM_RX && - substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - pr_err("Only capture supported with RX.\n"); - return -EINVAL; - } - - if (wl1273->mode != WL1273_MODE_FM_RX && - wl1273->mode != WL1273_MODE_FM_TX) { - pr_err("Unexpected mode: %d.\n", wl1273->mode); - return -EINVAL; - } - - r = snd_wl1273_fm_set_i2s_mode(core, rate, width); - if (r) - return r; - - wl1273->channels = params_channels(params); - r = snd_wl1273_fm_set_channel_number(core, wl1273->channels); - if (r) - return r; - - return 0; -} - -static const struct snd_soc_dai_ops wl1273_dai_ops = { - .startup = wl1273_startup, - .hw_params = wl1273_hw_params, -}; - -static struct snd_soc_dai_driver wl1273_dai = { - .name = "wl1273-fm", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE}, - .ops = &wl1273_dai_ops, -}; - -/* Audio interface format for the soc_card driver */ -int wl1273_get_format(struct snd_soc_component *component, unsigned int *fmt) -{ - struct wl1273_priv *wl1273; - - if (component == NULL || fmt == NULL) - return -EINVAL; - - wl1273 = snd_soc_component_get_drvdata(component); - - switch (wl1273->mode) { - case WL1273_MODE_FM_RX: - case WL1273_MODE_FM_TX: - *fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBP_CFP; - - break; - case WL1273_MODE_BT: - *fmt = SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBP_CFP; - - break; - default: - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL_GPL(wl1273_get_format); - -static int wl1273_probe(struct snd_soc_component *component) -{ - struct wl1273_core **core = component->dev->platform_data; - struct wl1273_priv *wl1273; - - dev_dbg(component->dev, "%s.\n", __func__); - - if (!core) { - dev_err(component->dev, "Platform data is missing.\n"); - return -EINVAL; - } - - wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL); - if (!wl1273) - return -ENOMEM; - - wl1273->mode = WL1273_MODE_BT; - wl1273->core = *core; - - snd_soc_component_set_drvdata(component, wl1273); - - return 0; -} - -static void wl1273_remove(struct snd_soc_component *component) -{ - struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component); - - dev_dbg(component->dev, "%s\n", __func__); - kfree(wl1273); -} - -static const struct snd_soc_component_driver soc_component_dev_wl1273 = { - .probe = wl1273_probe, - .remove = wl1273_remove, - .controls = wl1273_controls, - .num_controls = ARRAY_SIZE(wl1273_controls), - .dapm_widgets = wl1273_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wl1273_dapm_widgets), - .dapm_routes = wl1273_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wl1273_dapm_routes), - .idle_bias_on = 1, - .use_pmdown_time = 1, - .endianness = 1, -}; - -static int wl1273_platform_probe(struct platform_device *pdev) -{ - return devm_snd_soc_register_component(&pdev->dev, - &soc_component_dev_wl1273, - &wl1273_dai, 1); -} - -MODULE_ALIAS("platform:wl1273-codec"); - -static struct platform_driver wl1273_platform_driver = { - .driver = { - .name = "wl1273-codec", - }, - .probe = wl1273_platform_probe, -}; - -module_platform_driver(wl1273_platform_driver); - -MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>"); -MODULE_DESCRIPTION("ASoC WL1273 codec driver"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/wl1273.h b/sound/soc/codecs/wl1273.h deleted file mode 100644 index 66c312fa7eee..000000000000 --- a/sound/soc/codecs/wl1273.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * sound/soc/codec/wl1273.h - * - * ALSA SoC WL1273 codec driver - * - * Copyright (C) Nokia Corporation - * Author: Matti Aaltonen <matti.j.aaltonen@nokia.com> - */ - -#ifndef __WL1273_CODEC_H__ -#define __WL1273_CODEC_H__ - -int wl1273_get_format(struct snd_soc_component *component, unsigned int *fmt); - -#endif /* End of __WL1273_CODEC_H__ */ diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 9be4f6cadba3..75d923c2c9ca 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1536,7 +1536,7 @@ static int wm8993_probe(struct snd_soc_component *component) * VMID as an output and can disable it. */ if (wm8993->pdata.lineout1_diff && wm8993->pdata.lineout2_diff) - dapm->idle_bias_off = 1; + dapm->idle_bias = false; return 0; diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 240ec1bed234..128c3a59beac 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -4182,8 +4182,8 @@ static int wm8994_component_probe(struct snd_soc_component *component) wm8994->micdet_irq = control->pdata.micdet_irq; - /* By default use idle_bias_off, will override for WM8994 */ - dapm->idle_bias_off = 1; + /* By default use idle_bias false, will override for WM8994 */ + dapm->idle_bias = false; /* Set revision-specific configuration */ switch (control->type) { @@ -4191,7 +4191,7 @@ static int wm8994_component_probe(struct snd_soc_component *component) /* Single ended line outputs should have VMID on. */ if (!control->pdata.lineout1_diff || !control->pdata.lineout2_diff) - dapm->idle_bias_off = 0; + dapm->idle_bias = true; switch (control->revision) { case 2: diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index bc584b17bf28..b28398aa9e48 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -106,33 +106,33 @@ struct wm8994_priv { int vss_ena[3]; int enh_eq_ena[3]; - /* Platform dependant DRC configuration */ + /* Platform dependent DRC configuration */ const char **drc_texts; int drc_cfg[WM8994_NUM_DRC]; struct soc_enum drc_enum; - /* Platform dependant ReTune mobile configuration */ + /* Platform dependent ReTune mobile configuration */ int num_retune_mobile_texts; const char **retune_mobile_texts; int retune_mobile_cfg[WM8994_NUM_EQ]; struct soc_enum retune_mobile_enum; - /* Platform dependant MBC configuration */ + /* Platform dependent MBC configuration */ int mbc_cfg; const char **mbc_texts; struct soc_enum mbc_enum; - /* Platform dependant VSS configuration */ + /* Platform dependent VSS configuration */ int vss_cfg; const char **vss_texts; struct soc_enum vss_enum; - /* Platform dependant VSS HPF configuration */ + /* Platform dependent VSS HPF configuration */ int vss_hpf_cfg; const char **vss_hpf_texts; struct soc_enum vss_hpf_enum; - /* Platform dependant enhanced EQ configuration */ + /* Platform dependent enhanced EQ configuration */ int enh_eq_cfg; const char **enh_eq_texts; struct soc_enum enh_eq_enum; diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 459b39998307..ee2040782532 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -77,7 +77,7 @@ struct wm8996_priv { int rx_rate[WM8996_AIFS]; int bclk_rate[WM8996_AIFS]; - /* Platform dependant ReTune mobile configuration */ + /* Platform dependent ReTune mobile configuration */ int num_retune_mobile_texts; const char **retune_mobile_texts; int retune_mobile_cfg[2]; diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 8a1d5cc75d6c..8782c331e925 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -173,7 +173,7 @@ struct wm_adsp_compr { struct snd_compressed_buffer size; u32 *raw_buf; - unsigned int copied_total; + u64 copied_total; unsigned int sample_rate; @@ -1043,7 +1043,7 @@ int wm_adsp_early_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: - queue_work(system_unbound_wq, &dsp->boot_work); + queue_work(system_dfl_wq, &dsp->boot_work); break; case SND_SOC_DAPM_PRE_PMD: wm_adsp_power_down(dsp); @@ -1860,7 +1860,7 @@ static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf) int wm_adsp_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct wm_adsp_compr *compr = stream->runtime->private_data; struct wm_adsp *dsp = compr->dsp; diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 25210d404bf1..8035fda71f8d 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -131,7 +131,7 @@ int wm_adsp_compr_trigger(struct snd_soc_component *component, int wm_adsp_compr_handle_irq(struct wm_adsp *dsp); int wm_adsp_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp); + struct snd_compr_tstamp64 *tstamp); int wm_adsp_compr_copy(struct snd_soc_component *component, struct snd_compr_stream *stream, char __user *buf, size_t count); diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c index 188363b03b93..ca4520ade79a 100644 --- a/sound/soc/codecs/wsa883x.c +++ b/sound/soc/codecs/wsa883x.c @@ -14,6 +14,7 @@ #include <linux/printk.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> +#include <linux/reset.h> #include <linux/slab.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_registers.h> @@ -468,6 +469,7 @@ struct wsa883x_priv { struct sdw_stream_runtime *sruntime; struct sdw_port_config port_config[WSA883X_MAX_SWR_PORTS]; struct gpio_desc *sd_n; + struct reset_control *sd_reset; bool port_prepared[WSA883X_MAX_SWR_PORTS]; bool port_enable[WSA883X_MAX_SWR_PORTS]; int active_ports; @@ -1546,6 +1548,46 @@ static const struct hwmon_chip_info wsa883x_hwmon_chip_info = { .info = wsa883x_hwmon_info, }; +static void wsa883x_reset_assert(void *data) +{ + struct wsa883x_priv *wsa883x = data; + + if (wsa883x->sd_reset) + reset_control_assert(wsa883x->sd_reset); + else + gpiod_direction_output(wsa883x->sd_n, 1); +} + +static void wsa883x_reset_deassert(struct wsa883x_priv *wsa883x) +{ + if (wsa883x->sd_reset) + reset_control_deassert(wsa883x->sd_reset); + else + gpiod_direction_output(wsa883x->sd_n, 0); +} + +static int wsa883x_get_reset(struct device *dev, struct wsa883x_priv *wsa883x) +{ + wsa883x->sd_reset = devm_reset_control_get_optional_shared(dev, NULL); + if (IS_ERR(wsa883x->sd_reset)) + return dev_err_probe(dev, PTR_ERR(wsa883x->sd_reset), + "Failed to get reset\n"); + /* + * if sd_reset: NULL, so use the backwards compatible way for powerdown-gpios, + * which does not handle sharing GPIO properly. + */ + if (!wsa883x->sd_reset) { + wsa883x->sd_n = devm_gpiod_get_optional(dev, "powerdown", + GPIOD_FLAGS_BIT_NONEXCLUSIVE | + GPIOD_OUT_HIGH); + if (IS_ERR(wsa883x->sd_n)) + return dev_err_probe(dev, PTR_ERR(wsa883x->sd_n), + "Shutdown Control GPIO not found\n"); + } + + return 0; +} + static int wsa883x_probe(struct sdw_slave *pdev, const struct sdw_device_id *id) { @@ -1566,13 +1608,9 @@ static int wsa883x_probe(struct sdw_slave *pdev, if (ret) return dev_err_probe(dev, ret, "Failed to enable vdd regulator\n"); - wsa883x->sd_n = devm_gpiod_get_optional(dev, "powerdown", - GPIOD_FLAGS_BIT_NONEXCLUSIVE | GPIOD_OUT_HIGH); - if (IS_ERR(wsa883x->sd_n)) { - ret = dev_err_probe(dev, PTR_ERR(wsa883x->sd_n), - "Shutdown Control GPIO not found\n"); + ret = wsa883x_get_reset(dev, wsa883x); + if (ret) goto err; - } dev_set_drvdata(dev, wsa883x); wsa883x->slave = pdev; @@ -1595,11 +1633,14 @@ static int wsa883x_probe(struct sdw_slave *pdev, pdev->prop.simple_clk_stop_capable = true; pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop; pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; - gpiod_direction_output(wsa883x->sd_n, 0); + + wsa883x_reset_deassert(wsa883x); + ret = devm_add_action_or_reset(dev, wsa883x_reset_assert, wsa883x); + if (ret) + return ret; wsa883x->regmap = devm_regmap_init_sdw(pdev, &wsa883x_regmap_config); if (IS_ERR(wsa883x->regmap)) { - gpiod_direction_output(wsa883x->sd_n, 1); ret = dev_err_probe(dev, PTR_ERR(wsa883x->regmap), "regmap_init failed\n"); goto err; diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index 5614a8b909ed..3de448ef724c 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -17,12 +17,6 @@ #include <sound/pcm_params.h> #include <sound/soc.h> -struct qmc_dai_chan { - struct qmc_dai_prtd *prtd_tx; - struct qmc_dai_prtd *prtd_rx; - struct qmc_chan *qmc_chan; -}; - struct qmc_dai { char *name; int id; @@ -33,7 +27,7 @@ struct qmc_dai { unsigned int nb_chans_avail; unsigned int nb_chans_used_tx; unsigned int nb_chans_used_rx; - struct qmc_dai_chan *chans; + struct qmc_chan **qmc_chans; }; struct qmc_audio { @@ -57,7 +51,6 @@ struct qmc_dai_prtd { size_t ch_dma_offset; unsigned int channels; - DECLARE_BITMAP(chans_pending, 64); struct snd_pcm_substream *substream; }; @@ -126,17 +119,14 @@ static int qmc_audio_pcm_write_submit(struct qmc_dai_prtd *prtd) int ret; for (i = 0; i < prtd->channels; i++) { - bitmap_set(prtd->chans_pending, i, 1); - - ret = qmc_chan_write_submit(prtd->qmc_dai->chans[i].qmc_chan, + ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chans[i], prtd->ch_dma_addr_current + i * prtd->ch_dma_offset, prtd->ch_dma_size, - qmc_audio_pcm_write_complete, - &prtd->qmc_dai->chans[i]); + i == prtd->channels - 1 ? qmc_audio_pcm_write_complete : + NULL, prtd); if (ret) { dev_err(prtd->qmc_dai->dev, "write_submit %u failed %d\n", i, ret); - bitmap_clear(prtd->chans_pending, i, 1); return ret; } } @@ -146,20 +136,7 @@ static int qmc_audio_pcm_write_submit(struct qmc_dai_prtd *prtd) static void qmc_audio_pcm_write_complete(void *context) { - struct qmc_dai_chan *chan = context; - struct qmc_dai_prtd *prtd; - - prtd = chan->prtd_tx; - - /* Mark the current channel as completed */ - bitmap_clear(prtd->chans_pending, chan - prtd->qmc_dai->chans, 1); - - /* - * All QMC channels involved must have completed their transfer before - * submitting a new one. - */ - if (!bitmap_empty(prtd->chans_pending, 64)) - return; + struct qmc_dai_prtd *prtd = context; prtd->buffer_ended += prtd->period_size; if (prtd->buffer_ended >= prtd->buffer_size) @@ -182,17 +159,14 @@ static int qmc_audio_pcm_read_submit(struct qmc_dai_prtd *prtd) int ret; for (i = 0; i < prtd->channels; i++) { - bitmap_set(prtd->chans_pending, i, 1); - - ret = qmc_chan_read_submit(prtd->qmc_dai->chans[i].qmc_chan, + ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chans[i], prtd->ch_dma_addr_current + i * prtd->ch_dma_offset, prtd->ch_dma_size, - qmc_audio_pcm_read_complete, - &prtd->qmc_dai->chans[i]); + i == prtd->channels - 1 ? qmc_audio_pcm_read_complete : + NULL, prtd); if (ret) { dev_err(prtd->qmc_dai->dev, "read_submit %u failed %d\n", i, ret); - bitmap_clear(prtd->chans_pending, i, 1); return ret; } } @@ -202,26 +176,13 @@ static int qmc_audio_pcm_read_submit(struct qmc_dai_prtd *prtd) static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags) { - struct qmc_dai_chan *chan = context; - struct qmc_dai_prtd *prtd; - - prtd = chan->prtd_rx; - - /* Mark the current channel as completed */ - bitmap_clear(prtd->chans_pending, chan - prtd->qmc_dai->chans, 1); + struct qmc_dai_prtd *prtd = context; if (length != prtd->ch_dma_size) { dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n", length, prtd->ch_dma_size); } - /* - * All QMC channels involved must have completed their transfer before - * submitting a new one. - */ - if (!bitmap_empty(prtd->chans_pending, 64)) - return; - prtd->buffer_ended += prtd->period_size; if (prtd->buffer_ended >= prtd->buffer_size) prtd->buffer_ended = 0; @@ -239,7 +200,6 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { struct qmc_dai_prtd *prtd = substream->runtime->private_data; - unsigned int i; int ret; if (!prtd->qmc_dai) { @@ -249,14 +209,10 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, switch (cmd) { case SNDRV_PCM_TRIGGER_START: - bitmap_zero(prtd->chans_pending, 64); prtd->buffer_ended = 0; prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - for (i = 0; i < prtd->channels; i++) - prtd->qmc_dai->chans[i].prtd_tx = prtd; - /* Submit first chunk ... */ ret = qmc_audio_pcm_write_submit(prtd); if (ret) @@ -272,9 +228,6 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, if (ret) return ret; } else { - for (i = 0; i < prtd->channels; i++) - prtd->qmc_dai->chans[i].prtd_rx = prtd; - /* Submit first chunk ... */ ret = qmc_audio_pcm_read_submit(prtd); if (ret) @@ -644,9 +597,9 @@ static int qmc_dai_hw_params(struct snd_pcm_substream *substream, chan_param.mode = QMC_TRANSPARENT; chan_param.transp.max_rx_buf_size = params_period_bytes(params) / nb_chans_used; for (i = 0; i < nb_chans_used; i++) { - ret = qmc_chan_set_param(qmc_dai->chans[i].qmc_chan, &chan_param); + ret = qmc_chan_set_param(qmc_dai->qmc_chans[i], &chan_param); if (ret) { - dev_err(dai->dev, "chans[%u], set param failed %d\n", + dev_err(dai->dev, "qmc_chans[%u], set param failed %d\n", i, ret); return ret; } @@ -688,7 +641,7 @@ static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: for (i = 0; i < nb_chans_used; i++) { - ret = qmc_chan_start(qmc_dai->chans[i].qmc_chan, direction); + ret = qmc_chan_start(qmc_dai->qmc_chans[i], direction); if (ret) goto err_stop; } @@ -697,13 +650,13 @@ static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_STOP: /* Stop and reset all QMC channels and return the first error encountered */ for (i = 0; i < nb_chans_used; i++) { - ret_tmp = qmc_chan_stop(qmc_dai->chans[i].qmc_chan, direction); + ret_tmp = qmc_chan_stop(qmc_dai->qmc_chans[i], direction); if (!ret) ret = ret_tmp; if (ret_tmp) continue; - ret_tmp = qmc_chan_reset(qmc_dai->chans[i].qmc_chan, direction); + ret_tmp = qmc_chan_reset(qmc_dai->qmc_chans[i], direction); if (!ret) ret = ret_tmp; } @@ -715,7 +668,7 @@ static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* Stop all QMC channels and return the first error encountered */ for (i = 0; i < nb_chans_used; i++) { - ret_tmp = qmc_chan_stop(qmc_dai->chans[i].qmc_chan, direction); + ret_tmp = qmc_chan_stop(qmc_dai->qmc_chans[i], direction); if (!ret) ret = ret_tmp; } @@ -731,8 +684,8 @@ static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd, err_stop: while (i--) { - qmc_chan_stop(qmc_dai->chans[i].qmc_chan, direction); - qmc_chan_reset(qmc_dai->chans[i].qmc_chan, direction); + qmc_chan_stop(qmc_dai->qmc_chans[i], direction); + qmc_chan_reset(qmc_dai->qmc_chans[i], direction); } return ret; } @@ -791,12 +744,17 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node * struct qmc_dai *qmc_dai, struct snd_soc_dai_driver *qmc_soc_dai_driver) { + struct qmc_chan_ts_info ts_info; struct qmc_chan_info info; unsigned long rx_fs_rate; unsigned long tx_fs_rate; + int prev_last_rx_ts = 0; + int prev_last_tx_ts = 0; unsigned int nb_tx_ts; unsigned int nb_rx_ts; unsigned int i; + int last_rx_ts; + int last_tx_ts; int count; u32 val; int ret; @@ -823,19 +781,20 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node * return dev_err_probe(qmc_audio->dev, -EINVAL, "dai %d no QMC channel defined\n", qmc_dai->id); - qmc_dai->chans = devm_kcalloc(qmc_audio->dev, count, sizeof(*qmc_dai->chans), GFP_KERNEL); - if (!qmc_dai->chans) + qmc_dai->qmc_chans = devm_kcalloc(qmc_audio->dev, count, sizeof(*qmc_dai->qmc_chans), + GFP_KERNEL); + if (!qmc_dai->qmc_chans) return -ENOMEM; for (i = 0; i < count; i++) { - qmc_dai->chans[i].qmc_chan = devm_qmc_chan_get_byphandles_index(qmc_audio->dev, np, - "fsl,qmc-chan", i); - if (IS_ERR(qmc_dai->chans[i].qmc_chan)) { - return dev_err_probe(qmc_audio->dev, PTR_ERR(qmc_dai->chans[i].qmc_chan), + qmc_dai->qmc_chans[i] = devm_qmc_chan_get_byphandles_index(qmc_audio->dev, np, + "fsl,qmc-chan", i); + if (IS_ERR(qmc_dai->qmc_chans[i])) { + return dev_err_probe(qmc_audio->dev, PTR_ERR(qmc_dai->qmc_chans[i]), "dai %d get QMC channel %d failed\n", qmc_dai->id, i); } - ret = qmc_chan_get_info(qmc_dai->chans[i].qmc_chan, &info); + ret = qmc_chan_get_info(qmc_dai->qmc_chans[i], &info); if (ret) { dev_err(qmc_audio->dev, "dai %d get QMC %d channel info failed %d\n", qmc_dai->id, i, ret); @@ -879,6 +838,30 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node * return -EINVAL; } } + + ret = qmc_chan_get_ts_info(qmc_dai->qmc_chans[i], &ts_info); + if (ret) { + dev_err(qmc_audio->dev, "dai %d get QMC %d channel TS info failed %d\n", + qmc_dai->id, i, ret); + return ret; + } + + last_rx_ts = fls64(ts_info.rx_ts_mask); + last_tx_ts = fls64(ts_info.tx_ts_mask); + + if (prev_last_rx_ts > last_rx_ts) { + dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (RX timeslot %d before %d)\n", + qmc_dai->id, i, prev_last_rx_ts, last_rx_ts); + return -EINVAL; + } + if (prev_last_tx_ts > last_tx_ts) { + dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (TX timeslot %d before %d)\n", + qmc_dai->id, i, prev_last_tx_ts, last_tx_ts); + return -EINVAL; + } + + prev_last_rx_ts = last_rx_ts; + prev_last_tx_ts = last_tx_ts; } qmc_dai->nb_chans_avail = count; diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index d0367b21f775..757e7868e322 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1244,7 +1244,6 @@ static struct regmap_config fsl_sai_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .fast_io = true, .max_register = FSL_SAI_RMR, .reg_defaults = fsl_sai_reg_defaults_ofs0, @@ -1346,7 +1345,7 @@ static int fsl_sai_read_dlcfg(struct fsl_sai *sai) num_cfg = elems / 3; /* Add one more for default value */ - cfg = devm_kzalloc(&pdev->dev, (num_cfg + 1) * sizeof(*cfg), GFP_KERNEL); + cfg = devm_kcalloc(&pdev->dev, num_cfg + 1, sizeof(*cfg), GFP_KERNEL); if (!cfg) return -ENOMEM; diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index cc2918ee2cf5..f8335a04595a 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -305,7 +305,7 @@ static int imx_audmux_probe(struct platform_device *pdev) return -EINVAL; } - regcache = devm_kzalloc(&pdev->dev, sizeof(u32) * reg_max, GFP_KERNEL); + regcache = devm_kcalloc(&pdev->dev, reg_max, sizeof(u32), GFP_KERNEL); if (!regcache) return -ENOMEM; diff --git a/sound/soc/fsl/imx-hdmi.c b/sound/soc/fsl/imx-hdmi.c index fe47b439a818..1115189cc640 100644 --- a/sound/soc/fsl/imx-hdmi.c +++ b/sound/soc/fsl/imx-hdmi.c @@ -101,7 +101,6 @@ static int imx_hdmi_probe(struct platform_device *pdev) bool hdmi_out = of_property_read_bool(np, "hdmi-out"); bool hdmi_in = of_property_read_bool(np, "hdmi-in"); struct snd_soc_dai_link_component *dlc; - struct platform_device *cpu_pdev; struct device_node *cpu_np; struct imx_hdmi_data *data; int ret; @@ -117,17 +116,9 @@ static int imx_hdmi_probe(struct platform_device *pdev) goto fail; } - cpu_pdev = of_find_device_by_node(cpu_np); - if (!cpu_pdev) { - dev_err(&pdev->dev, "failed to find SAI platform device\n"); - ret = -EINVAL; - goto fail; - } - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) { ret = -ENOMEM; - put_device(&cpu_pdev->dev); goto fail; } @@ -140,15 +131,13 @@ static int imx_hdmi_probe(struct platform_device *pdev) data->dai.name = "i.MX HDMI"; data->dai.stream_name = "i.MX HDMI"; - data->dai.cpus->dai_name = dev_name(&cpu_pdev->dev); + data->dai.cpus->of_node = cpu_np; data->dai.platforms->of_node = cpu_np; data->dai.ops = &imx_hdmi_ops; data->dai.playback_only = true; data->dai.capture_only = false; data->dai.init = imx_hdmi_init; - put_device(&cpu_pdev->dev); - if (of_node_name_eq(cpu_np, "sai")) { data->cpu_priv.sysclk_id[1] = FSL_SAI_CLK_MAST1; data->cpu_priv.sysclk_id[0] = FSL_SAI_CLK_MAST1; diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c index 89b995987e2d..2e49066dedd4 100644 --- a/sound/soc/generic/test-component.c +++ b/sound/soc/generic/test-component.c @@ -547,8 +547,8 @@ static int test_driver_probe(struct platform_device *pdev) priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); cdriv = devm_kzalloc(dev, sizeof(*cdriv), GFP_KERNEL); - ddriv = devm_kzalloc(dev, sizeof(*ddriv) * num, GFP_KERNEL); - dname = devm_kzalloc(dev, sizeof(*dname) * num, GFP_KERNEL); + ddriv = devm_kcalloc(dev, num, sizeof(*ddriv), GFP_KERNEL); + dname = devm_kcalloc(dev, num, sizeof(*dname), GFP_KERNEL); if (!priv || !cdriv || !ddriv || !dname || !adata) return -EINVAL; diff --git a/sound/soc/intel/atom/sst-mfld-platform-compress.c b/sound/soc/intel/atom/sst-mfld-platform-compress.c index 89c9c5ad6b21..9dfb0a814b94 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-compress.c +++ b/sound/soc/intel/atom/sst-mfld-platform-compress.c @@ -18,6 +18,7 @@ #include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/compress_driver.h> +#include <asm/div64.h> #include "sst-mfld-platform.h" /* compress stream operations */ @@ -202,15 +203,16 @@ static int sst_platform_compr_trigger(struct snd_soc_component *component, static int sst_platform_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct sst_runtime_stream *stream; + u64 temp_copied_total = tstamp->copied_total; - stream = cstream->runtime->private_data; + stream = cstream->runtime->private_data; stream->compr_ops->tstamp(sst->dev, stream->id, tstamp); - tstamp->byte_offset = tstamp->copied_total % - (u32)cstream->runtime->buffer_size; - pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset); + tstamp->byte_offset = + do_div(temp_copied_total, cstream->runtime->buffer_size); + pr_debug("calc bytes offset/copied bytes as %u\n", tstamp->byte_offset); return 0; } diff --git a/sound/soc/intel/atom/sst-mfld-platform.h b/sound/soc/intel/atom/sst-mfld-platform.h index 8b5777d3229a..a0e33f7f01c5 100644 --- a/sound/soc/intel/atom/sst-mfld-platform.h +++ b/sound/soc/intel/atom/sst-mfld-platform.h @@ -105,7 +105,7 @@ struct compress_sst_ops { int (*stream_pause_release)(struct device *dev, unsigned int str_id); int (*tstamp)(struct device *dev, unsigned int str_id, - struct snd_compr_tstamp *tstamp); + struct snd_compr_tstamp64 *tstamp); int (*ack)(struct device *dev, unsigned int str_id, unsigned long bytes); int (*close)(struct device *dev, unsigned int str_id); diff --git a/sound/soc/intel/atom/sst/sst.c b/sound/soc/intel/atom/sst/sst.c index e0357d257c6c..3c47c8de04b7 100644 --- a/sound/soc/intel/atom/sst/sst.c +++ b/sound/soc/intel/atom/sst/sst.c @@ -64,7 +64,7 @@ static irqreturn_t intel_sst_interrupt_mrfld(int irq, void *context) header.p.header_high.part.done = 0; sst_shim_write64(drv->shim, drv->ipc_reg.ipcx, header.full); - /* write 1 to clear status register */; + /* write 1 to clear status register */ isr.part.done_interrupt = 1; sst_shim_write64(drv->shim, SST_ISRX, isr.full); spin_unlock(&drv->ipc_spin_lock); diff --git a/sound/soc/intel/atom/sst/sst_drv_interface.c b/sound/soc/intel/atom/sst/sst_drv_interface.c index 8bb27f86eb65..2646c4632ca1 100644 --- a/sound/soc/intel/atom/sst/sst_drv_interface.c +++ b/sound/soc/intel/atom/sst/sst_drv_interface.c @@ -326,7 +326,7 @@ static int sst_cdev_stream_partial_drain(struct device *dev, } static int sst_cdev_tstamp(struct device *dev, unsigned int str_id, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_sst_tstamp fw_tstamp = {0,}; struct stream_info *stream; @@ -349,10 +349,11 @@ static int sst_cdev_tstamp(struct device *dev, unsigned int str_id, (u64)stream->num_ch * SST_GET_BYTES_PER_SAMPLE(24)); tstamp->sampling_rate = fw_tstamp.sampling_frequency; - dev_dbg(dev, "PCM = %u\n", tstamp->pcm_io_frames); - dev_dbg(dev, "Ptr Query on strid = %d copied_total %d, decodec %d\n", + dev_dbg(dev, "PCM = %llu\n", tstamp->pcm_io_frames); + dev_dbg(dev, + "Ptr Query on strid = %d copied_total %llu, decodec %llu\n", str_id, tstamp->copied_total, tstamp->pcm_frames); - dev_dbg(dev, "rendered %d\n", tstamp->pcm_io_frames); + dev_dbg(dev, "rendered %llu\n", tstamp->pcm_io_frames); return 0; } diff --git a/sound/soc/intel/avs/apl.c b/sound/soc/intel/avs/apl.c index 3dccf0a57a3a..b922eeaba843 100644 --- a/sound/soc/intel/avs/apl.c +++ b/sound/soc/intel/avs/apl.c @@ -10,6 +10,7 @@ #include <linux/slab.h> #include <sound/hdaudio_ext.h> #include "avs.h" +#include "debug.h" #include "messages.h" #include "path.h" #include "registers.h" diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index 4c096afc5848..0f8ddd0e9e5f 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -22,7 +22,6 @@ struct avs_dev; struct avs_tplg; struct avs_tplg_library; -struct avs_soc_component; struct avs_ipc_msg; #ifdef CONFIG_ACPI @@ -348,91 +347,18 @@ struct avs_soc_component { extern const struct snd_soc_dai_ops avs_dai_fe_ops; -int avs_soc_component_register(struct device *dev, const char *name, - struct snd_soc_component_driver *drv, - struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais); -int avs_dmic_platform_register(struct avs_dev *adev, const char *name); -int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned long port_mask, - unsigned long *tdms); -int avs_hda_platform_register(struct avs_dev *adev, const char *name); +int avs_register_dmic_component(struct avs_dev *adev, const char *name); +int avs_register_i2s_component(struct avs_dev *adev, const char *name, unsigned long port_mask, + unsigned long *tdms); +int avs_register_hda_component(struct avs_dev *adev, const char *name); +int avs_register_component(struct device *dev, const char *name, + struct snd_soc_component_driver *drv, + struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais); int avs_register_all_boards(struct avs_dev *adev); void avs_unregister_all_boards(struct avs_dev *adev); -/* Firmware tracing helpers */ - -#define avs_log_buffer_size(adev) \ - ((adev)->fw_cfg.trace_log_bytes / (adev)->hw_cfg.dsp_cores) - -#define avs_log_buffer_addr(adev, core) \ -({ \ - s32 __offset = avs_dsp_op(adev, log_buffer_offset, core); \ - (__offset < 0) ? NULL : \ - (avs_sram_addr(adev, AVS_DEBUG_WINDOW) + __offset); \ -}) - -static inline int avs_log_buffer_status_locked(struct avs_dev *adev, union avs_notify_msg *msg) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&adev->trace_lock, flags); - ret = avs_dsp_op(adev, log_buffer_status, msg); - spin_unlock_irqrestore(&adev->trace_lock, flags); - - return ret; -} - -struct avs_apl_log_buffer_layout { - u32 read_ptr; - u32 write_ptr; - u8 buffer[]; -} __packed; -static_assert(sizeof(struct avs_apl_log_buffer_layout) == 8); - -#define avs_apl_log_payload_size(adev) \ - (avs_log_buffer_size(adev) - sizeof(struct avs_apl_log_buffer_layout)) - -#define avs_apl_log_payload_addr(addr) \ - (addr + sizeof(struct avs_apl_log_buffer_layout)) - -#ifdef CONFIG_DEBUG_FS -#define AVS_SET_ENABLE_LOGS_OP(name) \ - .enable_logs = avs_##name##_enable_logs - -bool avs_logging_fw(struct avs_dev *adev); -void avs_dump_fw_log(struct avs_dev *adev, const void __iomem *src, unsigned int len); -void avs_dump_fw_log_wakeup(struct avs_dev *adev, const void __iomem *src, unsigned int len); - -int avs_probe_platform_register(struct avs_dev *adev, const char *name); - -void avs_debugfs_init(struct avs_dev *adev); -void avs_debugfs_exit(struct avs_dev *adev); -#else -#define AVS_SET_ENABLE_LOGS_OP(name) - -static inline bool avs_logging_fw(struct avs_dev *adev) -{ - return false; -} - -static inline void avs_dump_fw_log(struct avs_dev *adev, const void __iomem *src, unsigned int len) -{ -} - -static inline void -avs_dump_fw_log_wakeup(struct avs_dev *adev, const void __iomem *src, unsigned int len) -{ -} - -static inline int avs_probe_platform_register(struct avs_dev *adev, const char *name) -{ - return 0; -} - -static inline void avs_debugfs_init(struct avs_dev *adev) { } -static inline void avs_debugfs_exit(struct avs_dev *adev) { } -#endif +int avs_parse_sched_cfg(struct avs_dev *adev, const char *buf, size_t len); /* Filesystems integration */ diff --git a/sound/soc/intel/avs/board_selection.c b/sound/soc/intel/avs/board_selection.c index fb49167f5fc4..52e6266a7cb8 100644 --- a/sound/soc/intel/avs/board_selection.c +++ b/sound/soc/intel/avs/board_selection.c @@ -17,6 +17,8 @@ #include <sound/soc-acpi.h> #include <sound/soc-component.h> #include "avs.h" +#include "debug.h" +#include "pcm.h" #include "utils.h" static char *i2s_test; @@ -56,19 +58,13 @@ static const struct dmi_system_id kblr_dmi_table[] = { static struct snd_soc_acpi_mach *dmi_match_quirk(void *arg) { struct snd_soc_acpi_mach *mach = arg; - const struct dmi_system_id *dmi_id; struct dmi_system_id *dmi_table; - if (mach->quirk_data == NULL) - return mach; - dmi_table = (struct dmi_system_id *)mach->quirk_data; - dmi_id = dmi_first_match(dmi_table); - if (!dmi_id) - return NULL; - - return mach; + if (!dmi_table || dmi_first_match(dmi_table)) + return mach; + return NULL; } #define AVS_SSP(x) (BIT(x)) @@ -368,10 +364,10 @@ struct avs_acpi_boards { /* supported I2S boards per platform */ static const struct avs_acpi_boards i2s_boards[] = { - AVS_MACH_ENTRY(HDA_SKL_LP, avs_skl_i2s_machines), - AVS_MACH_ENTRY(HDA_KBL_LP, avs_kbl_i2s_machines), - AVS_MACH_ENTRY(HDA_APL, avs_apl_i2s_machines), - AVS_MACH_ENTRY(HDA_GML, avs_gml_i2s_machines), + AVS_MACH_ENTRY(HDA_SKL_LP, avs_skl_i2s_machines), + AVS_MACH_ENTRY(HDA_KBL_LP, avs_kbl_i2s_machines), + AVS_MACH_ENTRY(HDA_APL, avs_apl_i2s_machines), + AVS_MACH_ENTRY(HDA_GML, avs_gml_i2s_machines), AVS_MACH_ENTRY(HDA_CNL_LP, avs_cnl_i2s_machines), AVS_MACH_ENTRY(HDA_CNL_H, avs_cnl_i2s_machines), AVS_MACH_ENTRY(HDA_CML_LP, avs_cnl_i2s_machines), @@ -386,185 +382,122 @@ static const struct avs_acpi_boards i2s_boards[] = { { }, }; -static const struct avs_acpi_boards *avs_get_i2s_boards(struct avs_dev *adev) +static struct snd_soc_acpi_mach *avs_get_i2s_machines(struct avs_dev *adev) { int id, i; id = adev->base.pci->device; for (i = 0; i < ARRAY_SIZE(i2s_boards); i++) if (i2s_boards[i].id == id) - return &i2s_boards[i]; + return i2s_boards[i].machs; return NULL; } -/* platform devices owned by AVS audio are removed with this hook */ -static void board_pdev_unregister(void *data) +/* Platform devices spawned by AVS driver are removed with this hook. */ +static void avs_unregister_board(void *pdev) { - platform_device_unregister(data); + platform_device_unregister(pdev); } -static int __maybe_unused avs_register_probe_board(struct avs_dev *adev) +static struct platform_device *avs_register_board(struct avs_dev *adev, const char *name, + const void *data, size_t size) { - struct platform_device *board; - struct snd_soc_acpi_mach mach = {{0}}; + struct platform_device *pdev; int ret; - ret = avs_probe_platform_register(adev, "probe-platform"); - if (ret < 0) - return ret; - - mach.mach_params.platform = "probe-platform"; + pdev = platform_device_register_data(NULL, name, PLATFORM_DEVID_AUTO, data, size); + if (IS_ERR(pdev)) + return pdev; - board = platform_device_register_data(NULL, "avs_probe_mb", PLATFORM_DEVID_NONE, - (const void *)&mach, sizeof(mach)); - if (IS_ERR(board)) { - dev_err(adev->dev, "probe board register failed\n"); - return PTR_ERR(board); - } + ret = devm_add_action_or_reset(adev->dev, avs_unregister_board, pdev); + if (ret) + return ERR_PTR(ret); - ret = devm_add_action(adev->dev, board_pdev_unregister, board); - if (ret < 0) { - platform_device_unregister(board); - return ret; - } - return 0; + return pdev; } -static int avs_register_dmic_board(struct avs_dev *adev) +static struct platform_device *avs_register_board_pdata(struct avs_dev *adev, const char *name, + struct snd_soc_acpi_mach *mach, + struct hda_codec *codec, + unsigned long *tdms, char *codec_name) { - struct platform_device *codec, *board; - struct snd_soc_acpi_mach mach = {{0}}; struct avs_mach_pdata *pdata; - int ret; - - if (!acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, -1, -1)) { - dev_dbg(adev->dev, "no DMIC endpoints present\n"); - return 0; - } - - codec = platform_device_register_simple("dmic-codec", PLATFORM_DEVID_NONE, NULL, 0); - if (IS_ERR(codec)) { - dev_err(adev->dev, "dmic codec register failed\n"); - return PTR_ERR(codec); - } - - ret = devm_add_action(adev->dev, board_pdev_unregister, codec); - if (ret < 0) { - platform_device_unregister(codec); - return ret; - } - - ret = avs_dmic_platform_register(adev, "dmic-platform"); - if (ret < 0) - return ret; pdata = devm_kzalloc(adev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) - return -ENOMEM; - pdata->obsolete_card_names = obsolete_card_names; - mach.pdata = pdata; - mach.tplg_filename = "dmic-tplg.bin"; - mach.mach_params.platform = "dmic-platform"; - - board = platform_device_register_data(NULL, "avs_dmic", PLATFORM_DEVID_NONE, - (const void *)&mach, sizeof(mach)); - if (IS_ERR(board)) { - dev_err(adev->dev, "dmic board register failed\n"); - return PTR_ERR(board); - } + return ERR_PTR(-ENOMEM); - ret = devm_add_action(adev->dev, board_pdev_unregister, board); - if (ret < 0) { - platform_device_unregister(board); - return ret; - } + pdata->codec = codec; + pdata->tdms = tdms; + pdata->codec_name = codec_name; + pdata->obsolete_card_names = obsolete_card_names; + mach->pdata = pdata; - return 0; + return avs_register_board(adev, name, mach, sizeof(*mach)); } -static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach *mach) +static int __maybe_unused avs_register_probe_board(struct avs_dev *adev) { - struct platform_device *board; - struct avs_mach_pdata *pdata; - int num_ssps; - char *name; - int ret; - int uid; - - num_ssps = adev->hw_cfg.i2s_caps.ctrl_count; - if (fls(mach->mach_params.i2s_link_mask) > num_ssps) { - dev_err(adev->dev, "Platform supports %d SSPs but board %s requires SSP%ld\n", - num_ssps, mach->drv_name, - (unsigned long)__fls(mach->mach_params.i2s_link_mask)); - return -ENODEV; - } + struct platform_device *pdev; - pdata = mach->pdata; - if (!pdata) - pdata = devm_kzalloc(adev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - pdata->obsolete_card_names = obsolete_card_names; - mach->pdata = pdata; + pdev = avs_register_board(adev, "avs_probe_mb", NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); - uid = mach->mach_params.i2s_link_mask; - if (avs_mach_singular_ssp(mach)) - uid = (uid << AVS_CHANNELS_MAX) + avs_mach_ssp_tdm(mach, avs_mach_ssp_port(mach)); + return avs_register_probe_component(adev, dev_name(&pdev->dev)); +} - name = devm_kasprintf(adev->dev, GFP_KERNEL, "%s.%d-platform", mach->drv_name, uid); - if (!name) - return -ENOMEM; +static int avs_register_dmic_board(struct avs_dev *adev) +{ + static struct snd_soc_acpi_mach mach = { + .tplg_filename = "dmic-tplg.bin", + }; + struct platform_device *pdev; + char *codec_name; - ret = avs_i2s_platform_register(adev, name, mach->mach_params.i2s_link_mask, pdata->tdms); - if (ret < 0) - return ret; + if (!acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, -1, -1)) { + dev_dbg(adev->dev, "no DMIC endpoints present\n"); + return 0; + } - mach->mach_params.platform = name; + /* DMIC present in Intel PCH is enumerated statically. */ + pdev = avs_register_board(adev, "dmic-codec", NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); - board = platform_device_register_data(NULL, mach->drv_name, uid, - (const void *)mach, sizeof(*mach)); - if (IS_ERR(board)) { - dev_err(adev->dev, "ssp board register failed\n"); - return PTR_ERR(board); - } + codec_name = devm_kstrdup(adev->dev, dev_name(&pdev->dev), GFP_KERNEL); + if (!codec_name) + return -ENOMEM; - ret = devm_add_action(adev->dev, board_pdev_unregister, board); - if (ret < 0) { - platform_device_unregister(board); - return ret; - } + pdev = avs_register_board_pdata(adev, "avs_dmic", &mach, NULL, NULL, codec_name); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); - return 0; + return avs_register_dmic_component(adev, dev_name(&pdev->dev)); } static int avs_register_i2s_test_board(struct avs_dev *adev, int ssp_port, int tdm_slot) { - struct snd_soc_acpi_mach *mach; - int tdm_mask = BIT(tdm_slot); - unsigned long *tdm_cfg; - char *tplg_name; - int ret; - - mach = devm_kzalloc(adev->dev, sizeof(*mach), GFP_KERNEL); - tdm_cfg = devm_kcalloc(adev->dev, ssp_port + 1, sizeof(unsigned long), GFP_KERNEL); - tplg_name = devm_kasprintf(adev->dev, GFP_KERNEL, AVS_STRING_FMT("i2s", "-test-tplg.bin", - ssp_port, tdm_slot)); - if (!mach || !tdm_cfg || !tplg_name) + struct snd_soc_acpi_mach mach = {{0}}; + struct platform_device *pdev; + unsigned long *tdms; + + tdms = devm_kcalloc(adev->dev, ssp_port + 1, sizeof(*tdms), GFP_KERNEL); + mach.tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL, + AVS_STRING_FMT("i2s", "-test-tplg.bin", + ssp_port, tdm_slot)); + if (!tdms || !mach.tplg_filename) return -ENOMEM; - mach->drv_name = "avs_i2s_test"; - mach->mach_params.i2s_link_mask = AVS_SSP(ssp_port); - tdm_cfg[ssp_port] = tdm_mask; - mach->pdata = tdm_cfg; - mach->tplg_filename = tplg_name; + tdms[ssp_port] = BIT(tdm_slot); + mach.drv_name = "avs_i2s_test"; + mach.mach_params.i2s_link_mask = AVS_SSP(ssp_port); - ret = avs_register_i2s_board(adev, mach); - if (ret < 0) { - dev_warn(adev->dev, "register i2s %s failed: %d\n", mach->drv_name, ret); - return ret; - } + pdev = avs_register_board_pdata(adev, mach.drv_name, &mach, NULL, tdms, NULL); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); - return 0; + return avs_register_i2s_component(adev, dev_name(&pdev->dev), AVS_SSP(ssp_port), tdms); } static int avs_register_i2s_test_boards(struct avs_dev *adev) @@ -574,6 +507,9 @@ static int avs_register_i2s_test_boards(struct avs_dev *adev) unsigned long tdm_slots; u32 *array, num_elems; + if (!i2s_test) + return 0; + ret = parse_int_array(i2s_test, strlen(i2s_test), (int **)&array); if (ret) { dev_err(adev->dev, "failed to parse i2s_test parameter\n"); @@ -599,9 +535,26 @@ static int avs_register_i2s_test_boards(struct avs_dev *adev) return 0; } +static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach *mach) +{ + u32 i2s_mask = mach->mach_params.i2s_link_mask; + struct platform_device *pdev; + unsigned long *tdms = NULL; + + if (mach->pdata) + tdms = ((struct avs_mach_pdata *)mach->pdata)->tdms; + + pdev = avs_register_board_pdata(adev, mach->drv_name, mach, NULL, tdms, NULL); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + return avs_register_i2s_component(adev, dev_name(&pdev->dev), i2s_mask, tdms); +} + static int avs_register_i2s_boards(struct avs_dev *adev) { - const struct avs_acpi_boards *boards; + int num_ssps = adev->hw_cfg.i2s_caps.ctrl_count; + struct snd_soc_acpi_mach *machs; struct snd_soc_acpi_mach *mach; int ret; @@ -610,19 +563,22 @@ static int avs_register_i2s_boards(struct avs_dev *adev) return 0; } - if (i2s_test) - return avs_register_i2s_test_boards(adev); - - boards = avs_get_i2s_boards(adev); - if (!boards) { + machs = avs_get_i2s_machines(adev); + if (!machs) { dev_dbg(adev->dev, "no I2S endpoints supported\n"); return 0; } - for (mach = boards->machs; mach->id[0]; mach++) { + for (mach = machs; mach->id[0]; mach++) { if (!acpi_dev_present(mach->id, mach->uid, -1)) continue; + if (fls(mach->mach_params.i2s_link_mask) > num_ssps) { + dev_err(adev->dev, "Platform supports %d SSPs but board %s requires SSP%ld\n", + num_ssps, mach->drv_name, + (unsigned long)__fls(mach->mach_params.i2s_link_mask)); + continue; + } if (mach->machine_quirk) if (!mach->machine_quirk(mach)) continue; @@ -637,49 +593,20 @@ static int avs_register_i2s_boards(struct avs_dev *adev) static int avs_register_hda_board(struct avs_dev *adev, struct hda_codec *codec) { - struct snd_soc_acpi_mach mach = {{0}}; - struct platform_device *board; - struct avs_mach_pdata *pdata; struct hdac_device *hdev = &codec->core; - char *pname; - int ret, id; - - pname = devm_kasprintf(adev->dev, GFP_KERNEL, "%s-platform", dev_name(&hdev->dev)); - if (!pname) - return -ENOMEM; - - pdata = devm_kzalloc(adev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - pdata->obsolete_card_names = obsolete_card_names; - pdata->codec = codec; - - ret = avs_hda_platform_register(adev, pname); - if (ret < 0) - return ret; + struct snd_soc_acpi_mach mach = {{0}}; + struct platform_device *pdev; - mach.pdata = pdata; - mach.mach_params.platform = pname; mach.tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL, "hda-%08x-tplg.bin", hdev->vendor_id); if (!mach.tplg_filename) return -ENOMEM; - id = adev->base.core.idx * HDA_MAX_CODECS + hdev->addr; - board = platform_device_register_data(NULL, "avs_hdaudio", id, (const void *)&mach, - sizeof(mach)); - if (IS_ERR(board)) { - dev_err(adev->dev, "hda board register failed\n"); - return PTR_ERR(board); - } - - ret = devm_add_action(adev->dev, board_pdev_unregister, board); - if (ret < 0) { - platform_device_unregister(board); - return ret; - } + pdev = avs_register_board_pdata(adev, "avs_hdaudio", &mach, codec, NULL, NULL); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); - return 0; + return avs_register_hda_component(adev, dev_name(&pdev->dev)); } static int avs_register_hda_boards(struct avs_dev *adev) @@ -722,6 +649,10 @@ int avs_register_all_boards(struct avs_dev *adev) dev_warn(adev->dev, "enumerate DMIC endpoints failed: %d\n", ret); + ret = avs_register_i2s_test_boards(adev); + if (ret) + dev_dbg(adev->dev, "enumerate I2S TEST endpoints failed: %d\n", ret); + ret = avs_register_i2s_boards(adev); if (ret < 0) dev_warn(adev->dev, "enumerate I2S endpoints failed: %d\n", diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c index 3ef0db254142..6782dc7efae3 100644 --- a/sound/soc/intel/avs/boards/da7219.c +++ b/sound/soc/intel/avs/boards/da7219.c @@ -165,8 +165,8 @@ avs_da7219_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_param return 0; } -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -176,8 +176,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); @@ -193,6 +191,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 1; dl->platforms = platform; @@ -218,18 +217,16 @@ static int avs_da7219_probe(struct platform_device *pdev) struct snd_soc_card *card; struct snd_soc_jack *jack; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) return ret; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; @@ -259,10 +256,6 @@ static int avs_da7219_probe(struct platform_device *pdev) card->fully_routed = true; snd_soc_card_set_drvdata(card, jack); - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/dmic.c b/sound/soc/intel/avs/boards/dmic.c index a1448a98874d..bf6f580a5164 100644 --- a/sound/soc/intel/avs/boards/dmic.c +++ b/sound/soc/intel/avs/boards/dmic.c @@ -14,30 +14,6 @@ SND_SOC_DAILINK_DEF(dmic_pin, DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); SND_SOC_DAILINK_DEF(dmic_wov_pin, DAILINK_COMP_ARRAY(COMP_CPU("DMIC WoV Pin"))); -SND_SOC_DAILINK_DEF(dmic_codec, DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); -/* Name overridden on probe */ -SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM(""))); - -static struct snd_soc_dai_link card_dai_links[] = { - /* Back ends */ - { - .name = "DMIC", - .id = 0, - .capture_only = 1, - .nonatomic = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), - }, - { - .name = "DMIC WoV", - .id = 1, - .capture_only = 1, - .nonatomic = 1, - .no_pcm = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(dmic_wov_pin, dmic_codec, platform), - }, -}; static const struct snd_soc_dapm_widget card_widgets[] = { SND_SOC_DAPM_MIC("SoC DMIC", NULL), @@ -47,12 +23,56 @@ static const struct snd_soc_dapm_route card_routes[] = { {"DMic", NULL, "SoC DMIC"}, }; +static int avs_create_dai_links(struct device *dev, const char *codec_name, + struct snd_soc_dai_link **links, int *num_links) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + const int num_dl = 2; + + dl = devm_kcalloc(dev, num_dl, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); + if (!dl->codecs) + return -ENOMEM; + + dl->codecs->name = devm_kstrdup(dev, codec_name, GFP_KERNEL); + dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, "dmic-hifi"); + if (!dl->codecs->name || !dl->codecs->dai_name) + return -ENOMEM; + + platform->name = dev_name(dev); + dl[0].num_cpus = 1; + dl[0].num_codecs = 1; + dl[0].platforms = platform; + dl[0].num_platforms = 1; + dl[0].nonatomic = 1; + dl[0].no_pcm = 1; + dl[0].capture_only = 1; + memcpy(&dl[1], &dl[0], sizeof(*dl)); + + dl[0].name = "DMIC"; + dl[0].cpus = dmic_pin; + dl[0].id = 0; + dl[1].name = "DMIC WoV"; + dl[1].cpus = dmic_wov_pin; + dl[1].id = 1; + dl[1].ignore_suspend = 1; + + *links = dl; + *num_links = num_dl; + return 0; +} + static int avs_dmic_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct snd_soc_acpi_mach *mach; struct avs_mach_pdata *pdata; struct snd_soc_card *card; - struct device *dev = &pdev->dev; int ret; mach = dev_get_platdata(dev); @@ -62,6 +82,10 @@ static int avs_dmic_probe(struct platform_device *pdev) if (!card) return -ENOMEM; + ret = avs_create_dai_links(dev, pdata->codec_name, &card->dai_link, &card->num_links); + if (ret) + return ret; + if (pdata->obsolete_card_names) { card->name = "avs_dmic"; } else { @@ -70,18 +94,12 @@ static int avs_dmic_probe(struct platform_device *pdev) } card->dev = dev; card->owner = THIS_MODULE; - card->dai_link = card_dai_links; - card->num_links = ARRAY_SIZE(card_dai_links); card->dapm_widgets = card_widgets; card->num_dapm_widgets = ARRAY_SIZE(card_widgets); card->dapm_routes = card_routes; card->num_dapm_routes = ARRAY_SIZE(card_routes); card->fully_routed = true; - ret = snd_soc_fixup_dai_links_platform_name(card, mach->mach_params.platform); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/es8336.c b/sound/soc/intel/avs/boards/es8336.c index 1955f2d383c5..eb2b40894e3f 100644 --- a/sound/soc/intel/avs/boards/es8336.c +++ b/sound/soc/intel/avs/boards/es8336.c @@ -132,7 +132,7 @@ static int avs_es8336_codec_init(struct snd_soc_pcm_runtime *runtime) snd_jack_set_key(data->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); snd_soc_component_set_jack(component, &data->jack, NULL); - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; return 0; } @@ -195,8 +195,9 @@ static int avs_es8336_be_fixup(struct snd_soc_pcm_runtime *runtime, return 0; } -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) + +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -206,8 +207,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); @@ -222,6 +221,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 1; dl->platforms = platform; @@ -263,18 +263,16 @@ static int avs_es8336_probe(struct platform_device *pdev) struct avs_card_drvdata *data; struct snd_soc_card *card; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) return ret; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; @@ -306,10 +304,6 @@ static int avs_es8336_probe(struct platform_device *pdev) card->fully_routed = true; snd_soc_card_set_drvdata(card, data); - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/hdaudio.c b/sound/soc/intel/avs/boards/hdaudio.c index 19b2255a8ac3..aec769e2396c 100644 --- a/sound/soc/intel/avs/boards/hdaudio.c +++ b/sound/soc/intel/avs/boards/hdaudio.c @@ -16,7 +16,7 @@ #include "../utils.h" static int avs_create_dai_links(struct device *dev, struct hda_codec *codec, int pcm_count, - const char *platform_name, struct snd_soc_dai_link **links) + struct snd_soc_dai_link **links) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -29,7 +29,7 @@ static int avs_create_dai_links(struct device *dev, struct hda_codec *codec, int if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; + platform->name = dev_name(dev); pcm = list_first_entry(&codec->pcm_list_head, struct hda_pcm, list); for (i = 0; i < pcm_count; i++, pcm = list_next_entry(pcm, list)) { @@ -142,7 +142,7 @@ static int avs_probing_link_init(struct snd_soc_pcm_runtime *rtm) list_for_each_entry(pcm, &codec->pcm_list_head, list) pcm_count++; - ret = avs_create_dai_links(card->dev, codec, pcm_count, mach->mach_params.platform, &links); + ret = avs_create_dai_links(card->dev, codec, pcm_count, &links); if (ret < 0) { dev_err(card->dev, "create links failed: %d\n", ret); return ret; @@ -197,7 +197,7 @@ static int avs_hdaudio_probe(struct platform_device *pdev) if (!binder->codecs->name) return -ENOMEM; - binder->platforms->name = mach->mach_params.platform; + binder->platforms->name = dev_name(dev); binder->num_platforms = 1; binder->codecs->dai_name = "codec-probing-DAI"; binder->num_codecs = 1; @@ -207,7 +207,10 @@ static int avs_hdaudio_probe(struct platform_device *pdev) return -ENOMEM; if (pdata->obsolete_card_names) { - card->name = binder->codecs->name; + card->name = devm_kasprintf(dev, GFP_KERNEL, "hdaudioB%dD%d", codec->bus->core.idx, + codec->core.addr); + if (!card->name) + return -ENOMEM; } else { card->driver_name = "avs_hdaudio"; if (hda_codec_is_display(codec)) diff --git a/sound/soc/intel/avs/boards/i2s_test.c b/sound/soc/intel/avs/boards/i2s_test.c index f7b6d7715738..9a6b89ffdf14 100644 --- a/sound/soc/intel/avs/boards/i2s_test.c +++ b/sound/soc/intel/avs/boards/i2s_test.c @@ -14,8 +14,8 @@ #include <sound/soc-dapm.h> #include "../utils.h" -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -25,8 +25,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); @@ -39,6 +37,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 1; dl->platforms = platform; @@ -59,11 +58,9 @@ static int avs_i2s_test_probe(struct platform_device *pdev) struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; if (!avs_mach_singular_ssp(mach)) { @@ -94,7 +91,7 @@ static int avs_i2s_test_probe(struct platform_device *pdev) if (!card->name) return -ENOMEM; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d\n", ret); return ret; @@ -106,10 +103,6 @@ static int avs_i2s_test_probe(struct platform_device *pdev) card->num_links = 1; card->fully_routed = true; - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/max98357a.c b/sound/soc/intel/avs/boards/max98357a.c index 72053f83e98b..e9a87804f918 100644 --- a/sound/soc/intel/avs/boards/max98357a.c +++ b/sound/soc/intel/avs/boards/max98357a.c @@ -46,8 +46,8 @@ avs_max98357a_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_pa return 0; } -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -57,8 +57,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); @@ -73,6 +71,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 1; dl->platforms = platform; @@ -96,18 +95,16 @@ static int avs_max98357a_probe(struct platform_device *pdev) struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) return ret; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; @@ -135,10 +132,6 @@ static int avs_max98357a_probe(struct platform_device *pdev) card->num_dapm_routes = ARRAY_SIZE(card_base_routes); card->fully_routed = true; - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/max98373.c b/sound/soc/intel/avs/boards/max98373.c index cdba1c3ee20b..8b45b643ca29 100644 --- a/sound/soc/intel/avs/boards/max98373.c +++ b/sound/soc/intel/avs/boards/max98373.c @@ -95,8 +95,8 @@ static const struct snd_soc_ops avs_max98373_ops = { .hw_params = avs_max98373_hw_params, }; -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -106,8 +106,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); @@ -125,6 +123,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in !dl->codecs[1].name || !dl->codecs[1].dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 2; dl->platforms = platform; @@ -149,18 +148,16 @@ static int avs_max98373_probe(struct platform_device *pdev) struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) return ret; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; @@ -190,10 +187,6 @@ static int avs_max98373_probe(struct platform_device *pdev) card->num_dapm_routes = ARRAY_SIZE(card_base_routes); card->fully_routed = true; - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/max98927.c b/sound/soc/intel/avs/boards/max98927.c index a68e227044c5..db073125fa4d 100644 --- a/sound/soc/intel/avs/boards/max98927.c +++ b/sound/soc/intel/avs/boards/max98927.c @@ -92,8 +92,8 @@ static const struct snd_soc_ops avs_max98927_ops = { .hw_params = avs_max98927_hw_params, }; -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -103,8 +103,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); @@ -122,6 +120,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in !dl->codecs[1].name || !dl->codecs[1].dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 2; dl->platforms = platform; @@ -146,18 +145,16 @@ static int avs_max98927_probe(struct platform_device *pdev) struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) return ret; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; @@ -187,10 +184,6 @@ static int avs_max98927_probe(struct platform_device *pdev) card->num_dapm_routes = ARRAY_SIZE(card_base_routes); card->fully_routed = true; - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/nau8825.c b/sound/soc/intel/avs/boards/nau8825.c index 3fb1a5d07ae1..9ca400a6412e 100644 --- a/sound/soc/intel/avs/boards/nau8825.c +++ b/sound/soc/intel/avs/boards/nau8825.c @@ -172,8 +172,8 @@ static const struct snd_soc_ops avs_nau8825_ops = { .trigger = avs_nau8825_trigger, }; -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -183,8 +183,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); @@ -199,6 +197,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 1; dl->platforms = platform; @@ -250,18 +249,16 @@ static int avs_nau8825_probe(struct platform_device *pdev) struct snd_soc_card *card; struct snd_soc_jack *jack; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) return ret; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; @@ -293,10 +290,6 @@ static int avs_nau8825_probe(struct platform_device *pdev) card->fully_routed = true; snd_soc_card_set_drvdata(card, jack); - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/probe.c b/sound/soc/intel/avs/boards/probe.c index 06c1f19f27aa..73884f8a535c 100644 --- a/sound/soc/intel/avs/boards/probe.c +++ b/sound/soc/intel/avs/boards/probe.c @@ -9,45 +9,54 @@ #include <linux/device.h> #include <linux/module.h> #include <sound/soc.h> -#include <sound/soc-acpi.h> -SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY())); -SND_SOC_DAILINK_DEF(probe_cp, DAILINK_COMP_ARRAY(COMP_CPU("Probe Extraction CPU DAI"))); -SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("probe-platform"))); +static int avs_create_dai_links(struct device *dev, struct snd_soc_dai_link **links, int *num_links) +{ + struct snd_soc_dai_link *dl; -static struct snd_soc_dai_link probe_mb_dai_links[] = { - { - .name = "Compress Probe Capture", - .nonatomic = 1, - SND_SOC_DAILINK_REG(probe_cp, dummy, platform), - }, -}; + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); + if (!dl) + return -ENOMEM; + + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + dl->platforms = devm_kzalloc(dev, sizeof(*dl->platforms), GFP_KERNEL); + if (!dl->cpus || !dl->platforms) + return -ENOMEM; + + dl->name = "Compress Probe Capture"; + dl->cpus->dai_name = "Probe Extraction CPU DAI"; + dl->num_cpus = 1; + dl->codecs = &snd_soc_dummy_dlc; + dl->num_codecs = 1; + dl->platforms->name = dev_name(dev); + dl->num_platforms = 1; + dl->nonatomic = 1; + + *links = dl; + *num_links = 1; + return 0; +} static int avs_probe_mb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct snd_soc_acpi_mach *mach; struct snd_soc_card *card; int ret; - mach = dev_get_platdata(dev); - card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; + ret = avs_create_dai_links(dev, &card->dai_link, &card->num_links); + if (ret) + return ret; + card->driver_name = "avs_probe_mb"; card->long_name = card->name = "AVS PROBE"; card->dev = dev; card->owner = THIS_MODULE; - card->dai_link = probe_mb_dai_links; - card->num_links = ARRAY_SIZE(probe_mb_dai_links); card->fully_routed = true; - ret = snd_soc_fixup_dai_links_platform_name(card, mach->mach_params.platform); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/rt274.c b/sound/soc/intel/avs/boards/rt274.c index ec5382925157..4055ecc60838 100644 --- a/sound/soc/intel/avs/boards/rt274.c +++ b/sound/soc/intel/avs/boards/rt274.c @@ -117,7 +117,7 @@ static int avs_rt274_codec_init(struct snd_soc_pcm_runtime *runtime) return ret; } - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; return 0; } @@ -147,8 +147,8 @@ static int avs_rt274_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pc return 0; } -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -158,8 +158,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); @@ -174,6 +172,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 1; dl->platforms = platform; @@ -214,18 +213,16 @@ static int avs_rt274_probe(struct platform_device *pdev) struct snd_soc_card *card; struct snd_soc_jack *jack; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) return ret; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; @@ -257,10 +254,6 @@ static int avs_rt274_probe(struct platform_device *pdev) card->fully_routed = true; snd_soc_card_set_drvdata(card, jack); - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/rt286.c b/sound/soc/intel/avs/boards/rt286.c index 2566e971ce1c..4c9ac545555a 100644 --- a/sound/soc/intel/avs/boards/rt286.c +++ b/sound/soc/intel/avs/boards/rt286.c @@ -115,8 +115,8 @@ static const struct snd_soc_ops avs_rt286_ops = { .hw_params = avs_rt286_hw_params, }; -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -126,8 +126,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); @@ -142,6 +140,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 1; dl->platforms = platform; @@ -183,18 +182,16 @@ static int avs_rt286_probe(struct platform_device *pdev) struct snd_soc_card *card; struct snd_soc_jack *jack; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) return ret; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); @@ -227,10 +224,6 @@ static int avs_rt286_probe(struct platform_device *pdev) card->fully_routed = true; snd_soc_card_set_drvdata(card, jack); - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/rt298.c b/sound/soc/intel/avs/boards/rt298.c index 7be34c8ad167..2d7a7748d577 100644 --- a/sound/soc/intel/avs/boards/rt298.c +++ b/sound/soc/intel/avs/boards/rt298.c @@ -132,8 +132,8 @@ static const struct snd_soc_ops avs_rt298_ops = { .hw_params = avs_rt298_hw_params, }; -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -143,8 +143,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); @@ -159,6 +157,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 1; dl->platforms = platform; @@ -203,18 +202,16 @@ static int avs_rt298_probe(struct platform_device *pdev) struct snd_soc_card *card; struct snd_soc_jack *jack; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) return ret; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; @@ -246,10 +243,6 @@ static int avs_rt298_probe(struct platform_device *pdev) card->fully_routed = true; snd_soc_card_set_drvdata(card, jack); - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/rt5514.c b/sound/soc/intel/avs/boards/rt5514.c index 45f091f2ce22..00b99e36d23c 100644 --- a/sound/soc/intel/avs/boards/rt5514.c +++ b/sound/soc/intel/avs/boards/rt5514.c @@ -84,8 +84,8 @@ static const struct snd_soc_ops avs_rt5514_ops = { .hw_params = avs_rt5514_hw_params, }; -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -95,8 +95,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); @@ -111,6 +109,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 1; dl->platforms = platform; @@ -136,18 +135,16 @@ static int avs_rt5514_probe(struct platform_device *pdev) struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) return ret; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; @@ -173,10 +170,6 @@ static int avs_rt5514_probe(struct platform_device *pdev) card->num_dapm_routes = ARRAY_SIZE(card_base_routes); card->fully_routed = true; - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/rt5640.c b/sound/soc/intel/avs/boards/rt5640.c index 706b84ffe1ef..97d1fa944188 100644 --- a/sound/soc/intel/avs/boards/rt5640.c +++ b/sound/soc/intel/avs/boards/rt5640.c @@ -67,7 +67,7 @@ static int avs_rt5640_codec_init(struct snd_soc_pcm_runtime *runtime) return ret; snd_soc_component_set_jack(codec_dai->component, jack, NULL); - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; return 0; } diff --git a/sound/soc/intel/avs/boards/rt5663.c b/sound/soc/intel/avs/boards/rt5663.c index 51648801710a..68fea325376a 100644 --- a/sound/soc/intel/avs/boards/rt5663.c +++ b/sound/soc/intel/avs/boards/rt5663.c @@ -134,8 +134,8 @@ static const struct snd_soc_ops avs_rt5663_ops = { }; -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -145,8 +145,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); @@ -161,6 +159,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 1; dl->platforms = platform; @@ -202,18 +201,16 @@ static int avs_rt5663_probe(struct platform_device *pdev) struct snd_soc_card *card; struct rt5663_private *priv; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) return ret; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; @@ -245,10 +242,6 @@ static int avs_rt5663_probe(struct platform_device *pdev) card->fully_routed = true; snd_soc_card_set_drvdata(card, priv); - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/rt5682.c b/sound/soc/intel/avs/boards/rt5682.c index 9677b9ebeff1..81863728da1d 100644 --- a/sound/soc/intel/avs/boards/rt5682.c +++ b/sound/soc/intel/avs/boards/rt5682.c @@ -204,8 +204,8 @@ avs_rt5682_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_param return 0; } -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -215,8 +215,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); @@ -231,6 +229,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 1; dl->platforms = platform; @@ -272,7 +271,6 @@ static int avs_rt5682_probe(struct platform_device *pdev) struct snd_soc_card *card; struct snd_soc_jack *jack; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; if (pdev->id_entry && pdev->id_entry->driver_data) @@ -282,14 +280,13 @@ static int avs_rt5682_probe(struct platform_device *pdev) dev_dbg(dev, "avs_rt5682_quirk = %lx\n", avs_rt5682_quirk); mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) return ret; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; @@ -321,10 +318,6 @@ static int avs_rt5682_probe(struct platform_device *pdev) card->fully_routed = true; snd_soc_card_set_drvdata(card, jack); - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c index 3786eef8c494..ae0e6e27a8b8 100644 --- a/sound/soc/intel/avs/boards/ssm4567.c +++ b/sound/soc/intel/avs/boards/ssm4567.c @@ -81,8 +81,8 @@ avs_ssm4567_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_para return 0; } -static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - int tdm_slot, struct snd_soc_dai_link **dai_link) +static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, + struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -92,8 +92,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in if (!dl || !platform) return -ENOMEM; - platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); @@ -111,6 +109,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in !dl->codecs[1].name || !dl->codecs[1].dai_name) return -ENOMEM; + platform->name = dev_name(dev); dl->num_cpus = 1; dl->num_codecs = 2; dl->platforms = platform; @@ -135,18 +134,16 @@ static int avs_ssm4567_probe(struct platform_device *pdev) struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; - const char *pname; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); - pname = mach->mach_params.platform; pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) return ret; - ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; @@ -176,10 +173,6 @@ static int avs_ssm4567_probe(struct platform_device *pdev) card->num_dapm_routes = ARRAY_SIZE(card_base_routes); card->fully_routed = true; - ret = snd_soc_fixup_dai_links_platform_name(card, pname); - if (ret) - return ret; - return devm_snd_soc_register_deferrable_card(dev, card); } diff --git a/sound/soc/intel/avs/cnl.c b/sound/soc/intel/avs/cnl.c index 03f8fb0dc187..5b5359e9128b 100644 --- a/sound/soc/intel/avs/cnl.c +++ b/sound/soc/intel/avs/cnl.c @@ -8,6 +8,7 @@ #include <sound/hdaudio_ext.h> #include "avs.h" +#include "debug.h" #include "messages.h" #include "registers.h" diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c index 5ebadba07ecc..6e0e65584c7f 100644 --- a/sound/soc/intel/avs/core.c +++ b/sound/soc/intel/avs/core.c @@ -27,6 +27,7 @@ #include "../../codecs/hda.h" #include "avs.h" #include "cldma.h" +#include "debug.h" #include "messages.h" #include "pcm.h" diff --git a/sound/soc/intel/avs/debug.h b/sound/soc/intel/avs/debug.h new file mode 100644 index 000000000000..94fe8729a5c1 --- /dev/null +++ b/sound/soc/intel/avs/debug.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2024-2025 Intel Corporation + * + * Authors: Cezary Rojewski <cezary.rojewski@intel.com> + * Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> + */ + +#ifndef __SOUND_SOC_INTEL_AVS_DEBUG_H +#define __SOUND_SOC_INTEL_AVS_DEBUG_H + +#include "messages.h" +#include "registers.h" + +struct avs_dev; + +#define avs_log_buffer_size(adev) \ + ((adev)->fw_cfg.trace_log_bytes / (adev)->hw_cfg.dsp_cores) + +#define avs_log_buffer_addr(adev, core) \ +({ \ + s32 __offset = avs_dsp_op(adev, log_buffer_offset, core); \ + (__offset < 0) ? NULL : \ + (avs_sram_addr(adev, AVS_DEBUG_WINDOW) + __offset); \ +}) + +static inline int avs_log_buffer_status_locked(struct avs_dev *adev, union avs_notify_msg *msg) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&adev->trace_lock, flags); + ret = avs_dsp_op(adev, log_buffer_status, msg); + spin_unlock_irqrestore(&adev->trace_lock, flags); + + return ret; +} + +struct avs_apl_log_buffer_layout { + u32 read_ptr; + u32 write_ptr; + u8 buffer[]; +} __packed; +static_assert(sizeof(struct avs_apl_log_buffer_layout) == 8); + +#define avs_apl_log_payload_size(adev) \ + (avs_log_buffer_size(adev) - sizeof(struct avs_apl_log_buffer_layout)) + +#define avs_apl_log_payload_addr(addr) \ + (addr + sizeof(struct avs_apl_log_buffer_layout)) + +#ifdef CONFIG_DEBUG_FS +int avs_register_probe_component(struct avs_dev *adev, const char *name); + +#define AVS_SET_ENABLE_LOGS_OP(name) \ + .enable_logs = avs_##name##_enable_logs + +bool avs_logging_fw(struct avs_dev *adev); +void avs_dump_fw_log(struct avs_dev *adev, const void __iomem *src, unsigned int len); +void avs_dump_fw_log_wakeup(struct avs_dev *adev, const void __iomem *src, unsigned int len); + +void avs_debugfs_init(struct avs_dev *adev); +void avs_debugfs_exit(struct avs_dev *adev); + +#else +static inline int avs_register_probe_component(struct avs_dev *adev, const char *name) +{ + return -EOPNOTSUPP; +} + +#define AVS_SET_ENABLE_LOGS_OP(name) + +static inline bool avs_logging_fw(struct avs_dev *adev) +{ + return false; +} + +static inline void avs_dump_fw_log(struct avs_dev *adev, const void __iomem *src, unsigned int len) +{ +} + +static inline void avs_dump_fw_log_wakeup(struct avs_dev *adev, const void __iomem *src, + unsigned int len) +{ +} + +static inline void avs_debugfs_init(struct avs_dev *adev) { } +static inline void avs_debugfs_exit(struct avs_dev *adev) { } +#endif + +#endif diff --git a/sound/soc/intel/avs/debugfs.c b/sound/soc/intel/avs/debugfs.c index f508f215ecd2..3534de46f9e4 100644 --- a/sound/soc/intel/avs/debugfs.c +++ b/sound/soc/intel/avs/debugfs.c @@ -13,6 +13,7 @@ #include <linux/string_helpers.h> #include <sound/soc.h> #include "avs.h" +#include "debug.h" #include "messages.h" static unsigned int __kfifo_fromio(struct kfifo *fifo, const void __iomem *src, unsigned int len) diff --git a/sound/soc/intel/avs/icl.c b/sound/soc/intel/avs/icl.c index f8d327ea2656..d655e727bebd 100644 --- a/sound/soc/intel/avs/icl.c +++ b/sound/soc/intel/avs/icl.c @@ -10,6 +10,7 @@ #include <sound/hdaudio.h> #include <sound/hdaudio_ext.h> #include "avs.h" +#include "debug.h" #include "messages.h" #define ICL_VS_LTRP_GB_ICCMAX 95 diff --git a/sound/soc/intel/avs/ipc.c b/sound/soc/intel/avs/ipc.c index 6bfb9d1a1ca8..c0feb9edd7f6 100644 --- a/sound/soc/intel/avs/ipc.c +++ b/sound/soc/intel/avs/ipc.c @@ -10,6 +10,7 @@ #include <linux/slab.h> #include <sound/hdaudio_ext.h> #include "avs.h" +#include "debug.h" #include "messages.h" #include "registers.h" #include "trace.h" diff --git a/sound/soc/intel/avs/lnl.c b/sound/soc/intel/avs/lnl.c index 03208596dfb1..4fbc62bfd6c5 100644 --- a/sound/soc/intel/avs/lnl.c +++ b/sound/soc/intel/avs/lnl.c @@ -8,6 +8,7 @@ #include <sound/hdaudio_ext.h> #include "avs.h" +#include "debug.h" #include "registers.h" int avs_lnl_core_stall(struct avs_dev *adev, u32 core_mask, bool stall) diff --git a/sound/soc/intel/avs/mtl.c b/sound/soc/intel/avs/mtl.c index e7b7915b2a82..d8bdd03275d7 100644 --- a/sound/soc/intel/avs/mtl.c +++ b/sound/soc/intel/avs/mtl.c @@ -8,6 +8,7 @@ #include <sound/hdaudio_ext.h> #include "avs.h" +#include "debug.h" #include "registers.h" #include "trace.h" diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index e8e6b1c7fc90..7aa20fcf1a33 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -115,6 +115,55 @@ avs_path_find_variant(struct avs_dev *adev, return NULL; } +static struct avs_tplg_path *avs_condpath_find_variant(struct avs_dev *adev, + struct avs_tplg_path_template *template, + struct avs_path *source, + struct avs_path *sink) +{ + struct avs_tplg_path *variant; + + list_for_each_entry(variant, &template->path_list, node) { + if (variant->source_path_id == source->template->id && + variant->sink_path_id == sink->template->id) + return variant; + } + + return NULL; +} + +static bool avs_tplg_path_template_id_equal(struct avs_tplg_path_template_id *id, + struct avs_tplg_path_template_id *id2) +{ + return id->id == id2->id && !strcmp(id->tplg_name, id2->tplg_name); +} + +static struct avs_path *avs_condpath_find_match(struct avs_dev *adev, + struct avs_tplg_path_template *template, + struct avs_path *path, int dir) +{ + struct avs_tplg_path_template_id *id, *id2; + + if (dir) { + id = &template->source; + id2 = &template->sink; + } else { + id = &template->sink; + id2 = &template->source; + } + + /* Check whether this path is either source or sink of condpath template. */ + if (id->id != path->template->owner->id || + strcmp(id->tplg_name, path->template->owner->owner->name)) + return NULL; + + /* Unidirectional condpaths are allowed. */ + if (avs_tplg_path_template_id_equal(id, id2)) + return path; + + /* Now find the counterpart. */ + return avs_path_find_path(adev, id2->tplg_name, id2->id); +} + static struct acpi_nhlt_config * avs_nhlt_config_or_default(struct avs_dev *adev, struct avs_tplg_module *t); @@ -1051,6 +1100,10 @@ static int avs_path_init(struct avs_dev *adev, struct avs_path *path, path->dma_id = dma_id; INIT_LIST_HEAD(&path->ppl_list); INIT_LIST_HEAD(&path->node); + INIT_LIST_HEAD(&path->source_list); + INIT_LIST_HEAD(&path->sink_list); + INIT_LIST_HEAD(&path->source_node); + INIT_LIST_HEAD(&path->sink_node); /* create all the pipelines */ list_for_each_entry(tppl, &template->ppl_list, node) { @@ -1134,12 +1187,129 @@ err: return ERR_PTR(ret); } +static void avs_condpath_free(struct avs_dev *adev, struct avs_path *path) +{ + int ret; + + list_del(&path->source_node); + list_del(&path->sink_node); + + ret = avs_path_reset(path); + if (ret < 0) + dev_err(adev->dev, "reset condpath failed: %d\n", ret); + + ret = avs_path_unbind(path); + if (ret < 0) + dev_err(adev->dev, "unbind condpath failed: %d\n", ret); + + avs_path_free_unlocked(path); +} + +static struct avs_path *avs_condpath_create(struct avs_dev *adev, + struct avs_tplg_path *template, + struct avs_path *source, + struct avs_path *sink) +{ + struct avs_path *path; + int ret; + + path = avs_path_create_unlocked(adev, 0, template); + if (IS_ERR(path)) + return path; + + ret = avs_path_bind(path); + if (ret) + goto err_bind; + + ret = avs_path_reset(path); + if (ret) + goto err_reset; + + path->source = source; + path->sink = sink; + list_add_tail(&path->source_node, &source->source_list); + list_add_tail(&path->sink_node, &sink->sink_list); + + return path; + +err_reset: + avs_path_unbind(path); +err_bind: + avs_path_free_unlocked(path); + return ERR_PTR(ret); +} + +static int avs_condpaths_walk(struct avs_dev *adev, struct avs_path *path, int dir) +{ + struct avs_soc_component *acomp; + struct avs_path *source, *sink; + struct avs_path **other; + + if (dir) { + source = path; + other = &sink; + } else { + sink = path; + other = &source; + } + + list_for_each_entry(acomp, &adev->comp_list, node) { + for (int i = 0; i < acomp->tplg->num_condpath_tmpls; i++) { + struct avs_tplg_path_template *template; + struct avs_tplg_path *variant; + struct avs_path *cpath; + + template = &acomp->tplg->condpath_tmpls[i]; + + /* Do not create unidirectional condpaths twice. */ + if (avs_tplg_path_template_id_equal(&template->source, + &template->sink) && dir) + continue; + + *other = avs_condpath_find_match(adev, template, path, dir); + if (!*other) + continue; + + variant = avs_condpath_find_variant(adev, template, source, sink); + if (!variant) + continue; + + cpath = avs_condpath_create(adev, variant, source, sink); + if (IS_ERR(cpath)) + return PTR_ERR(cpath); + } + } + + return 0; +} + +/* Caller responsible for holding adev->path_mutex. */ +static int avs_condpaths_walk_all(struct avs_dev *adev, struct avs_path *path) +{ + int ret; + + ret = avs_condpaths_walk(adev, path, SNDRV_PCM_STREAM_CAPTURE); + if (ret) + return ret; + + return avs_condpaths_walk(adev, path, SNDRV_PCM_STREAM_PLAYBACK); +} + void avs_path_free(struct avs_path *path) { + struct avs_path *cpath, *csave; struct avs_dev *adev = path->owner; mutex_lock(&adev->path_mutex); + + /* Free all condpaths this path spawned. */ + list_for_each_entry_safe(cpath, csave, &path->source_list, source_node) + avs_condpath_free(path->owner, cpath); + list_for_each_entry_safe(cpath, csave, &path->sink_list, sink_node) + avs_condpath_free(path->owner, cpath); + avs_path_free_unlocked(path); + mutex_unlock(&adev->path_mutex); } @@ -1150,6 +1320,7 @@ struct avs_path *avs_path_create(struct avs_dev *adev, u32 dma_id, { struct avs_tplg_path *variant; struct avs_path *path; + int ret; variant = avs_path_find_variant(adev, template, fe_params, be_params); if (!variant) { @@ -1163,7 +1334,16 @@ struct avs_path *avs_path_create(struct avs_dev *adev, u32 dma_id, mutex_lock(&adev->comp_list_mutex); path = avs_path_create_unlocked(adev, dma_id, variant); + if (IS_ERR(path)) + goto exit; + + ret = avs_condpaths_walk_all(adev, path); + if (ret) { + avs_path_free_unlocked(path); + path = ERR_PTR(ret); + } +exit: mutex_unlock(&adev->comp_list_mutex); mutex_unlock(&adev->path_mutex); @@ -1286,6 +1466,42 @@ int avs_path_reset(struct avs_path *path) return 0; } +static int avs_condpath_pause(struct avs_dev *adev, struct avs_path *cpath) +{ + struct avs_path_pipeline *ppl; + int ret; + + if (cpath->state == AVS_PPL_STATE_PAUSED) + return 0; + + list_for_each_entry_reverse(ppl, &cpath->ppl_list, node) { + ret = avs_ipc_set_pipeline_state(adev, ppl->instance_id, AVS_PPL_STATE_PAUSED); + if (ret) { + dev_err(adev->dev, "pause cpath failed: %d\n", ret); + cpath->state = AVS_PPL_STATE_INVALID; + return AVS_IPC_RET(ret); + } + } + + cpath->state = AVS_PPL_STATE_PAUSED; + return 0; +} + +static void avs_condpaths_pause(struct avs_dev *adev, struct avs_path *path) +{ + struct avs_path *cpath; + + mutex_lock(&adev->path_mutex); + + /* If either source or sink stops, so do the attached conditional paths. */ + list_for_each_entry(cpath, &path->source_list, source_node) + avs_condpath_pause(adev, cpath); + list_for_each_entry(cpath, &path->sink_list, sink_node) + avs_condpath_pause(adev, cpath); + + mutex_unlock(&adev->path_mutex); +} + int avs_path_pause(struct avs_path *path) { struct avs_path_pipeline *ppl; @@ -1295,6 +1511,8 @@ int avs_path_pause(struct avs_path *path) if (path->state == AVS_PPL_STATE_PAUSED) return 0; + avs_condpaths_pause(adev, path); + list_for_each_entry_reverse(ppl, &path->ppl_list, node) { ret = avs_ipc_set_pipeline_state(adev, ppl->instance_id, AVS_PPL_STATE_PAUSED); @@ -1309,6 +1527,50 @@ int avs_path_pause(struct avs_path *path) return 0; } +static int avs_condpath_run(struct avs_dev *adev, struct avs_path *cpath, int trigger) +{ + struct avs_path_pipeline *ppl; + int ret; + + if (cpath->state == AVS_PPL_STATE_RUNNING) + return 0; + + list_for_each_entry(ppl, &cpath->ppl_list, node) { + if (ppl->template->cfg->trigger != trigger) + continue; + + ret = avs_ipc_set_pipeline_state(adev, ppl->instance_id, AVS_PPL_STATE_RUNNING); + if (ret) { + dev_err(adev->dev, "run cpath failed: %d\n", ret); + cpath->state = AVS_PPL_STATE_INVALID; + return AVS_IPC_RET(ret); + } + } + + cpath->state = AVS_PPL_STATE_RUNNING; + return 0; +} + +static void avs_condpaths_run(struct avs_dev *adev, struct avs_path *path, int trigger) +{ + struct avs_path *cpath; + + mutex_lock(&adev->path_mutex); + + /* Run conditional paths only if source and sink are both running. */ + list_for_each_entry(cpath, &path->source_list, source_node) + if (cpath->source->state == AVS_PPL_STATE_RUNNING && + cpath->sink->state == AVS_PPL_STATE_RUNNING) + avs_condpath_run(adev, cpath, trigger); + + list_for_each_entry(cpath, &path->sink_list, sink_node) + if (cpath->source->state == AVS_PPL_STATE_RUNNING && + cpath->sink->state == AVS_PPL_STATE_RUNNING) + avs_condpath_run(adev, cpath, trigger); + + mutex_unlock(&adev->path_mutex); +} + int avs_path_run(struct avs_path *path, int trigger) { struct avs_path_pipeline *ppl; @@ -1332,5 +1594,10 @@ int avs_path_run(struct avs_path *path, int trigger) } path->state = AVS_PPL_STATE_RUNNING; + + /* Granular pipeline triggering not intended for conditional paths. */ + if (trigger == AVS_TPLG_TRIGGER_AUTO) + avs_condpaths_run(adev, path, trigger); + return 0; } diff --git a/sound/soc/intel/avs/path.h b/sound/soc/intel/avs/path.h index c65ed84aa853..ceb89971a902 100644 --- a/sound/soc/intel/avs/path.h +++ b/sound/soc/intel/avs/path.h @@ -13,11 +13,24 @@ #include "avs.h" #include "topology.h" +#define AVS_COND_TYPE_NONE 0 +#define AVS_COND_TYPE_AECREF 1 + struct avs_path { u32 dma_id; struct list_head ppl_list; u32 state; + /* condpath navigation for standard paths */ + struct list_head source_list; + struct list_head sink_list; + + /* conditional path fields */ + struct avs_path *source; + struct avs_path *sink; + struct list_head source_node; + struct list_head sink_node; + struct avs_tplg_path *template; struct avs_dev *owner; /* device path management */ diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 67ce6675eea7..d31058e2de5b 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -1379,9 +1379,9 @@ static struct snd_soc_component_driver avs_component_driver = { .topology_name_prefix = "intel/avs", }; -int avs_soc_component_register(struct device *dev, const char *name, - struct snd_soc_component_driver *drv, - struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais) +int avs_register_component(struct device *dev, const char *name, + struct snd_soc_component_driver *drv, + struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais) { struct avs_soc_component *acomp; int ret; @@ -1390,16 +1390,18 @@ int avs_soc_component_register(struct device *dev, const char *name, if (!acomp) return -ENOMEM; - ret = snd_soc_component_initialize(&acomp->base, drv, dev); - if (ret < 0) - return ret; + acomp->base.name = devm_kstrdup(dev, name, GFP_KERNEL); + if (!acomp->base.name) + return -ENOMEM; - /* force name change after ASoC is done with its init */ - acomp->base.name = name; INIT_LIST_HEAD(&acomp->node); drv->use_dai_pcm_id = !obsolete_card_names; + ret = snd_soc_component_initialize(&acomp->base, drv, dev); + if (ret < 0) + return ret; + return snd_soc_add_component(&acomp->base, cpu_dais, num_cpu_dais); } @@ -1426,7 +1428,7 @@ static struct snd_soc_dai_driver dmic_cpu_dais[] = { }, }; -int avs_dmic_platform_register(struct avs_dev *adev, const char *name) +int avs_register_dmic_component(struct avs_dev *adev, const char *name) { const struct snd_soc_dai_ops *ops; @@ -1437,8 +1439,8 @@ int avs_dmic_platform_register(struct avs_dev *adev, const char *name) dmic_cpu_dais[0].ops = ops; dmic_cpu_dais[1].ops = ops; - return avs_soc_component_register(adev->dev, name, &avs_component_driver, dmic_cpu_dais, - ARRAY_SIZE(dmic_cpu_dais)); + return avs_register_component(adev->dev, name, &avs_component_driver, dmic_cpu_dais, + ARRAY_SIZE(dmic_cpu_dais)); } static const struct snd_soc_dai_driver i2s_dai_template = { @@ -1470,8 +1472,8 @@ static const struct snd_soc_dai_driver i2s_dai_template = { }, }; -int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned long port_mask, - unsigned long *tdms) +int avs_register_i2s_component(struct avs_dev *adev, const char *name, unsigned long port_mask, + unsigned long *tdms) { struct snd_soc_dai_driver *cpus, *dai; const struct snd_soc_dai_ops *ops; @@ -1537,7 +1539,7 @@ int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned l } plat_register: - return avs_soc_component_register(adev->dev, name, &avs_component_driver, cpus, cpu_count); + return avs_register_component(adev->dev, name, &avs_component_driver, cpus, cpu_count); } /* HD-Audio CPU DAI template */ @@ -1762,8 +1764,7 @@ static struct snd_soc_component_driver avs_hda_component_driver = { .topology_name_prefix = "intel/avs", }; -int avs_hda_platform_register(struct avs_dev *adev, const char *name) +int avs_register_hda_component(struct avs_dev *adev, const char *name) { - return avs_soc_component_register(adev->dev, name, - &avs_hda_component_driver, NULL, 0); + return avs_register_component(adev->dev, name, &avs_hda_component_driver, NULL, 0); } diff --git a/sound/soc/intel/avs/probes.c b/sound/soc/intel/avs/probes.c index a42736b9aa55..693ecfe68fd0 100644 --- a/sound/soc/intel/avs/probes.c +++ b/sound/soc/intel/avs/probes.c @@ -11,6 +11,7 @@ #include <sound/hdaudio.h> #include <sound/soc.h> #include "avs.h" +#include "debug.h" #include "messages.h" static int avs_dsp_init_probe(struct avs_dev *adev, union avs_connector_node_id node_id, @@ -213,7 +214,7 @@ static int avs_probe_compr_trigger(struct snd_compr_stream *cstream, int cmd, } static int avs_probe_compr_pointer(struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai) + struct snd_compr_tstamp64 *tstamp, struct snd_soc_dai *dai) { struct hdac_ext_stream *host_stream = avs_compr_get_host_stream(cstream); struct snd_soc_pcm_stream *pstream; @@ -284,14 +285,28 @@ static struct snd_soc_dai_driver probe_cpu_dais[] = { }, }; -static struct snd_soc_component_driver avs_probe_component_driver = { +static const struct snd_soc_component_driver avs_probe_component_driver = { .name = "avs-probe-compr", .compress_ops = &avs_probe_compress_ops, .module_get_upon_open = 1, /* increment refcount when a stream is opened */ }; -int avs_probe_platform_register(struct avs_dev *adev, const char *name) +int avs_register_probe_component(struct avs_dev *adev, const char *name) { - return avs_soc_component_register(adev->dev, name, &avs_probe_component_driver, - probe_cpu_dais, ARRAY_SIZE(probe_cpu_dais)); + struct snd_soc_component *component; + int ret; + + component = devm_kzalloc(adev->dev, sizeof(*component), GFP_KERNEL); + if (!component) + return -ENOMEM; + + component->name = devm_kstrdup(adev->dev, name, GFP_KERNEL); + if (!component->name) + return -ENOMEM; + + ret = snd_soc_component_initialize(component, &avs_probe_component_driver, adev->dev); + if (ret) + return ret; + + return snd_soc_add_component(component, probe_cpu_dais, ARRAY_SIZE(probe_cpu_dais)); } diff --git a/sound/soc/intel/avs/ptl.c b/sound/soc/intel/avs/ptl.c index 2be4b545c91d..07da9b0aa2b8 100644 --- a/sound/soc/intel/avs/ptl.c +++ b/sound/soc/intel/avs/ptl.c @@ -8,6 +8,7 @@ #include <sound/hdaudio_ext.h> #include "avs.h" +#include "debug.h" #include "registers.h" #include "trace.h" diff --git a/sound/soc/intel/avs/skl.c b/sound/soc/intel/avs/skl.c index d66ef000de9e..8fb86f364ff3 100644 --- a/sound/soc/intel/avs/skl.c +++ b/sound/soc/intel/avs/skl.c @@ -11,6 +11,7 @@ #include <sound/hdaudio_ext.h> #include "avs.h" #include "cldma.h" +#include "debug.h" #include "messages.h" #include "registers.h" diff --git a/sound/soc/intel/avs/tgl.c b/sound/soc/intel/avs/tgl.c index 9dbb3ad0954a..afb066516101 100644 --- a/sound/soc/intel/avs/tgl.c +++ b/sound/soc/intel/avs/tgl.c @@ -8,6 +8,7 @@ #include <linux/pci.h> #include "avs.h" +#include "debug.h" #include "messages.h" #define CPUID_TSC_LEAF 0x15 diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index f2e4ad8b8e14..dfe8cf505381 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -1387,6 +1387,27 @@ static const struct avs_tplg_token_parser path_parsers[] = { }, }; +static const struct avs_tplg_token_parser condpath_parsers[] = { + { + .token = AVS_TKN_CONDPATH_ID_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_path, id), + .parse = avs_parse_word_token, + }, + { + .token = AVS_TKN_CONDPATH_SOURCE_PATH_ID_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_path, source_path_id), + .parse = avs_parse_word_token, + }, + { + .token = AVS_TKN_CONDPATH_SINK_PATH_ID_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_path, sink_path_id), + .parse = avs_parse_word_token, + }, +}; + static struct avs_tplg_path * avs_tplg_path_create(struct snd_soc_component *comp, struct avs_tplg_path_template *owner, struct snd_soc_tplg_vendor_array *tuples, u32 block_size, @@ -1454,6 +1475,39 @@ static const struct avs_tplg_token_parser path_tmpl_parsers[] = { }, }; +static const struct avs_tplg_token_parser condpath_tmpl_parsers[] = { + { + .token = AVS_TKN_CONDPATH_TMPL_ID_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_path_template, id), + .parse = avs_parse_word_token, + }, + { + .token = AVS_TKN_CONDPATH_TMPL_SOURCE_TPLG_NAME_STRING, + .type = SND_SOC_TPLG_TUPLE_TYPE_STRING, + .offset = offsetof(struct avs_tplg_path_template, source.tplg_name), + .parse = avs_parse_string_token, + }, + { + .token = AVS_TKN_CONDPATH_TMPL_SOURCE_PATH_TMPL_ID_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_path_template, source.id), + .parse = avs_parse_word_token, + }, + { + .token = AVS_TKN_CONDPATH_TMPL_SINK_TPLG_NAME_STRING, + .type = SND_SOC_TPLG_TUPLE_TYPE_STRING, + .offset = offsetof(struct avs_tplg_path_template, sink.tplg_name), + .parse = avs_parse_string_token, + }, + { + .token = AVS_TKN_CONDPATH_TMPL_SINK_PATH_TMPL_ID_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_path_template, sink.id), + .parse = avs_parse_word_token, + }, +}; + static int parse_path_template(struct snd_soc_component *comp, struct snd_soc_tplg_vendor_array *tuples, u32 block_size, struct avs_tplg_path_template *template, @@ -1524,6 +1578,56 @@ avs_tplg_path_template_create(struct snd_soc_component *comp, struct avs_tplg *o return template; } +static int avs_tplg_parse_condpath_templates(struct snd_soc_component *comp, + struct snd_soc_tplg_vendor_array *tuples, + u32 block_size) +{ + struct avs_soc_component *acomp = to_avs_soc_component(comp); + struct avs_tplg *tplg = acomp->tplg; + int ret, i; + + ret = parse_dictionary_header(comp, tuples, (void **)&tplg->condpath_tmpls, + &tplg->num_condpath_tmpls, + sizeof(*tplg->condpath_tmpls), + AVS_TKN_MANIFEST_NUM_CONDPATH_TMPLS_U32); + if (ret) + return ret; + + block_size -= le32_to_cpu(tuples->size); + /* With header parsed, move on to parsing entries. */ + tuples = avs_tplg_vendor_array_next(tuples); + + for (i = 0; i < tplg->num_condpath_tmpls; i++) { + struct avs_tplg_path_template *template; + u32 esize; + + template = &tplg->condpath_tmpls[i]; + template->owner = tplg; /* Used when building sysfs hierarchy. */ + INIT_LIST_HEAD(&template->path_list); + INIT_LIST_HEAD(&template->node); + + ret = avs_tplg_vendor_entry_size(tuples, block_size, + AVS_TKN_CONDPATH_TMPL_ID_U32, &esize); + if (ret) + return ret; + + ret = parse_path_template(comp, tuples, esize, template, + condpath_tmpl_parsers, + ARRAY_SIZE(condpath_tmpl_parsers), + condpath_parsers, + ARRAY_SIZE(condpath_parsers)); + if (ret < 0) { + dev_err(comp->dev, "parse condpath_tmpl: %d failed: %d\n", i, ret); + return ret; + } + + block_size -= esize; + tuples = avs_tplg_vendor_array_at(tuples, esize); + } + + return 0; +} + static const struct avs_tplg_token_parser mod_init_config_parsers[] = { { .token = AVS_TKN_INIT_CONFIG_ID_U32, @@ -1891,6 +1995,12 @@ static int avs_manifest(struct snd_soc_component *comp, int index, return ret; } + /* Condpaths dictionary. */ + ret = avs_tplg_parse_condpath_templates(comp, tuples, + has_init_config ? offset : remaining); + if (ret < 0) + return ret; + if (!has_init_config) return 0; diff --git a/sound/soc/intel/avs/topology.h b/sound/soc/intel/avs/topology.h index f5601a4e3ec8..1e83fccf2ea2 100644 --- a/sound/soc/intel/avs/topology.h +++ b/sound/soc/intel/avs/topology.h @@ -33,6 +33,7 @@ struct avs_tplg { u32 num_pplcfgs; struct avs_tplg_binding *bindings; u32 num_bindings; + struct avs_tplg_path_template *condpath_tmpls; u32 num_condpath_tmpls; struct avs_tplg_init_config *init_configs; u32 num_init_configs; @@ -155,6 +156,10 @@ struct avs_tplg_path_template { struct snd_soc_dapm_widget *w; + /* Conditional path. */ + struct avs_tplg_path_template_id source; + struct avs_tplg_path_template_id sink; + struct list_head path_list; struct avs_tplg *owner; @@ -176,6 +181,9 @@ struct avs_tplg_path { /* Path format requirements. */ struct avs_audio_format *fe_fmt; struct avs_audio_format *be_fmt; + /* Condpath path-variant requirements. */ + u32 source_path_id; + u32 sink_path_id; struct list_head ppl_list; diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index 68a3d345dc25..27b63a853a48 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -77,7 +77,7 @@ static int byt_cht_cx2072x_init(struct snd_soc_pcm_runtime *rtd) byt_cht_cx2072x_acpi_gpios)) dev_warn(rtd->dev, "Unable to add GPIO mapping table\n"); - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; /* set the default PLL rate, the clock is handled by the codec driver */ ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(rtd, 0), CX2072X_MCLK_EXTERNAL_PLL, diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index 62594e7966ab..3b5f63112237 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -47,7 +47,8 @@ enum { BYT_CHT_ES8316_INTMIC_IN2_MAP, }; -#define BYT_CHT_ES8316_MAP(quirk) ((quirk) & GENMASK(3, 0)) +#define BYT_CHT_ES8316_MAP_MASK GENMASK(3, 0) +#define BYT_CHT_ES8316_MAP(quirk) ((quirk) & BYT_CHT_ES8316_MAP_MASK) #define BYT_CHT_ES8316_SSP0 BIT(16) #define BYT_CHT_ES8316_MONO_SPEAKER BIT(17) #define BYT_CHT_ES8316_JD_INVERTED BIT(18) @@ -60,10 +61,23 @@ MODULE_PARM_DESC(quirk, "Board-specific quirk override"); static void log_quirks(struct device *dev) { - if (BYT_CHT_ES8316_MAP(quirk) == BYT_CHT_ES8316_INTMIC_IN1_MAP) + int map; + + map = BYT_CHT_ES8316_MAP(quirk); + switch (map) { + case BYT_CHT_ES8316_INTMIC_IN1_MAP: dev_info(dev, "quirk IN1_MAP enabled"); - if (BYT_CHT_ES8316_MAP(quirk) == BYT_CHT_ES8316_INTMIC_IN2_MAP) + break; + case BYT_CHT_ES8316_INTMIC_IN2_MAP: dev_info(dev, "quirk IN2_MAP enabled"); + break; + default: + dev_warn_once(dev, "quirk sets invalid input map: 0x%x, default to INTMIC_IN1_MAP\n", map); + quirk &= ~BYT_CHT_ES8316_MAP_MASK; + quirk |= BYT_CHT_ES8316_INTMIC_IN1_MAP; + break; + } + if (quirk & BYT_CHT_ES8316_SSP0) dev_info(dev, "quirk SSP0 enabled"); if (quirk & BYT_CHT_ES8316_MONO_SPEAKER) @@ -165,7 +179,7 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime) int num_routes; int ret; - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; switch (BYT_CHT_ES8316_MAP(quirk)) { case BYT_CHT_ES8316_INTMIC_IN1_MAP: diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 0f3b8f44e701..1e9b1903fae8 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -68,7 +68,8 @@ enum { BYT_RT5640_OVCD_SF_1P5 = (RT5640_OVCD_SF_1P5 << 13), }; -#define BYT_RT5640_MAP(quirk) ((quirk) & GENMASK(3, 0)) +#define BYT_RT5640_MAP_MASK GENMASK(3, 0) +#define BYT_RT5640_MAP(quirk) ((quirk) & BYT_RT5640_MAP_MASK) #define BYT_RT5640_JDSRC(quirk) (((quirk) & GENMASK(7, 4)) >> 4) #define BYT_RT5640_OVCD_TH(quirk) (((quirk) & GENMASK(12, 8)) >> 8) #define BYT_RT5640_OVCD_SF(quirk) (((quirk) & GENMASK(14, 13)) >> 13) @@ -140,7 +141,9 @@ static void log_quirks(struct device *dev) dev_info(dev, "quirk NO_INTERNAL_MIC_MAP enabled\n"); break; default: - dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map); + dev_warn_once(dev, "quirk sets invalid input map: 0x%x, default to DMIC1_MAP\n", map); + byt_rt5640_quirk &= ~BYT_RT5640_MAP_MASK; + byt_rt5640_quirk |= BYT_RT5640_DMIC1_MAP; break; } if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1) @@ -1321,7 +1324,7 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) int num_routes = 0; int ret; - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; jack_data->use_platform_clock = true; /* Start with RC clk for jack-detect (we disable MCLK below) */ diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 67c62844ca2a..ca540a66f22c 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -58,7 +58,8 @@ enum { BYT_RT5651_OVCD_SF_1P5 = (RT5651_OVCD_SF_1P5 << 13), }; -#define BYT_RT5651_MAP(quirk) ((quirk) & GENMASK(3, 0)) +#define BYT_RT5651_MAP_MASK GENMASK(3, 0) +#define BYT_RT5651_MAP(quirk) ((quirk) & BYT_RT5651_MAP_MASK) #define BYT_RT5651_JDSRC(quirk) (((quirk) & GENMASK(7, 4)) >> 4) #define BYT_RT5651_OVCD_TH(quirk) (((quirk) & GENMASK(12, 8)) >> 8) #define BYT_RT5651_OVCD_SF(quirk) (((quirk) & GENMASK(14, 13)) >> 13) @@ -100,14 +101,29 @@ MODULE_PARM_DESC(quirk, "Board-specific quirk override"); static void log_quirks(struct device *dev) { - if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_DMIC_MAP) + int map; + + map = BYT_RT5651_MAP(byt_rt5651_quirk); + switch (map) { + case BYT_RT5651_DMIC_MAP: dev_info(dev, "quirk DMIC_MAP enabled"); - if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_MAP) + break; + case BYT_RT5651_IN1_MAP: dev_info(dev, "quirk IN1_MAP enabled"); - if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN2_MAP) + break; + case BYT_RT5651_IN2_MAP: dev_info(dev, "quirk IN2_MAP enabled"); - if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_IN2_MAP) + break; + case BYT_RT5651_IN1_IN2_MAP: dev_info(dev, "quirk IN1_IN2_MAP enabled"); + break; + default: + dev_warn_once(dev, "quirk sets invalid input map: 0x%x, default to DMIC_MAP\n", map); + byt_rt5651_quirk &= ~BYT_RT5651_MAP_MASK; + byt_rt5651_quirk |= BYT_RT5651_DMIC_MAP; + break; + } + if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) { dev_info(dev, "quirk realtek,jack-detect-source %ld\n", BYT_RT5651_JDSRC(byt_rt5651_quirk)); @@ -570,7 +586,7 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime) int report; int ret; - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; /* Start with RC clk for jack-detect (we disable MCLK below) */ if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c index a6dfbcfdf74e..72c0e5941ae8 100644 --- a/sound/soc/intel/boards/bytcr_wm5102.c +++ b/sound/soc/intel/boards/bytcr_wm5102.c @@ -288,7 +288,7 @@ static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime) const struct snd_soc_dapm_route *custom_map = NULL; int ret, jack_type, num_routes = 0; - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; ret = snd_soc_add_card_controls(card, byt_wm5102_controls, ARRAY_SIZE(byt_wm5102_controls)); diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c index 1211a2b8a2a2..10b189ea88db 100644 --- a/sound/soc/intel/boards/sof_es8336.c +++ b/sound/soc/intel/boards/sof_es8336.c @@ -276,7 +276,7 @@ static int sof_es8316_init(struct snd_soc_pcm_runtime *runtime) int num_routes; int ret; - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; if (quirk & SOC_ES8336_HEADSET_MIC1) { custom_map = sof_es8316_headset_mic1_map; diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 28f03a5f29f7..c013e31d098e 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -841,7 +841,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, (*codec_conf)++; } - if (sof_end->include_sidecar) { + if (sof_end->include_sidecar && sof_end->codec_info->add_sidecar) { ret = sof_end->codec_info->add_sidecar(card, dai_links, codec_conf); if (ret) return ret; diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index 75dc8935a794..ec9fd8486c05 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -948,6 +948,30 @@ static const struct snd_soc_acpi_adr_device cs42l42_0_adr[] = { } }; +static const struct snd_soc_acpi_adr_device tas2783_0_adr[] = { + { + .adr = 0x0000380102000001ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "tas2783-1" + }, + { + .adr = 0x0000390102000001ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "tas2783-2" + } +}; + +static const struct snd_soc_acpi_link_adr tas2783_link0[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(tas2783_0_adr), + .adr_d = tas2783_0_adr, + }, + {} +}; + static const struct snd_soc_acpi_link_adr cs42l42_link0_max98363_link2[] = { /* Expected order: jack -> amp */ { @@ -1081,6 +1105,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = { .sof_tplg_filename = "sof-mtl-rt715-rt711-rt1308-mono.tplg", }, { + .link_mask = BIT(0), + .links = tas2783_link0, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-mtl-tas2783.tplg", + }, + { .link_mask = GENMASK(3, 0), .links = mtl_rt713_l0_rt1316_l12_rt1713_l3, .drv_name = "sof_sdw", diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c index 95a083939f3e..a2a30a87a359 100644 --- a/sound/soc/mediatek/common/mtk-soundcard-driver.c +++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c @@ -89,40 +89,31 @@ static int set_dailink_daifmt(struct snd_soc_card *card, int parse_dai_link_info(struct snd_soc_card *card) { struct device *dev = card->dev; - struct device_node *sub_node; struct snd_soc_dai_link *dai_link; const char *dai_link_name; int ret, i; /* Loop over all the dai link sub nodes */ - for_each_available_child_of_node(dev->of_node, sub_node) { + for_each_available_child_of_node_scoped(dev->of_node, sub_node) { if (of_property_read_string(sub_node, "link-name", - &dai_link_name)) { - of_node_put(sub_node); + &dai_link_name)) return -EINVAL; - } for_each_card_prelinks(card, i, dai_link) { if (!strcmp(dai_link_name, dai_link->name)) break; } - if (i >= card->num_links) { - of_node_put(sub_node); + if (i >= card->num_links) return -EINVAL; - } ret = set_card_codec_info(card, sub_node, dai_link); - if (ret < 0) { - of_node_put(sub_node); + if (ret < 0) return ret; - } ret = set_dailink_daifmt(card, sub_node, dai_link); - if (ret < 0) { - of_node_put(sub_node); + if (ret < 0) return ret; - } } return 0; diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c index 7d6a3586cdd5..3d6d7bc05b87 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c @@ -159,7 +159,7 @@ static int mt8173_rt5650_hdmi_init(struct snd_soc_pcm_runtime *rtd) { int ret; - ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_AVOUT, &mt8173_rt5650_hdmi_jack); if (ret) return ret; diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index 3388e076ccc9..983f3b91119a 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -378,7 +378,7 @@ static int mt8183_da7219_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd) snd_soc_card_get_drvdata(rtd->card); int ret; - ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_AVOUT, &priv->hdmi_jack); if (ret) return ret; diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 497a9043be7b..0bc1f11e17aa 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -383,7 +383,7 @@ mt8183_mt6358_ts3a227_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd) snd_soc_card_get_drvdata(rtd->card); int ret; - ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_AVOUT, &priv->hdmi_jack); if (ret) return ret; diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366.c b/sound/soc/mediatek/mt8186/mt8186-mt6366.c index 43546012cf61..45df69809cba 100644 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366.c +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366.c @@ -362,7 +362,7 @@ static int mt8186_mt6366_rt1019_rt5682s_hdmi_init(struct snd_soc_pcm_runtime *rt return ret; } - ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, jack); + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_AVOUT, jack); if (ret) { dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret); return ret; diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c index ea814a0f726d..c6e7461e8f76 100644 --- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c +++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c @@ -250,14 +250,14 @@ enum mt8188_jacks { static struct snd_soc_jack_pin mt8188_hdmi_jack_pins[] = { { .pin = "HDMI", - .mask = SND_JACK_LINEOUT, + .mask = SND_JACK_AVOUT, }, }; static struct snd_soc_jack_pin mt8188_dp_jack_pins[] = { { .pin = "DP", - .mask = SND_JACK_LINEOUT, + .mask = SND_JACK_AVOUT, }, }; @@ -638,7 +638,7 @@ static int mt8188_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd) int ret = 0; ret = snd_soc_card_jack_new_pins(rtd->card, "HDMI Jack", - SND_JACK_LINEOUT, jack, + SND_JACK_AVOUT, jack, mt8188_hdmi_jack_pins, ARRAY_SIZE(mt8188_hdmi_jack_pins)); if (ret) { @@ -663,7 +663,7 @@ static int mt8188_dptx_codec_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; int ret = 0; - ret = snd_soc_card_jack_new_pins(rtd->card, "DP Jack", SND_JACK_LINEOUT, + ret = snd_soc_card_jack_new_pins(rtd->card, "DP Jack", SND_JACK_AVOUT, jack, mt8188_dp_jack_pins, ARRAY_SIZE(mt8188_dp_jack_pins)); if (ret) { diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index bf483a8fb34a..91c57765ab57 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -368,7 +368,7 @@ static int mt8192_mt6359_hdmi_init(struct snd_soc_pcm_runtime *rtd) snd_soc_rtd_to_codec(rtd, 0)->component; int ret; - ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, jack); + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_AVOUT, jack); if (ret) { dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret); return ret; diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359.c b/sound/soc/mediatek/mt8195/mt8195-mt6359.c index e57391c213e7..7b96c843a14a 100644 --- a/sound/soc/mediatek/mt8195/mt8195-mt6359.c +++ b/sound/soc/mediatek/mt8195/mt8195-mt6359.c @@ -360,7 +360,7 @@ static int mt8195_dptx_codec_init(struct snd_soc_pcm_runtime *rtd) snd_soc_rtd_to_codec(rtd, 0)->component; int ret; - ret = snd_soc_card_jack_new(rtd->card, "DP Jack", SND_JACK_LINEOUT, jack); + ret = snd_soc_card_jack_new(rtd->card, "DP Jack", SND_JACK_AVOUT, jack); if (ret) return ret; @@ -375,7 +375,7 @@ static int mt8195_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd) snd_soc_rtd_to_codec(rtd, 0)->component; int ret; - ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, jack); + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_AVOUT, jack); if (ret) return ret; diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index e026f9912a6d..e54abcd39f79 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -3,7 +3,7 @@ menu "PXA" config SND_PXA2XX_SOC tristate "SoC Audio for the Intel PXA2xx chip" - depends on ARCH_PXA || COMPILE_TEST + depends on ARCH_PXA || (COMPILE_TEST && GPIOLIB_LEGACY) select SND_PXA2XX_LIB help Say Y or M if you want to add support for codecs attached to @@ -26,7 +26,7 @@ config SND_PXA2XX_SOC_I2S config SND_PXA_SOC_SSP tristate "Soc Audio via PXA2xx/PXA3xx SSP ports" - depends on PLAT_PXA + depends on ARCH_PXA select PXA_SSP select SND_PXA2XX_LIB diff --git a/sound/soc/qcom/lpass-cdc-dma.c b/sound/soc/qcom/lpass-cdc-dma.c index 8106c586f68a..2dc8c75c4bf0 100644 --- a/sound/soc/qcom/lpass-cdc-dma.c +++ b/sound/soc/qcom/lpass-cdc-dma.c @@ -217,8 +217,9 @@ static int lpass_cdc_dma_daiops_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); struct lpaif_dmactl *dmactl = NULL; - unsigned int ret, regval; + unsigned int regval; unsigned int channels = params_channels(params); + int ret; int id; switch (channels) { diff --git a/sound/soc/qcom/lpass-hdmi.c b/sound/soc/qcom/lpass-hdmi.c index ce753ebc0894..6d9795306cfa 100644 --- a/sound/soc/qcom/lpass-hdmi.c +++ b/sound/soc/qcom/lpass-hdmi.c @@ -23,7 +23,6 @@ static int lpass_hdmi_daiops_hw_params(struct snd_pcm_substream *substream, snd_pcm_format_t format = params_format(params); unsigned int rate = params_rate(params); unsigned int channels = params_channels(params); - unsigned int ret; int bitwidth; unsigned int word_length; unsigned int ch_sts_buf0; @@ -33,6 +32,7 @@ static int lpass_hdmi_daiops_hw_params(struct snd_pcm_substream *substream, unsigned int ch = 0; struct lpass_dp_metadata_ctl *meta_ctl = drvdata->meta_ctl; struct lpass_sstream_ctl *sstream_ctl = drvdata->sstream_ctl; + int ret; bitwidth = snd_pcm_format_width(format); if (bitwidth < 0) { diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c index 3f5eed5afce5..2365424a9b42 100644 --- a/sound/soc/qcom/qdsp6/audioreach.c +++ b/sound/soc/qcom/qdsp6/audioreach.c @@ -811,6 +811,30 @@ static int audioreach_gapless_set_media_format(struct q6apm_graph *graph, EARLY_EOS_DELAY_MS); } +static int audioreach_set_module_config(struct q6apm_graph *graph, + struct audioreach_module *module, + struct audioreach_module_config *cfg) +{ + int payload_size = le32_to_cpu(module->data->size); + struct gpr_pkt *pkt; + int rc; + void *p; + + pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + if (IS_ERR(pkt)) + return PTR_ERR(pkt); + + p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE; + + memcpy(p, module->data->data, payload_size); + + rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); + + kfree(pkt); + + return rc; +} + static int audioreach_mfc_set_media_format(struct q6apm_graph *graph, struct audioreach_module *module, struct audioreach_module_config *cfg) @@ -859,6 +883,7 @@ static int audioreach_set_compr_media_format(struct media_format *media_fmt_hdr, struct payload_media_fmt_aac_t *aac_cfg; struct payload_media_fmt_pcm *mp3_cfg; struct payload_media_fmt_flac_t *flac_cfg; + struct payload_media_fmt_opus_t *opus_cfg; switch (mcfg->fmt) { case SND_AUDIOCODEC_MP3: @@ -901,6 +926,32 @@ static int audioreach_set_compr_media_format(struct media_format *media_fmt_hdr, flac_cfg->min_frame_size = mcfg->codec.options.flac_d.min_frame_size; flac_cfg->max_frame_size = mcfg->codec.options.flac_d.max_frame_size; break; + case SND_AUDIOCODEC_OPUS_RAW: + media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED; + media_fmt_hdr->fmt_id = MEDIA_FMT_ID_OPUS; + media_fmt_hdr->payload_size = sizeof(*opus_cfg); + p = p + sizeof(*media_fmt_hdr); + opus_cfg = p; + /* raw opus packets prepended with 4 bytes of length */ + opus_cfg->bitstream_format = 1; + /* + * payload_type: + * 0 -- read metadata from opus stream; + * 1 -- metadata is provided by filling in the struct here. + */ + opus_cfg->payload_type = 1; + opus_cfg->version = mcfg->codec.options.opus_d.version; + opus_cfg->num_channels = mcfg->codec.options.opus_d.num_channels; + opus_cfg->pre_skip = mcfg->codec.options.opus_d.pre_skip; + opus_cfg->sample_rate = mcfg->codec.options.opus_d.sample_rate; + opus_cfg->output_gain = mcfg->codec.options.opus_d.output_gain; + opus_cfg->mapping_family = mcfg->codec.options.opus_d.mapping_family; + opus_cfg->stream_count = mcfg->codec.options.opus_d.chan_map.stream_count; + opus_cfg->coupled_count = mcfg->codec.options.opus_d.chan_map.coupled_count; + memcpy(opus_cfg->channel_mapping, mcfg->codec.options.opus_d.chan_map.channel_map, + sizeof(opus_cfg->channel_mapping)); + opus_cfg->reserved[0] = opus_cfg->reserved[1] = opus_cfg->reserved[2] = 0; + break; default: return -EINVAL; } @@ -1248,6 +1299,9 @@ int audioreach_set_media_format(struct q6apm_graph *graph, struct audioreach_mod case MODULE_ID_DISPLAY_PORT_SINK: rc = audioreach_display_port_set_media_format(graph, module, cfg); break; + case MODULE_ID_SMECNS_V2: + rc = audioreach_set_module_config(graph, module, cfg); + break; case MODULE_ID_I2S_SOURCE: case MODULE_ID_I2S_SINK: rc = audioreach_i2s_set_media_format(graph, module, cfg); diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h index 61a69df4f50f..d1b60b36468a 100644 --- a/sound/soc/qcom/qdsp6/audioreach.h +++ b/sound/soc/qcom/qdsp6/audioreach.h @@ -4,6 +4,7 @@ #define __AUDIOREACH_H__ #include <linux/types.h> #include <linux/soc/qcom/apr.h> +#include <uapi/sound/snd_ar_tokens.h> #include <sound/soc.h> struct q6apm; struct q6apm_graph; @@ -17,18 +18,20 @@ struct q6apm_graph; #define MODULE_ID_PCM_DEC 0x07001005 #define MODULE_ID_PLACEHOLDER_ENCODER 0x07001008 #define MODULE_ID_PLACEHOLDER_DECODER 0x07001009 -#define MODULE_ID_SAL 0x07001010 -#define MODULE_ID_MFC 0x07001015 -#define MODULE_ID_CODEC_DMA_SINK 0x07001023 -#define MODULE_ID_CODEC_DMA_SOURCE 0x07001024 #define MODULE_ID_I2S_SINK 0x0700100A #define MODULE_ID_I2S_SOURCE 0x0700100B +#define MODULE_ID_SAL 0x07001010 +#define MODULE_ID_MFC 0x07001015 #define MODULE_ID_DATA_LOGGING 0x0700101A #define MODULE_ID_AAC_DEC 0x0700101F +#define MODULE_ID_CODEC_DMA_SINK 0x07001023 +#define MODULE_ID_CODEC_DMA_SOURCE 0x07001024 #define MODULE_ID_FLAC_DEC 0x0700102F +#define MODULE_ID_SMECNS_V2 0x07001031 #define MODULE_ID_MP3_DECODE 0x0700103B #define MODULE_ID_GAPLESS 0x0700104D #define MODULE_ID_DISPLAY_PORT_SINK 0x07001069 +#define MODULE_ID_OPUS_DEC 0x07001174 #define APM_CMD_GET_SPF_STATE 0x01001021 #define APM_CMD_RSP_GET_SPF_STATE 0x02001007 @@ -255,6 +258,22 @@ struct payload_media_fmt_aac_t { uint32_t sample_rate; } __packed; +#define MEDIA_FMT_ID_OPUS 0x09001039 +struct payload_media_fmt_opus_t { + uint16_t bitstream_format; + uint16_t payload_type; + uint8_t version; + uint8_t num_channels; + uint16_t pre_skip; + uint32_t sample_rate; + uint16_t output_gain; + uint8_t mapping_family; + uint8_t stream_count; + uint8_t coupled_count; + uint8_t channel_mapping[8]; + uint8_t reserved[3]; +} __packed; + #define DATA_CMD_WR_SH_MEM_EP_EOS 0x04001002 #define WR_SH_MEM_EP_EOS_POLICY_LAST 1 #define WR_SH_MEM_EP_EOS_POLICY_EACH 2 @@ -461,8 +480,8 @@ struct param_id_i2s_intf_cfg { } __packed; #define I2S_INTF_TYPE_PRIMARY 0 -#define I2S_INTF_TYPE_SECOINDARY 1 -#define I2S_INTF_TYPE_TERTINARY 2 +#define I2S_INTF_TYPE_SECONDARY 1 +#define I2S_INTF_TYPE_TERTIARY 2 #define I2S_INTF_TYPE_QUATERNARY 3 #define I2S_INTF_TYPE_QUINARY 4 #define I2S_SD0 1 @@ -707,9 +726,6 @@ struct audioreach_module { uint32_t max_ip_port; uint32_t max_op_port; - uint32_t in_port; - uint32_t out_port; - uint32_t num_connections; /* Connections */ uint32_t src_mod_inst_id; @@ -745,6 +761,7 @@ struct audioreach_module { struct list_head node; struct audioreach_container *container; struct snd_soc_dapm_widget *widget; + struct audioreach_module_priv_data *data; }; struct audioreach_module_config { diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 2cd522108221..4ecaff45c518 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -11,6 +11,7 @@ #include <sound/soc-dapm.h> #include <linux/spinlock.h> #include <sound/pcm.h> +#include <asm/div64.h> #include <asm/dma.h> #include <linux/dma-mapping.h> #include <sound/pcm_params.h> @@ -65,9 +66,9 @@ struct q6apm_dai_rtd { unsigned int pcm_size; unsigned int pcm_count; unsigned int periods; - unsigned int bytes_sent; - unsigned int bytes_received; - unsigned int copied_total; + uint64_t bytes_sent; + uint64_t bytes_received; + uint64_t copied_total; uint16_t bits_per_sample; snd_pcm_uframes_t queue_ptr; bool next_track; @@ -550,10 +551,11 @@ static int q6apm_dai_compr_get_caps(struct snd_soc_component *component, caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE; caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS; caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS; - caps->num_codecs = 3; + caps->num_codecs = 4; caps->codecs[0] = SND_AUDIOCODEC_MP3; caps->codecs[1] = SND_AUDIOCODEC_AAC; caps->codecs[2] = SND_AUDIOCODEC_FLAC; + caps->codecs[3] = SND_AUDIOCODEC_OPUS_RAW; return 0; } @@ -575,15 +577,17 @@ static int q6apm_dai_compr_get_codec_caps(struct snd_soc_component *component, static int q6apm_dai_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_compr_runtime *runtime = stream->runtime; struct q6apm_dai_rtd *prtd = runtime->private_data; unsigned long flags; + uint64_t temp_copied_total; spin_lock_irqsave(&prtd->lock, flags); tstamp->copied_total = prtd->copied_total; - tstamp->byte_offset = prtd->copied_total % prtd->pcm_size; + temp_copied_total = tstamp->copied_total; + tstamp->byte_offset = do_div(temp_copied_total, prtd->pcm_size); spin_unlock_irqrestore(&prtd->lock, flags); return 0; @@ -760,21 +764,24 @@ static int q6apm_compr_copy(struct snd_soc_component *component, size_t copy; u32 wflags = 0; u32 app_pointer; - u32 bytes_received; + uint64_t bytes_received; + uint64_t temp_bytes_received; uint32_t bytes_to_write; - int avail, bytes_in_flight = 0; + uint64_t avail, bytes_in_flight = 0; bytes_received = prtd->bytes_received; + temp_bytes_received = bytes_received; /** * Make sure that next track data pointer is aligned at 32 bit boundary * This is a Mandatory requirement from DSP data buffers alignment */ - if (prtd->next_track) + if (prtd->next_track) { bytes_received = ALIGN(prtd->bytes_received, prtd->pcm_count); + temp_bytes_received = bytes_received; + } - app_pointer = bytes_received/prtd->pcm_size; - app_pointer = bytes_received - (app_pointer * prtd->pcm_size); + app_pointer = do_div(temp_bytes_received, prtd->pcm_size); dstn = prtd->dma_buffer.area + app_pointer; if (count < prtd->pcm_size - app_pointer) { diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index b4ffa0f0b188..0e667a7eb546 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c @@ -354,6 +354,9 @@ int q6apm_set_real_module_id(struct device *dev, struct q6apm_graph *graph, case SND_AUDIOCODEC_FLAC: module_id = MODULE_ID_FLAC_DEC; break; + case SND_AUDIOCODEC_OPUS_RAW: + module_id = MODULE_ID_OPUS_DEC; + break; default: return -EINVAL; } diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index a400c9a31fea..b616ce316d2f 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -14,6 +14,7 @@ #include <sound/pcm.h> #include <linux/spinlock.h> #include <sound/compress_driver.h> +#include <asm/div64.h> #include <asm/dma.h> #include <linux/dma-mapping.h> #include <sound/pcm_params.h> @@ -59,9 +60,9 @@ struct q6asm_dai_rtd { unsigned int pcm_count; unsigned int pcm_irq_pos; /* IRQ position */ unsigned int periods; - unsigned int bytes_sent; - unsigned int bytes_received; - unsigned int copied_total; + uint64_t bytes_sent; + uint64_t bytes_received; + uint64_t copied_total; uint16_t bits_per_sample; uint16_t source; /* Encoding source bit mask */ struct audio_client *audio_client; @@ -1026,16 +1027,18 @@ static int q6asm_dai_compr_trigger(struct snd_soc_component *component, static int q6asm_dai_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_compr_runtime *runtime = stream->runtime; struct q6asm_dai_rtd *prtd = runtime->private_data; unsigned long flags; + uint64_t temp_copied_total; spin_lock_irqsave(&prtd->lock, flags); tstamp->copied_total = prtd->copied_total; - tstamp->byte_offset = prtd->copied_total % prtd->pcm_size; + temp_copied_total = tstamp->copied_total; + tstamp->byte_offset = do_div(temp_copied_total, prtd->pcm_size); spin_unlock_irqrestore(&prtd->lock, flags); @@ -1050,23 +1053,26 @@ static int q6asm_compr_copy(struct snd_soc_component *component, struct q6asm_dai_rtd *prtd = runtime->private_data; unsigned long flags; u32 wflags = 0; - int avail, bytes_in_flight = 0; + uint64_t avail, bytes_in_flight = 0; void *dstn; size_t copy; u32 app_pointer; - u32 bytes_received; + uint64_t bytes_received; + uint64_t temp_bytes_received; bytes_received = prtd->bytes_received; + temp_bytes_received = bytes_received; /** * Make sure that next track data pointer is aligned at 32 bit boundary * This is a Mandatory requirement from DSP data buffers alignment */ - if (prtd->next_track) + if (prtd->next_track) { bytes_received = ALIGN(prtd->bytes_received, prtd->pcm_count); + temp_bytes_received = bytes_received; + } - app_pointer = bytes_received/prtd->pcm_size; - app_pointer = bytes_received - (app_pointer * prtd->pcm_size); + app_pointer = do_div(temp_bytes_received, prtd->pcm_size); dstn = prtd->dma_buffer.area + app_pointer; if (count < prtd->pcm_size - app_pointer) { diff --git a/sound/soc/qcom/qdsp6/topology.c b/sound/soc/qcom/qdsp6/topology.c index 83319a928f29..f61285e7dcf2 100644 --- a/sound/soc/qcom/qdsp6/topology.c +++ b/sound/soc/qcom/qdsp6/topology.c @@ -305,6 +305,34 @@ static struct snd_soc_tplg_vendor_array *audioreach_get_module_array( return NULL; } +static struct audioreach_module_priv_data *audioreach_get_module_priv_data( + struct snd_soc_tplg_private *private) +{ + int sz; + + for (sz = 0; sz < le32_to_cpu(private->size); ) { + struct snd_soc_tplg_vendor_array *mod_array; + + mod_array = (struct snd_soc_tplg_vendor_array *)((u8 *)private->array + sz); + if (le32_to_cpu(mod_array->type) == SND_SOC_AR_TPLG_MODULE_CFG_TYPE) { + struct audioreach_module_priv_data *pdata; + + pdata = kzalloc(struct_size(pdata, data, le32_to_cpu(mod_array->size)), + GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + memcpy(pdata, ((u8 *)private->data + sz), struct_size(pdata, data, + le32_to_cpu(mod_array->size))); + return pdata; + } + + sz = sz + le32_to_cpu(mod_array->size); + } + + return NULL; +} + static struct audioreach_sub_graph *audioreach_parse_sg_tokens(struct q6apm *apm, struct snd_soc_tplg_private *private) { @@ -412,7 +440,7 @@ static struct audioreach_module *audioreach_parse_common_tokens(struct q6apm *ap struct snd_soc_tplg_private *private, struct snd_soc_dapm_widget *w) { - uint32_t max_ip_port = 0, max_op_port = 0, in_port = 0, out_port = 0; + uint32_t max_ip_port = 0, max_op_port = 0; uint32_t src_mod_op_port_id[AR_MAX_MOD_LINKS] = { 0, }; uint32_t dst_mod_inst_id[AR_MAX_MOD_LINKS] = { 0, }; uint32_t dst_mod_ip_port_id[AR_MAX_MOD_LINKS] = { 0, }; @@ -455,12 +483,6 @@ static struct audioreach_module *audioreach_parse_common_tokens(struct q6apm *ap case AR_TKN_U32_MODULE_MAX_OP_PORTS: max_op_port = le32_to_cpu(mod_elem->value); break; - case AR_TKN_U32_MODULE_IN_PORTS: - in_port = le32_to_cpu(mod_elem->value); - break; - case AR_TKN_U32_MODULE_OUT_PORTS: - out_port = le32_to_cpu(mod_elem->value); - break; case AR_TKN_U32_MODULE_SRC_INSTANCE_ID: src_mod_inst_id = le32_to_cpu(mod_elem->value); break; @@ -550,8 +572,6 @@ static struct audioreach_module *audioreach_parse_common_tokens(struct q6apm *ap mod->module_id = module_id; mod->max_ip_port = max_ip_port; mod->max_op_port = max_op_port; - mod->in_port = in_port; - mod->out_port = out_port; mod->src_mod_inst_id = src_mod_inst_id; for (pn = 0; pn < mod->max_op_port; pn++) { if (src_mod_op_port_id[pn] && dst_mod_inst_id[pn] && @@ -587,8 +607,10 @@ static int audioreach_widget_load_module_common(struct snd_soc_component *compon return PTR_ERR(cont); mod = audioreach_parse_common_tokens(apm, cont, &tplg_w->priv, w); - if (IS_ERR(mod)) - return PTR_ERR(mod); + if (IS_ERR_OR_NULL(mod)) + return mod ? PTR_ERR(mod) : -ENODEV; + + mod->data = audioreach_get_module_priv_data(&tplg_w->priv); dobj = &w->dobj; dobj->private = mod; @@ -947,6 +969,7 @@ static int audioreach_widget_unload(struct snd_soc_component *scomp, cont->num_modules--; list_del(&mod->node); + kfree(mod->data); kfree(mod); /* Graph Info has N sub-graphs, sub-graph has N containers, Container has N Modules */ if (list_empty(&cont->modules_list)) { /* if no modules in the container then remove it */ diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 288ccd7f8866..78e327bc2f07 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -7,6 +7,7 @@ #include <sound/soc.h> #include <sound/soc-dapm.h> #include <sound/pcm.h> +#include <sound/pcm_params.h> #include <linux/soundwire/sdw.h> #include <sound/jack.h> #include <linux/input-event-codes.h> @@ -86,8 +87,10 @@ static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); rate->min = rate->max = 48000; + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); channels->min = 2; channels->max = 2; switch (cpu_dai->id) { @@ -191,8 +194,8 @@ static const struct of_device_id snd_sc8280xp_dt_match[] = { {.compatible = "qcom,qcm6490-idp-sndcard", "qcm6490"}, {.compatible = "qcom,qcs6490-rb3gen2-sndcard", "qcs6490"}, {.compatible = "qcom,qcs8275-sndcard", "qcs8300"}, - {.compatible = "qcom,qcs9075-sndcard", "qcs9075"}, - {.compatible = "qcom,qcs9100-sndcard", "qcs9100"}, + {.compatible = "qcom,qcs9075-sndcard", "sa8775p"}, + {.compatible = "qcom,qcs9100-sndcard", "sa8775p"}, {.compatible = "qcom,sc8280xp-sndcard", "sc8280xp"}, {.compatible = "qcom,sm8450-sndcard", "sm8450"}, {.compatible = "qcom,sm8550-sndcard", "sm8550"}, diff --git a/sound/soc/qcom/x1e80100.c b/sound/soc/qcom/x1e80100.c index 8eb57fc12f0d..444f2162889f 100644 --- a/sound/soc/qcom/x1e80100.c +++ b/sound/soc/qcom/x1e80100.c @@ -210,14 +210,15 @@ static int x1e80100_platform_probe(struct platform_device *pdev) if (ret) return ret; - card->driver_name = "x1e80100"; + card->driver_name = of_device_get_match_data(dev); x1e80100_add_be_ops(card); return devm_snd_soc_register_card(dev, card); } static const struct of_device_id snd_x1e80100_dt_match[] = { - { .compatible = "qcom,x1e80100-sndcard", }, + { .compatible = "qcom,x1e80100-sndcard", .data = "x1e80100" }, + { .compatible = "qcom,glymur-sndcard", .data = "glymur" }, {} }; MODULE_DEVICE_TABLE(of, snd_x1e80100_dt_match); diff --git a/sound/soc/renesas/fsi.c b/sound/soc/renesas/fsi.c index 221ce91f1950..630c2f52e1cf 100644 --- a/sound/soc/renesas/fsi.c +++ b/sound/soc/renesas/fsi.c @@ -343,14 +343,9 @@ static void __fsi_reg_mask_set(u32 __iomem *reg, u32 mask, u32 data) #define fsi_core_read(p, r) _fsi_master_read(p, p->core->r) static u32 _fsi_master_read(struct fsi_master *master, u32 reg) { - u32 ret; - unsigned long flags; + guard(spinlock_irqsave)(&master->lock); - spin_lock_irqsave(&master->lock, flags); - ret = __fsi_reg_read(master->base + reg); - spin_unlock_irqrestore(&master->lock, flags); - - return ret; + return __fsi_reg_read(master->base + reg); } #define fsi_master_mask_set(p, r, m, d) _fsi_master_mask_set(p, MST_##r, m, d) @@ -358,11 +353,9 @@ static u32 _fsi_master_read(struct fsi_master *master, u32 reg) static void _fsi_master_mask_set(struct fsi_master *master, u32 reg, u32 mask, u32 data) { - unsigned long flags; + guard(spinlock_irqsave)(&master->lock); - spin_lock_irqsave(&master->lock, flags); __fsi_reg_mask_set(master->base + reg, mask, data); - spin_unlock_irqrestore(&master->lock, flags); } /* @@ -499,14 +492,10 @@ static int fsi_stream_is_working(struct fsi_priv *fsi, struct fsi_stream *io) { struct fsi_master *master = fsi_get_master(fsi); - unsigned long flags; - int ret; - spin_lock_irqsave(&master->lock, flags); - ret = !!(io->substream && io->substream->runtime); - spin_unlock_irqrestore(&master->lock, flags); + guard(spinlock_irqsave)(&master->lock); - return ret; + return !!(io->substream && io->substream->runtime); } static struct fsi_priv *fsi_stream_to_priv(struct fsi_stream *io) @@ -520,9 +509,9 @@ static void fsi_stream_init(struct fsi_priv *fsi, { struct snd_pcm_runtime *runtime = substream->runtime; struct fsi_master *master = fsi_get_master(fsi); - unsigned long flags; - spin_lock_irqsave(&master->lock, flags); + guard(spinlock_irqsave)(&master->lock); + io->substream = substream; io->buff_sample_capa = fsi_frame2sample(fsi, runtime->buffer_size); io->buff_sample_pos = 0; @@ -533,16 +522,14 @@ static void fsi_stream_init(struct fsi_priv *fsi, io->oerr_num = -1; /* ignore 1st err */ io->uerr_num = -1; /* ignore 1st err */ fsi_stream_handler_call(io, init, fsi, io); - spin_unlock_irqrestore(&master->lock, flags); } static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io) { struct snd_soc_dai *dai = fsi_get_dai(io->substream); struct fsi_master *master = fsi_get_master(fsi); - unsigned long flags; - spin_lock_irqsave(&master->lock, flags); + guard(spinlock_irqsave)(&master->lock); if (io->oerr_num > 0) dev_err(dai->dev, "over_run = %d\n", io->oerr_num); @@ -560,7 +547,6 @@ static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io) io->bus_option = 0; io->oerr_num = 0; io->uerr_num = 0; - spin_unlock_irqrestore(&master->lock, flags); } static int fsi_stream_transfer(struct fsi_stream *io) diff --git a/sound/soc/renesas/rcar/core.c b/sound/soc/renesas/rcar/core.c index 9f086906a2e5..69fb19964a71 100644 --- a/sound/soc/renesas/rcar/core.c +++ b/sound/soc/renesas/rcar/core.c @@ -696,25 +696,21 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); int ret; - unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); + guard(spinlock_irqsave)(&priv->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: ret = rsnd_dai_call(init, io, priv); if (ret < 0) - goto dai_trigger_end; + break; ret = rsnd_dai_call(start, io, priv); if (ret < 0) - goto dai_trigger_end; + break; ret = rsnd_dai_call(irq, io, priv, 1); - if (ret < 0) - goto dai_trigger_end; - break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: @@ -729,9 +725,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, ret = -EINVAL; } -dai_trigger_end: - spin_unlock_irqrestore(&priv->lock, flags); - return ret; } @@ -1545,15 +1538,14 @@ static int rsnd_hw_update(struct snd_pcm_substream *substream, struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); struct rsnd_priv *priv = rsnd_io_to_priv(io); - unsigned long flags; int ret; - spin_lock_irqsave(&priv->lock, flags); + guard(spinlock_irqsave)(&priv->lock); + if (hw_params) ret = rsnd_dai_call(hw_params, io, substream, hw_params); else ret = rsnd_dai_call(hw_free, io, substream); - spin_unlock_irqrestore(&priv->lock, flags); return ret; } diff --git a/sound/soc/renesas/rcar/msiof.c b/sound/soc/renesas/rcar/msiof.c index 36d31ab8ac6a..f2addfbac923 100644 --- a/sound/soc/renesas/rcar/msiof.c +++ b/sound/soc/renesas/rcar/msiof.c @@ -7,7 +7,7 @@ // /* - * [NOTE] + * [NOTE-CLOCK-MODE] * * This driver doesn't support Clock/Frame Provider Mode * @@ -24,12 +24,64 @@ * Clock/Frame Consumer Mode. */ +/* + * [NOTE-RESET] + * + * MSIOF has TXRST/RXRST to reset FIFO, but it shouldn't be used during SYNC signal was asserted, + * because it will be cause of HW issue. + * + * When MSIOF is used as Sound driver, this driver is assuming it is used as clock consumer mode + * (= Codec is clock provider). This means, it can't control SYNC signal by itself. + * + * We need to use SW reset (= reset_control_xxx()) instead of TXRST/RXRST. + */ + +/* + * [NOTE-BOTH-SETTING] + * + * SITMDRn / SIRMDRn and some other registers should not be updated during working even though it + * was not related the target direction (for example, do TX settings during RX is working), + * otherwise it cause a FSERR. + * + * Setup both direction (Playback/Capture) in the same time. + */ + +/* + * [NOTE-R/L] + * + * The data of Captured might be R/L opposite. + * + * This driver is assuming MSIOF is used as Clock/Frame Consumer Mode, and there is a case that some + * Codec (= Clock/Frame Provider) might output Clock/Frame before setup MSIOF. It depends on Codec + * driver implementation. + * + * MSIOF will capture data without checking SYNC signal Hi/Low (= R/L). + * + * This means, if MSIOF RXE bit was set as 1 in case of SYNC signal was Hi (= R) timing, it will + * start capture data since next SYNC low singla (= L). Because Linux assumes sound data is lined + * up as R->L->R->L->..., the data R/L will be opposite. + * + * The only solution in this case is start CLK/SYNC *after* MSIOF settings, but it depends when and + * how Codec driver start it. + */ + +/* + * [NOTE-FSERR] + * + * We can't remove all FSERR. + * + * Renesas have tried to minimize the occurrence of FSERR errors as much as possible, but + * unfortunately we cannot remove them completely, because MSIOF might setup its register during + * CLK/SYNC are inputed. It can be happen because MSIOF is working as Clock/Frame Consumer. + */ + #include <linux/module.h> #include <linux/of.h> #include <linux/of_dma.h> #include <linux/of_graph.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/reset.h> #include <linux/spi/sh_msiof.h> #include <sound/dmaengine_pcm.h> #include <sound/soc.h> @@ -37,7 +89,6 @@ /* SISTR */ #define SISTR_ERR_TX (SISTR_TFSERR | SISTR_TFOVF | SISTR_TFUDF) #define SISTR_ERR_RX (SISTR_RFSERR | SISTR_RFOVF | SISTR_RFUDF) -#define SISTR_ERR (SISTR_ERR_TX | SISTR_ERR_RX) /* * The data on memory in 24bit case is located at <right> side @@ -61,10 +112,13 @@ struct msiof_priv { struct device *dev; struct snd_pcm_substream *substream[SNDRV_PCM_STREAM_LAST + 1]; + struct reset_control *reset; spinlock_t lock; void __iomem *base; resource_size_t phy_addr; + int count; + /* for error */ int err_syc[SNDRV_PCM_STREAM_LAST + 1]; int err_ovf[SNDRV_PCM_STREAM_LAST + 1]; @@ -80,15 +134,19 @@ struct msiof_priv { #define msiof_is_play(substream) ((substream)->stream == SNDRV_PCM_STREAM_PLAYBACK) #define msiof_read(priv, reg) ioread32((priv)->base + reg) #define msiof_write(priv, reg, val) iowrite32(val, (priv)->base + reg) -#define msiof_status_clear(priv) msiof_write(priv, SISTR, SISTR_ERR) -static void msiof_update(struct msiof_priv *priv, u32 reg, u32 mask, u32 val) +static int msiof_update(struct msiof_priv *priv, u32 reg, u32 mask, u32 val) { u32 old = msiof_read(priv, reg); u32 new = (old & ~mask) | (val & mask); + int updated = false; - if (old != new) + if (old != new) { msiof_write(priv, reg, new); + updated = true; + } + + return updated; } static void msiof_update_and_wait(struct msiof_priv *priv, u32 reg, u32 mask, u32 val, u32 expect) @@ -96,7 +154,9 @@ static void msiof_update_and_wait(struct msiof_priv *priv, u32 reg, u32 mask, u3 u32 data; int ret; - msiof_update(priv, reg, mask, val); + ret = msiof_update(priv, reg, mask, val); + if (!ret) /* no update */ + return; ret = readl_poll_timeout_atomic(priv->base + reg, data, (data & mask) == expect, 1, 128); @@ -116,7 +176,7 @@ static int msiof_hw_start(struct snd_soc_component *component, /* * see - * [NOTE] on top of this driver + * [NOTE-CLOCK-MODE] on top of this driver */ /* * see @@ -126,39 +186,63 @@ static int msiof_hw_start(struct snd_soc_component *component, * RX: Fig 109.15 */ - /* reset errors */ - priv->err_syc[substream->stream] = + /* + * Use reset_control_xx() instead of TXRST/RXRST. + * see + * [NOTE-RESET] + */ + if (!priv->count) + reset_control_deassert(priv->reset); + + priv->count++; + + /* + * Reset errors. ignore 1st FSERR + * + * see + * [NOTE-FSERR] + */ + priv->err_syc[substream->stream] = -1; priv->err_ovf[substream->stream] = priv->err_udf[substream->stream] = 0; + /* Start DMAC */ + snd_dmaengine_pcm_trigger(substream, cmd); + + /* + * setup both direction (Playback/Capture) in the same time. + * see + * above [NOTE-BOTH-SETTING] + */ + /* SITMDRx */ - if (is_play) { - val = SITMDR1_PCON | - FIELD_PREP(SIMDR1_SYNCMD, SIMDR1_SYNCMD_LR) | - SIMDR1_SYNCAC | SIMDR1_XXSTP; - if (msiof_flag_has(priv, MSIOF_FLAGS_NEED_DELAY)) - val |= FIELD_PREP(SIMDR1_DTDL, 1); + val = SITMDR1_PCON | SIMDR1_SYNCAC | SIMDR1_XXSTP | + FIELD_PREP(SIMDR1_SYNCMD, SIMDR1_SYNCMD_LR); + if (msiof_flag_has(priv, MSIOF_FLAGS_NEED_DELAY)) + val |= FIELD_PREP(SIMDR1_DTDL, 1); - msiof_write(priv, SITMDR1, val); + msiof_write(priv, SITMDR1, val); - val = FIELD_PREP(SIMDR2_BITLEN1, width - 1); - msiof_write(priv, SITMDR2, val | FIELD_PREP(SIMDR2_GRP, 1)); - msiof_write(priv, SITMDR3, val); + val = FIELD_PREP(SIMDR2_BITLEN1, width - 1); + msiof_write(priv, SITMDR2, val | FIELD_PREP(SIMDR2_GRP, 1)); + msiof_write(priv, SITMDR3, val); - } /* SIRMDRx */ - else { - val = FIELD_PREP(SIMDR1_SYNCMD, SIMDR1_SYNCMD_LR) | - SIMDR1_SYNCAC; - if (msiof_flag_has(priv, MSIOF_FLAGS_NEED_DELAY)) - val |= FIELD_PREP(SIMDR1_DTDL, 1); + val = SIMDR1_SYNCAC | + FIELD_PREP(SIMDR1_SYNCMD, SIMDR1_SYNCMD_LR); + if (msiof_flag_has(priv, MSIOF_FLAGS_NEED_DELAY)) + val |= FIELD_PREP(SIMDR1_DTDL, 1); - msiof_write(priv, SIRMDR1, val); + msiof_write(priv, SIRMDR1, val); - val = FIELD_PREP(SIMDR2_BITLEN1, width - 1); - msiof_write(priv, SIRMDR2, val | FIELD_PREP(SIMDR2_GRP, 1)); - msiof_write(priv, SIRMDR3, val); - } + val = FIELD_PREP(SIMDR2_BITLEN1, width - 1); + msiof_write(priv, SIRMDR2, val | FIELD_PREP(SIMDR2_GRP, 1)); + msiof_write(priv, SIRMDR3, val); + + /* SIFCTR */ + msiof_write(priv, SIFCTR, + FIELD_PREP(SIFCTR_TFWM, SIFCTR_TFWM_1) | + FIELD_PREP(SIFCTR_RFWM, SIFCTR_RFWM_1)); /* SIIER */ if (is_play) @@ -167,18 +251,21 @@ static int msiof_hw_start(struct snd_soc_component *component, val = SIIER_RDREQE | SIIER_RDMAE | SISTR_ERR_RX; msiof_update(priv, SIIER, val, val); + /* clear status */ + if (is_play) + val = SISTR_ERR_TX; + else + val = SISTR_ERR_RX; + msiof_update(priv, SISTR, val, val); + /* SICTR */ + val = SICTR_TEDG | SICTR_REDG; if (is_play) - val = SICTR_TXE | SICTR_TEDG; + val |= SICTR_TXE; else - val = SICTR_RXE | SICTR_REDG; + val |= SICTR_RXE; msiof_update_and_wait(priv, SICTR, val, val, val); - msiof_status_clear(priv); - - /* Start DMAC */ - snd_dmaengine_pcm_trigger(substream, cmd); - return 0; } @@ -197,9 +284,6 @@ static int msiof_hw_stop(struct snd_soc_component *component, val = SIIER_RDREQE | SIIER_RDMAE | SISTR_ERR_RX; msiof_update(priv, SIIER, val, 0); - /* Stop DMAC */ - snd_dmaengine_pcm_trigger(substream, cmd); - /* SICTR */ if (is_play) val = SICTR_TXE; @@ -207,16 +291,33 @@ static int msiof_hw_stop(struct snd_soc_component *component, val = SICTR_RXE; msiof_update_and_wait(priv, SICTR, val, 0, 0); + /* Stop DMAC */ + snd_dmaengine_pcm_trigger(substream, cmd); + + /* + * Ignore 1st FSERR + * + * see + * [NOTE-FSERR] + */ + if (priv->err_syc[substream->stream] < 0) + priv->err_syc[substream->stream] = 0; + /* indicate error status if exist */ if (priv->err_syc[substream->stream] || priv->err_ovf[substream->stream] || priv->err_udf[substream->stream]) - dev_warn(dev, "FSERR(%s) = %d, FOVF = %d, FUDF = %d\n", + dev_warn(dev, "%s: FSERR = %d, FOVF = %d, FUDF = %d\n", snd_pcm_direction_name(substream->stream), priv->err_syc[substream->stream], priv->err_ovf[substream->stream], priv->err_udf[substream->stream]); + priv->count--; + + if (!priv->count) + reset_control_assert(priv->reset); + return 0; } @@ -292,6 +393,9 @@ static struct snd_soc_dai_driver msiof_dai_driver = { .channels_max = 2, }, .ops = &msiof_dai_ops, + .symmetric_rate = 1, + .symmetric_channels = 1, + .symmetric_sample_bits = 1, }; static struct snd_pcm_hardware msiof_pcm_hardware = { @@ -362,10 +466,9 @@ static int msiof_trigger(struct snd_soc_component *component, { struct device *dev = component->dev; struct msiof_priv *priv = dev_get_drvdata(dev); - unsigned long flags; int ret = -EINVAL; - spin_lock_irqsave(&priv->lock, flags); + guard(spinlock_irqsave)(&priv->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -382,8 +485,6 @@ static int msiof_trigger(struct snd_soc_component *component, break; } - spin_unlock_irqrestore(&priv->lock, flags); - return ret; } @@ -394,23 +495,18 @@ static int msiof_hw_params(struct snd_soc_component *component, struct msiof_priv *priv = dev_get_drvdata(component->dev); struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); struct dma_slave_config cfg = {}; - unsigned long flags; int ret; - spin_lock_irqsave(&priv->lock, flags); + guard(spinlock_irqsave)(&priv->lock); ret = snd_hwparams_to_dma_slave_config(substream, params, &cfg); if (ret < 0) - goto hw_params_out; + return ret; cfg.dst_addr = priv->phy_addr + SITFDR; cfg.src_addr = priv->phy_addr + SIRFDR; - ret = dmaengine_slave_config(chan, &cfg); -hw_params_out: - spin_unlock_irqrestore(&priv->lock, flags); - - return ret; + return dmaengine_slave_config(chan, &cfg); } static const struct snd_soc_component_driver msiof_component_driver = { @@ -429,12 +525,10 @@ static irqreturn_t msiof_interrupt(int irq, void *data) struct snd_pcm_substream *substream; u32 sistr; - spin_lock(&priv->lock); - - sistr = msiof_read(priv, SISTR); - msiof_status_clear(priv); - - spin_unlock(&priv->lock); + scoped_guard(spinlock, &priv->lock) { + sistr = msiof_read(priv, SISTR); + msiof_write(priv, SISTR, SISTR_ERR_TX | SISTR_ERR_RX); + } /* overflow/underflow error */ substream = priv->substream[SNDRV_PCM_STREAM_PLAYBACK]; @@ -490,12 +584,19 @@ static int msiof_probe(struct platform_device *pdev) if (IS_ERR(priv->base)) return PTR_ERR(priv->base); + priv->reset = devm_reset_control_get_exclusive(dev, NULL); + if (IS_ERR(priv->reset)) + return PTR_ERR(priv->reset); + + reset_control_assert(priv->reset); + ret = devm_request_irq(dev, irq, msiof_interrupt, 0, dev_name(dev), priv); if (ret) return ret; priv->dev = dev; priv->phy_addr = res->start; + priv->count = 0; spin_lock_init(&priv->lock); platform_set_drvdata(pdev, priv); diff --git a/sound/soc/renesas/rcar/src.c b/sound/soc/renesas/rcar/src.c index f47bf38c2f94..6a3dbc84f474 100644 --- a/sound/soc/renesas/rcar/src.c +++ b/sound/soc/renesas/rcar/src.c @@ -558,19 +558,16 @@ static void __rsnd_src_interrupt(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); bool stop = false; - spin_lock(&priv->lock); - - /* ignore all cases if not working */ - if (!rsnd_io_is_working(io)) - goto rsnd_src_interrupt_out; + scoped_guard(spinlock, &priv->lock) { + /* ignore all cases if not working */ + if (!rsnd_io_is_working(io)) + break; - if (rsnd_src_error_occurred(mod)) - stop = true; + if (rsnd_src_error_occurred(mod)) + stop = true; - rsnd_src_status_clear(mod); -rsnd_src_interrupt_out: - - spin_unlock(&priv->lock); + rsnd_src_status_clear(mod); + } if (stop) snd_pcm_stop_xrun(io->substream); diff --git a/sound/soc/renesas/rcar/ssi.c b/sound/soc/renesas/rcar/ssi.c index d52056caa3ec..0420041e282c 100644 --- a/sound/soc/renesas/rcar/ssi.c +++ b/sound/soc/renesas/rcar/ssi.c @@ -680,31 +680,30 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, bool elapsed = false; bool stop = false; - spin_lock(&priv->lock); + scoped_guard(spinlock, &priv->lock) { - /* ignore all cases if not working */ - if (!rsnd_io_is_working(io)) - goto rsnd_ssi_interrupt_out; + /* ignore all cases if not working */ + if (!rsnd_io_is_working(io)) + break; - status = rsnd_ssi_status_get(mod); + status = rsnd_ssi_status_get(mod); - /* PIO only */ - if (!is_dma && (status & DIRQ)) - elapsed = rsnd_ssi_pio_interrupt(mod, io); + /* PIO only */ + if (!is_dma && (status & DIRQ)) + elapsed = rsnd_ssi_pio_interrupt(mod, io); - /* DMA only */ - if (is_dma && (status & (UIRQ | OIRQ))) { - rsnd_print_irq_status(dev, "%s err status : 0x%08x\n", - rsnd_mod_name(mod), status); + /* DMA only */ + if (is_dma && (status & (UIRQ | OIRQ))) { + rsnd_print_irq_status(dev, "%s err status : 0x%08x\n", + rsnd_mod_name(mod), status); - stop = true; - } + stop = true; + } - stop |= rsnd_ssiu_busif_err_status_clear(mod); + stop |= rsnd_ssiu_busif_err_status_clear(mod); - rsnd_ssi_status_clear(mod); -rsnd_ssi_interrupt_out: - spin_unlock(&priv->lock); + rsnd_ssi_status_clear(mod); + } if (elapsed) snd_pcm_period_elapsed(io->substream); diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index 0f7458a43901..e00940814157 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -188,24 +188,18 @@ static void rz_ssi_set_substream(struct rz_ssi_stream *strm, struct snd_pcm_substream *substream) { struct rz_ssi_priv *ssi = strm->priv; - unsigned long flags; - spin_lock_irqsave(&ssi->lock, flags); + guard(spinlock_irqsave)(&ssi->lock); + strm->substream = substream; - spin_unlock_irqrestore(&ssi->lock, flags); } static bool rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) { - unsigned long flags; - bool ret; - - spin_lock_irqsave(&ssi->lock, flags); - ret = strm->substream && strm->substream->runtime; - spin_unlock_irqrestore(&ssi->lock, flags); + guard(spinlock_irqsave)(&ssi->lock); - return ret; + return strm->substream && strm->substream->runtime; } static inline bool rz_ssi_is_stream_running(struct rz_ssi_stream *strm) diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.h b/sound/soc/rockchip/rockchip_i2s_tdm.h index 0aa1c6da1e2c..0171e05ee886 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.h +++ b/sound/soc/rockchip/rockchip_i2s_tdm.h @@ -10,6 +10,8 @@ #ifndef _ROCKCHIP_I2S_TDM_H #define _ROCKCHIP_I2S_TDM_H +#include <linux/hw_bitfield.h> + /* * TXCR * transmit operation control register @@ -285,7 +287,7 @@ enum { #define I2S_TDM_RXCR (0x0034) #define I2S_CLKDIV (0x0038) -#define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK((h), (l)) << 16)) +#define HIWORD_UPDATE(v, h, l) (FIELD_PREP_WM16_CONST(GENMASK((h), (l)), (v))) /* PX30 GRF CONFIGS */ #define PX30_I2S0_CLK_IN_SRC_FROM_TX HIWORD_UPDATE(1, 13, 12) diff --git a/sound/soc/sdw_utils/Makefile b/sound/soc/sdw_utils/Makefile index daf019113553..a87c53e1a2c1 100644 --- a/sound/soc/sdw_utils/Makefile +++ b/sound/soc/sdw_utils/Makefile @@ -6,5 +6,6 @@ snd-soc-sdw-utils-y := soc_sdw_utils.o soc_sdw_dmic.o soc_sdw_rt_dmic.o \ soc_sdw_bridge_cs35l56.o \ soc_sdw_cs42l42.o soc_sdw_cs42l43.o \ soc_sdw_cs_amp.o \ - soc_sdw_maxim.o + soc_sdw_maxim.o \ + soc_sdw_ti_amp.o obj-$(CONFIG_SND_SOC_SDW_UTILS) += snd-soc-sdw-utils.o diff --git a/sound/soc/sdw_utils/soc_sdw_ti_amp.c b/sound/soc/sdw_utils/soc_sdw_ti_amp.c new file mode 100644 index 000000000000..f0011360ae9b --- /dev/null +++ b/sound/soc/sdw_utils/soc_sdw_ti_amp.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2025 Texas Instruments Inc. + +/* + * soc_sdw_ti_amp - Helpers to handle TI's soundwire based codecs + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include <sound/soc-dai.h> +#include <sound/soc_sdw_utils.h> + +#define TIAMP_SPK_VOLUME_0DB 200 + +int asoc_sdw_ti_amp_initial_settings(struct snd_soc_card *card, + const char *name_prefix) +{ + char *volume_ctl_name; + int ret; + + volume_ctl_name = kasprintf(GFP_KERNEL, "%s Speaker Volume", + name_prefix); + if (!volume_ctl_name) + return -ENOMEM; + + ret = snd_soc_limit_volume(card, volume_ctl_name, + TIAMP_SPK_VOLUME_0DB); + if (ret) + dev_err(card->dev, + "%s update failed %d\n", + volume_ctl_name, ret); + + kfree(volume_ctl_name); + return 0; +} +EXPORT_SYMBOL_NS(asoc_sdw_ti_amp_initial_settings, "SND_SOC_SDW_UTILS"); + +int asoc_sdw_ti_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *dai) +{ + struct snd_soc_card *card = rtd->card; + char widget_name[16]; + char speaker[16]; + struct snd_soc_dapm_route route = {speaker, NULL, widget_name}; + struct snd_soc_dai *codec_dai; + const char *prefix; + int i, ret = 0; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + if (!strstr(codec_dai->name, "tas2783")) + continue; + + prefix = codec_dai->component->name_prefix; + if (!strncmp(prefix, "tas2783-1", strlen("tas2783-1"))) { + strscpy(speaker, "Left Spk", sizeof(speaker)); + } else if (!strncmp(prefix, "tas2783-2", strlen("tas2783-2"))) { + strscpy(speaker, "Right Spk", sizeof(speaker)); + } else { + ret = -EINVAL; + dev_err(card->dev, "unhandled prefix %s", prefix); + break; + } + + snprintf(widget_name, sizeof(widget_name), "%s SPK", prefix); + ret = asoc_sdw_ti_amp_initial_settings(card, prefix); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(&card->dapm, &route, 1); + if (ret) + return ret; + } + + return ret; +} +EXPORT_SYMBOL_NS(asoc_sdw_ti_spk_rtd_init, "SND_SOC_SDW_UTILS"); + +int asoc_sdw_ti_amp_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback) +{ + if (!playback) + return 0; + + info->amp_num++; + + return 0; +} +EXPORT_SYMBOL_NS(asoc_sdw_ti_amp_init, "SND_SOC_SDW_UTILS"); diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c index 1580331cd34c..56c72ef27e7b 100644 --- a/sound/soc/sdw_utils/soc_sdw_utils.c +++ b/sound/soc/sdw_utils/soc_sdw_utils.c @@ -35,12 +35,12 @@ static const struct snd_kcontrol_new generic_spk_controls[] = { SOC_DAPM_PIN_SWITCH("Speaker"), }; -static const struct snd_soc_dapm_widget maxim_widgets[] = { +static const struct snd_soc_dapm_widget lr_spk_widgets[] = { SND_SOC_DAPM_SPK("Left Spk", NULL), SND_SOC_DAPM_SPK("Right Spk", NULL), }; -static const struct snd_kcontrol_new maxim_controls[] = { +static const struct snd_kcontrol_new lr_spk_controls[] = { SOC_DAPM_PIN_SWITCH("Left Spk"), SOC_DAPM_PIN_SWITCH("Right Spk"), }; @@ -59,6 +59,24 @@ static const struct snd_kcontrol_new rt700_controls[] = { struct asoc_sdw_codec_info codec_info_list[] = { { + .part_id = 0x0000, /* TAS2783A */ + .dais = { + { + .direction = {true, true}, + .dai_name = "tas2783-codec", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID}, + .init = asoc_sdw_ti_amp_init, + .rtd_init = asoc_sdw_ti_spk_rtd_init, + .controls = lr_spk_controls, + .num_controls = ARRAY_SIZE(lr_spk_controls), + .widgets = lr_spk_widgets, + .num_widgets = ARRAY_SIZE(lr_spk_widgets), + }, + }, + .dai_num = 1, + }, + { .part_id = 0x700, .dais = { { @@ -450,10 +468,10 @@ struct asoc_sdw_codec_info codec_info_list[] = { .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID}, .init = asoc_sdw_maxim_init, .rtd_init = asoc_sdw_maxim_spk_rtd_init, - .controls = maxim_controls, - .num_controls = ARRAY_SIZE(maxim_controls), - .widgets = maxim_widgets, - .num_widgets = ARRAY_SIZE(maxim_widgets), + .controls = lr_spk_controls, + .num_controls = ARRAY_SIZE(lr_spk_controls), + .widgets = lr_spk_widgets, + .num_widgets = ARRAY_SIZE(lr_spk_widgets), }, }, .dai_num = 1, @@ -469,10 +487,10 @@ struct asoc_sdw_codec_info codec_info_list[] = { .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, .init = asoc_sdw_maxim_init, .rtd_init = asoc_sdw_maxim_spk_rtd_init, - .controls = maxim_controls, - .num_controls = ARRAY_SIZE(maxim_controls), - .widgets = maxim_widgets, - .num_widgets = ARRAY_SIZE(maxim_widgets), + .controls = lr_spk_controls, + .num_controls = ARRAY_SIZE(lr_spk_controls), + .widgets = lr_spk_widgets, + .num_widgets = ARRAY_SIZE(lr_spk_widgets), }, }, .dai_num = 1, diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 65c495094024..c815fd1b3fd1 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -637,7 +637,7 @@ int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes) EXPORT_SYMBOL_GPL(snd_soc_component_compr_ack); int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 01d1d6bee28c..7b81dffc6a93 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -457,7 +457,7 @@ err: } static int soc_compr_pointer(struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; int ret; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index cc9125ffe92a..9dd84d73046b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -717,7 +717,7 @@ int snd_soc_suspend(struct device *dev) * means it's doing something, * otherwise fall through. */ - if (dapm->idle_bias_off) { + if (!dapm->idle_bias) { dev_dbg(component->dev, "ASoC: idle_bias_off CODEC on over suspend\n"); break; @@ -1652,7 +1652,7 @@ static int soc_probe_component(struct snd_soc_card *card, if (ret < 0) goto err_probe; - WARN(dapm->idle_bias_off && + WARN(!dapm->idle_bias && dapm->bias_level != SND_SOC_BIAS_OFF, "codec %s can not start from non-off bias with idle_bias_off==1\n", component->name); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 32f46a38682b..f231b4174b5f 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -774,7 +774,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack); int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { int ret = 0; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a37d44cd04c6..51fb09d56c5a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -165,6 +165,27 @@ static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...) kfree(buf); } +struct device *snd_soc_dapm_to_dev(struct snd_soc_dapm_context *dapm) +{ + if (dapm->component) + return dapm->component->dev; + + return dapm->card->dev; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_to_dev); + +struct snd_soc_card *snd_soc_dapm_to_card(struct snd_soc_dapm_context *dapm) +{ + return dapm->card; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_to_card); + +struct snd_soc_component *snd_soc_dapm_to_component(struct snd_soc_dapm_context *dapm) +{ + return dapm->component; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_to_component); + static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w) { return !list_empty(&w->dirty); @@ -838,13 +859,13 @@ static struct list_head *dapm_kcontrol_get_path_list( list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \ list_kcontrol) -unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol) +unsigned int snd_soc_dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol) { struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); return data->value; } -EXPORT_SYMBOL_GPL(dapm_kcontrol_get_value); +EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_get_value); static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol, unsigned int value) @@ -877,31 +898,42 @@ static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol, } /** - * snd_soc_dapm_kcontrol_widget() - Returns the widget associated to a + * snd_soc_dapm_kcontrol_to_widget() - Returns the widget associated to a * kcontrol * @kcontrol: The kcontrol */ -struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_widget( - struct snd_kcontrol *kcontrol) +struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_to_widget(struct snd_kcontrol *kcontrol) { return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]; } -EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_widget); +EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_to_widget); /** - * snd_soc_dapm_kcontrol_dapm() - Returns the dapm context associated to a - * kcontrol + * snd_soc_dapm_kcontrol_to_dapm() - Returns the dapm context associated to a kcontrol * @kcontrol: The kcontrol * * Note: This function must only be used on kcontrols that are known to have * been registered for a CODEC. Otherwise the behaviour is undefined. */ -struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm( - struct snd_kcontrol *kcontrol) +struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_to_dapm(struct snd_kcontrol *kcontrol) { return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->dapm; } -EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_dapm); +EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_to_dapm); + +/** + * snd_soc_dapm_kcontrol_to_component() - Returns the component associated to a + * kcontrol + * @kcontrol: The kcontrol + * + * This function must only be used on DAPM contexts that are known to be part of + * a COMPONENT (e.g. in a COMPONENT driver). Otherwise the behavior is undefined + */ +struct snd_soc_component *snd_soc_dapm_kcontrol_to_component(struct snd_kcontrol *kcontrol) +{ + return snd_soc_dapm_to_component(snd_soc_dapm_kcontrol_to_dapm(kcontrol)); +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_to_component); static void dapm_reset(struct snd_soc_card *card) { @@ -1000,6 +1032,25 @@ int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, EXPORT_SYMBOL_GPL(snd_soc_dapm_force_bias_level); /** + * snd_soc_dapm_init_bias_level() - Initialize DAPM bias level + * @dapm: The DAPM context to initialize + * @level: The DAPM level to initialize to + * + * This function only sets the driver internal state of the DAPM level and will + * not modify the state of the device. Hence it should not be used during normal + * operation, but only to synchronize the internal state to the device state. + * E.g. during driver probe to set the DAPM level to the one corresponding with + * the power-on reset state of the device. + * + * To change the DAPM state of the device use snd_soc_dapm_set_bias_level(). + */ +void snd_soc_dapm_init_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) +{ + dapm->bias_level = level; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_init_bias_level); + +/** * snd_soc_dapm_set_bias_level - set the bias level for the system * @dapm: DAPM context * @level: level to configure @@ -1037,6 +1088,18 @@ out: return ret; } +/** + * snd_soc_dapm_get_bias_level() - Get current DAPM bias level + * @dapm: The context for which to get the bias level + * + * Returns: The current bias level of the passed DAPM context. + */ +enum snd_soc_bias_level snd_soc_dapm_get_bias_level(struct snd_soc_dapm_context *dapm) +{ + return dapm->bias_level; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_get_bias_level); + static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm, struct snd_soc_dapm_widget *kcontrolw, const struct snd_kcontrol_new *kcontrol_new, @@ -2117,21 +2180,26 @@ end: dapm_seq_insert(w, down_list, false); } -static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm) +bool snd_soc_dapm_get_idle_bias(struct snd_soc_dapm_context *dapm) { - if (dapm->idle_bias_off) - return true; + if (dapm->idle_bias) { + struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); + unsigned int state = snd_power_get_state(dapm->card->snd_card); - switch (snd_power_get_state(dapm->card->snd_card)) { - case SNDRV_CTL_POWER_D3hot: - case SNDRV_CTL_POWER_D3cold: - return dapm->suspend_bias_off; - default: - break; + if ((state == SNDRV_CTL_POWER_D3hot || (state == SNDRV_CTL_POWER_D3cold)) && + component) + return !component->driver->suspend_bias_off; } - return false; + return dapm->idle_bias; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_get_idle_bias); + +void snd_soc_dapm_set_idle_bias(struct snd_soc_dapm_context *dapm, bool on) +{ + dapm->idle_bias = on; } +EXPORT_SYMBOL_GPL(snd_soc_dapm_set_idle_bias); /* * Scan each dapm widget for complete audio path. @@ -2158,10 +2226,10 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event, trace_snd_soc_dapm_start(card, event); for_each_card_dapms(card, d) { - if (dapm_idle_bias_off(d)) - d->target_bias_level = SND_SOC_BIAS_OFF; - else + if (snd_soc_dapm_get_idle_bias(d)) d->target_bias_level = SND_SOC_BIAS_STANDBY; + else + d->target_bias_level = SND_SOC_BIAS_OFF; } dapm_reset(card); @@ -2225,7 +2293,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event, if (d->target_bias_level > bias) bias = d->target_bias_level; for_each_card_dapms(card, d) - if (!dapm_idle_bias_off(d)) + if (snd_soc_dapm_get_idle_bias(d)) d->target_bias_level = bias; trace_snd_soc_dapm_walk_done(card); @@ -4759,8 +4827,7 @@ void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm, if (component) { dapm->dev = component->dev; - dapm->idle_bias_off = !component->driver->idle_bias_on; - dapm->suspend_bias_off = component->driver->suspend_bias_off; + dapm->idle_bias = component->driver->idle_bias_on; } else { dapm->dev = card->dev; } diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index a629e0eacb20..d2b6fb8e0b6c 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -118,6 +118,7 @@ static int soc_mixer_reg_to_ctl(struct soc_mixer_control *mc, unsigned int reg_v if (mc->sign_bit) val = sign_extend32(val, mc->sign_bit); + val = clamp(val, mc->min, mc->max); val -= mc->min; if (mc->invert) diff --git a/sound/soc/sof/amd/acp-probes.c b/sound/soc/sof/amd/acp-probes.c index 0d0f8ec4aed8..ce51ed108a47 100644 --- a/sound/soc/sof/amd/acp-probes.c +++ b/sound/soc/sof/amd/acp-probes.c @@ -108,7 +108,7 @@ static int acp_probes_compr_trigger(struct sof_client_dev *cdev, static int acp_probes_compr_pointer(struct sof_client_dev *cdev, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp, + struct snd_compr_tstamp64 *tstamp, struct snd_soc_dai *dai) { struct acp_dsp_stream *stream = cstream->runtime->private_data; diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index d7b044f33d79..90b932ae3bab 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -361,7 +361,7 @@ static int sof_compr_copy(struct snd_soc_component *component, static int sof_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_sof_pcm *spcm; struct snd_soc_pcm_runtime *rtd = cstream->private_data; diff --git a/sound/soc/sof/imx/imx-common.c b/sound/soc/sof/imx/imx-common.c index d66c198b861a..e787d3932fbb 100644 --- a/sound/soc/sof/imx/imx-common.c +++ b/sound/soc/sof/imx/imx-common.c @@ -354,8 +354,8 @@ static int imx_probe(struct snd_sof_dev *sdev) common = devm_kzalloc(sdev->dev, sizeof(*common), GFP_KERNEL); if (!common) - return dev_err_probe(sdev->dev, -ENOMEM, - "failed to allocate common data\n"); + return -ENOMEM; + sdev->pdata->hw_pdata = common; common->ipc_dev = platform_device_register_data(sdev->dev, "imx-dsp", @@ -382,7 +382,7 @@ static int imx_probe(struct snd_sof_dev *sdev) imx_unregister_action, sdev); if (ret) - return dev_err_probe(sdev->dev, ret, "failed to add devm action\n"); + return ret; common->ipc_handle = dev_get_drvdata(&common->ipc_dev->dev); if (!common->ipc_handle) diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index b73dd91bd529..7e9eab2e3034 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -171,8 +171,7 @@ static int imx8m_probe(struct snd_sof_dev *sdev) chip = devm_kzalloc(sdev->dev, sizeof(*chip), GFP_KERNEL); if (!chip) - return dev_err_probe(sdev->dev, -ENOMEM, - "failed to allocate chip data\n"); + return -ENOMEM; chip->dap = devm_ioremap(sdev->dev, IMX8M_DAP_DEBUG, IMX8M_DAP_DEBUG_SIZE); if (!chip->dap) diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 2f9925830d1d..37674ea452d6 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -260,9 +260,6 @@ void hda_codec_detect_mask(struct snd_sof_dev *sdev) sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC)) return; - /* Accept unsolicited responses */ - snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL); - /* detect codecs */ if (!bus->codec_mask) { bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS); diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 4f34fd919a00..8332d4bda558 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -183,7 +183,7 @@ int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable) } EXPORT_SYMBOL_NS(hda_dsp_ctrl_clock_power_gating, "SND_SOC_SOF_INTEL_HDA_COMMON"); -int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev) +int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool detect_codec) { struct hdac_bus *bus = sof_to_bus(sdev); struct hdac_stream *stream; @@ -220,7 +220,11 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev) } usleep_range(1000, 1200); - hda_codec_detect_mask(sdev); + /* Accept unsolicited responses */ + snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL); + + if (detect_codec) + hda_codec_detect_mask(sdev); /* clear stream status */ list_for_each_entry(stream, &bus->stream_list, list) { diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index f64e8a6a9a33..3ab6d5ce6329 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -870,7 +870,7 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) snd_sof_pci_update_bits(sdev, PCI_TCSEL, 0x07, 0); /* reset and start hda controller */ - ret = hda_dsp_ctrl_init_chip(sdev); + ret = hda_dsp_ctrl_init_chip(sdev, false); if (ret < 0) { dev_err(sdev->dev, "error: failed to start controller after resume\n"); diff --git a/sound/soc/sof/intel/hda-probes.c b/sound/soc/sof/intel/hda-probes.c index c645346c2c84..b06933cebc45 100644 --- a/sound/soc/sof/intel/hda-probes.c +++ b/sound/soc/sof/intel/hda-probes.c @@ -112,7 +112,7 @@ static int hda_probes_compr_trigger(struct sof_client_dev *cdev, static int hda_probes_compr_pointer(struct sof_client_dev *cdev, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp, + struct snd_compr_tstamp64 *tstamp, struct snd_soc_dai *dai) { struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream); diff --git a/sound/soc/sof/intel/hda-sdw-bpt.c b/sound/soc/sof/intel/hda-sdw-bpt.c index 1327f1cad0bc..ff5abccf0d88 100644 --- a/sound/soc/sof/intel/hda-sdw-bpt.c +++ b/sound/soc/sof/intel/hda-sdw-bpt.c @@ -150,7 +150,7 @@ static int hda_sdw_bpt_dma_deprepare(struct device *dev, struct hdac_ext_stream u32 mask; int ret; - ret = hda_cl_cleanup(sdev->dev, dmab_bdl, true, sdw_bpt_stream); + ret = hda_cl_cleanup(sdev->dev, dmab_bdl, false, sdw_bpt_stream); if (ret < 0) { dev_err(sdev->dev, "%s: SDW BPT DMA cleanup failed\n", __func__); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index c387efec41e9..52e86fa60077 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -616,7 +616,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev) dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n"); /* Init HDA controller after i915 init */ - ret = hda_dsp_ctrl_init_chip(sdev); + ret = hda_dsp_ctrl_init_chip(sdev, true); if (ret < 0) { dev_err(bus->dev, "error: init chip failed with ret: %d\n", ret); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index e14f82c0831f..28daf0a3b984 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -757,7 +757,7 @@ void hda_dsp_ctrl_ppcap_int_enable(struct snd_sof_dev *sdev, bool enable); int hda_dsp_ctrl_link_reset(struct snd_sof_dev *sdev, bool reset); void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable); int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable); -int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev); +int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool detect_codec); void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev); /* * HDA bus operations. diff --git a/sound/soc/sof/ipc3-dtrace.c b/sound/soc/sof/ipc3-dtrace.c index e5c8fec173c4..6ec391fd39a9 100644 --- a/sound/soc/sof/ipc3-dtrace.c +++ b/sound/soc/sof/ipc3-dtrace.c @@ -126,7 +126,7 @@ static int trace_filter_parse(struct snd_sof_dev *sdev, char *string, capacity += TRACE_FILTER_ELEMENTS_PER_ENTRY; entry = strchr(entry + 1, entry_delimiter[0]); } - *out = kmalloc(capacity * sizeof(**out), GFP_KERNEL); + *out = kmalloc_array(capacity, sizeof(**out), GFP_KERNEL); if (!*out) return -ENOMEM; diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 374dc10d10fd..24f82a6f3610 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -639,14 +639,14 @@ static int ipc4_ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, if (params_rate(params) == le32_to_cpu(hw_config->fsync_rate) && params_width(params) == le32_to_cpu(hw_config->tdm_slot_width) && - params_channels(params) == le32_to_cpu(hw_config->tdm_slots)) { + params_channels(params) <= le32_to_cpu(hw_config->tdm_slots)) { current_config = le32_to_cpu(hw_config->id); partial_match = false; /* best match found */ break; } else if (current_config < 0 && params_rate(params) == le32_to_cpu(hw_config->fsync_rate) && - params_channels(params) == le32_to_cpu(hw_config->tdm_slots)) { + params_channels(params) <= le32_to_cpu(hw_config->tdm_slots)) { current_config = le32_to_cpu(hw_config->id); partial_match = true; /* keep looking for better match */ @@ -727,6 +727,58 @@ static int sof_ipc4_pcm_dai_link_fixup_rate(struct snd_sof_dev *sdev, return 0; } +static int sof_ipc4_pcm_dai_link_fixup_channels(struct snd_sof_dev *sdev, + struct snd_pcm_hw_params *params, + struct sof_ipc4_copier *ipc4_copier) +{ + struct sof_ipc4_pin_format *pin_fmts = ipc4_copier->available_fmt.input_pin_fmts; + struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + int num_input_formats = ipc4_copier->available_fmt.num_input_formats; + unsigned int fe_channels = params_channels(params); + bool fe_be_match = false; + bool single_be_channels = true; + unsigned int be_channels, val; + int i; + + if (WARN_ON_ONCE(!num_input_formats)) + return -EINVAL; + + /* + * Copier does not change channels, so we + * need to only consider the input pin information. + */ + be_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(pin_fmts[0].audio_fmt.fmt_cfg); + for (i = 0; i < num_input_formats; i++) { + val = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(pin_fmts[i].audio_fmt.fmt_cfg); + + if (val != be_channels) + single_be_channels = false; + + if (val == fe_channels) { + fe_be_match = true; + break; + } + } + + /* + * If channels is different than FE channels, topology must contain a + * module which can change the number of channels. But we do require + * topology to define a single channels in the DAI copier config in + * this case (FE channels may be variable). + */ + if (!fe_be_match) { + if (!single_be_channels) { + dev_err(sdev->dev, "Unable to select channels for DAI link\n"); + return -EINVAL; + } + + channels->min = be_channels; + channels->max = be_channels; + } + + return 0; +} + static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -790,6 +842,10 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, if (ret) return ret; + ret = sof_ipc4_pcm_dai_link_fixup_channels(sdev, params, ipc4_copier); + if (ret) + return ret; + if (single_bitdepth) { snd_mask_none(fmt); valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(ipc4_fmt->fmt_cfg); diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 591ee30551ba..b6a732d0adb4 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -38,6 +38,36 @@ MODULE_PARM_DESC(ipc4_ignore_cpc, static DEFINE_IDA(alh_group_ida); static DEFINE_IDA(pipeline_ida); +struct sof_comp_domains { + const char *name; + enum sof_comp_domain domain; +}; + +static const struct sof_comp_domains sof_domains[] = { + { "LL", SOF_COMP_DOMAIN_LL, }, + { "DP", SOF_COMP_DOMAIN_DP, } +}; + +static enum sof_comp_domain find_domain(const char *name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(sof_domains); i++) { + if (strcmp(name, sof_domains[i].name) == 0) + return sof_domains[i].domain; + } + /* No valid value found, fall back to manifest value */ + return SOF_COMP_DOMAIN_UNSET; +} + +static int get_token_comp_domain(void *elem, void *object, u32 offset) +{ + u32 *val = (u32 *)((u8 *)object + offset); + + *val = find_domain((const char *)elem); + return 0; +} + static const struct sof_topology_token ipc4_sched_tokens[] = { {SOF_TKN_SCHED_LP_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, offsetof(struct sof_ipc4_pipeline, lp_mode)}, @@ -127,6 +157,8 @@ static const struct sof_topology_token comp_ext_tokens[] = { offsetof(struct snd_sof_widget, uuid)}, {SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, offsetof(struct snd_sof_widget, core)}, + {SOF_TKN_COMP_SCHED_DOMAIN, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_domain, + offsetof(struct snd_sof_widget, comp_domain)}, }; static const struct sof_topology_token gain_tokens[] = { @@ -497,7 +529,17 @@ static int sof_ipc4_widget_setup_msg(struct snd_sof_widget *swidget, struct sof_ msg->extension = SOF_IPC4_MOD_EXT_CORE_ID(swidget->core); - type = (fw_module->man4_module_entry.type & SOF_IPC4_MODULE_DP) ? 1 : 0; + switch (swidget->comp_domain) { + case SOF_COMP_DOMAIN_LL: + type = 0; + break; + case SOF_COMP_DOMAIN_DP: + type = 1; + break; + default: + type = (fw_module->man4_module_entry.type & SOF_IPC4_MODULE_DP) ? 1 : 0; + break; + } msg->extension |= SOF_IPC4_MOD_EXT_DOMAIN(type); return 0; @@ -1292,6 +1334,23 @@ static int sof_ipc4_widget_assign_instance_id(struct snd_sof_dev *sdev, return 0; } +static u32 sof_ipc4_fmt_cfg_to_type(u32 fmt_cfg) +{ + /* Fetch the sample type from the fmt for 8 and 32 bit formats */ + u32 __bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt_cfg); + + if (__bits == 8 || __bits == 32) + return SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt_cfg); + + /* + * Return LSB integer type for 20 and 24 formats as the firmware is + * handling the LSB/MSB alignment internally, for the kernel this + * should not be taken into account, we treat them as LSB to match with + * the format we support on the PCM side. + */ + return SOF_IPC4_TYPE_LSB_INTEGER; +} + /* update hw_params based on the audio stream format */ static int sof_ipc4_update_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params, struct sof_ipc4_audio_format *fmt, u32 param_to_update) @@ -1300,10 +1359,27 @@ static int sof_ipc4_update_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw if (param_to_update & BIT(SNDRV_PCM_HW_PARAM_FORMAT)) { int valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); + int type = sof_ipc4_fmt_cfg_to_type(fmt->fmt_cfg); snd_pcm_format_t snd_fmt; struct snd_mask *m; switch (valid_bits) { + case 8: + switch (type) { + case SOF_IPC4_TYPE_A_LAW: + snd_fmt = SNDRV_PCM_FORMAT_A_LAW; + break; + case SOF_IPC4_TYPE_MU_LAW: + snd_fmt = SNDRV_PCM_FORMAT_MU_LAW; + break; + case SOF_IPC4_TYPE_UNSIGNED_INTEGER: + snd_fmt = SNDRV_PCM_FORMAT_U8; + break; + default: + dev_err(sdev->dev, "Unsupported PCM 8-bit IPC4 type %d\n", type); + return -EINVAL; + } + break; case 16: snd_fmt = SNDRV_PCM_FORMAT_S16_LE; break; @@ -1311,7 +1387,17 @@ static int sof_ipc4_update_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw snd_fmt = SNDRV_PCM_FORMAT_S24_LE; break; case 32: - snd_fmt = SNDRV_PCM_FORMAT_S32_LE; + switch (type) { + case SOF_IPC4_TYPE_LSB_INTEGER: + snd_fmt = SNDRV_PCM_FORMAT_S32_LE; + break; + case SOF_IPC4_TYPE_FLOAT: + snd_fmt = SNDRV_PCM_FORMAT_FLOAT_LE; + break; + default: + dev_err(sdev->dev, "Unsupported PCM 32-bit IPC4 type %d\n", type); + return -EINVAL; + } break; default: dev_err(sdev->dev, "invalid PCM valid_bits %d\n", valid_bits); @@ -1375,7 +1461,7 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev, struct sof_ipc4_base_module_cfg *base_config, struct sof_ipc4_available_audio_format *available_fmt, u32 out_ref_rate, u32 out_ref_channels, - u32 out_ref_valid_bits) + u32 out_ref_valid_bits, u32 out_ref_type) { struct sof_ipc4_pin_format *pin_fmts = available_fmt->output_pin_fmts; u32 pin_fmts_size = available_fmt->num_output_formats; @@ -1401,19 +1487,22 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev, for (i = 0; i < pin_fmts_size; i++) { struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt; - u32 _out_rate, _out_channels, _out_valid_bits; + u32 _out_rate, _out_channels, _out_valid_bits, _out_type; _out_rate = fmt->sampling_frequency; _out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); _out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); + _out_type = sof_ipc4_fmt_cfg_to_type(fmt->fmt_cfg); if (_out_rate == out_ref_rate && _out_channels == out_ref_channels && - _out_valid_bits == out_ref_valid_bits) + _out_valid_bits == out_ref_valid_bits && _out_type == out_ref_type) goto out_fmt; } - dev_err(sdev->dev, "%s: Unsupported audio format: %uHz, %ubit, %u channels\n", - __func__, out_ref_rate, out_ref_valid_bits, out_ref_channels); + dev_err(sdev->dev, + "%s: Unsupported audio format: %uHz, %ubit, %u channels, type: %d\n", + __func__, out_ref_rate, out_ref_valid_bits, out_ref_channels, + out_ref_type); return -EINVAL; @@ -1426,18 +1515,46 @@ out_fmt: static int sof_ipc4_get_valid_bits(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params) { switch (params_format(params)) { + case SNDRV_PCM_FORMAT_U8: + case SNDRV_PCM_FORMAT_MU_LAW: + case SNDRV_PCM_FORMAT_A_LAW: + return 8; case SNDRV_PCM_FORMAT_S16_LE: return 16; case SNDRV_PCM_FORMAT_S24_LE: return 24; case SNDRV_PCM_FORMAT_S32_LE: return 32; + case SNDRV_PCM_FORMAT_FLOAT_LE: + return 32; default: dev_err(sdev->dev, "invalid pcm frame format %d\n", params_format(params)); return -EINVAL; } } +static int sof_ipc4_get_sample_type(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params) +{ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_A_LAW: + return SOF_IPC4_TYPE_A_LAW; + case SNDRV_PCM_FORMAT_MU_LAW: + return SOF_IPC4_TYPE_MU_LAW; + case SNDRV_PCM_FORMAT_U8: + return SOF_IPC4_TYPE_UNSIGNED_INTEGER; + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S32_LE: + case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: + return SOF_IPC4_TYPE_LSB_INTEGER; + case SNDRV_PCM_FORMAT_FLOAT_LE: + return SOF_IPC4_TYPE_FLOAT; + default: + dev_err(sdev->dev, "invalid pcm sample type %d\n", params_format(params)); + return -EINVAL; + } +} + static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, struct sof_ipc4_base_module_cfg *base_config, @@ -1449,8 +1566,10 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev, u32 valid_bits; u32 channels; u32 rate; + u32 type; bool single_format; int sample_valid_bits; + int sample_type; int i = 0; if (!pin_fmts_size) { @@ -1466,6 +1585,10 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev, if (sample_valid_bits < 0) return sample_valid_bits; + sample_type = sof_ipc4_get_sample_type(sdev, params); + if (sample_type < 0) + return sample_type; + /* * Search supported input audio formats with pin index 0 to match rate, channels and * sample_valid_bits from reference params @@ -1479,14 +1602,17 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev, rate = fmt->sampling_frequency; channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); + type = sof_ipc4_fmt_cfg_to_type(fmt->fmt_cfg); if (params_rate(params) == rate && params_channels(params) == channels && - sample_valid_bits == valid_bits) + sample_valid_bits == valid_bits && sample_type == type) break; } if (i == pin_fmts_size) { - dev_err(sdev->dev, "%s: Unsupported audio format: %uHz, %ubit, %u channels\n", - __func__, params_rate(params), sample_valid_bits, params_channels(params)); + dev_err(sdev->dev, + "%s: Unsupported audio format: %uHz, %ubit, %u channels, type: %d\n", + __func__, params_rate(params), sample_valid_bits, + params_channels(params), sample_type); return -EINVAL; } @@ -1882,7 +2008,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, int *ipc_config_size; u32 **data; int ipc_size, ret, out_ref_valid_bits; - u32 out_ref_rate, out_ref_channels; + u32 out_ref_rate, out_ref_channels, out_ref_type; u32 deep_buffer_dma_ms = 0; bool single_output_bitdepth; int i; @@ -1923,10 +2049,13 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, host_dma_id = platform_params->stream_tag - 1; pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_HOST_ID(host_dma_id); - /* Set SCS bit for S16_LE format only */ if (params_format(fe_params) == SNDRV_PCM_FORMAT_S16_LE) pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK; + /* Set SCS bit for 8 and 16 bit formats */ + if (params_physical_width(fe_params) <= 16) + pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK; + /* * Despite its name the bitfield 'fifo_size' is used to define DMA buffer * size. The expression calculates 2ms buffer size. @@ -2051,6 +2180,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; out_ref_rate = in_fmt->sampling_frequency; out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); + out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg); if (!single_output_bitdepth) out_ref_valid_bits = @@ -2061,6 +2191,11 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, case snd_soc_dapm_dai_in: out_ref_rate = params_rate(fe_params); out_ref_channels = params_channels(fe_params); + ret = sof_ipc4_get_sample_type(sdev, fe_params); + if (ret < 0) + return ret; + out_ref_type = (u32)ret; + if (!single_output_bitdepth) { out_ref_valid_bits = sof_ipc4_get_valid_bits(sdev, fe_params); if (out_ref_valid_bits < 0) @@ -2085,12 +2220,14 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, out_fmt = &available_fmt->output_pin_fmts[0].audio_fmt; out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg); + out_ref_type = sof_ipc4_fmt_cfg_to_type(out_fmt->fmt_cfg); } output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, &copier_data->base_config, available_fmt, out_ref_rate, - out_ref_channels, out_ref_valid_bits); + out_ref_channels, out_ref_valid_bits, + out_ref_type); if (output_fmt_index < 0) return output_fmt_index; @@ -2319,7 +2456,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, struct sof_ipc4_gain *gain = swidget->private; struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt; struct sof_ipc4_audio_format *in_fmt; - u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; + u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type; int input_fmt_index, output_fmt_index; input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, @@ -2333,13 +2470,15 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, out_ref_rate = in_fmt->sampling_frequency; out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); + out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg); output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, &gain->data.base_config, available_fmt, out_ref_rate, out_ref_channels, - out_ref_valid_bits); + out_ref_valid_bits, + out_ref_type); if (output_fmt_index < 0) return output_fmt_index; @@ -2362,7 +2501,7 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, struct sof_ipc4_mixer *mixer = swidget->private; struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt; struct sof_ipc4_audio_format *in_fmt; - u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; + u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type; int input_fmt_index, output_fmt_index; input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, @@ -2376,13 +2515,15 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, out_ref_rate = in_fmt->sampling_frequency; out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); + out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg); output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, &mixer->base_config, available_fmt, out_ref_rate, out_ref_channels, - out_ref_valid_bits); + out_ref_valid_bits, + out_ref_type); if (output_fmt_index < 0) return output_fmt_index; @@ -2406,7 +2547,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt = &src->available_fmt; struct sof_ipc4_audio_format *out_audio_fmt; struct sof_ipc4_audio_format *in_audio_fmt; - u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; + u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type; int output_fmt_index, input_fmt_index; input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, @@ -2433,6 +2574,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, in_audio_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_audio_fmt->fmt_cfg); out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_audio_fmt->fmt_cfg); + out_ref_type = sof_ipc4_fmt_cfg_to_type(in_audio_fmt->fmt_cfg); /* * For capture, the SRC module should convert the rate to match the rate requested by the @@ -2446,7 +2588,8 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, available_fmt, out_ref_rate, out_ref_channels, - out_ref_valid_bits); + out_ref_valid_bits, + out_ref_type); if (output_fmt_index < 0) return output_fmt_index; @@ -2570,20 +2713,22 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, struct sof_ipc4_audio_format *in_fmt; struct sof_ipc4_pin_format *pin_fmt; u32 out_ref_rate, out_ref_channels; - int out_ref_valid_bits; + int out_ref_valid_bits, out_ref_type; in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; out_ref_rate = in_fmt->sampling_frequency; out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); + out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg); output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, &process->base_config, available_fmt, out_ref_rate, out_ref_channels, - out_ref_valid_bits); + out_ref_valid_bits, + out_ref_type); if (output_fmt_index < 0) return output_fmt_index; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 14ba58d2be03..dfa1a6c2ffa8 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -41,6 +41,15 @@ #define SOF_IPC4_FW_MAX_PAGE_COUNT 20 #define SOF_IPC4_FW_MAX_QUEUE_COUNT 8 +/* IPC4 sample types */ +#define SOF_IPC4_TYPE_MSB_INTEGER 0 +#define SOF_IPC4_TYPE_LSB_INTEGER 1 +#define SOF_IPC4_TYPE_SIGNED_INTEGER 2 +#define SOF_IPC4_TYPE_UNSIGNED_INTEGER 3 +#define SOF_IPC4_TYPE_FLOAT 4 +#define SOF_IPC4_TYPE_A_LAW 5 +#define SOF_IPC4_TYPE_MU_LAW 6 + /* Node index and mask applicable for host copier and ALH/HDA type DAI copiers */ #define SOF_IPC4_NODE_INDEX_MASK 0xFF #define SOF_IPC4_NODE_INDEX(x) ((x) & SOF_IPC4_NODE_INDEX_MASK) @@ -109,6 +118,13 @@ enum sof_ipc4_copier_module_config_params { SOF_IPC4_COPIER_MODULE_CFG_ATTENUATION, }; +/* Scheduling domain, unset, Low Latency, or Data Processing */ +enum sof_comp_domain { + SOF_COMP_DOMAIN_UNSET = 0, /* Take domain value from manifest */ + SOF_COMP_DOMAIN_LL, /* Low Latency scheduling domain */ + SOF_COMP_DOMAIN_DP, /* Data Processing scheduling domain */ +}; + struct sof_ipc4_copier_config_set_sink_format { /* Id of sink */ u32 sink_id; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 36ab75e11779..db6973c8eac3 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -451,6 +451,9 @@ struct snd_sof_widget { */ bool dynamic_pipeline_widget; + /* Scheduling domain (enum sof_comp_domain), unset, Low Latency, or Data Processing */ + u32 comp_domain; + struct snd_soc_dapm_widget *widget; struct list_head list; /* list in sdev widget list */ struct snd_sof_pipeline *spipe; diff --git a/sound/soc/sof/sof-client-probes-ipc3.c b/sound/soc/sof/sof-client-probes-ipc3.c index 816df745c9af..a78ec0954a61 100644 --- a/sound/soc/sof/sof-client-probes-ipc3.c +++ b/sound/soc/sof/sof-client-probes-ipc3.c @@ -100,9 +100,11 @@ static int ipc3_probes_deinit(struct sof_client_dev *cdev) } static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd, - void **params, size_t *num_params) + void **params, size_t *num_params, + enum sof_probe_info_type type) { size_t max_msg_size = sof_client_get_ipc_max_payload_size(cdev); + struct device *dev = &cdev->auxdev.dev; struct sof_ipc_probe_info_params msg = {{{0}}}; struct sof_ipc_probe_info_params *reply; size_t bytes; @@ -111,6 +113,11 @@ static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd, *params = NULL; *num_params = 0; + if (type != PROBES_INFO_ACTIVE_PROBES) { + dev_err(dev, "%s: info type %u not supported", __func__, type); + return -EOPNOTSUPP; + } + reply = kzalloc(max_msg_size, GFP_KERNEL); if (!reply) return -ENOMEM; @@ -142,21 +149,25 @@ exit: } /** - * ipc3_probes_points_info - retrieve list of active probe points + * ipc3_probes_points_info - retrieve list of probe points * @cdev: SOF client device * @desc: Returned list of active probes * @num_desc: Returned count of active probes + * @type: Either PROBES_INFO_ACTIVE_PROBES or PROBES_INFO_AVAILABE_PROBES + * + * If type is PROBES_INFO_ACTIVE_PROBES, host sends PROBE_POINT_INFO + * request to obtain list of active probe points, valid for + * disconnection when given probe is no longer required. * - * Host sends PROBE_POINT_INFO request to obtain list of active probe - * points, valid for disconnection when given probe is no longer - * required. + * Type PROBES_INFO_AVAILABE_PROBES is not yet supported. */ static int ipc3_probes_points_info(struct sof_client_dev *cdev, struct sof_probe_point_desc **desc, - size_t *num_desc) + size_t *num_desc, + enum sof_probe_info_type type) { return ipc3_probes_info(cdev, SOF_IPC_PROBE_POINT_INFO, - (void **)desc, num_desc); + (void **)desc, num_desc, type); } /** diff --git a/sound/soc/sof/sof-client-probes-ipc4.c b/sound/soc/sof/sof-client-probes-ipc4.c index 603aed222480..758a56d271d7 100644 --- a/sound/soc/sof/sof-client-probes-ipc4.c +++ b/sound/soc/sof/sof-client-probes-ipc4.c @@ -8,7 +8,7 @@ #include <sound/soc.h> #include <sound/sof/ipc4/header.h> #include <uapi/sound/sof/header.h> -#include "sof-priv.h" +#include "sof-audio.h" #include "ipc4-priv.h" #include "sof-client.h" #include "sof-client-probes.h" @@ -28,6 +28,7 @@ enum sof_ipc4_probe_runtime_param { SOF_IPC4_PROBE_INJECTION_DMA_DETACH, SOF_IPC4_PROBE_POINTS, SOF_IPC4_PROBE_POINTS_DISCONNECT, + SOF_IPC4_PROBE_POINTS_AVAILABLE, }; struct sof_ipc4_probe_gtw_cfg { @@ -49,14 +50,42 @@ enum sof_ipc4_probe_type { SOF_IPC4_PROBE_TYPE_INTERNAL }; +#define SOF_IPC4_PROBE_TYPE_SHIFT 24 +#define SOF_IPC4_PROBE_TYPE_MASK GENMASK(25, 24) +#define SOF_IPC4_PROBE_TYPE_GET(x) (((x) & SOF_IPC4_PROBE_TYPE_MASK) \ + >> SOF_IPC4_PROBE_TYPE_SHIFT) +#define SOF_IPC4_PROBE_IDX_SHIFT 26 +#define SOF_IPC4_PROBE_IDX_MASK GENMASK(31, 26) +#define SOF_IPC4_PROBE_IDX_GET(x) (((x) & SOF_IPC4_PROBE_IDX_MASK) \ + >> SOF_IPC4_PROBE_IDX_SHIFT) + struct sof_ipc4_probe_point { u32 point_id; u32 purpose; u32 stream_tag; } __packed __aligned(4); +struct sof_ipc4_probe_info { + unsigned int num_elems; + DECLARE_FLEX_ARRAY(struct sof_ipc4_probe_point, points); +} __packed; + #define INVALID_PIPELINE_ID 0xFF +static const char *sof_probe_ipc4_type_string(u32 type) +{ + switch (type) { + case SOF_IPC4_PROBE_TYPE_INPUT: + return "input"; + case SOF_IPC4_PROBE_TYPE_OUTPUT: + return "output"; + case SOF_IPC4_PROBE_TYPE_INTERNAL: + return "internal"; + default: + return "UNKNOWN"; + } +} + /** * sof_ipc4_probe_get_module_info - Get IPC4 module info for probe module * @cdev: SOF client device @@ -164,25 +193,113 @@ static int ipc4_probes_deinit(struct sof_client_dev *cdev) } /** - * ipc4_probes_points_info - retrieve list of active probe points + * ipc4_probes_points_info - retrieve list of probe points * @cdev: SOF client device * @desc: Returned list of active probes * @num_desc: Returned count of active probes + * @type: Either PROBES_INFO_ACTIVE_PROBES or PROBES_INFO_AVAILABE_PROBES * @return: 0 on success, negative error code on error * - * Dummy implementation returning empty list of probes. + * Returns list if active probe points if type is + * PROBES_INFO_ACTIVE_PROBES, or list of all available probe points if + * type is PROBES_INFO_AVAILABE_PROBES. */ static int ipc4_probes_points_info(struct sof_client_dev *cdev, struct sof_probe_point_desc **desc, - size_t *num_desc) + size_t *num_desc, + enum sof_probe_info_type type) { - /* TODO: Firmware side implementation needed first */ - *desc = NULL; - *num_desc = 0; + struct sof_man4_module *mentry = sof_ipc4_probe_get_module_info(cdev); + struct device *dev = &cdev->auxdev.dev; + struct sof_ipc4_probe_info *info; + struct sof_ipc4_msg msg; + u32 param_id; + int i, ret; + + if (!mentry) + return -ENODEV; + + switch (type) { + case PROBES_INFO_ACTIVE_PROBES: + param_id = SOF_IPC4_PROBE_POINTS; + break; + case PROBES_INFO_AVAILABE_PROBES: + param_id = SOF_IPC4_PROBE_POINTS_AVAILABLE; + break; + default: + dev_err(dev, "%s: info type %u not supported", __func__, type); + return -EOPNOTSUPP; + } + + msg.primary = mentry->id; + msg.primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); + msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); + + msg.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(param_id); + + msg.data_size = sof_client_get_ipc_max_payload_size(cdev); + msg.data_ptr = kzalloc(msg.data_size, GFP_KERNEL); + if (!msg.data_ptr) + return -ENOMEM; + + ret = sof_client_ipc_set_get_data(cdev, &msg, false); + if (ret) { + kfree(msg.data_ptr); + return ret; + } + info = msg.data_ptr; + *num_desc = info->num_elems; + dev_dbg(dev, "%s: got %zu probe points", __func__, *num_desc); + + *desc = kzalloc(*num_desc * sizeof(**desc), GFP_KERNEL); + if (!*desc) { + kfree(msg.data_ptr); + return -ENOMEM; + } + + for (i = 0; i < *num_desc; i++) { + (*desc)[i].buffer_id = info->points[i].point_id; + (*desc)[i].purpose = info->points[i].purpose; + (*desc)[i].stream_tag = info->points[i].stream_tag; + } + kfree(msg.data_ptr); + return 0; } /** + * ipc4_probes_point_print - Human readable print of probe point descriptor + * @cdev: SOF client device + * @buf: Buffer to print to + * @size: Available bytes in buffer + * @desc: Describes the probe point to print + * @return: Number of bytes printed or an error code (snprintf return value) + */ +static int ipc4_probes_point_print(struct sof_client_dev *cdev, char *buf, size_t size, + struct sof_probe_point_desc *desc) +{ + struct device *dev = &cdev->auxdev.dev; + struct snd_sof_widget *swidget; + int ret; + + swidget = sof_client_ipc4_find_swidget_by_id(cdev, SOF_IPC4_MOD_ID_GET(desc->buffer_id), + SOF_IPC4_MOD_INSTANCE_GET(desc->buffer_id)); + if (!swidget) + dev_err(dev, "%s: Failed to find widget for module %lu.%lu\n", + __func__, SOF_IPC4_MOD_ID_GET(desc->buffer_id), + SOF_IPC4_MOD_INSTANCE_GET(desc->buffer_id)); + + ret = snprintf(buf, size, "%#x,%#x,%#x\t%s %s buf idx %lu %s\n", + desc->buffer_id, desc->purpose, desc->stream_tag, + swidget ? swidget->widget->name : "<unknown>", + sof_probe_ipc4_type_string(SOF_IPC4_PROBE_TYPE_GET(desc->buffer_id)), + SOF_IPC4_PROBE_IDX_GET(desc->buffer_id), + desc->stream_tag ? "(connected)" : ""); + + return ret; +} + +/** * ipc4_probes_points_add - connect specified probes * @cdev: SOF client device * @desc: List of probe points to connect @@ -202,7 +319,7 @@ static int ipc4_probes_points_add(struct sof_client_dev *cdev, int i, ret; if (!mentry) - return -ENODEV; + return -EOPNOTSUPP; /* The sof_probe_point_desc and sof_ipc4_probe_point structs * are of same size and even the integers are the same in the @@ -286,6 +403,7 @@ const struct sof_probes_ipc_ops ipc4_probe_ops = { .init = ipc4_probes_init, .deinit = ipc4_probes_deinit, .points_info = ipc4_probes_points_info, + .point_print = ipc4_probes_point_print, .points_add = ipc4_probes_points_add, .points_remove = ipc4_probes_points_remove, }; diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c index 663c0d3c314c..5dbc0aacb8e3 100644 --- a/sound/soc/sof/sof-client-probes.c +++ b/sound/soc/sof/sof-client-probes.c @@ -17,8 +17,14 @@ #include <sound/soc.h> #include <sound/sof/header.h> +#include <sound/sof/ipc4/header.h> #include "sof-client.h" #include "sof-client-probes.h" +#include "sof-audio.h" + +#ifdef CONFIG_SND_SOC_SOF_IPC4 +#include "ipc4-priv.h" +#endif #define SOF_PROBES_SUSPEND_DELAY_MS 3000 /* only extraction supported for now */ @@ -69,7 +75,8 @@ static int sof_probes_compr_shutdown(struct snd_compr_stream *cstream, int i, ret; /* disconnect all probe points */ - ret = ipc->points_info(cdev, &desc, &num_desc); + ret = ipc->points_info(cdev, &desc, &num_desc, + PROBES_INFO_ACTIVE_PROBES); if (ret < 0) { dev_err(dai->dev, "Failed to get probe points: %d\n", ret); goto exit; @@ -137,7 +144,7 @@ static int sof_probes_compr_trigger(struct snd_compr_stream *cstream, int cmd, } static int sof_probes_compr_pointer(struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp, + struct snd_compr_tstamp64 *tstamp, struct snd_soc_dai *dai) { struct snd_soc_card *card = snd_soc_component_get_drvdata(dai->component); @@ -189,7 +196,8 @@ static const struct snd_compress_ops sof_probes_compressed_ops = { }; static ssize_t sof_probes_dfs_points_read(struct file *file, char __user *to, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos, + enum sof_probe_info_type type) { struct sof_client_dev *cdev = file->private_data; struct sof_probes_priv *priv = cdev->data; @@ -216,16 +224,20 @@ static ssize_t sof_probes_dfs_points_read(struct file *file, char __user *to, goto exit; } - ret = ipc->points_info(cdev, &desc, &num_desc); + ret = ipc->points_info(cdev, &desc, &num_desc, type); if (ret < 0) goto pm_error; for (i = 0; i < num_desc; i++) { offset = strlen(buf); remaining = PAGE_SIZE - offset; - ret = snprintf(buf + offset, remaining, - "Id: %#010x Purpose: %u Node id: %#x\n", - desc[i].buffer_id, desc[i].purpose, desc[i].stream_tag); + if (ipc->point_print) + ret = ipc->point_print(cdev, buf + offset, remaining, &desc[i]); + else + ret = snprintf(buf + offset, remaining, + "Id: %#010x Purpose: %u Node id: %#x\n", + desc[i].buffer_id, desc[i].purpose, desc[i].stream_tag); + if (ret < 0 || ret >= remaining) { /* truncate the output buffer at the last full line */ buf[offset] = '\0'; @@ -247,6 +259,22 @@ exit: return ret; } +static ssize_t sof_probes_dfs_active_points_read(struct file *file, + char __user *to, + size_t count, loff_t *ppos) +{ + return sof_probes_dfs_points_read(file, to, count, ppos, + PROBES_INFO_ACTIVE_PROBES); +} + +static ssize_t sof_probes_dfs_available_points_read(struct file *file, + char __user *to, + size_t count, loff_t *ppos) +{ + return sof_probes_dfs_points_read(file, to, count, ppos, + PROBES_INFO_AVAILABE_PROBES); +} + static ssize_t sof_probes_dfs_points_write(struct file *file, const char __user *from, size_t count, loff_t *ppos) @@ -296,15 +324,23 @@ exit: return ret; } -static const struct file_operations sof_probes_points_fops = { +static const struct file_operations sof_probes_active_points_fops = { .open = simple_open, - .read = sof_probes_dfs_points_read, + .read = sof_probes_dfs_active_points_read, .write = sof_probes_dfs_points_write, .llseek = default_llseek, .owner = THIS_MODULE, }; +static const struct file_operations sof_probes_available_points_fops = { + .open = simple_open, + .read = sof_probes_dfs_available_points_read, + .llseek = default_llseek, + + .owner = THIS_MODULE, +}; + static ssize_t sof_probes_dfs_points_remove_write(struct file *file, const char __user *from, size_t count, loff_t *ppos) @@ -449,13 +485,17 @@ static int sof_probes_client_probe(struct auxiliary_device *auxdev, /* create read-write probes_points debugfs entry */ priv->dfs_points = debugfs_create_file("probe_points", 0644, dfsroot, - cdev, &sof_probes_points_fops); + cdev, &sof_probes_active_points_fops); /* create read-write probe_points_remove debugfs entry */ priv->dfs_points_remove = debugfs_create_file("probe_points_remove", 0644, dfsroot, cdev, &sof_probes_points_remove_fops); + /* create read-write probes_points debugfs entry */ + priv->dfs_points = debugfs_create_file("probe_points_available", 0644, dfsroot, + cdev, &sof_probes_available_points_fops); + links = devm_kcalloc(dev, SOF_PROBES_NUM_DAI_LINKS, sizeof(*links), GFP_KERNEL); cpus = devm_kcalloc(dev, SOF_PROBES_NUM_DAI_LINKS, sizeof(*cpus), GFP_KERNEL); if (!links || !cpus) { @@ -485,7 +525,7 @@ static int sof_probes_client_probe(struct auxiliary_device *auxdev, card->dai_link = links; /* set idle_bias_off to prevent the core from resuming the card->dev */ - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; snd_soc_card_set_drvdata(card, cdev); diff --git a/sound/soc/sof/sof-client-probes.h b/sound/soc/sof/sof-client-probes.h index da04d65b8d99..47d0582b8eb8 100644 --- a/sound/soc/sof/sof-client-probes.h +++ b/sound/soc/sof/sof-client-probes.h @@ -4,7 +4,7 @@ #define __SOF_CLIENT_PROBES_H struct snd_compr_stream; -struct snd_compr_tstamp; +struct snd_compr_tstamp64; struct snd_compr_params; struct sof_client_dev; struct snd_soc_dai; @@ -24,7 +24,7 @@ struct sof_probes_host_ops { int (*trigger)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream, int cmd, struct snd_soc_dai *dai); int (*pointer)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp, + struct snd_compr_tstamp64 *tstamp, struct snd_soc_dai *dai); }; @@ -34,13 +34,20 @@ struct sof_probe_point_desc { unsigned int stream_tag; } __packed; +enum sof_probe_info_type { + PROBES_INFO_ACTIVE_PROBES, + PROBES_INFO_AVAILABE_PROBES, +}; + struct sof_probes_ipc_ops { int (*init)(struct sof_client_dev *cdev, u32 stream_tag, size_t buffer_size); int (*deinit)(struct sof_client_dev *cdev); int (*points_info)(struct sof_client_dev *cdev, struct sof_probe_point_desc **desc, - size_t *num_desc); + size_t *num_desc, enum sof_probe_info_type type); + int (*point_print)(struct sof_client_dev *cdev, char *buf, size_t size, + struct sof_probe_point_desc *desc); int (*points_add)(struct sof_client_dev *cdev, struct sof_probe_point_desc *desc, size_t num_desc); diff --git a/sound/soc/sof/sof-client.c b/sound/soc/sof/sof-client.c index 4c7951338c66..2dbfc7699c73 100644 --- a/sound/soc/sof/sof-client.c +++ b/sound/soc/sof/sof-client.c @@ -45,13 +45,30 @@ struct sof_state_event_entry { struct list_head list; }; +/** + * struct sof_client_dev_entry - client device entry for internal management use + * @sdev: pointer to SOF core device struct + * @list: item in SOF core client dev list + * @client_dev: SOF client device + */ +struct sof_client_dev_entry { + struct snd_sof_dev *sdev; + struct list_head list; + + struct sof_client_dev client_dev; +}; + +#define cdev_to_centry(cdev) \ + container_of(cdev, struct sof_client_dev_entry, client_dev) + static void sof_client_auxdev_release(struct device *dev) { struct auxiliary_device *auxdev = to_auxiliary_dev(dev); struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev); + struct sof_client_dev_entry *centry = cdev_to_centry(cdev); kfree(cdev->auxdev.dev.platform_data); - kfree(cdev); + kfree(centry); } static int sof_client_dev_add_data(struct sof_client_dev *cdev, const void *data, @@ -208,15 +225,18 @@ void sof_unregister_clients(struct snd_sof_dev *sdev) int sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, u32 id, const void *data, size_t size) { + struct sof_client_dev_entry *centry; struct auxiliary_device *auxdev; struct sof_client_dev *cdev; int ret; - cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); - if (!cdev) + centry = kzalloc(sizeof(*centry), GFP_KERNEL); + if (!centry) return -ENOMEM; - cdev->sdev = sdev; + cdev = ¢ry->client_dev; + + centry->sdev = sdev; auxdev = &cdev->auxdev; auxdev->name = name; auxdev->dev.parent = sdev->dev; @@ -246,7 +266,7 @@ int sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, u32 id, /* add to list of SOF client devices */ mutex_lock(&sdev->ipc_client_mutex); - list_add(&cdev->list, &sdev->ipc_client_list); + list_add(¢ry->list, &sdev->ipc_client_list); mutex_unlock(&sdev->ipc_client_mutex); return 0; @@ -255,7 +275,7 @@ err_dev_init: kfree(cdev->auxdev.dev.platform_data); err_dev_add_data: - kfree(cdev); + kfree(centry); return ret; } @@ -263,7 +283,7 @@ EXPORT_SYMBOL_NS_GPL(sof_client_dev_register, "SND_SOC_SOF_CLIENT"); void sof_client_dev_unregister(struct snd_sof_dev *sdev, const char *name, u32 id) { - struct sof_client_dev *cdev; + struct sof_client_dev_entry *centry; mutex_lock(&sdev->ipc_client_mutex); @@ -271,9 +291,11 @@ void sof_client_dev_unregister(struct snd_sof_dev *sdev, const char *name, u32 i * sof_client_auxdev_release() will be invoked to free up memory * allocations through put_device() */ - list_for_each_entry(cdev, &sdev->ipc_client_list, list) { + list_for_each_entry(centry, &sdev->ipc_client_list, list) { + struct sof_client_dev *cdev = ¢ry->client_dev; + if (!strcmp(cdev->auxdev.name, name) && cdev->auxdev.id == id) { - list_del(&cdev->list); + list_del(¢ry->list); auxiliary_device_delete(&cdev->auxdev); auxiliary_device_uninit(&cdev->auxdev); break; @@ -287,15 +309,17 @@ EXPORT_SYMBOL_NS_GPL(sof_client_dev_unregister, "SND_SOC_SOF_CLIENT"); int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg, void *reply_data, size_t reply_bytes) { - if (cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_3) { + struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); + + if (sdev->pdata->ipc_type == SOF_IPC_TYPE_3) { struct sof_ipc_cmd_hdr *hdr = ipc_msg; - return sof_ipc_tx_message(cdev->sdev->ipc, ipc_msg, hdr->size, + return sof_ipc_tx_message(sdev->ipc, ipc_msg, hdr->size, reply_data, reply_bytes); - } else if (cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { + } else if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { struct sof_ipc4_msg *msg = ipc_msg; - return sof_ipc_tx_message(cdev->sdev->ipc, ipc_msg, msg->data_size, + return sof_ipc_tx_message(sdev->ipc, ipc_msg, msg->data_size, reply_data, reply_bytes); } @@ -305,16 +329,18 @@ EXPORT_SYMBOL_NS_GPL(sof_client_ipc_tx_message, "SND_SOC_SOF_CLIENT"); int sof_client_ipc_rx_message(struct sof_client_dev *cdev, void *ipc_msg, void *msg_buf) { + struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); + if (IS_ENABLED(CONFIG_SND_SOC_SOF_IPC3) && - cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_3) { + sdev->pdata->ipc_type == SOF_IPC_TYPE_3) { struct sof_ipc_cmd_hdr *hdr = ipc_msg; if (hdr->size < sizeof(hdr)) { - dev_err(cdev->sdev->dev, "The received message size is invalid\n"); + dev_err(sdev->dev, "The received message size is invalid\n"); return -EINVAL; } - sof_ipc3_do_rx_work(cdev->sdev, ipc_msg, msg_buf); + sof_ipc3_do_rx_work(sdev, ipc_msg, msg_buf); return 0; } @@ -325,16 +351,17 @@ EXPORT_SYMBOL_NS_GPL(sof_client_ipc_rx_message, "SND_SOC_SOF_CLIENT"); int sof_client_ipc_set_get_data(struct sof_client_dev *cdev, void *ipc_msg, bool set) { - if (cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_3) { + struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); + + if (sdev->pdata->ipc_type == SOF_IPC_TYPE_3) { struct sof_ipc_cmd_hdr *hdr = ipc_msg; - return sof_ipc_set_get_data(cdev->sdev->ipc, ipc_msg, hdr->size, - set); - } else if (cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { + return sof_ipc_set_get_data(sdev->ipc, ipc_msg, hdr->size, set); + } else if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { struct sof_ipc4_msg *msg = ipc_msg; - return sof_ipc_set_get_data(cdev->sdev->ipc, ipc_msg, - msg->data_size, set); + return sof_ipc_set_get_data(sdev->ipc, ipc_msg, msg->data_size, + set); } return -EINVAL; @@ -344,7 +371,7 @@ EXPORT_SYMBOL_NS_GPL(sof_client_ipc_set_get_data, "SND_SOC_SOF_CLIENT"); #ifdef CONFIG_SND_SOC_SOF_IPC4 struct sof_ipc4_fw_module *sof_client_ipc4_find_module(struct sof_client_dev *c, const guid_t *uuid) { - struct snd_sof_dev *sdev = c->sdev; + struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(c); if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) return sof_ipc4_find_module_by_uuid(sdev, uuid); @@ -353,16 +380,31 @@ struct sof_ipc4_fw_module *sof_client_ipc4_find_module(struct sof_client_dev *c, return NULL; } EXPORT_SYMBOL_NS_GPL(sof_client_ipc4_find_module, "SND_SOC_SOF_CLIENT"); + +struct snd_sof_widget *sof_client_ipc4_find_swidget_by_id(struct sof_client_dev *cdev, + u32 module_id, int instance_id) +{ + struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); + + if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) + return sof_ipc4_find_swidget_by_ids(sdev, module_id, instance_id); + dev_err(sdev->dev, "Only supported with IPC4\n"); + + return NULL; +} +EXPORT_SYMBOL_NS_GPL(sof_client_ipc4_find_swidget_by_id, "SND_SOC_SOF_CLIENT"); #endif int sof_suspend_clients(struct snd_sof_dev *sdev, pm_message_t state) { const struct auxiliary_driver *adrv; - struct sof_client_dev *cdev; + struct sof_client_dev_entry *centry; mutex_lock(&sdev->ipc_client_mutex); - list_for_each_entry(cdev, &sdev->ipc_client_list, list) { + list_for_each_entry(centry, &sdev->ipc_client_list, list) { + struct sof_client_dev *cdev = ¢ry->client_dev; + /* Skip devices without loaded driver */ if (!cdev->auxdev.dev.driver) continue; @@ -381,11 +423,13 @@ EXPORT_SYMBOL_NS_GPL(sof_suspend_clients, "SND_SOC_SOF_CLIENT"); int sof_resume_clients(struct snd_sof_dev *sdev) { const struct auxiliary_driver *adrv; - struct sof_client_dev *cdev; + struct sof_client_dev_entry *centry; mutex_lock(&sdev->ipc_client_mutex); - list_for_each_entry(cdev, &sdev->ipc_client_list, list) { + list_for_each_entry(centry, &sdev->ipc_client_list, list) { + struct sof_client_dev *cdev = ¢ry->client_dev; + /* Skip devices without loaded driver */ if (!cdev->auxdev.dev.driver) continue; @@ -403,14 +447,18 @@ EXPORT_SYMBOL_NS_GPL(sof_resume_clients, "SND_SOC_SOF_CLIENT"); struct dentry *sof_client_get_debugfs_root(struct sof_client_dev *cdev) { - return cdev->sdev->debugfs_root; + struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); + + return sdev->debugfs_root; } EXPORT_SYMBOL_NS_GPL(sof_client_get_debugfs_root, "SND_SOC_SOF_CLIENT"); /* DMA buffer allocation in client drivers must use the core SOF device */ struct device *sof_client_get_dma_dev(struct sof_client_dev *cdev) { - return cdev->sdev->dev; + struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); + + return sdev->dev; } EXPORT_SYMBOL_NS_GPL(sof_client_get_dma_dev, "SND_SOC_SOF_CLIENT"); @@ -498,10 +546,10 @@ int sof_client_register_ipc_rx_handler(struct sof_client_dev *cdev, if (!callback) return -EINVAL; - if (cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_3) { + if (sdev->pdata->ipc_type == SOF_IPC_TYPE_3) { if (!(ipc_msg_type & SOF_GLB_TYPE_MASK)) return -EINVAL; - } else if (cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { + } else if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { if (!(ipc_msg_type & SOF_IPC4_NOTIFICATION_TYPE_MASK)) return -EINVAL; } else { @@ -611,3 +659,11 @@ enum sof_fw_state sof_client_get_fw_state(struct sof_client_dev *cdev) return sdev->fw_state; } EXPORT_SYMBOL_NS_GPL(sof_client_get_fw_state, "SND_SOC_SOF_CLIENT"); + +struct snd_sof_dev *sof_client_dev_to_sof_dev(struct sof_client_dev *cdev) +{ + struct sof_client_dev_entry *centry = cdev_to_centry(cdev); + + return centry->sdev; +} +EXPORT_SYMBOL_NS_GPL(sof_client_dev_to_sof_dev, "SND_SOC_SOF_CLIENT"); diff --git a/sound/soc/sof/sof-client.h b/sound/soc/sof/sof-client.h index b6ccc2cd69e5..1a9015e38474 100644 --- a/sound/soc/sof/sof-client.h +++ b/sound/soc/sof/sof-client.h @@ -18,19 +18,13 @@ struct sof_ipc4_fw_module; /** * struct sof_client_dev - SOF client device * @auxdev: auxiliary device - * @sdev: pointer to SOF core device struct - * @list: item in SOF core client dev list * @data: device specific data */ struct sof_client_dev { struct auxiliary_device auxdev; - struct snd_sof_dev *sdev; - struct list_head list; void *data; }; -#define sof_client_dev_to_sof_dev(cdev) ((cdev)->sdev) - #define auxiliary_dev_to_sof_client_dev(auxiliary_dev) \ container_of(auxiliary_dev, struct sof_client_dev, auxdev) @@ -47,6 +41,8 @@ int sof_client_ipc_set_get_data(struct sof_client_dev *cdev, void *ipc_msg, bool set); struct sof_ipc4_fw_module *sof_client_ipc4_find_module(struct sof_client_dev *c, const guid_t *u); +struct snd_sof_widget *sof_client_ipc4_find_swidget_by_id(struct sof_client_dev *cdev, + u32 module_id, int instance_id); struct dentry *sof_client_get_debugfs_root(struct sof_client_dev *cdev); struct device *sof_client_get_dma_dev(struct sof_client_dev *cdev); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index abbb5ee7e08c..0f624d8cde20 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -838,7 +838,11 @@ int sof_stream_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream); /* SOF client support */ +struct sof_client_dev; + #if IS_ENABLED(CONFIG_SND_SOC_SOF_CLIENT) +struct snd_sof_dev *sof_client_dev_to_sof_dev(struct sof_client_dev *cdev); + int sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, u32 id, const void *data, size_t size); void sof_client_dev_unregister(struct snd_sof_dev *sdev, const char *name, u32 id); @@ -849,6 +853,11 @@ void sof_client_fw_state_dispatcher(struct snd_sof_dev *sdev); int sof_suspend_clients(struct snd_sof_dev *sdev, pm_message_t state); int sof_resume_clients(struct snd_sof_dev *sdev); #else /* CONFIG_SND_SOC_SOF_CLIENT */ +static inline struct snd_sof_dev * +sof_client_dev_to_sof_dev(struct sof_client_dev *cdev) { + return NULL; +} + static inline int sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, u32 id, const void *data, size_t size) { diff --git a/sound/soc/sprd/sprd-pcm-compress.c b/sound/soc/sprd/sprd-pcm-compress.c index 57bd1a0728ac..4b6ebfa5b033 100644 --- a/sound/soc/sprd/sprd-pcm-compress.c +++ b/sound/soc/sprd/sprd-pcm-compress.c @@ -85,9 +85,9 @@ struct sprd_compr_stream { int info_size; /* Data size copied to IRAM buffer */ - int copied_total; + u64 copied_total; /* Total received data size from userspace */ - int received_total; + u64 received_total; /* Stage 0 IRAM buffer received data size */ int received_stage0; /* Stage 1 DDR buffer received data size */ @@ -513,7 +513,7 @@ static int sprd_platform_compr_trigger(struct snd_soc_component *component, static int sprd_platform_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_compr_runtime *runtime = cstream->runtime; struct sprd_compr_stream *stream = runtime->private_data; diff --git a/sound/soc/sprd/sprd-pcm-dma.h b/sound/soc/sprd/sprd-pcm-dma.h index be5e385f5e42..c5935a1367e6 100644 --- a/sound/soc/sprd/sprd-pcm-dma.h +++ b/sound/soc/sprd/sprd-pcm-dma.h @@ -19,7 +19,7 @@ struct sprd_compr_playinfo { int total_time; int current_time; int total_data_length; - int current_data_offset; + u64 current_data_offset; }; struct sprd_compr_params { @@ -46,7 +46,7 @@ struct sprd_compr_ops { int (*stop)(int str_id); int (*pause)(int str_id); int (*pause_release)(int str_id); - int (*drain)(int received_total); + int (*drain)(u64 received_total); int (*set_params)(int str_id, struct sprd_compr_params *params); }; diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 463a2b7d023b..0ae1eae2a59e 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -672,6 +672,14 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai, struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); int ret; + /* + * The mclk rate is determined at runtime from the audio stream rate. + * Skip calls to the set_sysclk callback that are not relevant during the + * initialization phase. + */ + if (!snd_soc_card_is_instantiated(cpu_dai->component->card)) + return 0; + if (dir == SND_SOC_CLOCK_OUT && sai->sai_mclk) { ret = stm32_sai_sub_reg_up(sai, STM_SAI_CR1_REGX, SAI_XCR1_NODIV, diff --git a/sound/soc/uniphier/aio-compress.c b/sound/soc/uniphier/aio-compress.c index 4a19d4908ffd..b18af98a552b 100644 --- a/sound/soc/uniphier/aio-compress.c +++ b/sound/soc/uniphier/aio-compress.c @@ -249,7 +249,7 @@ static int uniphier_aio_compr_trigger(struct snd_soc_component *component, static int uniphier_aio_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_compr_runtime *runtime = cstream->runtime; diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index e73d3b262f57..da04ed5cbac4 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -346,34 +346,25 @@ static struct snd_amd7930 *amd7930_list; /* Idle the AMD7930 chip. The amd->lock is not held. */ static __inline__ void amd7930_idle(struct snd_amd7930 *amd) { - unsigned long flags; - - spin_lock_irqsave(&amd->lock, flags); + guard(spinlock_irqsave)(&amd->lock); sbus_writeb(AMR_INIT, amd->regs + AMD7930_CR); sbus_writeb(0, amd->regs + AMD7930_DR); - spin_unlock_irqrestore(&amd->lock, flags); } /* Enable chip interrupts. The amd->lock is not held. */ static __inline__ void amd7930_enable_ints(struct snd_amd7930 *amd) { - unsigned long flags; - - spin_lock_irqsave(&amd->lock, flags); + guard(spinlock_irqsave)(&amd->lock); sbus_writeb(AMR_INIT, amd->regs + AMD7930_CR); sbus_writeb(AM_INIT_ACTIVE, amd->regs + AMD7930_DR); - spin_unlock_irqrestore(&amd->lock, flags); } /* Disable chip interrupts. The amd->lock is not held. */ static __inline__ void amd7930_disable_ints(struct snd_amd7930 *amd) { - unsigned long flags; - - spin_lock_irqsave(&amd->lock, flags); + guard(spinlock_irqsave)(&amd->lock); sbus_writeb(AMR_INIT, amd->regs + AMD7930_CR); sbus_writeb(AM_INIT_ACTIVE | AM_INIT_DISABLE_INTS, amd->regs + AMD7930_DR); - spin_unlock_irqrestore(&amd->lock, flags); } /* Commit amd7930_map settings to the hardware. @@ -497,34 +488,33 @@ static irqreturn_t snd_amd7930_interrupt(int irq, void *dev_id) unsigned int elapsed; u8 ir; - spin_lock(&amd->lock); - - elapsed = 0; - - ir = sbus_readb(amd->regs + AMD7930_IR); - if (ir & AMR_IR_BBUF) { - u8 byte; - - if (amd->flags & AMD7930_FLAG_PLAYBACK) { - if (amd->p_left > 0) { - byte = *(amd->p_cur++); - amd->p_left--; - sbus_writeb(byte, amd->regs + AMD7930_BBTB); - if (amd->p_left == 0) - elapsed |= AMD7930_FLAG_PLAYBACK; - } else - sbus_writeb(0, amd->regs + AMD7930_BBTB); - } else if (amd->flags & AMD7930_FLAG_CAPTURE) { - byte = sbus_readb(amd->regs + AMD7930_BBRB); - if (amd->c_left > 0) { - *(amd->c_cur++) = byte; - amd->c_left--; - if (amd->c_left == 0) - elapsed |= AMD7930_FLAG_CAPTURE; + scoped_guard(spinlock, &amd->lock) { + elapsed = 0; + + ir = sbus_readb(amd->regs + AMD7930_IR); + if (ir & AMR_IR_BBUF) { + u8 byte; + + if (amd->flags & AMD7930_FLAG_PLAYBACK) { + if (amd->p_left > 0) { + byte = *(amd->p_cur++); + amd->p_left--; + sbus_writeb(byte, amd->regs + AMD7930_BBTB); + if (amd->p_left == 0) + elapsed |= AMD7930_FLAG_PLAYBACK; + } else + sbus_writeb(0, amd->regs + AMD7930_BBTB); + } else if (amd->flags & AMD7930_FLAG_CAPTURE) { + byte = sbus_readb(amd->regs + AMD7930_BBRB); + if (amd->c_left > 0) { + *(amd->c_cur++) = byte; + amd->c_left--; + if (amd->c_left == 0) + elapsed |= AMD7930_FLAG_CAPTURE; + } } } } - spin_unlock(&amd->lock); if (elapsed & AMD7930_FLAG_PLAYBACK) snd_pcm_period_elapsed(amd->playback_substream); @@ -536,10 +526,9 @@ static irqreturn_t snd_amd7930_interrupt(int irq, void *dev_id) static int snd_amd7930_trigger(struct snd_amd7930 *amd, unsigned int flag, int cmd) { - unsigned long flags; int result = 0; - spin_lock_irqsave(&amd->lock, flags); + guard(spinlock_irqsave)(&amd->lock); if (cmd == SNDRV_PCM_TRIGGER_START) { if (!(amd->flags & flag)) { amd->flags |= flag; @@ -559,7 +548,6 @@ static int snd_amd7930_trigger(struct snd_amd7930 *amd, unsigned int flag, int c } else { result = -EINVAL; } - spin_unlock_irqrestore(&amd->lock, flags); return result; } @@ -583,10 +571,9 @@ static int snd_amd7930_playback_prepare(struct snd_pcm_substream *substream) struct snd_amd7930 *amd = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned long flags; u8 new_mmr1; - spin_lock_irqsave(&amd->lock, flags); + guard(spinlock_irqsave)(&amd->lock); amd->flags |= AMD7930_FLAG_PLAYBACK; @@ -605,8 +592,6 @@ static int snd_amd7930_playback_prepare(struct snd_pcm_substream *substream) __amd7930_update_map(amd); } - spin_unlock_irqrestore(&amd->lock, flags); - return 0; } @@ -615,10 +600,9 @@ static int snd_amd7930_capture_prepare(struct snd_pcm_substream *substream) struct snd_amd7930 *amd = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned long flags; u8 new_mmr1; - spin_lock_irqsave(&amd->lock, flags); + guard(spinlock_irqsave)(&amd->lock); amd->flags |= AMD7930_FLAG_CAPTURE; @@ -637,8 +621,6 @@ static int snd_amd7930_capture_prepare(struct snd_pcm_substream *substream) __amd7930_update_map(amd); } - spin_unlock_irqrestore(&amd->lock, flags); - return 0; } @@ -805,7 +787,6 @@ static int snd_amd7930_get_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { struct snd_amd7930 *amd = snd_kcontrol_chip(kctl); - unsigned long flags; int type = kctl->private_value; int *swval, change; @@ -822,7 +803,7 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem break; } - spin_lock_irqsave(&amd->lock, flags); + guard(spinlock_irqsave)(&amd->lock); if (*swval != ucontrol->value.integer.value[0]) { *swval = ucontrol->value.integer.value[0] & 0xff; @@ -831,8 +812,6 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem } else change = 0; - spin_unlock_irqrestore(&amd->lock, flags); - return change; } @@ -921,7 +900,6 @@ static int snd_amd7930_create(struct snd_card *card, struct snd_amd7930 **ramd) { struct snd_amd7930 *amd; - unsigned long flags; int err; *ramd = NULL; @@ -955,25 +933,23 @@ static int snd_amd7930_create(struct snd_card *card, amd7930_enable_ints(amd); - spin_lock_irqsave(&amd->lock, flags); - - amd->rgain = 128; - amd->pgain = 200; - amd->mgain = 0; - - memset(&amd->map, 0, sizeof(amd->map)); - amd->map.mmr1 = (AM_MAP_MMR1_GX | AM_MAP_MMR1_GER | - AM_MAP_MMR1_GR | AM_MAP_MMR1_STG); - amd->map.mmr2 = (AM_MAP_MMR2_LS | AM_MAP_MMR2_AINB); + scoped_guard(spinlock_irqsave, &amd->lock) { + amd->rgain = 128; + amd->pgain = 200; + amd->mgain = 0; - __amd7930_update_map(amd); + memset(&amd->map, 0, sizeof(amd->map)); + amd->map.mmr1 = (AM_MAP_MMR1_GX | AM_MAP_MMR1_GER | + AM_MAP_MMR1_GR | AM_MAP_MMR1_STG); + amd->map.mmr2 = (AM_MAP_MMR2_LS | AM_MAP_MMR2_AINB); - /* Always MUX audio (Ba) to channel Bb. */ - sbus_writeb(AMR_MUX_MCR1, amd->regs + AMD7930_CR); - sbus_writeb(AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bb << 4), - amd->regs + AMD7930_DR); + __amd7930_update_map(amd); - spin_unlock_irqrestore(&amd->lock, flags); + /* Always MUX audio (Ba) to channel Bb. */ + sbus_writeb(AMR_MUX_MCR1, amd->regs + AMD7930_CR); + sbus_writeb(AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bb << 4), + amd->regs + AMD7930_DR); + } err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, amd, &snd_amd7930_dev_ops); diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 1a1fe3ceb76c..d9e5cca94c73 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -357,10 +357,9 @@ static void snd_cs4231_busy_wait(struct snd_cs4231 *chip) static void snd_cs4231_mce_up(struct snd_cs4231 *chip) { - unsigned long flags; int timeout; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); snd_cs4231_ready(chip); #ifdef CONFIG_SND_DEBUG if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) @@ -376,7 +375,6 @@ static void snd_cs4231_mce_up(struct snd_cs4231 *chip) if (!(timeout & CS4231_MCE)) __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231U(chip, REGSEL)); - spin_unlock_irqrestore(&chip->lock, flags); } static void snd_cs4231_mce_down(struct snd_cs4231 *chip) @@ -486,7 +484,6 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream, int cmd) { unsigned int what = 0; struct snd_pcm_substream *s; - unsigned long flags; snd_pcm_group_for_each_entry(s, substream) { if (s == chip->playback_substream) { @@ -498,7 +495,7 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream, int cmd) } } - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); if (cmd == SNDRV_PCM_TRIGGER_START) { cs4231_dma_trigger(substream, what, 1); chip->image[CS4231_IFACE_CTRL] |= what; @@ -508,7 +505,6 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream, int cmd) } snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); - spin_unlock_irqrestore(&chip->lock, flags); break; } default: @@ -564,14 +560,11 @@ static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, int format, static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute) { - unsigned long flags; - mute = mute ? 1 : 0; - spin_lock_irqsave(&chip->lock, flags); - if (chip->calibrate_mute == mute) { - spin_unlock_irqrestore(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); + if (chip->calibrate_mute == mute) return; - } + if (!mute) { snd_cs4231_dout(chip, CS4231_LEFT_INPUT, chip->image[CS4231_LEFT_INPUT]); @@ -599,31 +592,27 @@ static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute) snd_cs4231_dout(chip, CS4231_MONO_CTRL, mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]); chip->calibrate_mute = mute; - spin_unlock_irqrestore(&chip->lock, flags); } static void snd_cs4231_playback_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, unsigned char pdfr) { - unsigned long flags; - - mutex_lock(&chip->mce_mutex); + guard(mutex)(&chip->mce_mutex); snd_cs4231_calibrate_mute(chip, 1); snd_cs4231_mce_up(chip); - spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, - (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) ? - (pdfr & 0xf0) | (chip->image[CS4231_REC_FORMAT] & 0x0f) : - pdfr); - spin_unlock_irqrestore(&chip->lock, flags); + scoped_guard(spinlock_irqsave, &chip->lock) { + snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, + (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) ? + (pdfr & 0xf0) | (chip->image[CS4231_REC_FORMAT] & 0x0f) : + pdfr); + } snd_cs4231_mce_down(chip); snd_cs4231_calibrate_mute(chip, 0); - mutex_unlock(&chip->mce_mutex); } static void snd_cs4231_capture_format(struct snd_cs4231 *chip, @@ -632,7 +621,7 @@ static void snd_cs4231_capture_format(struct snd_cs4231 *chip, { unsigned long flags; - mutex_lock(&chip->mce_mutex); + guard(mutex)(&chip->mce_mutex); snd_cs4231_calibrate_mute(chip, 1); snd_cs4231_mce_up(chip); @@ -653,7 +642,6 @@ static void snd_cs4231_capture_format(struct snd_cs4231 *chip, snd_cs4231_mce_down(chip); snd_cs4231_calibrate_mute(chip, 0); - mutex_unlock(&chip->mce_mutex); } /* @@ -669,11 +657,10 @@ static unsigned long snd_cs4231_timer_resolution(struct snd_timer *timer) static int snd_cs4231_timer_start(struct snd_timer *timer) { - unsigned long flags; unsigned int ticks; struct snd_cs4231 *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); ticks = timer->sticks; if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 || (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] || @@ -688,44 +675,39 @@ static int snd_cs4231_timer_start(struct snd_timer *timer) chip->image[CS4231_ALT_FEATURE_1] | CS4231_TIMER_ENABLE); } - spin_unlock_irqrestore(&chip->lock, flags); return 0; } static int snd_cs4231_timer_stop(struct snd_timer *timer) { - unsigned long flags; struct snd_cs4231 *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE; snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); - spin_unlock_irqrestore(&chip->lock, flags); return 0; } static void snd_cs4231_init(struct snd_cs4231 *chip) { - unsigned long flags; - snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE pr_debug("init: (1)\n"); #endif snd_cs4231_mce_up(chip); - spin_lock_irqsave(&chip->lock, flags); - chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | - CS4231_PLAYBACK_PIO | - CS4231_RECORD_ENABLE | - CS4231_RECORD_PIO | - CS4231_CALIB_MODE); - chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB; - snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); - spin_unlock_irqrestore(&chip->lock, flags); + scoped_guard(spinlock_irqsave, &chip->lock) { + chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | + CS4231_PLAYBACK_PIO | + CS4231_RECORD_ENABLE | + CS4231_RECORD_PIO | + CS4231_CALIB_MODE); + chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB; + snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); + } snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE @@ -733,10 +715,10 @@ static void snd_cs4231_init(struct snd_cs4231 *chip) #endif snd_cs4231_mce_up(chip); - spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1]); - spin_unlock_irqrestore(&chip->lock, flags); + scoped_guard(spinlock_irqsave, &chip->lock) { + snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, + chip->image[CS4231_ALT_FEATURE_1]); + } snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE @@ -744,16 +726,16 @@ static void snd_cs4231_init(struct snd_cs4231 *chip) chip->image[CS4231_ALT_FEATURE_1]); #endif - spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, - chip->image[CS4231_ALT_FEATURE_2]); - spin_unlock_irqrestore(&chip->lock, flags); + scoped_guard(spinlock_irqsave, &chip->lock) { + snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, + chip->image[CS4231_ALT_FEATURE_2]); + } snd_cs4231_mce_up(chip); - spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, - chip->image[CS4231_PLAYBK_FORMAT]); - spin_unlock_irqrestore(&chip->lock, flags); + scoped_guard(spinlock_irqsave, &chip->lock) { + snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, + chip->image[CS4231_PLAYBK_FORMAT]); + } snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE @@ -761,9 +743,9 @@ static void snd_cs4231_init(struct snd_cs4231 *chip) #endif snd_cs4231_mce_up(chip); - spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT]); - spin_unlock_irqrestore(&chip->lock, flags); + scoped_guard(spinlock_irqsave, &chip->lock) { + snd_cs4231_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT]); + } snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE @@ -773,20 +755,15 @@ static void snd_cs4231_init(struct snd_cs4231 *chip) static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode) { - unsigned long flags; - - mutex_lock(&chip->open_mutex); - if ((chip->mode & mode)) { - mutex_unlock(&chip->open_mutex); + guard(mutex)(&chip->open_mutex); + if ((chip->mode & mode)) return -EAGAIN; - } if (chip->mode & CS4231_MODE_OPEN) { chip->mode |= mode; - mutex_unlock(&chip->open_mutex); return 0; } /* ok. now enable and ack CODEC IRQ */ - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ | CS4231_RECORD_IRQ | CS4231_TIMER_IRQ); @@ -799,10 +776,7 @@ static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode) CS4231_TIMER_IRQ); snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); - spin_unlock_irqrestore(&chip->lock, flags); - chip->mode = mode; - mutex_unlock(&chip->open_mutex); return 0; } @@ -810,12 +784,10 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) { unsigned long flags; - mutex_lock(&chip->open_mutex); + guard(mutex)(&chip->open_mutex); chip->mode &= ~mode; - if (chip->mode & CS4231_MODE_OPEN) { - mutex_unlock(&chip->open_mutex); + if (chip->mode & CS4231_MODE_OPEN) return; - } snd_cs4231_calibrate_mute(chip, 1); /* disable IRQ */ @@ -851,7 +823,6 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) snd_cs4231_calibrate_mute(chip, 0); chip->mode = 0; - mutex_unlock(&chip->open_mutex); } /* @@ -905,25 +876,18 @@ static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream) { struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; - int ret = 0; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO); - if (WARN_ON(runtime->period_size > 0xffff + 1)) { - ret = -EINVAL; - goto out; - } + if (WARN_ON(runtime->period_size > 0xffff + 1)) + return -EINVAL; chip->p_periods_sent = 0; -out: - spin_unlock_irqrestore(&chip->lock, flags); - - return ret; + return 0; } static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream, @@ -943,27 +907,23 @@ static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream, static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream) { struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); - unsigned long flags; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); chip->c_periods_sent = 0; - spin_unlock_irqrestore(&chip->lock, flags); return 0; } static void snd_cs4231_overrange(struct snd_cs4231 *chip) { - unsigned long flags; unsigned char res; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); res = snd_cs4231_in(chip, CS4231_TEST_INIT); - spin_unlock_irqrestore(&chip->lock, flags); /* detect overrange only above 0dB; may be user selectable? */ if (res & (0x08 | 0x02)) @@ -1022,7 +982,6 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer( static int snd_cs4231_probe(struct snd_cs4231 *chip) { - unsigned long flags; int i; int id = 0; int vers = 0; @@ -1033,11 +992,10 @@ static int snd_cs4231_probe(struct snd_cs4231 *chip) if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) msleep(2); else { - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); snd_cs4231_out(chip, CS4231_MISC_INFO, CS4231_MODE2); id = snd_cs4231_in(chip, CS4231_MISC_INFO) & 0x0f; vers = snd_cs4231_in(chip, CS4231_VERSION); - spin_unlock_irqrestore(&chip->lock, flags); if (id == 0x0a) break; /* this is valid value */ } @@ -1047,14 +1005,12 @@ static int snd_cs4231_probe(struct snd_cs4231 *chip) if (id != 0x0a) return -ENODEV; /* no valid device found */ - spin_lock_irqsave(&chip->lock, flags); - - /* clear any pendings IRQ */ - __cs4231_readb(chip, CS4231U(chip, STATUS)); - __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); - mb(); - - spin_unlock_irqrestore(&chip->lock, flags); + scoped_guard(spinlock_irqsave, &chip->lock) { + /* clear any pendings IRQ */ + __cs4231_readb(chip, CS4231U(chip, STATUS)); + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); + mb(); + } chip->image[CS4231_MISC_INFO] = CS4231_MODE2; chip->image[CS4231_IFACE_CTRL] = @@ -1068,12 +1024,10 @@ static int snd_cs4231_probe(struct snd_cs4231 *chip) snd_cs4231_mce_down(chip); - spin_lock_irqsave(&chip->lock, flags); - - for (i = 0; i < 32; i++) /* ok.. fill all CS4231 registers */ - snd_cs4231_out(chip, i, *ptr++); - - spin_unlock_irqrestore(&chip->lock, flags); + scoped_guard(spinlock_irqsave, &chip->lock) { + for (i = 0; i < 32; i++) /* ok.. fill all CS4231 registers */ + snd_cs4231_out(chip, i, *ptr++); + } snd_cs4231_mce_up(chip); @@ -1282,14 +1236,12 @@ static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6; ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6; - spin_unlock_irqrestore(&chip->lock, flags); return 0; } @@ -1298,7 +1250,6 @@ static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; unsigned short left, right; int change; @@ -1308,7 +1259,7 @@ static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, left = ucontrol->value.enumerated.item[0] << 6; right = ucontrol->value.enumerated.item[1] << 6; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left; right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right; @@ -1317,8 +1268,6 @@ static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, snd_cs4231_out(chip, CS4231_LEFT_INPUT, left); snd_cs4231_out(chip, CS4231_RIGHT_INPUT, right); - spin_unlock_irqrestore(&chip->lock, flags); - return change; } @@ -1340,18 +1289,15 @@ static int snd_cs4231_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask; - spin_unlock_irqrestore(&chip->lock, flags); - if (invert) ucontrol->value.integer.value[0] = (mask - ucontrol->value.integer.value[0]); @@ -1363,7 +1309,6 @@ static int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; @@ -1376,14 +1321,12 @@ static int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, val = mask - val; val <<= shift; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); val = (chip->image[reg] & ~(mask << shift)) | val; change = val != chip->image[reg]; snd_cs4231_out(chip, reg, val); - spin_unlock_irqrestore(&chip->lock, flags); - return change; } @@ -1405,7 +1348,6 @@ static int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int shift_left = (kcontrol->private_value >> 16) & 0x07; @@ -1413,15 +1355,13 @@ static int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, int mask = (kcontrol->private_value >> 24) & 0xff; int invert = (kcontrol->private_value >> 22) & 1; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask; ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->lock, flags); - if (invert) { ucontrol->value.integer.value[0] = (mask - ucontrol->value.integer.value[0]); @@ -1436,7 +1376,6 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; int shift_left = (kcontrol->private_value >> 16) & 0x07; @@ -1455,7 +1394,7 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, val1 <<= shift_left; val2 <<= shift_right; - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; @@ -1464,8 +1403,6 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, snd_cs4231_out(chip, left_reg, val1); snd_cs4231_out(chip, right_reg, val2); - spin_unlock_irqrestore(&chip->lock, flags); - return change; } @@ -1610,7 +1547,6 @@ out_err: static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id) { - unsigned long flags; unsigned char status; u32 csr; struct snd_cs4231 *chip = dev_id; @@ -1647,9 +1583,8 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id) snd_cs4231_overrange(chip); /* ACK the CS4231 interrupt. */ - spin_lock_irqsave(&chip->lock, flags); + guard(spinlock_irqsave)(&chip->lock); snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); - spin_unlock_irqrestore(&chip->lock, flags); return IRQ_HANDLED; } @@ -1661,42 +1596,34 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id) static int sbus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len) { - unsigned long flags; u32 test, csr; - int err; struct sbus_dma_info *base = &dma_cont->sbus_info; if (len >= (1 << 24)) return -EINVAL; - spin_lock_irqsave(&base->lock, flags); + guard(spinlock_irqsave)(&base->lock); csr = sbus_readl(base->regs + APCCSR); - err = -EINVAL; test = APC_CDMA_READY; if (base->dir == APC_PLAY) test = APC_PDMA_READY; if (!(csr & test)) - goto out; - err = -EBUSY; + return -EINVAL; test = APC_XINT_CNVA; if (base->dir == APC_PLAY) test = APC_XINT_PNVA; if (!(csr & test)) - goto out; - err = 0; + return -EBUSY; sbus_writel(bus_addr, base->regs + base->dir + APCNVA); sbus_writel(len, base->regs + base->dir + APCNC); -out: - spin_unlock_irqrestore(&base->lock, flags); - return err; + return 0; } static void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d) { - unsigned long flags; u32 csr, test; struct sbus_dma_info *base = &dma_cont->sbus_info; - spin_lock_irqsave(&base->lock, flags); + guard(spinlock_irqsave)(&base->lock); csr = sbus_readl(base->regs + APCCSR); test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL | @@ -1706,16 +1633,14 @@ static void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d) APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL; csr |= test; sbus_writel(csr, base->regs + APCCSR); - spin_unlock_irqrestore(&base->lock, flags); } static void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on) { - unsigned long flags; u32 csr, shift; struct sbus_dma_info *base = &dma_cont->sbus_info; - spin_lock_irqsave(&base->lock, flags); + guard(spinlock_irqsave)(&base->lock); if (!on) { sbus_writel(0, base->regs + base->dir + APCNC); sbus_writel(0, base->regs + base->dir + APCNVA); @@ -1740,8 +1665,6 @@ static void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on) else csr &= ~(APC_CDMA_READY << shift); sbus_writel(csr, base->regs + APCCSR); - - spin_unlock_irqrestore(&base->lock, flags); } static unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont) diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 93cbe158009f..75f82a92ff44 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -758,40 +758,38 @@ static void dbri_initialize(struct snd_dbri *dbri) u32 dvma_addr = (u32)dbri->dma_dvma; s32 *cmd; u32 dma_addr; - unsigned long flags; int n; - spin_lock_irqsave(&dbri->lock, flags); - - dbri_reset(dbri); + scoped_guard(spinlock_irqsave, &dbri->lock) { + dbri_reset(dbri); - /* Initialize pipes */ - for (n = 0; n < DBRI_NO_PIPES; n++) - dbri->pipes[n].desc = dbri->pipes[n].first_desc = -1; + /* Initialize pipes */ + for (n = 0; n < DBRI_NO_PIPES; n++) + dbri->pipes[n].desc = dbri->pipes[n].first_desc = -1; - spin_lock_init(&dbri->cmdlock); - /* - * Initialize the interrupt ring buffer. - */ - dma_addr = dvma_addr + dbri_dma_off(intr, 0); - dbri->dma->intr[0] = dma_addr; - dbri->dbri_irqp = 1; - /* - * Set up the interrupt queue - */ - spin_lock(&dbri->cmdlock); - cmd = dbri->cmdptr = dbri->dma->cmd; - *(cmd++) = DBRI_CMD(D_IIQ, 0, 0); - *(cmd++) = dma_addr; - *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); - dbri->cmdptr = cmd; - *(cmd++) = DBRI_CMD(D_WAIT, 1, 0); - *(cmd++) = DBRI_CMD(D_WAIT, 1, 0); - dma_addr = dvma_addr + dbri_dma_off(cmd, 0); - sbus_writel(dma_addr, dbri->regs + REG8); - spin_unlock(&dbri->cmdlock); + spin_lock_init(&dbri->cmdlock); + /* + * Initialize the interrupt ring buffer. + */ + dma_addr = dvma_addr + dbri_dma_off(intr, 0); + dbri->dma->intr[0] = dma_addr; + dbri->dbri_irqp = 1; + /* + * Set up the interrupt queue + */ + scoped_guard(spinlock, &dbri->cmdlock) { + cmd = dbri->cmdptr = dbri->dma->cmd; + *(cmd++) = DBRI_CMD(D_IIQ, 0, 0); + *(cmd++) = dma_addr; + *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); + dbri->cmdptr = cmd; + *(cmd++) = DBRI_CMD(D_WAIT, 1, 0); + *(cmd++) = DBRI_CMD(D_WAIT, 1, 0); + dma_addr = dvma_addr + dbri_dma_off(cmd, 0); + sbus_writel(dma_addr, dbri->regs + REG8); + } + } - spin_unlock_irqrestore(&dbri->lock, flags); dbri_cmdwait(dbri); } @@ -1002,7 +1000,6 @@ static void unlink_time_slot(struct snd_dbri *dbri, int pipe, static void xmit_fixed(struct snd_dbri *dbri, int pipe, unsigned int data) { s32 *cmd; - unsigned long flags; if (pipe < 16 || pipe > DBRI_MAX_PIPE) { printk(KERN_ERR "DBRI: xmit_fixed: Illegal pipe number\n"); @@ -1037,9 +1034,10 @@ static void xmit_fixed(struct snd_dbri *dbri, int pipe, unsigned int data) *(cmd++) = data; *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); - spin_lock_irqsave(&dbri->lock, flags); - dbri_cmdsend(dbri, cmd, 3); - spin_unlock_irqrestore(&dbri->lock, flags); + scoped_guard(spinlock_irqsave, &dbri->lock) { + dbri_cmdsend(dbri, cmd, 3); + } + dbri_cmdwait(dbri); } @@ -1317,33 +1315,31 @@ to the DBRI via the CHI interface and few of the DBRI's PIO pins. */ static void cs4215_setup_pipes(struct snd_dbri *dbri) { - unsigned long flags; - - spin_lock_irqsave(&dbri->lock, flags); - /* - * Data mode: - * Pipe 4: Send timeslots 1-4 (audio data) - * Pipe 20: Send timeslots 5-8 (part of ctrl data) - * Pipe 6: Receive timeslots 1-4 (audio data) - * Pipe 21: Receive timeslots 6-7. We can only receive 20 bits via - * interrupt, and the rest of the data (slot 5 and 8) is - * not relevant for us (only for doublechecking). - * - * Control mode: - * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only) - * Pipe 18: Receive timeslot 1 (clb). - * Pipe 19: Receive timeslot 7 (version). - */ + scoped_guard(spinlock_irqsave, &dbri->lock) { + /* + * Data mode: + * Pipe 4: Send timeslots 1-4 (audio data) + * Pipe 20: Send timeslots 5-8 (part of ctrl data) + * Pipe 6: Receive timeslots 1-4 (audio data) + * Pipe 21: Receive timeslots 6-7. We can only receive 20 bits via + * interrupt, and the rest of the data (slot 5 and 8) is + * not relevant for us (only for doublechecking). + * + * Control mode: + * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only) + * Pipe 18: Receive timeslot 1 (clb). + * Pipe 19: Receive timeslot 7 (version). + */ - setup_pipe(dbri, 4, D_SDP_MEM | D_SDP_TO_SER | D_SDP_MSB); - setup_pipe(dbri, 20, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB); - setup_pipe(dbri, 6, D_SDP_MEM | D_SDP_FROM_SER | D_SDP_MSB); - setup_pipe(dbri, 21, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); + setup_pipe(dbri, 4, D_SDP_MEM | D_SDP_TO_SER | D_SDP_MSB); + setup_pipe(dbri, 20, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB); + setup_pipe(dbri, 6, D_SDP_MEM | D_SDP_FROM_SER | D_SDP_MSB); + setup_pipe(dbri, 21, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); - setup_pipe(dbri, 17, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB); - setup_pipe(dbri, 18, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); - setup_pipe(dbri, 19, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); - spin_unlock_irqrestore(&dbri->lock, flags); + setup_pipe(dbri, 17, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB); + setup_pipe(dbri, 18, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); + setup_pipe(dbri, 19, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); + } dbri_cmdwait(dbri); } @@ -1418,7 +1414,6 @@ static void cs4215_open(struct snd_dbri *dbri) { int data_width; u32 tmp; - unsigned long flags; dprintk(D_MM, "cs4215_open: %d channels, %d bits\n", dbri->mm.channels, dbri->mm.precision); @@ -1443,35 +1438,35 @@ static void cs4215_open(struct snd_dbri *dbri) * bits. The CS4215, it seems, observes TSIN (the delayed signal) * even if it's the CHI master. Don't ask me... */ - spin_lock_irqsave(&dbri->lock, flags); - tmp = sbus_readl(dbri->regs + REG0); - tmp &= ~(D_C); /* Disable CHI */ - sbus_writel(tmp, dbri->regs + REG0); + scoped_guard(spinlock_irqsave, &dbri->lock) { + tmp = sbus_readl(dbri->regs + REG0); + tmp &= ~(D_C); /* Disable CHI */ + sbus_writel(tmp, dbri->regs + REG0); - /* Switch CS4215 to data mode - set PIO3 to 1 */ - sbus_writel(D_ENPIO | D_PIO1 | D_PIO3 | - (dbri->mm.onboard ? D_PIO0 : D_PIO2), dbri->regs + REG2); + /* Switch CS4215 to data mode - set PIO3 to 1 */ + sbus_writel(D_ENPIO | D_PIO1 | D_PIO3 | + (dbri->mm.onboard ? D_PIO0 : D_PIO2), dbri->regs + REG2); - reset_chi(dbri, CHIslave, 128); + reset_chi(dbri, CHIslave, 128); - /* Note: this next doesn't work for 8-bit stereo, because the two - * channels would be on timeslots 1 and 3, with 2 and 4 idle. - * (See CS4215 datasheet Fig 15) - * - * DBRI non-contiguous mode would be required to make this work. - */ - data_width = dbri->mm.channels * dbri->mm.precision; + /* Note: this next doesn't work for 8-bit stereo, because the two + * channels would be on timeslots 1 and 3, with 2 and 4 idle. + * (See CS4215 datasheet Fig 15) + * + * DBRI non-contiguous mode would be required to make this work. + */ + data_width = dbri->mm.channels * dbri->mm.precision; - link_time_slot(dbri, 4, 16, 16, data_width, dbri->mm.offset); - link_time_slot(dbri, 20, 4, 16, 32, dbri->mm.offset + 32); - link_time_slot(dbri, 6, 16, 16, data_width, dbri->mm.offset); - link_time_slot(dbri, 21, 6, 16, 16, dbri->mm.offset + 40); + link_time_slot(dbri, 4, 16, 16, data_width, dbri->mm.offset); + link_time_slot(dbri, 20, 4, 16, 32, dbri->mm.offset + 32); + link_time_slot(dbri, 6, 16, 16, data_width, dbri->mm.offset); + link_time_slot(dbri, 21, 6, 16, 16, dbri->mm.offset + 40); - /* FIXME: enable CHI after _setdata? */ - tmp = sbus_readl(dbri->regs + REG0); - tmp |= D_C; /* Enable CHI */ - sbus_writel(tmp, dbri->regs + REG0); - spin_unlock_irqrestore(&dbri->lock, flags); + /* FIXME: enable CHI after _setdata? */ + tmp = sbus_readl(dbri->regs + REG0); + tmp |= D_C; /* Enable CHI */ + sbus_writel(tmp, dbri->regs + REG0); + } cs4215_setdata(dbri, 0); } @@ -1483,7 +1478,6 @@ static int cs4215_setctrl(struct snd_dbri *dbri) { int i, val; u32 tmp; - unsigned long flags; /* FIXME - let the CPU do something useful during these delays */ @@ -1520,34 +1514,34 @@ static int cs4215_setctrl(struct snd_dbri *dbri) * done in hardware by a TI 248 that delays the DBRI->4215 * frame sync signal by eight clock cycles. Anybody know why? */ - spin_lock_irqsave(&dbri->lock, flags); - tmp = sbus_readl(dbri->regs + REG0); - tmp &= ~D_C; /* Disable CHI */ - sbus_writel(tmp, dbri->regs + REG0); - - reset_chi(dbri, CHImaster, 128); - - /* - * Control mode: - * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only) - * Pipe 18: Receive timeslot 1 (clb). - * Pipe 19: Receive timeslot 7 (version). - */ + scoped_guard(spinlock_irqsave, &dbri->lock) { + tmp = sbus_readl(dbri->regs + REG0); + tmp &= ~D_C; /* Disable CHI */ + sbus_writel(tmp, dbri->regs + REG0); + + reset_chi(dbri, CHImaster, 128); + + /* + * Control mode: + * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only) + * Pipe 18: Receive timeslot 1 (clb). + * Pipe 19: Receive timeslot 7 (version). + */ - link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset); - link_time_slot(dbri, 18, 16, 16, 8, dbri->mm.offset); - link_time_slot(dbri, 19, 18, 16, 8, dbri->mm.offset + 48); - spin_unlock_irqrestore(&dbri->lock, flags); + link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset); + link_time_slot(dbri, 18, 16, 16, 8, dbri->mm.offset); + link_time_slot(dbri, 19, 18, 16, 8, dbri->mm.offset + 48); + } /* Wait for the chip to echo back CLB (Control Latch Bit) as zero */ dbri->mm.ctrl[0] &= ~CS4215_CLB; xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl); - spin_lock_irqsave(&dbri->lock, flags); - tmp = sbus_readl(dbri->regs + REG0); - tmp |= D_C; /* Enable CHI */ - sbus_writel(tmp, dbri->regs + REG0); - spin_unlock_irqrestore(&dbri->lock, flags); + scoped_guard(spinlock_irqsave, &dbri->lock) { + tmp = sbus_readl(dbri->regs + REG0); + tmp |= D_C; /* Enable CHI */ + sbus_writel(tmp, dbri->regs + REG0); + } for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) msleep_interruptible(1); @@ -1709,7 +1703,6 @@ static void xmit_descs(struct snd_dbri *dbri) struct dbri_streaminfo *info; u32 dvma_addr; s32 *cmd; - unsigned long flags; int first_td; if (dbri == NULL) @@ -1717,7 +1710,7 @@ static void xmit_descs(struct snd_dbri *dbri) dvma_addr = (u32)dbri->dma_dvma; info = &dbri->stream_info[DBRI_REC]; - spin_lock_irqsave(&dbri->lock, flags); + guard(spinlock_irqsave)(&dbri->lock); if (info->pipe >= 0) { first_td = dbri->pipes[info->pipe].first_desc; @@ -1760,8 +1753,6 @@ static void xmit_descs(struct snd_dbri *dbri) dbri->pipes[info->pipe].desc = first_td; } } - - spin_unlock_irqrestore(&dbri->lock, flags); } /* transmission_complete_intr() @@ -1932,7 +1923,7 @@ static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id) if (dbri == NULL) return IRQ_NONE; - spin_lock(&dbri->lock); + guard(spinlock)(&dbri->lock); /* * Read it, so the interrupt goes away. @@ -1977,8 +1968,6 @@ static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id) dbri_process_interrupt_buffer(dbri); - spin_unlock(&dbri->lock); - return IRQ_HANDLED; } @@ -2046,17 +2035,16 @@ static int snd_dbri_open(struct snd_pcm_substream *substream) struct snd_dbri *dbri = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream); - unsigned long flags; dprintk(D_USR, "open audio output.\n"); runtime->hw = snd_dbri_pcm_hw; - spin_lock_irqsave(&dbri->lock, flags); - info->substream = substream; - info->offset = 0; - info->dvma_buffer = 0; - info->pipe = -1; - spin_unlock_irqrestore(&dbri->lock, flags); + scoped_guard(spinlock_irqsave, &dbri->lock) { + info->substream = substream; + info->offset = 0; + info->dvma_buffer = 0; + info->pipe = -1; + } snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, snd_hw_rule_format, NULL, SNDRV_PCM_HW_PARAM_FORMAT, @@ -2160,7 +2148,7 @@ static int snd_dbri_prepare(struct snd_pcm_substream *substream) else info->pipe = 6; /* Receive pipe */ - spin_lock_irq(&dbri->lock); + guard(spinlock_irq)(&dbri->lock); info->offset = 0; /* Setup the all the transmit/receive descriptors to cover the @@ -2169,8 +2157,6 @@ static int snd_dbri_prepare(struct snd_pcm_substream *substream) ret = setup_descs(dbri, DBRI_STREAMNO(substream), snd_pcm_lib_period_bytes(substream)); - spin_unlock_irq(&dbri->lock); - dprintk(D_USR, "prepare audio output. %d bytes\n", info->size); return ret; } diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c index a0a7f90b6146..0c2394733dc4 100644 --- a/sound/spi/at73c213.c +++ b/sound/spi/at73c213.c @@ -273,9 +273,8 @@ static int snd_at73c213_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); - int retval = 0; - spin_lock(&chip->lock); + guard(spinlock)(&chip->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -288,13 +287,11 @@ static int snd_at73c213_pcm_trigger(struct snd_pcm_substream *substream, break; default: dev_dbg(&chip->spi->dev, "spurious command %x\n", cmd); - retval = -EINVAL; + return -EINVAL; break; } - spin_unlock(&chip->lock); - - return retval; + return 0; } static snd_pcm_uframes_t @@ -358,30 +355,29 @@ static irqreturn_t snd_at73c213_interrupt(int irq, void *dev_id) int next_period; int retval = IRQ_NONE; - spin_lock(&chip->lock); + scoped_guard(spinlock, &chip->lock) { + block_size = frames_to_bytes(runtime, runtime->period_size); + status = ssc_readl(chip->ssc->regs, IMR); - block_size = frames_to_bytes(runtime, runtime->period_size); - status = ssc_readl(chip->ssc->regs, IMR); - - if (status & SSC_BIT(IMR_ENDTX)) { - chip->period++; - if (chip->period == runtime->periods) - chip->period = 0; - next_period = chip->period + 1; - if (next_period == runtime->periods) - next_period = 0; - - offset = block_size * next_period; - - ssc_writel(chip->ssc->regs, PDC_TNPR, - (long)runtime->dma_addr + offset); - ssc_writel(chip->ssc->regs, PDC_TNCR, - runtime->period_size * runtime->channels); - retval = IRQ_HANDLED; - } + if (status & SSC_BIT(IMR_ENDTX)) { + chip->period++; + if (chip->period == runtime->periods) + chip->period = 0; + next_period = chip->period + 1; + if (next_period == runtime->periods) + next_period = 0; + + offset = block_size * next_period; - ssc_readl(chip->ssc->regs, IMR); - spin_unlock(&chip->lock); + ssc_writel(chip->ssc->regs, PDC_TNPR, + (long)runtime->dma_addr + offset); + ssc_writel(chip->ssc->regs, PDC_TNCR, + runtime->period_size * runtime->channels); + retval = IRQ_HANDLED; + } + + ssc_readl(chip->ssc->regs, IMR); + } if (status & SSC_BIT(IMR_ENDTX)) snd_pcm_period_elapsed(chip->substream); @@ -401,7 +397,7 @@ static int snd_at73c213_mono_get(struct snd_kcontrol *kcontrol, int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - mutex_lock(&chip->mixer_lock); + guard(mutex)(&chip->mixer_lock); ucontrol->value.integer.value[0] = (chip->reg_image[reg] >> shift) & mask; @@ -410,8 +406,6 @@ static int snd_at73c213_mono_get(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - mutex_unlock(&chip->mixer_lock); - return 0; } @@ -431,14 +425,12 @@ static int snd_at73c213_mono_put(struct snd_kcontrol *kcontrol, val = mask - val; val <<= shift; - mutex_lock(&chip->mixer_lock); + guard(mutex)(&chip->mixer_lock); val = (chip->reg_image[reg] & ~(mask << shift)) | val; change = val != chip->reg_image[reg]; retval = snd_at73c213_write_reg(chip, reg, val); - mutex_unlock(&chip->mixer_lock); - if (retval) return retval; @@ -473,7 +465,7 @@ static int snd_at73c213_stereo_get(struct snd_kcontrol *kcontrol, int mask = (kcontrol->private_value >> 24) & 0xff; int invert = (kcontrol->private_value >> 22) & 1; - mutex_lock(&chip->mixer_lock); + guard(mutex)(&chip->mixer_lock); ucontrol->value.integer.value[0] = (chip->reg_image[left_reg] >> shift_left) & mask; @@ -487,8 +479,6 @@ static int snd_at73c213_stereo_get(struct snd_kcontrol *kcontrol, mask - ucontrol->value.integer.value[1]; } - mutex_unlock(&chip->mixer_lock); - return 0; } @@ -514,29 +504,20 @@ static int snd_at73c213_stereo_put(struct snd_kcontrol *kcontrol, val1 <<= shift_left; val2 <<= shift_right; - mutex_lock(&chip->mixer_lock); + guard(mutex)(&chip->mixer_lock); val1 = (chip->reg_image[left_reg] & ~(mask << shift_left)) | val1; val2 = (chip->reg_image[right_reg] & ~(mask << shift_right)) | val2; change = val1 != chip->reg_image[left_reg] || val2 != chip->reg_image[right_reg]; retval = snd_at73c213_write_reg(chip, left_reg, val1); - if (retval) { - mutex_unlock(&chip->mixer_lock); - goto out; - } + if (retval) + return retval; retval = snd_at73c213_write_reg(chip, right_reg, val2); - if (retval) { - mutex_unlock(&chip->mixer_lock); - goto out; - } - - mutex_unlock(&chip->mixer_lock); + if (retval) + return retval; return change; - -out: - return retval; } #define snd_at73c213_mono_switch_info snd_ctl_boolean_mono_info @@ -549,7 +530,7 @@ static int snd_at73c213_mono_switch_get(struct snd_kcontrol *kcontrol, int shift = (kcontrol->private_value >> 8) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - mutex_lock(&chip->mixer_lock); + guard(mutex)(&chip->mixer_lock); ucontrol->value.integer.value[0] = (chip->reg_image[reg] >> shift) & 0x01; @@ -558,8 +539,6 @@ static int snd_at73c213_mono_switch_get(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] = 0x01 - ucontrol->value.integer.value[0]; - mutex_unlock(&chip->mixer_lock); - return 0; } @@ -583,15 +562,13 @@ static int snd_at73c213_mono_switch_put(struct snd_kcontrol *kcontrol, val = mask - val; val <<= shift; - mutex_lock(&chip->mixer_lock); + guard(mutex)(&chip->mixer_lock); val |= (chip->reg_image[reg] & ~(mask << shift)); change = val != chip->reg_image[reg]; retval = snd_at73c213_write_reg(chip, reg, val); - mutex_unlock(&chip->mixer_lock); - if (retval) return retval; diff --git a/sound/synth/emux/emux_effect.c b/sound/synth/emux/emux_effect.c index 3c7314f5fb19..bfe383fa90ba 100644 --- a/sound/synth/emux/emux_effect.c +++ b/sound/synth/emux/emux_effect.c @@ -168,7 +168,6 @@ snd_emux_send_effect(struct snd_emux_port *port, struct snd_midi_channel *chan, unsigned char *srcp, *origp; struct snd_emux *emu; struct snd_emux_effect_table *fx; - unsigned long flags; emu = port->emu; fx = chan->private; @@ -195,22 +194,22 @@ snd_emux_send_effect(struct snd_emux_port *port, struct snd_midi_channel *chan, offset++; #endif /* modify the register values */ - spin_lock_irqsave(&emu->voice_lock, flags); - for (i = 0; i < emu->max_voices; i++) { - struct snd_emux_voice *vp = &emu->voices[i]; - if (!STATE_IS_PLAYING(vp->state) || vp->chan != chan) - continue; - srcp = (unsigned char*)&vp->reg.parm + offset; - origp = (unsigned char*)&vp->zone->v.parm + offset; - if (parm_defs[i].type & PARM_IS_BYTE) { - *srcp = *origp; - effect_set_byte(srcp, chan, type); - } else { - *(unsigned short*)srcp = *(unsigned short*)origp; - effect_set_word((unsigned short*)srcp, chan, type); + scoped_guard(spinlock_irqsave, &emu->voice_lock) { + for (i = 0; i < emu->max_voices; i++) { + struct snd_emux_voice *vp = &emu->voices[i]; + if (!STATE_IS_PLAYING(vp->state) || vp->chan != chan) + continue; + srcp = (unsigned char *)&vp->reg.parm + offset; + origp = (unsigned char *)&vp->zone->v.parm + offset; + if (parm_defs[i].type & PARM_IS_BYTE) { + *srcp = *origp; + effect_set_byte(srcp, chan, type); + } else { + *(unsigned short *)srcp = *(unsigned short *)origp; + effect_set_word((unsigned short *)srcp, chan, type); + } } } - spin_unlock_irqrestore(&emu->voice_lock, flags); /* activate them */ snd_emux_update_channel(port, chan, parm_defs[type].update); diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c index 820351f52551..16d6c9a1e24f 100644 --- a/sound/synth/emux/emux_proc.c +++ b/sound/synth/emux/emux_proc.c @@ -19,7 +19,7 @@ snd_emux_proc_info_read(struct snd_info_entry *entry, int i; emu = entry->private_data; - mutex_lock(&emu->register_mutex); + guard(mutex)(&emu->register_mutex); if (emu->name) snd_iprintf(buf, "Device: %s\n", emu->name); snd_iprintf(buf, "Ports: %d\n", emu->num_ports); @@ -38,13 +38,12 @@ snd_emux_proc_info_read(struct snd_info_entry *entry, snd_iprintf(buf, "Memory Size: 0\n"); } if (emu->sflist) { - mutex_lock(&emu->sflist->presets_mutex); + guard(mutex)(&emu->sflist->presets_mutex); snd_iprintf(buf, "SoundFonts: %d\n", emu->sflist->fonts_size); snd_iprintf(buf, "Instruments: %d\n", emu->sflist->zone_counter); snd_iprintf(buf, "Samples: %d\n", emu->sflist->sample_counter); snd_iprintf(buf, "Locked Instruments: %d\n", emu->sflist->zone_locked); snd_iprintf(buf, "Locked Samples: %d\n", emu->sflist->sample_locked); - mutex_unlock(&emu->sflist->presets_mutex); } #if 0 /* debug */ if (emu->voices[0].state != SNDRV_EMUX_ST_OFF && emu->voices[0].ch >= 0) { @@ -85,7 +84,6 @@ snd_emux_proc_info_read(struct snd_info_entry *entry, snd_iprintf(buf, "sample_mode=%x, rate=%x\n", vp->reg.sample_mode, vp->reg.rate_offset); } #endif - mutex_unlock(&emu->register_mutex); } diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c index 9daced0e6c59..9d63ac006aa5 100644 --- a/sound/synth/emux/emux_seq.c +++ b/sound/synth/emux/emux_seq.c @@ -272,12 +272,8 @@ __snd_emux_inc_count(struct snd_emux *emu) int snd_emux_inc_count(struct snd_emux *emu) { - int ret; - - mutex_lock(&emu->register_mutex); - ret = __snd_emux_inc_count(emu); - mutex_unlock(&emu->register_mutex); - return ret; + guard(mutex)(&emu->register_mutex); + return __snd_emux_inc_count(emu); } /* @@ -295,9 +291,8 @@ __snd_emux_dec_count(struct snd_emux *emu) void snd_emux_dec_count(struct snd_emux *emu) { - mutex_lock(&emu->register_mutex); + guard(mutex)(&emu->register_mutex); __snd_emux_dec_count(emu); - mutex_unlock(&emu->register_mutex); } /* @@ -316,10 +311,9 @@ snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info) if (snd_BUG_ON(!emu)) return -EINVAL; - mutex_lock(&emu->register_mutex); + guard(mutex)(&emu->register_mutex); snd_emux_init_port(p); __snd_emux_inc_count(emu); - mutex_unlock(&emu->register_mutex); return 0; } @@ -339,10 +333,9 @@ snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info) if (snd_BUG_ON(!emu)) return -EINVAL; - mutex_lock(&emu->register_mutex); + guard(mutex)(&emu->register_mutex); snd_emux_sounds_off_all(p); __snd_emux_dec_count(emu); - mutex_unlock(&emu->register_mutex); return 0; } diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c index cff6aba9bfc3..6982e1317da5 100644 --- a/sound/synth/emux/emux_synth.c +++ b/sound/synth/emux/emux_synth.c @@ -49,7 +49,6 @@ snd_emux_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) int i, key, nvoices; struct snd_emux_voice *vp; struct snd_sf_zone *table[SNDRV_EMUX_MAX_MULTI_VOICES]; - unsigned long flags; struct snd_emux_port *port; port = p; @@ -77,7 +76,7 @@ snd_emux_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) terminate_note1(emu, key, chan, 0); #endif - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); for (i = 0; i < nvoices; i++) { /* set up each voice parameter */ @@ -124,7 +123,6 @@ snd_emux_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) vp->ontime = jiffies; /* remember the trigger timing */ } } - spin_unlock_irqrestore(&emu->voice_lock, flags); #ifdef SNDRV_EMUX_USE_RAW_EFFECT if (port->port_mode == SNDRV_EMUX_PORT_MODE_OSS_SYNTH) { @@ -147,7 +145,6 @@ snd_emux_note_off(void *p, int note, int vel, struct snd_midi_channel *chan) int ch; struct snd_emux *emu; struct snd_emux_voice *vp; - unsigned long flags; struct snd_emux_port *port; port = p; @@ -158,7 +155,7 @@ snd_emux_note_off(void *p, int note, int vel, struct snd_midi_channel *chan) if (snd_BUG_ON(!emu || !emu->ops.release)) return; - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); for (ch = 0; ch < emu->max_voices; ch++) { vp = &emu->voices[ch]; if (STATE_IS_PLAYING(vp->state) && @@ -180,7 +177,6 @@ snd_emux_note_off(void *p, int note, int vel, struct snd_midi_channel *chan) emu->ops.release(vp); } } - spin_unlock_irqrestore(&emu->voice_lock, flags); } /* @@ -192,10 +188,9 @@ void snd_emux_timer_callback(struct timer_list *t) { struct snd_emux *emu = timer_container_of(emu, t, tlist); struct snd_emux_voice *vp; - unsigned long flags; int ch, do_again = 0; - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); for (ch = 0; ch < emu->max_voices; ch++) { vp = &emu->voices[ch]; if (vp->state == SNDRV_EMUX_ST_PENDING) { @@ -212,7 +207,6 @@ void snd_emux_timer_callback(struct timer_list *t) emu->timer_active = 1; } else emu->timer_active = 0; - spin_unlock_irqrestore(&emu->voice_lock, flags); } /* @@ -224,7 +218,6 @@ snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan) int ch; struct snd_emux *emu; struct snd_emux_voice *vp; - unsigned long flags; struct snd_emux_port *port; port = p; @@ -235,7 +228,7 @@ snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan) if (snd_BUG_ON(!emu || !emu->ops.update)) return; - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); for (ch = 0; ch < emu->max_voices; ch++) { vp = &emu->voices[ch]; if (vp->state == SNDRV_EMUX_ST_ON && @@ -244,7 +237,6 @@ snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan) update_voice(emu, vp, SNDRV_EMUX_UPDATE_VOLUME); } } - spin_unlock_irqrestore(&emu->voice_lock, flags); } @@ -257,7 +249,6 @@ snd_emux_update_channel(struct snd_emux_port *port, struct snd_midi_channel *cha struct snd_emux *emu; struct snd_emux_voice *vp; int i; - unsigned long flags; if (! update) return; @@ -266,13 +257,12 @@ snd_emux_update_channel(struct snd_emux_port *port, struct snd_midi_channel *cha if (snd_BUG_ON(!emu || !emu->ops.update)) return; - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); for (i = 0; i < emu->max_voices; i++) { vp = &emu->voices[i]; if (vp->chan == chan) update_voice(emu, vp, update); } - spin_unlock_irqrestore(&emu->voice_lock, flags); } /* @@ -284,7 +274,6 @@ snd_emux_update_port(struct snd_emux_port *port, int update) struct snd_emux *emu; struct snd_emux_voice *vp; int i; - unsigned long flags; if (! update) return; @@ -293,13 +282,12 @@ snd_emux_update_port(struct snd_emux_port *port, int update) if (snd_BUG_ON(!emu || !emu->ops.update)) return; - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); for (i = 0; i < emu->max_voices; i++) { vp = &emu->voices[i]; if (vp->port == port) update_voice(emu, vp, update); } - spin_unlock_irqrestore(&emu->voice_lock, flags); } @@ -365,16 +353,14 @@ terminate_note1(struct snd_emux *emu, int note, struct snd_midi_channel *chan, i { int i; struct snd_emux_voice *vp; - unsigned long flags; - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); for (i = 0; i < emu->max_voices; i++) { vp = &emu->voices[i]; if (STATE_IS_PLAYING(vp->state) && vp->chan == chan && vp->key == note) terminate_voice(emu, vp, free); } - spin_unlock_irqrestore(&emu->voice_lock, flags); } @@ -407,9 +393,8 @@ snd_emux_terminate_all(struct snd_emux *emu) { int i; struct snd_emux_voice *vp; - unsigned long flags; - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); for (i = 0; i < emu->max_voices; i++) { vp = &emu->voices[i]; if (STATE_IS_PLAYING(vp->state)) @@ -424,7 +409,6 @@ snd_emux_terminate_all(struct snd_emux *emu) } /* initialize allocation time */ emu->use_time = 0; - spin_unlock_irqrestore(&emu->voice_lock, flags); } EXPORT_SYMBOL(snd_emux_terminate_all); @@ -438,7 +422,6 @@ snd_emux_sounds_off_all(struct snd_emux_port *port) int i; struct snd_emux *emu; struct snd_emux_voice *vp; - unsigned long flags; if (snd_BUG_ON(!port)) return; @@ -446,7 +429,7 @@ snd_emux_sounds_off_all(struct snd_emux_port *port) if (snd_BUG_ON(!emu || !emu->ops.terminate)) return; - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); for (i = 0; i < emu->max_voices; i++) { vp = &emu->voices[i]; if (STATE_IS_PLAYING(vp->state) && @@ -459,7 +442,6 @@ snd_emux_sounds_off_all(struct snd_emux_port *port) emu->ops.reset(emu, i); } } - spin_unlock_irqrestore(&emu->voice_lock, flags); } @@ -472,9 +454,8 @@ exclusive_note_off(struct snd_emux *emu, struct snd_emux_port *port, int exclass { struct snd_emux_voice *vp; int i; - unsigned long flags; - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); for (i = 0; i < emu->max_voices; i++) { vp = &emu->voices[i]; if (STATE_IS_PLAYING(vp->state) && vp->port == port && @@ -482,7 +463,6 @@ exclusive_note_off(struct snd_emux *emu, struct snd_emux_port *port, int exclass terminate_voice(emu, vp, 0); } } - spin_unlock_irqrestore(&emu->voice_lock, flags); } /* @@ -916,9 +896,8 @@ snd_emux_init_voices(struct snd_emux *emu) { struct snd_emux_voice *vp; int i; - unsigned long flags; - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); for (i = 0; i < emu->max_voices; i++) { vp = &emu->voices[i]; vp->ch = -1; /* not used */ @@ -929,23 +908,19 @@ snd_emux_init_voices(struct snd_emux *emu) vp->emu = emu; vp->hw = emu->hw; } - spin_unlock_irqrestore(&emu->voice_lock, flags); } /* */ void snd_emux_lock_voice(struct snd_emux *emu, int voice) { - unsigned long flags; - - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); if (emu->voices[voice].state == SNDRV_EMUX_ST_OFF) emu->voices[voice].state = SNDRV_EMUX_ST_LOCKED; else dev_warn(emu->card->dev, "invalid voice for lock %d (state = %x)\n", voice, emu->voices[voice].state); - spin_unlock_irqrestore(&emu->voice_lock, flags); } EXPORT_SYMBOL(snd_emux_lock_voice); @@ -954,16 +929,13 @@ EXPORT_SYMBOL(snd_emux_lock_voice); */ void snd_emux_unlock_voice(struct snd_emux *emu, int voice) { - unsigned long flags; - - spin_lock_irqsave(&emu->voice_lock, flags); + guard(spinlock_irqsave)(&emu->voice_lock); if (emu->voices[voice].state == SNDRV_EMUX_ST_LOCKED) emu->voices[voice].state = SNDRV_EMUX_ST_OFF; else dev_warn(emu->card->dev, "invalid voice for unlock %d (state = %x)\n", voice, emu->voices[voice].state); - spin_unlock_irqrestore(&emu->voice_lock, flags); } EXPORT_SYMBOL(snd_emux_unlock_voice); diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index b38a4e231790..59f3b1b6df4a 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c @@ -61,47 +61,16 @@ static void snd_sf_init(struct snd_sf_list *sflist); static void snd_sf_clear(struct snd_sf_list *sflist); /* - * lock access to sflist - */ -static void -lock_preset(struct snd_sf_list *sflist) -{ - unsigned long flags; - mutex_lock(&sflist->presets_mutex); - spin_lock_irqsave(&sflist->lock, flags); - sflist->presets_locked = 1; - spin_unlock_irqrestore(&sflist->lock, flags); -} - - -/* - * remove lock - */ -static void -unlock_preset(struct snd_sf_list *sflist) -{ - unsigned long flags; - spin_lock_irqsave(&sflist->lock, flags); - sflist->presets_locked = 0; - spin_unlock_irqrestore(&sflist->lock, flags); - mutex_unlock(&sflist->presets_mutex); -} - - -/* * close the patch if the patch was opened by this client. */ int snd_soundfont_close_check(struct snd_sf_list *sflist, int client) { - unsigned long flags; - spin_lock_irqsave(&sflist->lock, flags); - if (sflist->open_client == client) { - spin_unlock_irqrestore(&sflist->lock, flags); - return close_patch(sflist); + scoped_guard(spinlock_irqsave, &sflist->lock) { + if (sflist->open_client != client) + return 0; } - spin_unlock_irqrestore(&sflist->lock, flags); - return 0; + return close_patch(sflist); } @@ -119,7 +88,6 @@ snd_soundfont_load(struct snd_card *card, long count, int client) { struct soundfont_patch_info patch; - unsigned long flags; int rc; if (count < (long)sizeof(patch)) { @@ -148,21 +116,17 @@ snd_soundfont_load(struct snd_card *card, if (patch.type == SNDRV_SFNT_OPEN_PATCH) { /* grab sflist to open */ - lock_preset(sflist); - rc = open_patch(sflist, data, count, client); - unlock_preset(sflist); - return rc; + guard(snd_soundfont_lock_preset)(sflist); + return open_patch(sflist, data, count, client); } /* check if other client already opened patch */ - spin_lock_irqsave(&sflist->lock, flags); - if (sflist->open_client != client) { - spin_unlock_irqrestore(&sflist->lock, flags); - return -EBUSY; + scoped_guard(spinlock_irqsave, &sflist->lock) { + if (sflist->open_client != client) + return -EBUSY; } - spin_unlock_irqrestore(&sflist->lock, flags); - lock_preset(sflist); + guard(snd_soundfont_lock_preset)(sflist); rc = -EINVAL; switch (patch.type) { case SNDRV_SFNT_LOAD_INFO: @@ -200,7 +164,6 @@ snd_soundfont_load(struct snd_card *card, } break; } - unlock_preset(sflist); return rc; } @@ -223,14 +186,11 @@ open_patch(struct snd_sf_list *sflist, const char __user *data, { struct soundfont_open_parm parm; struct snd_soundfont *sf; - unsigned long flags; - spin_lock_irqsave(&sflist->lock, flags); - if (sflist->open_client >= 0 || sflist->currsf) { - spin_unlock_irqrestore(&sflist->lock, flags); - return -EBUSY; + scoped_guard(spinlock_irqsave, &sflist->lock) { + if (sflist->open_client >= 0 || sflist->currsf) + return -EBUSY; } - spin_unlock_irqrestore(&sflist->lock, flags); if (copy_from_user(&parm, data, sizeof(parm))) return -EFAULT; @@ -244,10 +204,10 @@ open_patch(struct snd_sf_list *sflist, const char __user *data, return -ENOMEM; } - spin_lock_irqsave(&sflist->lock, flags); - sflist->open_client = client; - sflist->currsf = sf; - spin_unlock_irqrestore(&sflist->lock, flags); + scoped_guard(spinlock_irqsave, &sflist->lock) { + sflist->open_client = client; + sflist->currsf = sf; + } return 0; } @@ -305,12 +265,10 @@ is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name) static int close_patch(struct snd_sf_list *sflist) { - unsigned long flags; - - spin_lock_irqsave(&sflist->lock, flags); - sflist->currsf = NULL; - sflist->open_client = -1; - spin_unlock_irqrestore(&sflist->lock, flags); + scoped_guard(spinlock_irqsave, &sflist->lock) { + sflist->currsf = NULL; + sflist->open_client = -1; + } rebuild_presets(sflist); @@ -1168,11 +1126,8 @@ snd_soundfont_load_guspatch(struct snd_card *card, struct snd_sf_list *sflist, const char __user *data, long count) { - int rc; - lock_preset(sflist); - rc = load_guspatch(card, sflist, data, count); - unlock_preset(sflist); - return rc; + guard(snd_soundfont_lock_preset)(sflist); + return load_guspatch(card, sflist, data, count); } @@ -1278,17 +1233,14 @@ snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel, struct snd_sf_zone **table, int max_layers) { int nvoices; - unsigned long flags; /* this function is supposed to be called atomically, * so we check the lock. if it's busy, just returns 0 to * tell the caller the busy state */ - spin_lock_irqsave(&sflist->lock, flags); - if (sflist->presets_locked) { - spin_unlock_irqrestore(&sflist->lock, flags); + guard(spinlock_irqsave)(&sflist->lock); + if (sflist->presets_locked) return 0; - } nvoices = search_zones(sflist, notep, vel, preset, bank, table, max_layers, 0); if (! nvoices) { @@ -1297,7 +1249,6 @@ snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel, def_preset, def_bank, table, max_layers, 0); } - spin_unlock_irqrestore(&sflist->lock, flags); return nvoices; } @@ -1465,11 +1416,11 @@ snd_sf_free(struct snd_sf_list *sflist) if (sflist == NULL) return; - lock_preset(sflist); - if (sflist->callback.sample_reset) - sflist->callback.sample_reset(sflist->callback.private_data); - snd_sf_clear(sflist); - unlock_preset(sflist); + scoped_guard(snd_soundfont_lock_preset, sflist) { + if (sflist->callback.sample_reset) + sflist->callback.sample_reset(sflist->callback.private_data); + snd_sf_clear(sflist); + } kfree(sflist); } @@ -1481,11 +1432,10 @@ snd_sf_free(struct snd_sf_list *sflist) int snd_soundfont_remove_samples(struct snd_sf_list *sflist) { - lock_preset(sflist); + guard(snd_soundfont_lock_preset)(sflist); if (sflist->callback.sample_reset) sflist->callback.sample_reset(sflist->callback.private_data); snd_sf_clear(sflist); - unlock_preset(sflist); return 0; } @@ -1501,7 +1451,7 @@ snd_soundfont_remove_unlocked(struct snd_sf_list *sflist) struct snd_sf_zone *zp, *nextzp; struct snd_sf_sample *sp, *nextsp; - lock_preset(sflist); + guard(snd_soundfont_lock_preset)(sflist); if (sflist->callback.sample_reset) sflist->callback.sample_reset(sflist->callback.private_data); @@ -1535,6 +1485,5 @@ snd_soundfont_remove_unlocked(struct snd_sf_list *sflist) rebuild_presets(sflist); - unlock_preset(sflist); return 0; } diff --git a/sound/synth/util_mem.c b/sound/synth/util_mem.c index 304a8f1740c3..2fd577c2a8eb 100644 --- a/sound/synth/util_mem.c +++ b/sound/synth/util_mem.c @@ -124,11 +124,8 @@ __snd_util_memblk_new(struct snd_util_memhdr *hdr, unsigned int units, struct snd_util_memblk * snd_util_mem_alloc(struct snd_util_memhdr *hdr, int size) { - struct snd_util_memblk *blk; - mutex_lock(&hdr->block_mutex); - blk = __snd_util_mem_alloc(hdr, size); - mutex_unlock(&hdr->block_mutex); - return blk; + guard(mutex)(&hdr->block_mutex); + return __snd_util_mem_alloc(hdr, size); } @@ -153,9 +150,8 @@ int snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk) if (snd_BUG_ON(!hdr || !blk)) return -EINVAL; - mutex_lock(&hdr->block_mutex); + guard(mutex)(&hdr->block_mutex); __snd_util_mem_free(hdr, blk); - mutex_unlock(&hdr->block_mutex); return 0; } @@ -164,11 +160,8 @@ int snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk) */ int snd_util_mem_avail(struct snd_util_memhdr *hdr) { - unsigned int size; - mutex_lock(&hdr->block_mutex); - size = hdr->size - hdr->used; - mutex_unlock(&hdr->block_mutex); - return size; + guard(mutex)(&hdr->block_mutex); + return hdr->size - hdr->used; } diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c index 9eb4bf9b138b..5ff78814e687 100644 --- a/sound/usb/6fire/chip.c +++ b/sound/usb/6fire/chip.c @@ -88,24 +88,22 @@ static int usb6fire_chip_probe(struct usb_interface *intf, struct snd_card *card = NULL; /* look if we already serve this card and return if so */ - mutex_lock(®ister_mutex); - for (i = 0; i < SNDRV_CARDS; i++) { - if (devices[i] == device) { - if (chips[i]) - chips[i]->intf_count++; - usb_set_intfdata(intf, chips[i]); - mutex_unlock(®ister_mutex); - return 0; - } else if (!devices[i] && regidx < 0) - regidx = i; - } - if (regidx < 0) { - mutex_unlock(®ister_mutex); - dev_err(&intf->dev, "too many cards registered.\n"); - return -ENODEV; + scoped_guard(mutex, ®ister_mutex) { + for (i = 0; i < SNDRV_CARDS; i++) { + if (devices[i] == device) { + if (chips[i]) + chips[i]->intf_count++; + usb_set_intfdata(intf, chips[i]); + return 0; + } else if (!devices[i] && regidx < 0) + regidx = i; + } + if (regidx < 0) { + dev_err(&intf->dev, "too many cards registered.\n"); + return -ENODEV; + } + devices[regidx] = device; } - devices[regidx] = device; - mutex_unlock(®ister_mutex); /* check, if firmware is present on device, upload it if not */ ret = usb6fire_fw_init(intf); @@ -175,10 +173,10 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf) if (chip) { /* if !chip, fw upload has been performed */ chip->intf_count--; if (!chip->intf_count) { - mutex_lock(®ister_mutex); - devices[chip->regidx] = NULL; - chips[chip->regidx] = NULL; - mutex_unlock(®ister_mutex); + scoped_guard(mutex, ®ister_mutex) { + devices[chip->regidx] = NULL; + chips[chip->regidx] = NULL; + } chip->shutdown = true; usb6fire_chip_abort(chip); diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c index 923f7767e62f..4d1eeb32c5fe 100644 --- a/sound/usb/6fire/midi.c +++ b/sound/usb/6fire/midi.c @@ -23,9 +23,8 @@ static void usb6fire_midi_out_handler(struct urb *urb) { struct midi_runtime *rt = urb->context; int ret; - unsigned long flags; - spin_lock_irqsave(&rt->out_lock, flags); + guard(spinlock_irqsave)(&rt->out_lock); if (rt->out) { ret = snd_rawmidi_transmit(rt->out, rt->out_buffer + 4, @@ -43,18 +42,14 @@ static void usb6fire_midi_out_handler(struct urb *urb) } else /* no more data to transmit */ rt->out = NULL; } - spin_unlock_irqrestore(&rt->out_lock, flags); } static void usb6fire_midi_in_received( struct midi_runtime *rt, u8 *data, int length) { - unsigned long flags; - - spin_lock_irqsave(&rt->in_lock, flags); + guard(spinlock_irqsave)(&rt->in_lock); if (rt->in) snd_rawmidi_receive(rt->in, data, length); - spin_unlock_irqrestore(&rt->in_lock, flags); } static int usb6fire_midi_out_open(struct snd_rawmidi_substream *alsa_sub) @@ -73,14 +68,11 @@ static void usb6fire_midi_out_trigger( struct midi_runtime *rt = alsa_sub->rmidi->private_data; struct urb *urb = &rt->out_urb; __s8 ret; - unsigned long flags; - spin_lock_irqsave(&rt->out_lock, flags); + guard(spinlock_irqsave)(&rt->out_lock); if (up) { /* start transfer */ - if (rt->out) { /* we are already transmitting so just return */ - spin_unlock_irqrestore(&rt->out_lock, flags); + if (rt->out) /* we are already transmitting so just return */ return; - } ret = snd_rawmidi_transmit(alsa_sub, rt->out_buffer + 4, MIDI_BUFSIZE - 4); @@ -99,7 +91,6 @@ static void usb6fire_midi_out_trigger( } } else if (rt->out == alsa_sub) rt->out = NULL; - spin_unlock_irqrestore(&rt->out_lock, flags); } static void usb6fire_midi_out_drain(struct snd_rawmidi_substream *alsa_sub) @@ -125,14 +116,12 @@ static void usb6fire_midi_in_trigger( struct snd_rawmidi_substream *alsa_sub, int up) { struct midi_runtime *rt = alsa_sub->rmidi->private_data; - unsigned long flags; - spin_lock_irqsave(&rt->in_lock, flags); + guard(spinlock_irqsave)(&rt->in_lock); if (up) rt->in = alsa_sub; else rt->in = NULL; - spin_unlock_irqrestore(&rt->in_lock, flags); } static const struct snd_rawmidi_ops out_ops = { diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index d53cad97889a..08515da5dcc8 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c @@ -289,7 +289,7 @@ static void usb6fire_pcm_in_urb_handler(struct urb *usb_urb) struct pcm_urb *out_urb = in_urb->peer; struct pcm_runtime *rt = in_urb->chip->pcm; struct pcm_substream *sub; - unsigned long flags; + bool period_elapsed; int total_length = 0; int frame_count; int frame; @@ -313,17 +313,18 @@ static void usb6fire_pcm_in_urb_handler(struct urb *usb_urb) /* receive our capture data */ sub = &rt->capture; - spin_lock_irqsave(&sub->lock, flags); - if (sub->active) { - usb6fire_pcm_capture(sub, in_urb); - if (sub->period_off >= sub->instance->runtime->period_size) { - sub->period_off %= sub->instance->runtime->period_size; - spin_unlock_irqrestore(&sub->lock, flags); - snd_pcm_period_elapsed(sub->instance); - } else - spin_unlock_irqrestore(&sub->lock, flags); - } else - spin_unlock_irqrestore(&sub->lock, flags); + period_elapsed = false; + scoped_guard(spinlock_irqsave, &sub->lock) { + if (sub->active) { + usb6fire_pcm_capture(sub, in_urb); + if (sub->period_off >= sub->instance->runtime->period_size) { + sub->period_off %= sub->instance->runtime->period_size; + period_elapsed = true; + } + } + } + if (period_elapsed) + snd_pcm_period_elapsed(sub->instance); /* setup out urb structure */ for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { @@ -338,17 +339,18 @@ static void usb6fire_pcm_in_urb_handler(struct urb *usb_urb) /* now send our playback data (if a free out urb was found) */ sub = &rt->playback; - spin_lock_irqsave(&sub->lock, flags); - if (sub->active) { - usb6fire_pcm_playback(sub, out_urb); - if (sub->period_off >= sub->instance->runtime->period_size) { - sub->period_off %= sub->instance->runtime->period_size; - spin_unlock_irqrestore(&sub->lock, flags); - snd_pcm_period_elapsed(sub->instance); - } else - spin_unlock_irqrestore(&sub->lock, flags); - } else - spin_unlock_irqrestore(&sub->lock, flags); + period_elapsed = false; + scoped_guard(spinlock_irqsave, &sub->lock) { + if (sub->active) { + usb6fire_pcm_playback(sub, out_urb); + if (sub->period_off >= sub->instance->runtime->period_size) { + sub->period_off %= sub->instance->runtime->period_size; + period_elapsed = true; + } + } + } + if (period_elapsed) + snd_pcm_period_elapsed(sub->instance); /* setup the 4th byte of each sample (0x40 for analog channels) */ dest = out_urb->buffer; @@ -392,7 +394,7 @@ static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub) if (rt->panic) return -EPIPE; - mutex_lock(&rt->stream_mutex); + guard(mutex)(&rt->stream_mutex); alsa_rt->hw = pcm_hw; if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -408,14 +410,12 @@ static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub) } if (!sub) { - mutex_unlock(&rt->stream_mutex); dev_err(&rt->chip->dev->dev, "invalid stream type.\n"); return -EINVAL; } sub->instance = alsa_sub; sub->active = false; - mutex_unlock(&rt->stream_mutex); return 0; } @@ -423,18 +423,17 @@ static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub) { struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); - unsigned long flags; if (rt->panic) return 0; - mutex_lock(&rt->stream_mutex); + guard(mutex)(&rt->stream_mutex); if (sub) { /* deactivate substream */ - spin_lock_irqsave(&sub->lock, flags); - sub->instance = NULL; - sub->active = false; - spin_unlock_irqrestore(&sub->lock, flags); + scoped_guard(spinlock_irqsave, &sub->lock) { + sub->instance = NULL; + sub->active = false; + } /* all substreams closed? if so, stop streaming */ if (!rt->playback.instance && !rt->capture.instance) { @@ -442,7 +441,6 @@ static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub) rt->rate = ARRAY_SIZE(rates); } } - mutex_unlock(&rt->stream_mutex); return 0; } @@ -458,7 +456,7 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) if (!sub) return -ENODEV; - mutex_lock(&rt->stream_mutex); + guard(mutex)(&rt->stream_mutex); sub->dma_off = 0; sub->period_off = 0; @@ -467,7 +465,6 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) if (alsa_rt->rate == rates[rt->rate]) break; if (rt->rate == ARRAY_SIZE(rates)) { - mutex_unlock(&rt->stream_mutex); dev_err(&rt->chip->dev->dev, "invalid rate %d in prepare.\n", alsa_rt->rate); @@ -475,19 +472,15 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) } ret = usb6fire_pcm_set_rate(rt); - if (ret) { - mutex_unlock(&rt->stream_mutex); + if (ret) return ret; - } ret = usb6fire_pcm_stream_start(rt); if (ret) { - mutex_unlock(&rt->stream_mutex); dev_err(&rt->chip->dev->dev, "could not start pcm stream.\n"); return ret; } } - mutex_unlock(&rt->stream_mutex); return 0; } @@ -495,26 +488,22 @@ static int usb6fire_pcm_trigger(struct snd_pcm_substream *alsa_sub, int cmd) { struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); - unsigned long flags; if (rt->panic) return -EPIPE; if (!sub) return -ENODEV; + guard(spinlock_irqsave)(&sub->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - spin_lock_irqsave(&sub->lock, flags); sub->active = true; - spin_unlock_irqrestore(&sub->lock, flags); return 0; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - spin_lock_irqsave(&sub->lock, flags); sub->active = false; - spin_unlock_irqrestore(&sub->lock, flags); return 0; default: @@ -527,15 +516,13 @@ static snd_pcm_uframes_t usb6fire_pcm_pointer( { struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); - unsigned long flags; snd_pcm_uframes_t ret; if (rt->panic || !sub) return SNDRV_PCM_POS_XRUN; - spin_lock_irqsave(&sub->lock, flags); + guard(spinlock_irqsave)(&sub->lock); ret = sub->dma_off; - spin_unlock_irqrestore(&sub->lock, flags); return ret; } diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 41c47301bc19..9b890abd96d3 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig @@ -117,6 +117,18 @@ config SND_USB_US122L To compile this driver as a module, choose M here: the module will be called snd-usb-us122l. +config SND_USB_US144MKII + tristate "Tascam US-144MKII USB driver" + depends on X86 || COMPILE_TEST + select SND_RAWMIDI + select SND_PCM + help + Say Y here to include support for Tascam US-144MKII USB Audio/MIDI + interface. + + To compile this driver as a module, choose M here: the module + will be called snd-usb-us144mkii. + config SND_USB_6FIRE tristate "TerraTec DMX 6Fire USB" select FW_LOADER diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c index 392b4d8e9e76..bebb48cb9abc 100644 --- a/sound/usb/bcd2000/bcd2000.c +++ b/sound/usb/bcd2000/bcd2000.c @@ -369,23 +369,19 @@ static int bcd2000_probe(struct usb_interface *interface, char usb_path[32]; int err; - mutex_lock(&devices_mutex); + guard(mutex)(&devices_mutex); for (card_index = 0; card_index < SNDRV_CARDS; ++card_index) if (!test_bit(card_index, devices_used)) break; - if (card_index >= SNDRV_CARDS) { - mutex_unlock(&devices_mutex); + if (card_index >= SNDRV_CARDS) return -ENOENT; - } err = snd_card_new(&interface->dev, index[card_index], id[card_index], THIS_MODULE, sizeof(*bcd2k), &card); - if (err < 0) { - mutex_unlock(&devices_mutex); + if (err < 0) return err; - } bcd2k = card->private_data; bcd2k->dev = interface_to_usbdev(interface); @@ -413,14 +409,12 @@ static int bcd2000_probe(struct usb_interface *interface, usb_set_intfdata(interface, bcd2k); set_bit(card_index, devices_used); - mutex_unlock(&devices_mutex); return 0; probe_error: dev_info(&bcd2k->dev->dev, PREFIX "error during probing"); bcd2000_free_usb_related_resources(bcd2k, interface); snd_card_free(card); - mutex_unlock(&devices_mutex); return err; } @@ -431,7 +425,7 @@ static void bcd2000_disconnect(struct usb_interface *interface) if (!bcd2k) return; - mutex_lock(&devices_mutex); + guard(mutex)(&devices_mutex); /* make sure that userspace cannot create new requests */ snd_card_disconnect(bcd2k->card); @@ -441,8 +435,6 @@ static void bcd2000_disconnect(struct usb_interface *interface) clear_bit(bcd2k->card_index, devices_used); snd_card_free_when_closed(bcd2k->card); - - mutex_unlock(&devices_mutex); } static struct usb_driver bcd2000_driver = { diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index 05f964347ed6..95d425dd9d70 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -51,29 +51,24 @@ static void activate_substream(struct snd_usb_caiaqdev *cdev, struct snd_pcm_substream *sub) { - spin_lock(&cdev->spinlock); + guard(spinlock)(&cdev->spinlock); if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) cdev->sub_playback[sub->number] = sub; else cdev->sub_capture[sub->number] = sub; - - spin_unlock(&cdev->spinlock); } static void deactivate_substream(struct snd_usb_caiaqdev *cdev, struct snd_pcm_substream *sub) { - unsigned long flags; - spin_lock_irqsave(&cdev->spinlock, flags); + guard(spinlock_irqsave)(&cdev->spinlock); if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) cdev->sub_playback[sub->number] = NULL; else cdev->sub_capture[sub->number] = NULL; - - spin_unlock_irqrestore(&cdev->spinlock, flags); } static int @@ -285,25 +280,18 @@ snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub) { int index = sub->number; struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub); - snd_pcm_uframes_t ptr; - spin_lock(&cdev->spinlock); + guard(spinlock)(&cdev->spinlock); - if (cdev->input_panic || cdev->output_panic) { - ptr = SNDRV_PCM_POS_XRUN; - goto unlock; - } + if (cdev->input_panic || cdev->output_panic) + return SNDRV_PCM_POS_XRUN; if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) - ptr = bytes_to_frames(sub->runtime, - cdev->audio_out_buf_pos[index]); + return bytes_to_frames(sub->runtime, + cdev->audio_out_buf_pos[index]); else - ptr = bytes_to_frames(sub->runtime, - cdev->audio_in_buf_pos[index]); - -unlock: - spin_unlock(&cdev->spinlock); - return ptr; + return bytes_to_frames(sub->runtime, + cdev->audio_in_buf_pos[index]); } /* operators for both playback and capture */ @@ -601,7 +589,6 @@ static void read_completed(struct urb *urb) struct device *dev; struct urb *out = NULL; int i, frame, len, send_it = 0, outframe = 0; - unsigned long flags; size_t offset = 0; if (urb->status || !info) @@ -638,10 +625,10 @@ static void read_completed(struct urb *urb) offset += len; if (len > 0) { - spin_lock_irqsave(&cdev->spinlock, flags); - fill_out_urb(cdev, out, &out->iso_frame_desc[outframe]); - read_in_urb(cdev, urb, &urb->iso_frame_desc[frame]); - spin_unlock_irqrestore(&cdev->spinlock, flags); + scoped_guard(spinlock_irqsave, &cdev->spinlock) { + fill_out_urb(cdev, out, &out->iso_frame_desc[outframe]); + read_in_urb(cdev, urb, &urb->iso_frame_desc[frame]); + } check_for_elapsed_periods(cdev, cdev->sub_playback); check_for_elapsed_periods(cdev, cdev->sub_capture); send_it = 1; diff --git a/sound/usb/card.c b/sound/usb/card.c index 10d9b7285597..1d5a65eac933 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -73,7 +73,7 @@ static bool lowlatency = true; static char *quirk_alias[SNDRV_CARDS]; static char *delayed_register[SNDRV_CARDS]; static bool implicit_fb[SNDRV_CARDS]; -static unsigned int quirk_flags[SNDRV_CARDS]; +static char *quirk_flags[SNDRV_CARDS]; bool snd_usb_use_vmalloc = true; bool snd_usb_skip_validation; @@ -103,13 +103,32 @@ module_param_array(delayed_register, charp, NULL, 0444); MODULE_PARM_DESC(delayed_register, "Quirk for delayed registration, given by id:iface, e.g. 0123abcd:4."); module_param_array(implicit_fb, bool, NULL, 0444); MODULE_PARM_DESC(implicit_fb, "Apply generic implicit feedback sync mode."); -module_param_array(quirk_flags, uint, NULL, 0444); -MODULE_PARM_DESC(quirk_flags, "Driver quirk bit flags."); module_param_named(use_vmalloc, snd_usb_use_vmalloc, bool, 0444); MODULE_PARM_DESC(use_vmalloc, "Use vmalloc for PCM intermediate buffers (default: yes)."); module_param_named(skip_validation, snd_usb_skip_validation, bool, 0444); MODULE_PARM_DESC(skip_validation, "Skip unit descriptor validation (default: no)."); +/* protects quirk_flags */ +static DEFINE_MUTEX(quirk_flags_mutex); + +static int param_set_quirkp(const char *val, + const struct kernel_param *kp) +{ + guard(mutex)(&quirk_flags_mutex); + return param_set_charp(val, kp); +} + +static const struct kernel_param_ops param_ops_quirkp = { + .set = param_set_quirkp, + .get = param_get_charp, + .free = param_free_charp, +}; + +#define param_check_quirkp param_check_charp + +module_param_array(quirk_flags, quirkp, NULL, 0644); +MODULE_PARM_DESC(quirk_flags, "Add/modify USB audio quirks"); + /* * we keep the snd_usb_audio_t instances by ourselves for merging * the all interfaces on the same card as one sound device. @@ -692,6 +711,31 @@ static void usb_audio_make_longname(struct usb_device *dev, } } +static void snd_usb_init_quirk_flags(int idx, struct snd_usb_audio *chip) +{ + size_t i; + + guard(mutex)(&quirk_flags_mutex); + + /* old style option found: the position-based integer value */ + if (quirk_flags[idx] && + !kstrtou32(quirk_flags[idx], 0, &chip->quirk_flags)) { + snd_usb_apply_flag_dbg("module param", chip, chip->quirk_flags); + return; + } + + /* take the default quirk from the quirk table */ + snd_usb_init_quirk_flags_table(chip); + + /* add or correct quirk bits from options */ + for (i = 0; i < ARRAY_SIZE(quirk_flags); i++) { + if (!quirk_flags[i] || !*quirk_flags[i]) + break; + + snd_usb_init_quirk_flags_parse_string(chip, quirk_flags[i]); + } +} + /* * create a chip instance and set its names. */ @@ -750,10 +794,7 @@ static int snd_usb_audio_create(struct usb_interface *intf, INIT_LIST_HEAD(&chip->midi_v2_list); INIT_LIST_HEAD(&chip->mixer_list); - if (quirk_flags[idx]) - chip->quirk_flags = quirk_flags[idx]; - else - snd_usb_init_quirk_flags(chip); + snd_usb_init_quirk_flags(idx, chip); card->private_free = snd_usb_audio_free; @@ -900,7 +941,7 @@ static int usb_audio_probe(struct usb_interface *intf, /* check whether it's already registered */ chip = NULL; - mutex_lock(®ister_mutex); + guard(mutex)(®ister_mutex); for (i = 0; i < SNDRV_CARDS; i++) { if (usb_chip[i] && usb_chip[i]->dev == dev) { if (atomic_read(&usb_chip[i]->shutdown)) { @@ -1015,7 +1056,6 @@ static int usb_audio_probe(struct usb_interface *intf, if (platform_ops && platform_ops->connect_cb) platform_ops->connect_cb(chip); - mutex_unlock(®ister_mutex); return 0; @@ -1033,7 +1073,6 @@ static int usb_audio_probe(struct usb_interface *intf, if (!chip->num_interfaces) snd_card_free(chip->card); } - mutex_unlock(®ister_mutex); return err; } @@ -1041,18 +1080,14 @@ static int usb_audio_probe(struct usb_interface *intf, * we need to take care of counter, since disconnection can be called also * many times as well as usb_audio_probe(). */ -static void usb_audio_disconnect(struct usb_interface *intf) +static bool __usb_audio_disconnect(struct usb_interface *intf, + struct snd_usb_audio *chip, + struct snd_card *card) { - struct snd_usb_audio *chip = usb_get_intfdata(intf); - struct snd_card *card; struct list_head *p; - if (chip == USB_AUDIO_IFACE_UNUSED) - return; - - card = chip->card; + guard(mutex)(®ister_mutex); - mutex_lock(®ister_mutex); if (platform_ops && platform_ops->disconnect_cb) platform_ops->disconnect_cb(chip); @@ -1098,13 +1133,24 @@ static void usb_audio_disconnect(struct usb_interface *intf) usb_enable_autosuspend(interface_to_usbdev(intf)); chip->num_interfaces--; - if (chip->num_interfaces <= 0) { - usb_chip[chip->index] = NULL; - mutex_unlock(®ister_mutex); + if (chip->num_interfaces > 0) + return false; + + usb_chip[chip->index] = NULL; + return true; +} + +static void usb_audio_disconnect(struct usb_interface *intf) +{ + struct snd_usb_audio *chip = usb_get_intfdata(intf); + struct snd_card *card; + + if (chip == USB_AUDIO_IFACE_UNUSED) + return; + + card = chip->card; + if (__usb_audio_disconnect(intf, chip, card)) snd_card_free_when_closed(card); - } else { - mutex_unlock(®ister_mutex); - } } /* lock the shutdown (disconnect) task and autoresume */ diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 7b01e7b4e335..880f5afcce60 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -163,22 +163,19 @@ int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep) static int slave_next_packet_size(struct snd_usb_endpoint *ep, unsigned int avail) { - unsigned long flags; unsigned int phase; int ret; if (ep->fill_max) return ep->maxframesize; - spin_lock_irqsave(&ep->lock, flags); + guard(spinlock_irqsave)(&ep->lock); phase = (ep->phase & 0xffff) + (ep->freqm << ep->datainterval); ret = min(phase >> 16, ep->maxframesize); if (avail && ret >= avail) ret = -EAGAIN; else ep->phase = phase; - spin_unlock_irqrestore(&ep->lock, flags); - return ret; } @@ -440,11 +437,8 @@ next_packet_fifo_dequeue(struct snd_usb_endpoint *ep) static void push_back_to_ready_list(struct snd_usb_endpoint *ep, struct snd_urb_ctx *ctx) { - unsigned long flags; - - spin_lock_irqsave(&ep->lock, flags); + guard(spinlock_irqsave)(&ep->lock); list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs); - spin_unlock_irqrestore(&ep->lock, flags); } /* @@ -466,23 +460,21 @@ int snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep, bool implicit_fb = snd_usb_endpoint_implicit_feedback_sink(ep); while (ep_state_running(ep)) { - - unsigned long flags; struct snd_usb_packet_info *packet; struct snd_urb_ctx *ctx = NULL; int err, i; - spin_lock_irqsave(&ep->lock, flags); - if ((!implicit_fb || ep->next_packet_queued > 0) && - !list_empty(&ep->ready_playback_urbs)) { - /* take URB out of FIFO */ - ctx = list_first_entry(&ep->ready_playback_urbs, - struct snd_urb_ctx, ready_list); - list_del_init(&ctx->ready_list); - if (implicit_fb) - packet = next_packet_fifo_dequeue(ep); + scoped_guard(spinlock_irqsave, &ep->lock) { + if ((!implicit_fb || ep->next_packet_queued > 0) && + !list_empty(&ep->ready_playback_urbs)) { + /* take URB out of FIFO */ + ctx = list_first_entry(&ep->ready_playback_urbs, + struct snd_urb_ctx, ready_list); + list_del_init(&ctx->ready_list); + if (implicit_fb) + packet = next_packet_fifo_dequeue(ep); + } } - spin_unlock_irqrestore(&ep->lock, flags); if (ctx == NULL) break; @@ -768,12 +760,8 @@ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, const struct audioformat *fp, const struct snd_pcm_hw_params *params) { - bool ret; - - mutex_lock(&chip->mutex); - ret = endpoint_compatible(ep, fp, params); - mutex_unlock(&chip->mutex); - return ret; + guard(mutex)(&chip->mutex); + return endpoint_compatible(ep, fp, params); } /* @@ -799,11 +787,11 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep; int ep_num = is_sync_ep ? fp->sync_ep : fp->endpoint; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); ep = snd_usb_get_endpoint(chip, ep_num); if (!ep) { usb_audio_err(chip, "Cannot find EP 0x%x to open\n", ep_num); - goto unlock; + return NULL; } if (!ep->opened) { @@ -820,17 +808,13 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, ep_num, ep->iface, ep->altsetting, ep->ep_idx); ep->iface_ref = iface_ref_find(chip, ep->iface); - if (!ep->iface_ref) { - ep = NULL; - goto unlock; - } + if (!ep->iface_ref) + return NULL; if (fp->protocol != UAC_VERSION_1) { ep->clock_ref = clock_ref_find(chip, fp->clock); - if (!ep->clock_ref) { - ep = NULL; - goto unlock; - } + if (!ep->clock_ref) + return NULL; ep->clock_ref->opened++; } @@ -859,16 +843,13 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, ep->implicit_fb_sync); } else { - if (WARN_ON(!ep->iface_ref)) { - ep = NULL; - goto unlock; - } + if (WARN_ON(!ep->iface_ref)) + return NULL; if (!endpoint_compatible(ep, fp, params)) { usb_audio_err(chip, "Incompatible EP setup for 0x%x\n", ep_num); - ep = NULL; - goto unlock; + return NULL; } usb_audio_dbg(chip, "Reopened EP 0x%x (count %d)\n", @@ -879,9 +860,6 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, ep->iface_ref->need_setup = true; ep->opened++; - - unlock: - mutex_unlock(&chip->mutex); return ep; } @@ -964,7 +942,7 @@ retry: void snd_usb_endpoint_close(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep) { - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); usb_audio_dbg(chip, "Closing EP 0x%x (count %d)\n", ep->ep_num, ep->opened); @@ -985,7 +963,6 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip, ep->clock_ref = NULL; usb_audio_dbg(chip, "EP 0x%x closed\n", ep->ep_num); } - mutex_unlock(&chip->mutex); } /* Prepare for suspening EP, called from the main suspend handler */ @@ -1047,7 +1024,6 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) static int stop_urbs(struct snd_usb_endpoint *ep, bool force, bool keep_pending) { unsigned int i; - unsigned long flags; if (!force && atomic_read(&ep->running)) return -EBUSY; @@ -1055,11 +1031,11 @@ static int stop_urbs(struct snd_usb_endpoint *ep, bool force, bool keep_pending) if (!ep_state_update(ep, EP_STATE_RUNNING, EP_STATE_STOPPING)) return 0; - spin_lock_irqsave(&ep->lock, flags); - INIT_LIST_HEAD(&ep->ready_playback_urbs); - ep->next_packet_head = 0; - ep->next_packet_queued = 0; - spin_unlock_irqrestore(&ep->lock, flags); + scoped_guard(spinlock_irqsave, &ep->lock) { + INIT_LIST_HEAD(&ep->ready_playback_urbs); + ep->next_packet_head = 0; + ep->next_packet_queued = 0; + } if (keep_pending) return 0; @@ -1360,16 +1336,16 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep) { const struct audioformat *fmt = ep->cur_audiofmt; - int err = 0; + int err; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); if (!ep->need_setup) - goto unlock; + return 0; /* release old buffers, if any */ err = release_urbs(ep, false); if (err < 0) - goto unlock; + return err; ep->datainterval = fmt->datainterval; ep->maxpacksize = fmt->maxpacksize; @@ -1407,7 +1383,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, usb_audio_dbg(chip, "Set up %d URBS, ret=%d\n", ep->nurbs, err); if (err < 0) - goto unlock; + return err; /* some unit conversions in runtime */ ep->maxframesize = ep->maxpacksize / ep->cur_frame_bytes; @@ -1419,8 +1395,6 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, err = 0; } - unlock: - mutex_unlock(&chip->mutex); return err; } @@ -1467,11 +1441,11 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, bool iface_first; int err = 0; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); if (WARN_ON(!ep->iface_ref)) - goto unlock; + return 0; if (!ep->need_prepare) - goto unlock; + return 0; /* If the interface has been already set up, just set EP parameters */ if (!ep->iface_ref->need_setup) { @@ -1481,7 +1455,7 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, if (ep->cur_audiofmt->protocol == UAC_VERSION_1) { err = init_sample_rate(chip, ep); if (err < 0) - goto unlock; + return err; } goto done; } @@ -1499,37 +1473,33 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, if (iface_first) { err = endpoint_set_interface(chip, ep, true); if (err < 0) - goto unlock; + return err; } err = snd_usb_init_pitch(chip, ep->cur_audiofmt); if (err < 0) - goto unlock; + return err; err = init_sample_rate(chip, ep); if (err < 0) - goto unlock; + return err; err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt); if (err < 0) - goto unlock; + return err; /* for UAC2/3, enable the interface altset here at last */ if (!iface_first) { err = endpoint_set_interface(chip, ep, true); if (err < 0) - goto unlock; + return err; } ep->iface_ref->need_setup = false; done: ep->need_prepare = false; - err = 1; - -unlock: - mutex_unlock(&chip->mutex); - return err; + return 1; } EXPORT_SYMBOL_GPL(snd_usb_endpoint_prepare); @@ -1541,14 +1511,13 @@ int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock) if (!clock) return 0; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); list_for_each_entry(ref, &chip->clock_ref_list, list) { if (ref->clock == clock) { rate = ref->rate; break; } } - mutex_unlock(&chip->mutex); return rate; } @@ -1898,9 +1867,8 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, * If the frequency looks valid, set it. * This value is referred to in prepare_playback_urb(). */ - spin_lock_irqsave(&ep->lock, flags); + guard(spinlock_irqsave)(&ep->lock); ep->freqm = f; - spin_unlock_irqrestore(&ep->lock, flags); } else { /* * Out of range; maybe the shift value is wrong. diff --git a/sound/usb/fcp.c b/sound/usb/fcp.c index 98f9964311a7..5ee8d8b66058 100644 --- a/sound/usb/fcp.c +++ b/sound/usb/fcp.c @@ -820,7 +820,6 @@ static long fcp_hwdep_read(struct snd_hwdep *hw, char __user *buf, { struct usb_mixer_interface *mixer = hw->private_data; struct fcp_data *private = mixer->private_data; - unsigned long flags; long ret = 0; u32 event; @@ -832,10 +831,10 @@ static long fcp_hwdep_read(struct snd_hwdep *hw, char __user *buf, if (ret) return ret; - spin_lock_irqsave(&private->notify.lock, flags); - event = private->notify.event; - private->notify.event = 0; - spin_unlock_irqrestore(&private->notify.lock, flags); + scoped_guard(spinlock_irqsave, &private->notify.lock) { + event = private->notify.event; + private->notify.event = 0; + } if (copy_to_user(buf, &event, sizeof(event))) return -EFAULT; @@ -946,11 +945,9 @@ static void fcp_notify(struct urb *urb) } if (data) { - unsigned long flags; - - spin_lock_irqsave(&private->notify.lock, flags); - private->notify.event |= data; - spin_unlock_irqrestore(&private->notify.lock, flags); + scoped_guard(spinlock_irqsave, &private->notify.lock) { + private->notify.event |= data; + } wake_up_interruptible(&private->notify.queue); } diff --git a/sound/usb/hiface/chip.c b/sound/usb/hiface/chip.c index 95385e90882c..bce28f683666 100644 --- a/sound/usb/hiface/chip.c +++ b/sound/usb/hiface/chip.c @@ -101,7 +101,7 @@ static int hiface_chip_probe(struct usb_interface *intf, /* check whether the card is already registered */ chip = NULL; - mutex_lock(®ister_mutex); + guard(mutex)(®ister_mutex); for (i = 0; i < SNDRV_CARDS; i++) if (enable[i]) @@ -109,13 +109,12 @@ static int hiface_chip_probe(struct usb_interface *intf, if (i >= SNDRV_CARDS) { dev_err(&device->dev, "no available " CARD_NAME " audio device\n"); - ret = -ENODEV; - goto err; + return -ENODEV; } ret = hiface_chip_create(intf, device, i, quirk, &chip); if (ret < 0) - goto err; + return ret; ret = hiface_pcm_init(chip, quirk ? quirk->extra_freq : 0); if (ret < 0) @@ -127,15 +126,11 @@ static int hiface_chip_probe(struct usb_interface *intf, goto err_chip_destroy; } - mutex_unlock(®ister_mutex); - usb_set_intfdata(intf, chip); return 0; err_chip_destroy: snd_card_free(chip->card); -err: - mutex_unlock(®ister_mutex); return ret; } diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c index cf650fab54d7..27cd427fbaa5 100644 --- a/sound/usb/hiface/pcm.c +++ b/sound/usb/hiface/pcm.c @@ -305,7 +305,6 @@ static void hiface_pcm_out_urb_handler(struct urb *usb_urb) struct pcm_runtime *rt = out_urb->chip->pcm; struct pcm_substream *sub; bool do_period_elapsed = false; - unsigned long flags; int ret; if (rt->panic || rt->stream_state == STREAM_STOPPING) @@ -325,13 +324,12 @@ static void hiface_pcm_out_urb_handler(struct urb *usb_urb) /* now send our playback data (if a free out urb was found) */ sub = &rt->playback; - spin_lock_irqsave(&sub->lock, flags); - if (sub->active) - do_period_elapsed = hiface_pcm_playback(sub, out_urb); - else - memset(out_urb->buffer, 0, PCM_PACKET_SIZE); - - spin_unlock_irqrestore(&sub->lock, flags); + scoped_guard(spinlock_irqsave, &sub->lock) { + if (sub->active) + do_period_elapsed = hiface_pcm_playback(sub, out_urb); + else + memset(out_urb->buffer, 0, PCM_PACKET_SIZE); + } if (do_period_elapsed) snd_pcm_period_elapsed(sub->instance); @@ -356,7 +354,7 @@ static int hiface_pcm_open(struct snd_pcm_substream *alsa_sub) if (rt->panic) return -EPIPE; - mutex_lock(&rt->stream_mutex); + guard(mutex)(&rt->stream_mutex); alsa_rt->hw = pcm_hw; if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -364,7 +362,6 @@ static int hiface_pcm_open(struct snd_pcm_substream *alsa_sub) if (!sub) { struct device *device = &rt->chip->dev->dev; - mutex_unlock(&rt->stream_mutex); dev_err(device, "Invalid stream type\n"); return -EINVAL; } @@ -377,15 +374,12 @@ static int hiface_pcm_open(struct snd_pcm_substream *alsa_sub) ret = snd_pcm_hw_constraint_list(alsa_sub->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &constraints_extra_rates); - if (ret < 0) { - mutex_unlock(&rt->stream_mutex); + if (ret < 0) return ret; - } } sub->instance = alsa_sub; sub->active = false; - mutex_unlock(&rt->stream_mutex); return 0; } @@ -393,23 +387,19 @@ static int hiface_pcm_close(struct snd_pcm_substream *alsa_sub) { struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub); - unsigned long flags; if (rt->panic) return 0; - mutex_lock(&rt->stream_mutex); + guard(mutex)(&rt->stream_mutex); if (sub) { hiface_pcm_stream_stop(rt); /* deactivate substream */ - spin_lock_irqsave(&sub->lock, flags); + guard(spinlock_irqsave)(&sub->lock); sub->instance = NULL; sub->active = false; - spin_unlock_irqrestore(&sub->lock, flags); - } - mutex_unlock(&rt->stream_mutex); return 0; } @@ -425,7 +415,7 @@ static int hiface_pcm_prepare(struct snd_pcm_substream *alsa_sub) if (!sub) return -ENODEV; - mutex_lock(&rt->stream_mutex); + guard(mutex)(&rt->stream_mutex); hiface_pcm_stream_stop(rt); @@ -435,17 +425,12 @@ static int hiface_pcm_prepare(struct snd_pcm_substream *alsa_sub) if (rt->stream_state == STREAM_DISABLED) { ret = hiface_pcm_set_rate(rt, alsa_rt->rate); - if (ret) { - mutex_unlock(&rt->stream_mutex); + if (ret) return ret; - } ret = hiface_pcm_stream_start(rt); - if (ret) { - mutex_unlock(&rt->stream_mutex); + if (ret) return ret; - } } - mutex_unlock(&rt->stream_mutex); return 0; } @@ -462,16 +447,16 @@ static int hiface_pcm_trigger(struct snd_pcm_substream *alsa_sub, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - spin_lock_irq(&sub->lock); - sub->active = true; - spin_unlock_irq(&sub->lock); + scoped_guard(spinlock_irq, &sub->lock) { + sub->active = true; + } return 0; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - spin_lock_irq(&sub->lock); - sub->active = false; - spin_unlock_irq(&sub->lock); + scoped_guard(spinlock_irq, &sub->lock) { + sub->active = false; + } return 0; default: @@ -483,15 +468,13 @@ static snd_pcm_uframes_t hiface_pcm_pointer(struct snd_pcm_substream *alsa_sub) { struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub); struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); - unsigned long flags; snd_pcm_uframes_t dma_offset; if (rt->panic || !sub) return SNDRV_PCM_POS_XRUN; - spin_lock_irqsave(&sub->lock, flags); + guard(spinlock_irqsave)(&sub->lock); dma_offset = sub->dma_off; - spin_unlock_irqrestore(&sub->lock, flags); return bytes_to_frames(alsa_sub->runtime, dma_offset); } @@ -532,9 +515,8 @@ void hiface_pcm_abort(struct hiface_chip *chip) if (rt) { rt->panic = true; - mutex_lock(&rt->stream_mutex); + guard(mutex)(&rt->stream_mutex); hiface_pcm_stream_stop(rt); - mutex_unlock(&rt->stream_mutex); } } diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c index 84a9b7b76f43..9ef4faa006a0 100644 --- a/sound/usb/line6/capture.c +++ b/sound/usb/line6/capture.c @@ -145,8 +145,6 @@ void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length) static void audio_in_callback(struct urb *urb) { int i, index, length = 0, shutdown = 0; - unsigned long flags; - struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context; line6pcm->in.last_frame = urb->start_frame; @@ -156,7 +154,7 @@ static void audio_in_callback(struct urb *urb) if (urb == line6pcm->in.urbs[index]) break; - spin_lock_irqsave(&line6pcm->in.lock, flags); + guard(spinlock_irqsave)(&line6pcm->in.lock); for (i = 0; i < LINE6_ISO_PACKETS; ++i) { char *fbuf; @@ -211,8 +209,6 @@ static void audio_in_callback(struct urb *urb) test_bit(LINE6_STREAM_PCM, &line6pcm->in.running)) line6_capture_check_period(line6pcm, length); } - - spin_unlock_irqrestore(&line6pcm->in.lock, flags); } /* open capture callback */ diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index f2f9261489a2..e97368c31417 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -286,31 +286,30 @@ static void line6_data_received(struct urb *urb) { struct usb_line6 *line6 = (struct usb_line6 *)urb->context; struct midi_buffer *mb = &line6->line6midi->midibuf_in; - unsigned long flags; int done; if (urb->status == -ESHUTDOWN) return; if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { - spin_lock_irqsave(&line6->line6midi->lock, flags); - done = - line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length); - - if (done < urb->actual_length) { - line6_midibuf_ignore(mb, done); - dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n", - done, urb->actual_length); + scoped_guard(spinlock_irqsave, &line6->line6midi->lock) { + done = + line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length); + + if (done < urb->actual_length) { + line6_midibuf_ignore(mb, done); + dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n", + done, urb->actual_length); + } } - spin_unlock_irqrestore(&line6->line6midi->lock, flags); for (;;) { - spin_lock_irqsave(&line6->line6midi->lock, flags); - done = - line6_midibuf_read(mb, line6->buffer_message, - LINE6_MIDI_MESSAGE_MAXLEN, - LINE6_MIDIBUF_READ_RX); - spin_unlock_irqrestore(&line6->line6midi->lock, flags); + scoped_guard(spinlock_irqsave, &line6->line6midi->lock) { + done = + line6_midibuf_read(mb, line6->buffer_message, + LINE6_MIDI_MESSAGE_MAXLEN, + LINE6_MIDIBUF_READ_RX); + } if (done <= 0) break; @@ -628,16 +627,12 @@ line6_hwdep_write(struct snd_hwdep *hwdep, const char __user *data, long count, static __poll_t line6_hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait) { - __poll_t rv; struct usb_line6 *line6 = hwdep->private_data; poll_wait(file, &line6->messages.wait_queue, wait); - mutex_lock(&line6->messages.read_lock); - rv = kfifo_len(&line6->messages.fifo) == 0 ? 0 : EPOLLIN | EPOLLRDNORM; - mutex_unlock(&line6->messages.read_lock); - - return rv; + guard(mutex)(&line6->messages.read_lock); + return kfifo_len(&line6->messages.fifo) == 0 ? 0 : EPOLLIN | EPOLLRDNORM; } static const struct snd_hwdep_ops hwdep_ops = { diff --git a/sound/usb/line6/midi.c b/sound/usb/line6/midi.c index 1d77794b4490..4731293728e6 100644 --- a/sound/usb/line6/midi.c +++ b/sound/usb/line6/midi.c @@ -72,7 +72,6 @@ static void line6_midi_transmit(struct snd_rawmidi_substream *substream) */ static void midi_sent(struct urb *urb) { - unsigned long flags; int status; int num; struct usb_line6 *line6 = (struct usb_line6 *)urb->context; @@ -84,7 +83,7 @@ static void midi_sent(struct urb *urb) if (status == -ESHUTDOWN) return; - spin_lock_irqsave(&line6->line6midi->lock, flags); + guard(spinlock_irqsave)(&line6->line6midi->lock); num = --line6->line6midi->num_active_send_urbs; if (num == 0) { @@ -94,8 +93,6 @@ static void midi_sent(struct urb *urb) if (num == 0) wake_up(&line6->line6midi->send_wait); - - spin_unlock_irqrestore(&line6->line6midi->lock, flags); } /* @@ -158,17 +155,14 @@ static int line6_midi_output_close(struct snd_rawmidi_substream *substream) static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct usb_line6 *line6 = line6_rawmidi_substream_midi(substream)->line6; line6->line6midi->substream_transmit = substream; - spin_lock_irqsave(&line6->line6midi->lock, flags); + guard(spinlock_irqsave)(&line6->line6midi->lock); if (line6->line6midi->num_active_send_urbs == 0) line6_midi_transmit(substream); - - spin_unlock_irqrestore(&line6->line6midi->lock, flags); } static void line6_midi_output_drain(struct snd_rawmidi_substream *substream) diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c index c1e2a8ab66fa..f61d9f6cf754 100644 --- a/sound/usb/line6/pcm.c +++ b/sound/usb/line6/pcm.c @@ -182,11 +182,10 @@ static void line6_buffer_release(struct snd_line6_pcm *line6pcm, static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction, int type) { - unsigned long flags; struct line6_pcm_stream *pstr = get_stream(line6pcm, direction); int ret = 0; - spin_lock_irqsave(&pstr->lock, flags); + guard(spinlock_irqsave)(&pstr->lock); if (!test_and_set_bit(type, &pstr->running) && !(pstr->active_urbs || pstr->unlink_urbs)) { pstr->count = 0; @@ -199,7 +198,6 @@ static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction, if (ret < 0) clear_bit(type, &pstr->running); - spin_unlock_irqrestore(&pstr->lock, flags); return ret; } @@ -207,21 +205,20 @@ static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction, static void line6_stream_stop(struct snd_line6_pcm *line6pcm, int direction, int type) { - unsigned long flags; struct line6_pcm_stream *pstr = get_stream(line6pcm, direction); - spin_lock_irqsave(&pstr->lock, flags); - clear_bit(type, &pstr->running); - if (!pstr->running) { - spin_unlock_irqrestore(&pstr->lock, flags); - line6_unlink_audio_urbs(line6pcm, pstr); - spin_lock_irqsave(&pstr->lock, flags); - if (direction == SNDRV_PCM_STREAM_CAPTURE) { - line6pcm->prev_fbuf = NULL; - line6pcm->prev_fsize = 0; - } + scoped_guard(spinlock_irqsave, &pstr->lock) { + clear_bit(type, &pstr->running); + if (pstr->running) + return; + } + + line6_unlink_audio_urbs(line6pcm, pstr); + if (direction == SNDRV_PCM_STREAM_CAPTURE) { + guard(spinlock_irqsave)(&pstr->lock); + line6pcm->prev_fbuf = NULL; + line6pcm->prev_fsize = 0; } - spin_unlock_irqrestore(&pstr->lock, flags); } /* common PCM trigger callback */ @@ -295,6 +292,28 @@ snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream) return pstr->pos_done; } +/* Stop and release duplex streams */ +static void __line6_pcm_release(struct snd_line6_pcm *line6pcm, int type) +{ + struct line6_pcm_stream *pstr; + int dir; + + for (dir = 0; dir < 2; dir++) + line6_stream_stop(line6pcm, dir, type); + for (dir = 0; dir < 2; dir++) { + pstr = get_stream(line6pcm, dir); + line6_buffer_release(line6pcm, pstr, type); + } +} + +/* Stop and release duplex streams */ +void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type) +{ + guard(mutex)(&line6pcm->state_mutex); + __line6_pcm_release(line6pcm, type); +} +EXPORT_SYMBOL_GPL(line6_pcm_release); + /* Acquire and optionally start duplex streams: * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR */ @@ -304,7 +323,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, bool start) int ret = 0, dir; /* TODO: We should assert SNDRV_PCM_STREAM_PLAYBACK/CAPTURE == 0/1 */ - mutex_lock(&line6pcm->state_mutex); + guard(mutex)(&line6pcm->state_mutex); for (dir = 0; dir < 2; dir++) { pstr = get_stream(line6pcm, dir); ret = line6_buffer_acquire(line6pcm, pstr, dir, type); @@ -321,30 +340,12 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, bool start) } } error: - mutex_unlock(&line6pcm->state_mutex); if (ret < 0) - line6_pcm_release(line6pcm, type); + __line6_pcm_release(line6pcm, type); return ret; } EXPORT_SYMBOL_GPL(line6_pcm_acquire); -/* Stop and release duplex streams */ -void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type) -{ - struct line6_pcm_stream *pstr; - int dir; - - mutex_lock(&line6pcm->state_mutex); - for (dir = 0; dir < 2; dir++) - line6_stream_stop(line6pcm, dir, type); - for (dir = 0; dir < 2; dir++) { - pstr = get_stream(line6pcm, dir); - line6_buffer_release(line6pcm, pstr, type); - } - mutex_unlock(&line6pcm->state_mutex); -} -EXPORT_SYMBOL_GPL(line6_pcm_release); - /* common PCM hw_params callback */ int snd_line6_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) @@ -353,16 +354,14 @@ int snd_line6_hw_params(struct snd_pcm_substream *substream, struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); - mutex_lock(&line6pcm->state_mutex); + guard(mutex)(&line6pcm->state_mutex); ret = line6_buffer_acquire(line6pcm, pstr, substream->stream, LINE6_STREAM_PCM); if (ret < 0) - goto error; + return ret; pstr->period = params_period_bytes(hw_params); - error: - mutex_unlock(&line6pcm->state_mutex); - return ret; + return 0; } /* common PCM hw_free callback */ @@ -371,9 +370,8 @@ int snd_line6_hw_free(struct snd_pcm_substream *substream) struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); - mutex_lock(&line6pcm->state_mutex); + guard(mutex)(&line6pcm->state_mutex); line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM); - mutex_unlock(&line6pcm->state_mutex); return 0; } @@ -588,7 +586,7 @@ int snd_line6_prepare(struct snd_pcm_substream *substream) struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); - mutex_lock(&line6pcm->state_mutex); + guard(mutex)(&line6pcm->state_mutex); if (!pstr->running) line6_wait_clear_audio_urbs(line6pcm, pstr); @@ -602,6 +600,5 @@ int snd_line6_prepare(struct snd_pcm_substream *substream) line6pcm->in.bytes = 0; } - mutex_unlock(&line6pcm->state_mutex); return 0; } diff --git a/sound/usb/media.c b/sound/usb/media.c index d48db6f3ae65..0064f8d12422 100644 --- a/sound/usb/media.c +++ b/sound/usb/media.c @@ -140,11 +140,10 @@ int snd_media_start_pipeline(struct snd_usb_substream *subs) if (!mctl) return 0; - mutex_lock(&mctl->media_dev->graph_mutex); + guard(mutex)(&mctl->media_dev->graph_mutex); if (mctl->media_dev->enable_source) ret = mctl->media_dev->enable_source(&mctl->media_entity, &mctl->media_pipe); - mutex_unlock(&mctl->media_dev->graph_mutex); return ret; } @@ -155,10 +154,9 @@ void snd_media_stop_pipeline(struct snd_usb_substream *subs) if (!mctl) return; - mutex_lock(&mctl->media_dev->graph_mutex); + guard(mutex)(&mctl->media_dev->graph_mutex); if (mctl->media_dev->disable_source) mctl->media_dev->disable_source(&mctl->media_entity); - mutex_unlock(&mctl->media_dev->graph_mutex); } static int snd_media_mixer_init(struct snd_usb_audio *chip) diff --git a/sound/usb/midi.c b/sound/usb/midi.c index acb3bf92857c..dd8249e75970 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -265,16 +265,15 @@ static void snd_usbmidi_out_urb_complete(struct urb *urb) struct out_urb_context *context = urb->context; struct snd_usb_midi_out_endpoint *ep = context->ep; unsigned int urb_index; - unsigned long flags; - - spin_lock_irqsave(&ep->buffer_lock, flags); - urb_index = context - ep->urbs; - ep->active_urbs &= ~(1 << urb_index); - if (unlikely(ep->drain_urbs)) { - ep->drain_urbs &= ~(1 << urb_index); - wake_up(&ep->drain_wait); + + scoped_guard(spinlock_irqsave, &ep->buffer_lock) { + urb_index = context - ep->urbs; + ep->active_urbs &= ~(1 << urb_index); + if (unlikely(ep->drain_urbs)) { + ep->drain_urbs &= ~(1 << urb_index); + wake_up(&ep->drain_wait); + } } - spin_unlock_irqrestore(&ep->buffer_lock, flags); if (urb->status < 0) { int err = snd_usbmidi_urb_error(urb); if (err < 0) { @@ -295,13 +294,10 @@ static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint *ep) { unsigned int urb_index; struct urb *urb; - unsigned long flags; - spin_lock_irqsave(&ep->buffer_lock, flags); - if (ep->umidi->disconnected) { - spin_unlock_irqrestore(&ep->buffer_lock, flags); + guard(spinlock_irqsave)(&ep->buffer_lock); + if (ep->umidi->disconnected) return; - } urb_index = ep->next_urb; for (;;) { @@ -325,7 +321,6 @@ static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint *ep) break; } ep->next_urb = urb_index; - spin_unlock_irqrestore(&ep->buffer_lock, flags); } static void snd_usbmidi_out_work(struct work_struct *work) @@ -342,9 +337,8 @@ static void snd_usbmidi_error_timer(struct timer_list *t) struct snd_usb_midi *umidi = timer_container_of(umidi, t, error_timer); unsigned int i, j; - spin_lock(&umidi->disc_lock); + guard(spinlock)(&umidi->disc_lock); if (umidi->disconnected) { - spin_unlock(&umidi->disc_lock); return; } for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { @@ -361,7 +355,6 @@ static void snd_usbmidi_error_timer(struct timer_list *t) if (umidi->endpoints[i].out) snd_usbmidi_do_output(umidi->endpoints[i].out); } - spin_unlock(&umidi->disc_lock); } /* helper function to send static data that may not DMA-able */ @@ -1148,13 +1141,11 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir, struct snd_usb_midi *umidi = substream->rmidi->private_data; struct snd_kcontrol *ctl; - down_read(&umidi->disc_rwsem); - if (umidi->disconnected) { - up_read(&umidi->disc_rwsem); + guard(rwsem_read)(&umidi->disc_rwsem); + if (umidi->disconnected) return open ? -ENODEV : 0; - } - mutex_lock(&umidi->mutex); + guard(mutex)(&umidi->mutex); if (open) { if (!umidi->opened[0] && !umidi->opened[1]) { if (umidi->roland_load_ctl) { @@ -1183,8 +1174,6 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir, } } } - mutex_unlock(&umidi->mutex); - up_read(&umidi->disc_rwsem); return 0; } @@ -1522,15 +1511,14 @@ static void snd_usbmidi_free(struct snd_usb_midi *umidi) { int i; + if (!umidi->disconnected) + snd_usbmidi_disconnect(&umidi->list); + for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i]; - if (ep->out) - snd_usbmidi_out_endpoint_delete(ep->out); - if (ep->in) - snd_usbmidi_in_endpoint_delete(ep->in); + kfree(ep->out); } mutex_destroy(&umidi->mutex); - timer_shutdown_sync(&umidi->error_timer); kfree(umidi); } @@ -1548,11 +1536,10 @@ void snd_usbmidi_disconnect(struct list_head *p) * a timer may submit an URB. To reliably break the cycle * a flag under lock must be used */ - down_write(&umidi->disc_rwsem); - spin_lock_irq(&umidi->disc_lock); - umidi->disconnected = 1; - spin_unlock_irq(&umidi->disc_lock); - up_write(&umidi->disc_rwsem); + scoped_guard(rwsem_write, &umidi->disc_rwsem) { + guard(spinlock_irq)(&umidi->disc_lock); + umidi->disconnected = 1; + } timer_shutdown_sync(&umidi->error_timer); @@ -2094,11 +2081,10 @@ static int roland_load_put(struct snd_kcontrol *kcontrol, if (value->value.enumerated.item[0] > 1) return -EINVAL; - mutex_lock(&umidi->mutex); + guard(mutex)(&umidi->mutex); changed = value->value.enumerated.item[0] != kcontrol->private_value; if (changed) kcontrol->private_value = value->value.enumerated.item[0]; - mutex_unlock(&umidi->mutex); return changed; } @@ -2448,18 +2434,17 @@ static void snd_usbmidi_input_start_ep(struct snd_usb_midi *umidi, struct snd_usb_midi_in_endpoint *ep) { unsigned int i; - unsigned long flags; if (!ep) return; for (i = 0; i < INPUT_URBS; ++i) { struct urb *urb = ep->urbs[i]; - spin_lock_irqsave(&umidi->disc_lock, flags); - if (!atomic_read(&urb->use_count)) { - urb->dev = ep->umidi->dev; - snd_usbmidi_submit_urb(urb, GFP_ATOMIC); + scoped_guard(spinlock_irqsave, &umidi->disc_lock) { + if (!atomic_read(&urb->use_count)) { + urb->dev = ep->umidi->dev; + snd_usbmidi_submit_urb(urb, GFP_ATOMIC); + } } - spin_unlock_irqrestore(&umidi->disc_lock, flags); } } @@ -2488,9 +2473,8 @@ void snd_usbmidi_suspend(struct list_head *p) struct snd_usb_midi *umidi; umidi = list_entry(p, struct snd_usb_midi, list); - mutex_lock(&umidi->mutex); + guard(mutex)(&umidi->mutex); snd_usbmidi_input_stop(p); - mutex_unlock(&umidi->mutex); } EXPORT_SYMBOL(snd_usbmidi_suspend); @@ -2502,9 +2486,8 @@ void snd_usbmidi_resume(struct list_head *p) struct snd_usb_midi *umidi; umidi = list_entry(p, struct snd_usb_midi, list); - mutex_lock(&umidi->mutex); + guard(mutex)(&umidi->mutex); snd_usbmidi_input_start(p); - mutex_unlock(&umidi->mutex); } EXPORT_SYMBOL(snd_usbmidi_resume); diff --git a/sound/usb/midi2.c b/sound/usb/midi2.c index 030569fda416..e6793f3bdfc3 100644 --- a/sound/usb/midi2.c +++ b/sound/usb/midi2.c @@ -160,15 +160,13 @@ static void output_urb_complete(struct urb *urb) { struct snd_usb_midi2_urb *ctx = urb->context; struct snd_usb_midi2_endpoint *ep = ctx->ep; - unsigned long flags; - spin_lock_irqsave(&ep->lock, flags); + guard(spinlock_irqsave)(&ep->lock); set_bit(ctx->index, &ep->urb_free); if (urb->status >= 0 && atomic_read(&ep->running)) submit_output_urbs_locked(ep); if (ep->urb_free == ep->urb_free_mask) wake_up(&ep->wait); - spin_unlock_irqrestore(&ep->lock, flags); } /* prepare for input submission: just set the buffer length */ @@ -189,10 +187,9 @@ static void input_urb_complete(struct urb *urb) { struct snd_usb_midi2_urb *ctx = urb->context; struct snd_usb_midi2_endpoint *ep = ctx->ep; - unsigned long flags; int len; - spin_lock_irqsave(&ep->lock, flags); + guard(spinlock_irqsave)(&ep->lock); if (ep->disconnected || urb->status < 0) goto dequeue; len = urb->actual_length; @@ -208,22 +205,18 @@ static void input_urb_complete(struct urb *urb) submit_input_urbs_locked(ep); if (ep->urb_free == ep->urb_free_mask) wake_up(&ep->wait); - spin_unlock_irqrestore(&ep->lock, flags); } /* URB submission helper; for both direction */ static void submit_io_urbs(struct snd_usb_midi2_endpoint *ep) { - unsigned long flags; - if (!ep) return; - spin_lock_irqsave(&ep->lock, flags); + guard(spinlock_irqsave)(&ep->lock); if (ep->direction == STR_IN) submit_input_urbs_locked(ep); else submit_output_urbs_locked(ep); - spin_unlock_irqrestore(&ep->lock, flags); } /* kill URBs for close, suspend and disconnect */ @@ -248,13 +241,12 @@ static void drain_urb_queue(struct snd_usb_midi2_endpoint *ep) { if (!ep) return; - spin_lock_irq(&ep->lock); + guard(spinlock_irq)(&ep->lock); atomic_set(&ep->running, 0); wait_event_lock_irq_timeout(ep->wait, ep->disconnected || ep->urb_free == ep->urb_free_mask, ep->lock, msecs_to_jiffies(500)); - spin_unlock_irq(&ep->lock); } /* release URBs for an EP */ diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index e200e4af799c..76b6eb55dcc2 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -171,7 +171,6 @@ static void playback_urb_complete(struct urb *usb_urb) { struct ua101_urb *urb = (struct ua101_urb *)usb_urb; struct ua101 *ua = urb->urb.context; - unsigned long flags; if (unlikely(urb->urb.status == -ENOENT || /* unlinked */ urb->urb.status == -ENODEV || /* device removed */ @@ -184,14 +183,13 @@ static void playback_urb_complete(struct urb *usb_urb) if (test_bit(USB_PLAYBACK_RUNNING, &ua->states)) { /* append URB to FIFO */ - spin_lock_irqsave(&ua->lock, flags); + guard(spinlock_irqsave)(&ua->lock); list_add_tail(&urb->ready_list, &ua->ready_playback_urbs); if (ua->rate_feedback_count > 0) queue_work(system_highpri_wq, &ua->playback_work); ua->playback.substream->runtime->delay -= urb->urb.iso_frame_desc[0].length / ua->playback.frame_bytes; - spin_unlock_irqrestore(&ua->lock, flags); } } @@ -249,7 +247,6 @@ static inline void add_with_wraparound(struct ua101 *ua, static void playback_work(struct work_struct *work) { struct ua101 *ua = container_of(work, struct ua101, playback_work); - unsigned long flags; unsigned int frames; struct ua101_urb *urb; bool do_period_elapsed = false; @@ -269,43 +266,43 @@ static void playback_work(struct work_struct *work) * submitting playback URBs is possible as long as both FIFOs are * nonempty. */ - spin_lock_irqsave(&ua->lock, flags); - while (ua->rate_feedback_count > 0 && - !list_empty(&ua->ready_playback_urbs)) { - /* take packet size out of FIFO */ - frames = ua->rate_feedback[ua->rate_feedback_start]; - add_with_wraparound(ua, &ua->rate_feedback_start, 1); - ua->rate_feedback_count--; - - /* take URB out of FIFO */ - urb = list_first_entry(&ua->ready_playback_urbs, - struct ua101_urb, ready_list); - list_del(&urb->ready_list); - - /* fill packet with data or silence */ - urb->urb.iso_frame_desc[0].length = - frames * ua->playback.frame_bytes; - if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) - do_period_elapsed |= copy_playback_data(&ua->playback, - &urb->urb, - frames); - else - memset(urb->urb.transfer_buffer, 0, - urb->urb.iso_frame_desc[0].length); - - /* and off you go ... */ - err = usb_submit_urb(&urb->urb, GFP_ATOMIC); - if (unlikely(err < 0)) { - spin_unlock_irqrestore(&ua->lock, flags); - abort_usb_playback(ua); - abort_alsa_playback(ua); - dev_err(&ua->dev->dev, "USB request error %d: %s\n", - err, usb_error_string(err)); - return; + scoped_guard(spinlock_irqsave, &ua->lock) { + while (ua->rate_feedback_count > 0 && + !list_empty(&ua->ready_playback_urbs)) { + /* take packet size out of FIFO */ + frames = ua->rate_feedback[ua->rate_feedback_start]; + add_with_wraparound(ua, &ua->rate_feedback_start, 1); + ua->rate_feedback_count--; + + /* take URB out of FIFO */ + urb = list_first_entry(&ua->ready_playback_urbs, + struct ua101_urb, ready_list); + list_del(&urb->ready_list); + + /* fill packet with data or silence */ + urb->urb.iso_frame_desc[0].length = + frames * ua->playback.frame_bytes; + if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) + do_period_elapsed |= copy_playback_data(&ua->playback, + &urb->urb, + frames); + else + memset(urb->urb.transfer_buffer, 0, + urb->urb.iso_frame_desc[0].length); + + /* and off you go ... */ + err = usb_submit_urb(&urb->urb, GFP_ATOMIC); + if (unlikely(err < 0)) { + abort_usb_playback(ua); + abort_alsa_playback(ua); + dev_err(&ua->dev->dev, "USB request error %d: %s\n", + err, usb_error_string(err)); + return; + } + ua->playback.substream->runtime->delay += frames; } - ua->playback.substream->runtime->delay += frames; } - spin_unlock_irqrestore(&ua->lock, flags); + if (do_period_elapsed) snd_pcm_period_elapsed(ua->playback.substream); } @@ -347,7 +344,6 @@ static void capture_urb_complete(struct urb *urb) { struct ua101 *ua = urb->context; struct ua101_stream *stream = &ua->capture; - unsigned long flags; unsigned int frames, write_ptr; bool do_period_elapsed; int err; @@ -364,47 +360,45 @@ static void capture_urb_complete(struct urb *urb) else frames = 0; - spin_lock_irqsave(&ua->lock, flags); - - if (frames > 0 && test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) - do_period_elapsed = copy_capture_data(stream, urb, frames); - else - do_period_elapsed = false; + scoped_guard(spinlock_irqsave, &ua->lock) { - if (test_bit(USB_CAPTURE_RUNNING, &ua->states)) { - err = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(err < 0)) { - spin_unlock_irqrestore(&ua->lock, flags); - dev_err(&ua->dev->dev, "USB request error %d: %s\n", - err, usb_error_string(err)); - goto stream_stopped; - } + if (frames > 0 && test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) + do_period_elapsed = copy_capture_data(stream, urb, frames); + else + do_period_elapsed = false; + + if (test_bit(USB_CAPTURE_RUNNING, &ua->states)) { + err = usb_submit_urb(urb, GFP_ATOMIC); + if (unlikely(err < 0)) { + dev_err(&ua->dev->dev, "USB request error %d: %s\n", + err, usb_error_string(err)); + goto stream_stopped; + } - /* append packet size to FIFO */ - write_ptr = ua->rate_feedback_start; - add_with_wraparound(ua, &write_ptr, ua->rate_feedback_count); - ua->rate_feedback[write_ptr] = frames; - if (ua->rate_feedback_count < ua->playback.queue_length) { - ua->rate_feedback_count++; - if (ua->rate_feedback_count == - ua->playback.queue_length) - wake_up(&ua->rate_feedback_wait); - } else { - /* - * Ring buffer overflow; this happens when the playback - * stream is not running. Throw away the oldest entry, - * so that the playback stream, when it starts, sees - * the most recent packet sizes. - */ - add_with_wraparound(ua, &ua->rate_feedback_start, 1); + /* append packet size to FIFO */ + write_ptr = ua->rate_feedback_start; + add_with_wraparound(ua, &write_ptr, ua->rate_feedback_count); + ua->rate_feedback[write_ptr] = frames; + if (ua->rate_feedback_count < ua->playback.queue_length) { + ua->rate_feedback_count++; + if (ua->rate_feedback_count == + ua->playback.queue_length) + wake_up(&ua->rate_feedback_wait); + } else { + /* + * Ring buffer overflow; this happens when the playback + * stream is not running. Throw away the oldest entry, + * so that the playback stream, when it starts, sees + * the most recent packet sizes. + */ + add_with_wraparound(ua, &ua->rate_feedback_start, 1); + } + if (test_bit(USB_PLAYBACK_RUNNING, &ua->states) && + !list_empty(&ua->ready_playback_urbs)) + queue_work(system_highpri_wq, &ua->playback_work); } - if (test_bit(USB_PLAYBACK_RUNNING, &ua->states) && - !list_empty(&ua->ready_playback_urbs)) - queue_work(system_highpri_wq, &ua->playback_work); } - spin_unlock_irqrestore(&ua->lock, flags); - if (do_period_elapsed) snd_pcm_period_elapsed(stream->substream); @@ -558,9 +552,9 @@ static int start_usb_playback(struct ua101 *ua) clear_bit(PLAYBACK_URB_COMPLETED, &ua->states); ua->playback.urbs[0]->urb.complete = first_playback_urb_complete; - spin_lock_irq(&ua->lock); - INIT_LIST_HEAD(&ua->ready_playback_urbs); - spin_unlock_irq(&ua->lock); + scoped_guard(spinlock_irq, &ua->lock) { + INIT_LIST_HEAD(&ua->ready_playback_urbs); + } /* * We submit the initial URBs all at once, so we have to wait for the @@ -581,11 +575,11 @@ static int start_usb_playback(struct ua101 *ua) for (i = 0; i < ua->playback.queue_length; ++i) { /* all initial URBs contain silence */ - spin_lock_irq(&ua->lock); - frames = ua->rate_feedback[ua->rate_feedback_start]; - add_with_wraparound(ua, &ua->rate_feedback_start, 1); - ua->rate_feedback_count--; - spin_unlock_irq(&ua->lock); + scoped_guard(spinlock_irq, &ua->lock) { + frames = ua->rate_feedback[ua->rate_feedback_start]; + add_with_wraparound(ua, &ua->rate_feedback_start, 1); + ua->rate_feedback_count--; + } urb = &ua->playback.urbs[i]->urb; urb->iso_frame_desc[0].length = frames * ua->playback.frame_bytes; @@ -658,11 +652,10 @@ static int capture_pcm_open(struct snd_pcm_substream *substream) DIV_ROUND_CLOSEST(ua->rate, ua->packets_per_second); substream->runtime->delay = substream->runtime->hw.fifo_size; - mutex_lock(&ua->mutex); + guard(mutex)(&ua->mutex); err = start_usb_capture(ua); if (err >= 0) set_bit(ALSA_CAPTURE_OPEN, &ua->states); - mutex_unlock(&ua->mutex); return err; } @@ -679,31 +672,28 @@ static int playback_pcm_open(struct snd_pcm_substream *substream) DIV_ROUND_CLOSEST(ua->rate * ua->playback.queue_length, ua->packets_per_second); - mutex_lock(&ua->mutex); + guard(mutex)(&ua->mutex); err = start_usb_capture(ua); if (err < 0) - goto error; + return err; err = start_usb_playback(ua); if (err < 0) { if (!test_bit(ALSA_CAPTURE_OPEN, &ua->states)) stop_usb_capture(ua); - goto error; + return err; } set_bit(ALSA_PLAYBACK_OPEN, &ua->states); -error: - mutex_unlock(&ua->mutex); - return err; + return 0; } static int capture_pcm_close(struct snd_pcm_substream *substream) { struct ua101 *ua = substream->private_data; - mutex_lock(&ua->mutex); + guard(mutex)(&ua->mutex); clear_bit(ALSA_CAPTURE_OPEN, &ua->states); if (!test_bit(ALSA_PLAYBACK_OPEN, &ua->states)) stop_usb_capture(ua); - mutex_unlock(&ua->mutex); return 0; } @@ -711,12 +701,11 @@ static int playback_pcm_close(struct snd_pcm_substream *substream) { struct ua101 *ua = substream->private_data; - mutex_lock(&ua->mutex); + guard(mutex)(&ua->mutex); stop_usb_playback(ua); clear_bit(ALSA_PLAYBACK_OPEN, &ua->states); if (!test_bit(ALSA_CAPTURE_OPEN, &ua->states)) stop_usb_capture(ua); - mutex_unlock(&ua->mutex); return 0; } @@ -724,12 +713,9 @@ static int capture_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct ua101 *ua = substream->private_data; - int err; - mutex_lock(&ua->mutex); - err = start_usb_capture(ua); - mutex_unlock(&ua->mutex); - return err; + guard(mutex)(&ua->mutex); + return start_usb_capture(ua); } static int playback_pcm_hw_params(struct snd_pcm_substream *substream, @@ -738,11 +724,10 @@ static int playback_pcm_hw_params(struct snd_pcm_substream *substream, struct ua101 *ua = substream->private_data; int err; - mutex_lock(&ua->mutex); + guard(mutex)(&ua->mutex); err = start_usb_capture(ua); if (err >= 0) err = start_usb_playback(ua); - mutex_unlock(&ua->mutex); return err; } @@ -751,9 +736,9 @@ static int capture_pcm_prepare(struct snd_pcm_substream *substream) struct ua101 *ua = substream->private_data; int err; - mutex_lock(&ua->mutex); - err = start_usb_capture(ua); - mutex_unlock(&ua->mutex); + scoped_guard(mutex, &ua->mutex) { + err = start_usb_capture(ua); + } if (err < 0) return err; @@ -781,11 +766,11 @@ static int playback_pcm_prepare(struct snd_pcm_substream *substream) struct ua101 *ua = substream->private_data; int err; - mutex_lock(&ua->mutex); - err = start_usb_capture(ua); - if (err >= 0) - err = start_usb_playback(ua); - mutex_unlock(&ua->mutex); + scoped_guard(mutex, &ua->mutex) { + err = start_usb_capture(ua); + if (err >= 0) + err = start_usb_playback(ua); + } if (err < 0) return err; @@ -843,13 +828,8 @@ static int playback_pcm_trigger(struct snd_pcm_substream *substream, int cmd) static inline snd_pcm_uframes_t ua101_pcm_pointer(struct ua101 *ua, struct ua101_stream *stream) { - unsigned long flags; - unsigned int pos; - - spin_lock_irqsave(&ua->lock, flags); - pos = stream->buffer_pos; - spin_unlock_irqrestore(&ua->lock, flags); - return pos; + guard(spinlock_irqsave)(&ua->lock); + return stream->buffer_pos; } static snd_pcm_uframes_t capture_pcm_pointer(struct snd_pcm_substream *subs) @@ -1127,18 +1107,18 @@ static void free_usb_related_resources(struct ua101 *ua, unsigned int i; struct usb_interface *intf; - mutex_lock(&ua->mutex); - free_stream_urbs(&ua->capture); - free_stream_urbs(&ua->playback); - mutex_unlock(&ua->mutex); + scoped_guard(mutex, &ua->mutex) { + free_stream_urbs(&ua->capture); + free_stream_urbs(&ua->playback); + } free_stream_buffers(ua, &ua->capture); free_stream_buffers(ua, &ua->playback); for (i = 0; i < ARRAY_SIZE(ua->intf); ++i) { - mutex_lock(&ua->mutex); - intf = ua->intf[i]; - ua->intf[i] = NULL; - mutex_unlock(&ua->mutex); + scoped_guard(mutex, &ua->mutex) { + intf = ua->intf[i]; + ua->intf[i] = NULL; + } if (intf) { usb_set_intfdata(intf, NULL); if (intf != interface) @@ -1192,22 +1172,18 @@ static int ua101_probe(struct usb_interface *interface, intf_numbers[is_ua1000][0]) return -ENODEV; - mutex_lock(&devices_mutex); + guard(mutex)(&devices_mutex); for (card_index = 0; card_index < SNDRV_CARDS; ++card_index) if (enable[card_index] && !(devices_used & (1 << card_index))) break; - if (card_index >= SNDRV_CARDS) { - mutex_unlock(&devices_mutex); + if (card_index >= SNDRV_CARDS) return -ENOENT; - } err = snd_card_new(&interface->dev, index[card_index], id[card_index], THIS_MODULE, sizeof(*ua), &card); - if (err < 0) { - mutex_unlock(&devices_mutex); + if (err < 0) return err; - } card->private_free = ua101_card_free; ua = card->private_data; ua->dev = interface_to_usbdev(interface); @@ -1290,13 +1266,11 @@ static int ua101_probe(struct usb_interface *interface, usb_set_intfdata(interface, ua); devices_used |= 1 << card_index; - mutex_unlock(&devices_mutex); return 0; probe_error: free_usb_related_resources(ua, interface); snd_card_free(card); - mutex_unlock(&devices_mutex); return err; } @@ -1308,7 +1282,7 @@ static void ua101_disconnect(struct usb_interface *interface) if (!ua) return; - mutex_lock(&devices_mutex); + guard(mutex)(&devices_mutex); set_bit(DISCONNECTED, &ua->states); wake_up(&ua->rate_feedback_wait); @@ -1321,18 +1295,16 @@ static void ua101_disconnect(struct usb_interface *interface) snd_usbmidi_disconnect(midi); abort_alsa_playback(ua); abort_alsa_capture(ua); - mutex_lock(&ua->mutex); - stop_usb_playback(ua); - stop_usb_capture(ua); - mutex_unlock(&ua->mutex); + scoped_guard(mutex, &ua->mutex) { + stop_usb_playback(ua); + stop_usb_capture(ua); + } free_usb_related_resources(ua, interface); devices_used &= ~(1 << ua->card_index); snd_card_free_when_closed(ua->card); - - mutex_unlock(&devices_mutex); } static const struct usb_device_id ua101_ids[] = { diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 63b300bc67ba..34bcbfd8b54e 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -313,8 +313,8 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int timeout = 10; int idx = 0, err; - err = snd_usb_lock_shutdown(chip); - if (err < 0) + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) return -EIO; while (timeout-- > 0) { @@ -324,20 +324,15 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, validx, idx, buf, val_len); if (err >= val_len) { *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); - err = 0; - goto out; + return 0; } else if (err == -ETIMEDOUT) { - goto out; + return err; } } usb_audio_dbg(chip, "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", request, validx, idx, cval->val_type); - err = -EINVAL; - - out: - snd_usb_unlock_shutdown(chip); - return err; + return -EINVAL; } static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, @@ -362,14 +357,16 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, memset(buf, 0, sizeof(buf)); - if (snd_usb_lock_shutdown(chip)) - return -EIO; + { + CLASS(snd_usb_lock, pm)(chip); + if (pm.err) + return -EIO; - idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8); - ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, idx, buf, size); - snd_usb_unlock_shutdown(chip); + idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8); + ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + validx, idx, buf, size); + } if (ret < 0) { usb_audio_dbg(chip, @@ -484,8 +481,8 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, buf[2] = (value_set >> 16) & 0xff; buf[3] = (value_set >> 24) & 0xff; - err = snd_usb_lock_shutdown(chip); - if (err < 0) + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) return -EIO; while (timeout-- > 0) { @@ -494,20 +491,14 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, usb_sndctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, validx, idx, buf, val_len); - if (err >= 0) { - err = 0; - goto out; - } else if (err == -ETIMEDOUT) { - goto out; - } + if (err >= 0) + return 0; + else if (err == -ETIMEDOUT) + return err; } usb_audio_dbg(chip, "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", request, validx, idx, cval->val_type, buf[0], buf[1]); - err = -EINVAL; - - out: - snd_usb_unlock_shutdown(chip); - return err; + return -EINVAL; } static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, @@ -1191,6 +1182,13 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, cval->res = 1; } break; + case USB_ID(0x3302, 0x12db): /* MOONDROP Quark2 */ + if (!strcmp(kctl->id.name, "PCM Playback Volume")) { + usb_audio_info(chip, + "set volume quirk for MOONDROP Quark2\n"); + cval->min = -14208; /* Mute under it */ + } + break; } } @@ -1494,9 +1492,11 @@ static int get_connector_value(struct usb_mixer_elem_info *cval, validx = cval->control << 8 | 0; - ret = snd_usb_lock_shutdown(chip) ? -EIO : 0; - if (ret) + CLASS(snd_usb_lock, pm)(chip); + if (pm.err) { + ret = -EIO; goto error; + } idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8); if (cval->head.mixer->protocol == UAC_VERSION_2) { @@ -1517,8 +1517,6 @@ static int get_connector_value(struct usb_mixer_elem_info *cval, *val = !!uac3_conn.bmConInserted; } - snd_usb_unlock_shutdown(chip); - if (ret < 0) { if (name && strstr(name, "Speaker")) { if (val) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 3df537fdb9f1..828af3095b86 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -307,9 +307,9 @@ static int snd_audigy2nx_led_update(struct usb_mixer_interface *mixer, struct snd_usb_audio *chip = mixer->chip; int err; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; if (chip->usb_id == USB_ID(0x041e, 0x3042)) err = snd_usb_ctl_msg(chip->dev, @@ -327,7 +327,6 @@ static int snd_audigy2nx_led_update(struct usb_mixer_interface *mixer, usb_sndctrlpipe(chip->dev, 0), 0x24, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, value, index + 2, NULL, 0); - snd_usb_unlock_shutdown(chip); return err; } @@ -438,15 +437,14 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, for (i = 0; jacks[i].name; ++i) { snd_iprintf(buffer, "%s: ", jacks[i].name); - err = snd_usb_lock_shutdown(mixer->chip); - if (err < 0) + CLASS(snd_usb_lock, pm)(mixer->chip); + if (pm.err < 0) return; err = snd_usb_ctl_msg(mixer->chip->dev, usb_rcvctrlpipe(mixer->chip->dev, 0), UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, jacks[i].unitid << 8, buf, 3); - snd_usb_unlock_shutdown(mixer->chip); if (err == 3 && (buf[0] == 3 || buf[0] == 6)) snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); else @@ -474,21 +472,18 @@ static int snd_emu0204_ch_switch_update(struct usb_mixer_interface *mixer, int value) { struct snd_usb_audio *chip = mixer->chip; - int err; unsigned char buf[2]; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; buf[0] = 0x01; buf[1] = value ? 0x02 : 0x01; - err = snd_usb_ctl_msg(chip->dev, - usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - 0x0400, 0x0e00, buf, 2); - snd_usb_unlock_shutdown(chip); - return err; + return snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, + 0x0400, 0x0e00, buf, 2); } static int snd_emu0204_ch_switch_put(struct snd_kcontrol *kcontrol, @@ -804,17 +799,14 @@ static int snd_xonar_u1_switch_update(struct usb_mixer_interface *mixer, unsigned char status) { struct snd_usb_audio *chip = mixer->chip; - int err; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; - err = snd_usb_ctl_msg(chip->dev, - usb_sndctrlpipe(chip->dev, 0), 0x08, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, - 50, 0, &status, 1); - snd_usb_unlock_shutdown(chip); - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; + return snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), 0x08, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, + 50, 0, &status, 1); } static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, @@ -945,20 +937,17 @@ static int snd_mbox1_clk_switch_get(struct snd_kcontrol *kctl, struct snd_usb_audio *chip = list->mixer->chip; int err; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - goto err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; err = snd_mbox1_is_spdif_synced(chip); if (err < 0) - goto err; + return err; kctl->private_value = err; - err = 0; ucontrol->value.enumerated.item[0] = kctl->private_value; -err: - snd_usb_unlock_shutdown(chip); - return err; + return 0; } static int snd_mbox1_clk_switch_update(struct usb_mixer_interface *mixer, int is_spdif_sync) @@ -966,27 +955,24 @@ static int snd_mbox1_clk_switch_update(struct usb_mixer_interface *mixer, int is struct snd_usb_audio *chip = mixer->chip; int err; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; err = snd_mbox1_is_spdif_input(chip); if (err < 0) - goto err; + return err; err = snd_mbox1_is_spdif_synced(chip); if (err < 0) - goto err; + return err; /* FIXME: hardcoded sample rate */ err = snd_mbox1_set_clk_source(chip, is_spdif_sync ? 0 : 48000); if (err < 0) - goto err; + return err; - err = snd_mbox1_is_spdif_synced(chip); -err: - snd_usb_unlock_shutdown(chip); - return err; + return snd_mbox1_is_spdif_synced(chip); } static int snd_mbox1_clk_switch_put(struct snd_kcontrol *kctl, @@ -1037,26 +1023,23 @@ static int snd_mbox1_src_switch_update(struct usb_mixer_interface *mixer, int is struct snd_usb_audio *chip = mixer->chip; int err; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; err = snd_mbox1_is_spdif_input(chip); if (err < 0) - goto err; + return err; err = snd_mbox1_set_input_source(chip, is_spdif_input); if (err < 0) - goto err; + return err; err = snd_mbox1_is_spdif_input(chip); if (err < 0) - goto err; + return err; - err = snd_mbox1_is_spdif_synced(chip); -err: - snd_usb_unlock_shutdown(chip); - return err; + return snd_mbox1_is_spdif_synced(chip); } static int snd_mbox1_src_switch_put(struct snd_kcontrol *kctl, @@ -1167,17 +1150,14 @@ static int snd_ni_update_cur_val(struct usb_mixer_elem_list *list) { struct snd_usb_audio *chip = list->mixer->chip; unsigned int pval = list->kctl->private_value; - int err; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; - err = usb_control_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), - (pval >> 16) & 0xff, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, - pval >> 24, pval & 0xffff, NULL, 0, 1000); - snd_usb_unlock_shutdown(chip); - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; + return usb_control_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), + (pval >> 16) & 0xff, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + pval >> 24, pval & 0xffff, NULL, 0, 1000); } static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, @@ -1329,23 +1309,20 @@ static int snd_ftu_eff_switch_update(struct usb_mixer_elem_list *list) struct snd_usb_audio *chip = list->mixer->chip; unsigned int pval = list->kctl->private_value; unsigned char value[2]; - int err; value[0] = pval >> 24; value[1] = 0; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; - err = snd_usb_ctl_msg(chip->dev, - usb_sndctrlpipe(chip->dev, 0), - UAC_SET_CUR, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - pval & 0xff00, - snd_usb_ctrl_intf(list->mixer->hostif) | ((pval & 0xff) << 8), - value, 2); - snd_usb_unlock_shutdown(chip); - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; + return snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), + UAC_SET_CUR, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, + pval & 0xff00, + snd_usb_ctrl_intf(list->mixer->hostif) | ((pval & 0xff) << 8), + value, 2); } static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, @@ -1908,9 +1885,9 @@ static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol, unsigned char data[3]; int rate; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; ucontrol->value.iec958.status[0] = kcontrol->private_value & 0xff; ucontrol->value.iec958.status[1] = (kcontrol->private_value >> 8) & 0xff; @@ -1918,15 +1895,11 @@ static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol, /* use known values for that card: interface#1 altsetting#1 */ iface = usb_ifnum_to_if(chip->dev, 1); - if (!iface || iface->num_altsetting < 2) { - err = -EINVAL; - goto end; - } + if (!iface || iface->num_altsetting < 2) + return -EINVAL; alts = &iface->altsetting[1]; - if (get_iface_desc(alts)->bNumEndpoints < 1) { - err = -EINVAL; - goto end; - } + if (get_iface_desc(alts)->bNumEndpoints < 1) + return -EINVAL; ep = get_endpoint(alts, 0)->bEndpointAddress; err = snd_usb_ctl_msg(chip->dev, @@ -1938,16 +1911,13 @@ static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol, data, sizeof(data)); if (err < 0) - goto end; + return err; rate = data[0] | (data[1] << 8) | (data[2] << 16); ucontrol->value.iec958.status[3] = (rate == 48000) ? IEC958_AES3_CON_FS_48000 : IEC958_AES3_CON_FS_44100; - err = 0; - end: - snd_usb_unlock_shutdown(chip); - return err; + return 0; } static int snd_microii_spdif_default_update(struct usb_mixer_elem_list *list) @@ -1957,9 +1927,9 @@ static int snd_microii_spdif_default_update(struct usb_mixer_elem_list *list) u8 reg; int err; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; reg = ((pval >> 4) & 0xf0) | (pval & 0x0f); err = snd_usb_ctl_msg(chip->dev, @@ -1971,7 +1941,7 @@ static int snd_microii_spdif_default_update(struct usb_mixer_elem_list *list) NULL, 0); if (err < 0) - goto end; + return err; reg = (pval & IEC958_AES0_NONAUDIO) ? 0xa0 : 0x20; reg |= (pval >> 12) & 0x0f; @@ -1983,11 +1953,6 @@ static int snd_microii_spdif_default_update(struct usb_mixer_elem_list *list) 3, NULL, 0); - if (err < 0) - goto end; - - end: - snd_usb_unlock_shutdown(chip); return err; } @@ -2042,23 +2007,19 @@ static int snd_microii_spdif_switch_update(struct usb_mixer_elem_list *list) { struct snd_usb_audio *chip = list->mixer->chip; u8 reg = list->kctl->private_value; - int err; - - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; - err = snd_usb_ctl_msg(chip->dev, - usb_sndctrlpipe(chip->dev, 0), - UAC_SET_CUR, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, - reg, - 9, - NULL, - 0); + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; - snd_usb_unlock_shutdown(chip); - return err; + return snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), + UAC_SET_CUR, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, + reg, + 9, + NULL, + 0); } static int snd_microii_spdif_switch_put(struct snd_kcontrol *kcontrol, @@ -2137,21 +2098,18 @@ static int snd_soundblaster_e1_switch_update(struct usb_mixer_interface *mixer, unsigned char state) { struct snd_usb_audio *chip = mixer->chip; - int err; unsigned char buff[2]; buff[0] = 0x02; buff[1] = state ? 0x02 : 0x00; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; - err = snd_usb_ctl_msg(chip->dev, - usb_sndctrlpipe(chip->dev, 0), HID_REQ_SET_REPORT, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, - 0x0202, 3, buff, 2); - snd_usb_unlock_shutdown(chip); - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; + return snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), HID_REQ_SET_REPORT, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, + 0x0202, 3, buff, 2); } static int snd_soundblaster_e1_switch_put(struct snd_kcontrol *kcontrol, @@ -2273,32 +2231,28 @@ static int realtek_ctl_connector_get(struct snd_kcontrol *kcontrol, bool presence; int err; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; err = realtek_hda_get(chip, HDA_VERB_CMD(AC_VERB_GET_PIN_SENSE, node_id, 0), &sense); if (err < 0) - goto err; + return err; if (pv & REALTEK_MIC_FLAG) { err = realtek_hda_set(chip, HDA_VERB_CMD(AC_VERB_SET_COEF_INDEX, REALTEK_VENDOR_REGISTERS, REALTEK_CBJ_CTRL2)); if (err < 0) - goto err; + return err; err = realtek_hda_get(chip, HDA_VERB_CMD(AC_VERB_GET_PROC_COEF, REALTEK_VENDOR_REGISTERS, 0), &cbj_ctrl2); if (err < 0) - goto err; + return err; } -err: - snd_usb_unlock_shutdown(chip); - if (err < 0) - return err; presence = sense & AC_PINSENSE_PRESENCE; if (pv & REALTEK_MIC_FLAG) @@ -2485,14 +2439,11 @@ static int snd_rme_get_status1(struct snd_kcontrol *kcontrol, { struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); struct snd_usb_audio *chip = list->mixer->chip; - int err; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; - err = snd_rme_read_value(chip, SND_RME_GET_STATUS1, status1); - snd_usb_unlock_shutdown(chip); - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; + return snd_rme_read_value(chip, SND_RME_GET_STATUS1, status1); } static int snd_rme_rate_get(struct snd_kcontrol *kcontrol, @@ -2609,22 +2560,19 @@ static int snd_rme_current_freq_get(struct snd_kcontrol *kcontrol, unsigned int freq; int err; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; err = snd_rme_read_value(chip, SND_RME_GET_STATUS1, &status1); if (err < 0) - goto end; + return err; err = snd_rme_read_value(chip, SND_RME_GET_CURRENT_FREQ, &den); if (err < 0) - goto end; + return err; freq = (den == 0) ? 0 : div64_u64(num, den); freq <<= SND_RME_CLK_FREQMUL(status1); ucontrol->value.integer.value[0] = freq; - -end: - snd_usb_unlock_shutdown(chip); - return err; + return 0; } static int snd_rme_rate_info(struct snd_kcontrol *kcontrol, @@ -2831,13 +2779,12 @@ enum { static int snd_bbfpro_ctl_update(struct usb_mixer_interface *mixer, u8 reg, u8 index, u8 value) { - int err; u16 usb_req, usb_idx, usb_val; struct snd_usb_audio *chip = mixer->chip; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; if (reg == SND_BBFPRO_CTL_REG1) { usb_req = SND_BBFPRO_USBREQ_CTL_REG1; @@ -2854,13 +2801,10 @@ static int snd_bbfpro_ctl_update(struct usb_mixer_interface *mixer, u8 reg, usb_val = value ? usb_idx : 0; } - err = snd_usb_ctl_msg(chip->dev, - usb_sndctrlpipe(chip->dev, 0), usb_req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - usb_val, usb_idx, NULL, 0); - - snd_usb_unlock_shutdown(chip); - return err; + return snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), usb_req, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + usb_val, usb_idx, NULL, 0); } static int snd_bbfpro_ctl_get(struct snd_kcontrol *kcontrol, @@ -2975,7 +2919,6 @@ static int snd_bbfpro_ctl_resume(struct usb_mixer_elem_list *list) static int snd_bbfpro_gain_update(struct usb_mixer_interface *mixer, u8 channel, u8 gain) { - int err; struct snd_usb_audio *chip = mixer->chip; if (channel < 2) { @@ -2986,18 +2929,15 @@ static int snd_bbfpro_gain_update(struct usb_mixer_interface *mixer, gain = ((gain % 6) << 5) | (60 / 3); } - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; - - err = snd_usb_ctl_msg(chip->dev, - usb_sndctrlpipe(chip->dev, 0), - SND_BBFPRO_USBREQ_GAIN, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - gain, channel, NULL, 0); + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; - snd_usb_unlock_shutdown(chip); - return err; + return snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), + SND_BBFPRO_USBREQ_GAIN, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + gain, channel, NULL, 0); } static int snd_bbfpro_gain_get(struct snd_kcontrol *kcontrol, @@ -3084,14 +3024,13 @@ static int snd_bbfpro_vol_update(struct usb_mixer_interface *mixer, u16 index, u32 value) { struct snd_usb_audio *chip = mixer->chip; - int err; u16 idx; u16 usb_idx, usb_val; u32 v; - err = snd_usb_lock_shutdown(chip); - if (err < 0) - return err; + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; idx = index & SND_BBFPRO_MIXER_IDX_MASK; // 18 bit linear volume, split so 2 bits end up in index. @@ -3099,15 +3038,12 @@ static int snd_bbfpro_vol_update(struct usb_mixer_interface *mixer, u16 index, usb_idx = idx | (v & 0x3) << 14; usb_val = (v >> 2) & 0xffff; - err = snd_usb_ctl_msg(chip->dev, - usb_sndctrlpipe(chip->dev, 0), - SND_BBFPRO_USBREQ_MIXER, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, - usb_val, usb_idx, NULL, 0); - - snd_usb_unlock_shutdown(chip); - return err; + return snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), + SND_BBFPRO_USBREQ_MIXER, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, + usb_val, usb_idx, NULL, 0); } static int snd_bbfpro_vol_get(struct snd_kcontrol *kcontrol, @@ -4212,26 +4148,22 @@ static int snd_djm_controls_info(struct snd_kcontrol *kctl, static int snd_djm_controls_update(struct usb_mixer_interface *mixer, u8 device_idx, u8 group, u16 value) { - int err; const struct snd_djm_device *device = &snd_djm_devices[device_idx]; if (group >= device->ncontrols || value >= device->controls[group].noptions) return -EINVAL; - err = snd_usb_lock_shutdown(mixer->chip); - if (err) - return err; - - err = snd_usb_ctl_msg(mixer->chip->dev, - usb_sndctrlpipe(mixer->chip->dev, 0), - USB_REQ_SET_FEATURE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - device->controls[group].options[value], - device->controls[group].wIndex, - NULL, 0); + CLASS(snd_usb_lock, pm)(mixer->chip); + if (pm.err) + return pm.err; - snd_usb_unlock_shutdown(mixer->chip); - return err; + return snd_usb_ctl_msg(mixer->chip->dev, + usb_sndctrlpipe(mixer->chip->dev, 0), + USB_REQ_SET_FEATURE, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + device->controls[group].options[value], + device->controls[group].wIndex, + NULL, 0); } static int snd_djm_controls_get(struct snd_kcontrol *kctl, @@ -4611,10 +4543,20 @@ void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer, } /* lowest playback value is muted on some devices */ - if (mixer->chip->quirk_flags & QUIRK_FLAG_MIXER_MIN_MUTE) - if (strstr(kctl->id.name, "Playback")) + if (mixer->chip->quirk_flags & QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE) + if (strstr(kctl->id.name, "Playback")) { + usb_audio_info(mixer->chip, + "applying playback min mute quirk\n"); cval->min_mute = 1; + } + /* lowest capture value is muted on some devices */ + if (mixer->chip->quirk_flags & QUIRK_FLAG_MIXER_CAPTURE_MIN_MUTE) + if (strstr(kctl->id.name, "Capture")) { + usb_audio_info(mixer->chip, + "applying capture min mute quirk\n"); + cval->min_mute = 1; + } /* ALSA-ify some Plantronics headset control names */ if (USB_ID_VENDOR(mixer->chip->usb_id) == 0x047f && (cval->control == UAC_FU_MUTE || cval->control == UAC_FU_VOLUME)) diff --git a/sound/usb/mixer_s1810c.c b/sound/usb/mixer_s1810c.c index fac4bbc6b275..15960d25e748 100644 --- a/sound/usb/mixer_s1810c.c +++ b/sound/usb/mixer_s1810c.c @@ -93,6 +93,7 @@ struct s1810c_ctl_packet { #define SC1810C_CTL_LINE_SW 0 #define SC1810C_CTL_MUTE_SW 1 +#define SC1824C_CTL_MONO_SW 2 #define SC1810C_CTL_AB_SW 3 #define SC1810C_CTL_48V_SW 4 @@ -123,6 +124,7 @@ struct s1810c_state_packet { #define SC1810C_STATE_48V_SW 58 #define SC1810C_STATE_LINE_SW 59 #define SC1810C_STATE_MUTE_SW 60 +#define SC1824C_STATE_MONO_SW 61 #define SC1810C_STATE_AB_SW 62 struct s1810_mixer_state { @@ -145,12 +147,7 @@ snd_s1810c_send_ctl_packet(struct usb_device *dev, u32 a, pkt.b = b; pkt.c = c; pkt.d = d; - /* - * Value for settings 0/1 for this - * output channel is always 0 (probably because - * there is no ADAT output on 1810c) - */ - pkt.e = (c == 4) ? 0 : e; + pkt.e = e; ret = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SC1810C_CMD_REQ, @@ -213,115 +210,164 @@ snd_sc1810c_get_status_field(struct usb_device *dev, */ static int snd_s1810c_init_mixer_maps(struct snd_usb_audio *chip) { - u32 a, b, c, e, n, off; + u32 a, b, c, e, n, off, left, right; struct usb_device *dev = chip->dev; - /* Set initial volume levels ? */ - a = 0x64; - e = 0xbc; - for (n = 0; n < 2; n++) { - off = n * 18; - for (b = off; b < 18 + off; b++) { - /* This channel to all outputs ? */ - for (c = 0; c <= 8; c++) { + switch (chip->usb_id) { + case USB_ID(0x194f, 0x010c): /* 1810c */ + /* Set initial volume levels ? */ + a = 0x64; + e = 0xbc; + for (n = 0; n < 2; n++) { + off = n * 18; + for (b = off; b < 18 + off; b++) { + /* This channel to all outputs ? */ + for (c = 0; c <= 8; c++) { + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); + } + /* This channel to main output (again) */ + snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e); + snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e); + } + /* + * I noticed on UC that DAW channels have different + * initial volumes, so this makes sense. + */ + e = 0xb53bf0; + } + + /* Connect analog outputs ? */ + a = 0x65; + e = 0x01000000; + for (b = 1; b < 3; b++) { + snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e); + snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e); + } + snd_s1810c_send_ctl_packet(dev, a, 0, 0, 0, e); + snd_s1810c_send_ctl_packet(dev, a, 0, 0, 1, e); + + /* Set initial volume levels for S/PDIF mappings ? */ + a = 0x64; + e = 0xbc; + c = 3; + for (n = 0; n < 2; n++) { + off = n * 18; + for (b = off; b < 18 + off; b++) { snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); } - /* This channel to main output (again) */ + e = 0xb53bf0; + } + + /* Connect S/PDIF output ? */ + a = 0x65; + e = 0x01000000; + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e); + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e); + + /* Connect all outputs (again) ? */ + a = 0x65; + e = 0x01000000; + for (b = 0; b < 4; b++) { snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e); snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e); } - /* - * I noticed on UC that DAW channels have different - * initial volumes, so this makes sense. - */ - e = 0xb53bf0; - } - /* Connect analog outputs ? */ - a = 0x65; - e = 0x01000000; - for (b = 1; b < 3; b++) { - snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e); - snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e); - } - snd_s1810c_send_ctl_packet(dev, a, 0, 0, 0, e); - snd_s1810c_send_ctl_packet(dev, a, 0, 0, 1, e); - - /* Set initial volume levels for S/PDIF mappings ? */ - a = 0x64; - e = 0xbc; - c = 3; - for (n = 0; n < 2; n++) { - off = n * 18; - for (b = off; b < 18 + off; b++) { - snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); - snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); + /* Basic routing to get sound out of the device */ + a = 0x64; + e = 0x01000000; + for (c = 0; c < 4; c++) { + for (b = 0; b < 36; b++) { + if ((c == 0 && b == 18) || /* DAW1/2 -> Main */ + (c == 1 && b == 20) || /* DAW3/4 -> Line3/4 */ + (c == 2 && b == 22) || /* DAW4/5 -> Line5/6 */ + (c == 3 && b == 24)) { /* DAW5/6 -> S/PDIF */ + /* Left */ + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0); + b++; + /* Right */ + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0); + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); + } else { + /* Leave the rest disconnected */ + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0); + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0); + } + } } - e = 0xb53bf0; - } - /* Connect S/PDIF output ? */ - a = 0x65; - e = 0x01000000; - snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e); - snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e); - - /* Connect all outputs (again) ? */ - a = 0x65; - e = 0x01000000; - for (b = 0; b < 4; b++) { - snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e); - snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e); - } - - /* Basic routing to get sound out of the device */ - a = 0x64; - e = 0x01000000; - for (c = 0; c < 4; c++) { - for (b = 0; b < 36; b++) { - if ((c == 0 && b == 18) || /* DAW1/2 -> Main */ - (c == 1 && b == 20) || /* DAW3/4 -> Line3/4 */ - (c == 2 && b == 22) || /* DAW4/5 -> Line5/6 */ - (c == 3 && b == 24)) { /* DAW5/6 -> S/PDIF */ - /* Left */ + /* Set initial volume levels for S/PDIF (again) ? */ + a = 0x64; + e = 0xbc; + c = 3; + for (n = 0; n < 2; n++) { + off = n * 18; + for (b = off; b < 18 + off; b++) { snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); - snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0); - b++; - /* Right */ - snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0); snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); - } else { - /* Leave the rest disconnected */ - snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0); - snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0); } + e = 0xb53bf0; } - } - /* Set initial volume levels for S/PDIF (again) ? */ - a = 0x64; - e = 0xbc; - c = 3; - for (n = 0; n < 2; n++) { - off = n * 18; - for (b = off; b < 18 + off; b++) { + /* Connect S/PDIF outputs (again) ? */ + a = 0x65; + e = 0x01000000; + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e); + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e); + + /* Again ? */ + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e); + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e); + break; + + case USB_ID(0x194f, 0x010d): /* 1824c */ + /* Set all output faders to unity gain */ + a = 0x65; + c = 0x00; + e = 0x01000000; + + for (b = 0; b < 9; b++) { snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); } - e = 0xb53bf0; - } - - /* Connect S/PDIF outputs (again) ? */ - a = 0x65; - e = 0x01000000; - snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e); - snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e); - - /* Again ? */ - snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e); - snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e); + /* Set + * Daw 1 -> Line out 1 (left), Daw 2 -> Line out 2 (right) + * Daw 3 -> Line out 3, (left) Daw 4 -> Line out 4 (right) + * Daw 5 -> Line out 5, (left) Daw 6 -> Line out 6 (right) + * Daw 7 -> Line out 7, (left) Daw 8 -> Line out 8 (right) + * Daw 9 -> SPDIF out 1, (left) Daw 10 -> SPDIF out 2 (right) + * Daw 11 -> ADAT out 1, (left) Daw 12 -> ADAT out 2 (right) + * Daw 13 -> ADAT out 3, (left) Daw 14 -> ADAT out 4 (right) + * Daw 15 -> ADAT out 5, (left) Daw 16 -> ADAT out 6 (right) + * Daw 17 -> ADAT out 7, (left) Daw 18 -> ADAT out 8 (right) + * Everything else muted + */ + a = 0x64; + /* The first Daw channel is channel 18 */ + left = 18; + + for (c = 0; c < 9; c++) { + right = left + 1; + + for (b = 0; b < 36; b++) { + if (b == left) { + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0x01000000); + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0x00); + } else if (b == right) { + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0x00); + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0x01000000); + } else { + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0x00); + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0x00); + } + } + left += 2; + } + break; + } return 0; } @@ -338,18 +384,16 @@ snd_s1810c_get_switch_state(struct usb_mixer_interface *mixer, struct s1810_mixer_state *private = mixer->private_data; u32 field = 0; u32 ctl_idx = (u32) (kctl->private_value & 0xFF); - int ret = 0; + int ret; - mutex_lock(&private->usb_mutex); + guard(mutex)(&private->usb_mutex); ret = snd_sc1810c_get_status_field(chip->dev, &field, ctl_idx, &private->seqnum); if (ret < 0) - goto unlock; + return ret; *state = field; - unlock: - mutex_unlock(&private->usb_mutex); - return ret ? ret : 0; + return ret; } /* @@ -366,12 +410,9 @@ snd_s1810c_set_switch_state(struct usb_mixer_interface *mixer, u32 pval = (u32) kctl->private_value; u32 ctl_id = (pval >> 8) & 0xFF; u32 ctl_val = (pval >> 16) & 0x1; - int ret = 0; - mutex_lock(&private->usb_mutex); - ret = snd_s1810c_send_ctl_packet(chip->dev, 0, 0, 0, ctl_id, ctl_val); - mutex_unlock(&private->usb_mutex); - return ret; + guard(mutex)(&private->usb_mutex); + return snd_s1810c_send_ctl_packet(chip->dev, 0, 0, 0, ctl_id, ctl_val); } /* Generic get/set/init functions for switch controls */ @@ -386,12 +427,12 @@ snd_s1810c_switch_get(struct snd_kcontrol *kctl, u32 pval = (u32) kctl->private_value; u32 ctl_idx = pval & 0xFF; u32 state = 0; - int ret = 0; + int ret; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); ret = snd_s1810c_get_switch_state(mixer, kctl, &state); if (ret < 0) - goto unlock; + return ret; switch (ctl_idx) { case SC1810C_STATE_LINE_SW: @@ -402,9 +443,7 @@ snd_s1810c_switch_get(struct snd_kcontrol *kctl, ctl_elem->value.integer.value[0] = (long)state; } - unlock: - mutex_unlock(&private->data_mutex); - return (ret < 0) ? ret : 0; + return 0; } static int @@ -420,10 +459,10 @@ snd_s1810c_switch_set(struct snd_kcontrol *kctl, u32 newval = 0; int ret = 0; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); ret = snd_s1810c_get_switch_state(mixer, kctl, &curval); if (ret < 0) - goto unlock; + return ret; switch (ctl_idx) { case SC1810C_STATE_LINE_SW: @@ -435,14 +474,12 @@ snd_s1810c_switch_set(struct snd_kcontrol *kctl, } if (curval == newval) - goto unlock; + return 0; kctl->private_value &= ~(0x1 << 16); kctl->private_value |= (unsigned int)(newval & 0x1) << 16; ret = snd_s1810c_set_switch_state(mixer, kctl); - unlock: - mutex_unlock(&private->data_mutex); return (ret < 0) ? 0 : 1; } @@ -502,6 +539,15 @@ static const struct snd_kcontrol_new snd_s1810c_mute_sw = { .private_value = (SC1810C_STATE_MUTE_SW | SC1810C_CTL_MUTE_SW << 8) }; +static const struct snd_kcontrol_new snd_s1824c_mono_sw = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mono Main Out Switch", + .info = snd_ctl_boolean_mono_info, + .get = snd_s1810c_switch_get, + .put = snd_s1810c_switch_set, + .private_value = (SC1824C_STATE_MONO_SW | SC1824C_CTL_MONO_SW << 8) +}; + static const struct snd_kcontrol_new snd_s1810c_48v_sw = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "48V Phantom Power On Mic Inputs Switch", @@ -588,8 +634,17 @@ int snd_sc1810_init_mixer(struct usb_mixer_interface *mixer) if (ret < 0) return ret; - ret = snd_s1810c_switch_init(mixer, &snd_s1810c_ab_sw); - if (ret < 0) - return ret; + // The 1824c has a Mono Main switch instead of a + // A/B select switch. + if (mixer->chip->usb_id == USB_ID(0x194f, 0x010d)) { + ret = snd_s1810c_switch_init(mixer, &snd_s1824c_mono_sw); + if (ret < 0) + return ret; + } else if (mixer->chip->usb_id == USB_ID(0x194f, 0x010c)) { + ret = snd_s1810c_switch_init(mixer, &snd_s1810c_ab_sw); + if (ret < 0) + return ret; + } + return ret; } diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c index 1ec203cbbd94..f2446bf3982c 100644 --- a/sound/usb/mixer_scarlett2.c +++ b/sound/usb/mixer_scarlett2.c @@ -10,8 +10,9 @@ * - Solo/2i2/4i4 Gen 4 * - Clarett 2Pre/4Pre/8Pre USB * - Clarett+ 2Pre/4Pre/8Pre + * - Vocaster One/Two * - * Copyright (c) 2018-2024 by Geoffrey D. Bennett <g at b4.vu> + * Copyright (c) 2018-2025 by Geoffrey D. Bennett <g at b4.vu> * Copyright (c) 2020-2021 by Vladimir Sadovnikov <sadko4u@gmail.com> * Copyright (c) 2022 by Christian Colglazier <christian@cacolglazier.com> * @@ -75,6 +76,9 @@ * to many LinuxMusicians people and to Focusrite for hardware * donations). * + * Support for Vocaster One and Two added in Mar 2024 (thanks to many + * LinuxMusicians people and to Focusrite for hardware donations). + * * This ALSA mixer gives access to (model-dependent): * - input, output, mixer-matrix muxes * - mixer-matrix gain stages @@ -364,6 +368,21 @@ static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = { "Mute Playback Switch", "Dim Playback Switch" }; +/* Vocaster One speaker/headphone mute names */ +static const char *const vocaster_one_sp_hp_mute_names[] = { + "Speaker Mute Playback Switch", + "Headphones Mute Playback Switch", + NULL +}; + +/* Vocaster Two speaker/headphone mute names */ +static const char *const vocaster_two_sp_hp_mute_names[] = { + "Speaker Mute Playback Switch", + "Headphones 1 Mute Playback Switch", + "Headphones 2 Mute Playback Switch", + NULL +}; + /* The autogain_status is set based on the autogain_switch and * raw_autogain_status values. * @@ -547,6 +566,7 @@ enum { SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN, SCARLETT2_CONFIG_BLUETOOTH_VOLUME, SCARLETT2_CONFIG_SPDIF_MODE, + SCARLETT2_CONFIG_SP_HP_MUTE, SCARLETT2_CONFIG_COUNT }; @@ -814,6 +834,9 @@ static const struct scarlett2_config_set scarlett2_config_set_vocaster = { [SCARLETT2_CONFIG_BLUETOOTH_VOLUME] = { .offset = 0xbf, .size = 8, .activate = 28 }, + + [SCARLETT2_CONFIG_SP_HP_MUTE] = { + .offset = 0xab, .size = 8, .activate = 10 }, } }; @@ -1177,6 +1200,9 @@ struct scarlett2_device_info { /* additional description for the line out volume controls */ const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX]; + /* Vocaster speaker/headphone mute control names */ + const char * const *sp_hp_mute_names; + /* number of sources/destinations of each port type */ const int port_count[SCARLETT2_PORT_TYPE_COUNT][SCARLETT2_PORT_DIRNS]; @@ -1249,6 +1275,7 @@ struct scarlett2_data { u8 level_switch[SCARLETT2_LEVEL_SWITCH_MAX]; u8 pad_switch[SCARLETT2_PAD_SWITCH_MAX]; u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT]; + u8 sp_hp_mute; u8 air_switch[SCARLETT2_AIR_SWITCH_MAX]; u8 dsp_switch[SCARLETT2_DSP_SWITCH_MAX]; s32 compressor_values[SCARLETT2_COMPRESSOR_CTLS_MAX]; @@ -1791,6 +1818,7 @@ static const struct scarlett2_device_info vocaster_one_info = { .peq_flt_total_count = 4, .mute_input_count = 1, .gain_input_count = 1, + .sp_hp_mute_names = vocaster_one_sp_hp_mute_names, .port_count = { [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, @@ -1835,6 +1863,7 @@ static const struct scarlett2_device_info vocaster_two_info = { .mute_input_count = 2, .gain_input_count = 2, .has_bluetooth = 1, + .sp_hp_mute_names = vocaster_two_sp_hp_mute_names, .port_count = { [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, @@ -2348,7 +2377,8 @@ static int scarlett2_usb( { struct scarlett2_data *private = mixer->private_data; struct usb_device *dev = mixer->chip->dev; - struct scarlett2_usb_packet *req, *resp = NULL; + struct scarlett2_usb_packet *req __free(kfree) = NULL; + struct scarlett2_usb_packet *resp __free(kfree) = NULL; size_t req_buf_size = struct_size(req, data, req_size); size_t resp_buf_size = struct_size(resp, data, resp_size); int retries = 0; @@ -2356,18 +2386,14 @@ static int scarlett2_usb( int err; req = kmalloc(req_buf_size, GFP_KERNEL); - if (!req) { - err = -ENOMEM; - goto error; - } + if (!req) + return -ENOMEM; resp = kmalloc(resp_buf_size, GFP_KERNEL); - if (!resp) { - err = -ENOMEM; - goto error; - } + if (!resp) + return -ENOMEM; - mutex_lock(&private->usb_mutex); + guard(mutex)(&private->usb_mutex); /* build request message and send it */ @@ -2389,8 +2415,7 @@ retry: mixer->chip, "%s USB request result cmd %x was %d\n", private->series_name, cmd, err); - err = -EINVAL; - goto unlock; + return -EINVAL; } if (!wait_for_completion_timeout(&private->cmd_done, @@ -2400,8 +2425,7 @@ retry: "%s USB request timed out, cmd %x\n", private->series_name, cmd); - err = -ETIMEDOUT; - goto unlock; + return -ETIMEDOUT; } /* send a second message to get the response */ @@ -2418,17 +2442,14 @@ retry: * reboot request */ if (cmd == SCARLETT2_USB_REBOOT && - (err == -ESHUTDOWN || err == -EPROTO)) { - err = 0; - goto unlock; - } + (err == -ESHUTDOWN || err == -EPROTO)) + return 0; usb_audio_err( mixer->chip, "%s USB response result cmd %x was %d expected %zu\n", private->series_name, cmd, err, resp_buf_size); - err = -EINVAL; - goto unlock; + return -EINVAL; } /* cmd/seq/size should match except when initialising @@ -2451,18 +2472,12 @@ retry: resp_size, le16_to_cpu(resp->size), le32_to_cpu(resp->error), le32_to_cpu(resp->pad)); - err = -EINVAL; - goto unlock; + return -EINVAL; } if (resp_data && resp_size > 0) memcpy(resp_data, resp->data, resp_size); -unlock: - mutex_unlock(&private->usb_mutex); -error: - kfree(req); - kfree(resp); return err; } @@ -3321,25 +3336,20 @@ static int scarlett2_sync_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->sync_updated) { err = scarlett2_update_sync(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.enumerated.item[0] = private->sync; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static const struct snd_kcontrol_new scarlett2_sync_ctl = { @@ -3589,17 +3599,13 @@ static int scarlett2_autogain_switch_ctl_info( struct scarlett2_data *private = mixer->private_data; int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); err = scarlett2_check_input_phantom_updated(mixer); if (err < 0) - goto unlock; - - err = snd_ctl_boolean_mono_info(kctl, uinfo); + return err; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return snd_ctl_boolean_mono_info(kctl, uinfo); } static int scarlett2_autogain_switch_ctl_get( @@ -3610,23 +3616,18 @@ static int scarlett2_autogain_switch_ctl_get( struct scarlett2_data *private = mixer->private_data; int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_autogain_updated(mixer); if (err < 0) - goto unlock; + return err; ucontrol->value.enumerated.item[0] = private->autogain_switch[elem->control]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_autogain_status_ctl_get( @@ -3637,23 +3638,18 @@ static int scarlett2_autogain_status_ctl_get( struct scarlett2_data *private = mixer->private_data; int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_autogain_updated(mixer); if (err < 0) - goto unlock; + return err; ucontrol->value.enumerated.item[0] = private->autogain_status[elem->control]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_autogain_switch_ctl_put( @@ -3662,46 +3658,37 @@ static int scarlett2_autogain_switch_ctl_put( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int index = elem->control; int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_input_phantom_updated(mixer); if (err < 0) - goto unlock; + return err; - if (scarlett2_phantom_is_switching(private, index)) { - err = -EPERM; - goto unlock; - } + if (scarlett2_phantom_is_switching(private, index)) + return -EPERM; oval = private->autogain_switch[index]; val = !!ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->autogain_switch[index] = val; /* Send switch change to the device */ err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_AUTOGAIN_SWITCH, index, val); - if (err == 0) - err = 1; scarlett2_autogain_update_access(mixer); scarlett2_autogain_notify_access(mixer); -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static int scarlett2_autogain_status_ctl_info( @@ -3742,16 +3729,14 @@ static int scarlett2_ag_target_ctl_info( struct scarlett2_data *private = mixer->private_data; int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_autogain_updated(mixer); if (err < 0) - goto unlock; + return err; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; @@ -3759,9 +3744,7 @@ static int scarlett2_ag_target_ctl_info( uinfo->value.integer.max = 0; uinfo->value.integer.step = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_ag_target_ctl_get( @@ -3770,26 +3753,21 @@ static int scarlett2_ag_target_ctl_get( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->autogain_updated) { err = scarlett2_update_autogain(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->ag_targets[elem->control]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_ag_target_ctl_put( @@ -3798,39 +3776,32 @@ static int scarlett2_ag_target_ctl_put( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int index = elem->control; int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_put_during_autogain(mixer); if (err < 0) - goto unlock; + return err; oval = private->ag_targets[index]; val = clamp(ucontrol->value.integer.value[0], (long)SCARLETT2_AG_TARGET_MIN, 0L); if (oval == val) - goto unlock; + return 0; private->ag_targets[index] = val; /* Send new value to the device */ err = scarlett2_usb_set_config( mixer, scarlett2_ag_target_configs[index], 1, -val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const DECLARE_TLV_DB_MINMAX( @@ -3885,25 +3856,20 @@ static int scarlett2_input_select_ctl_get( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->input_select_updated) { err = scarlett2_update_input_select(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.enumerated.item[0] = private->input_select_switch; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_input_select_ctl_put( @@ -3913,19 +3879,16 @@ static int scarlett2_input_select_ctl_put( struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_put_during_autogain(mixer); if (err < 0) - goto unlock; + return err; oval = private->input_select_switch; val = ucontrol->value.integer.value[0]; @@ -3936,7 +3899,7 @@ static int scarlett2_input_select_ctl_put( val = info->gain_input_count - 1; if (oval == val) - goto unlock; + return 0; private->input_select_switch = val; @@ -3944,12 +3907,8 @@ static int scarlett2_input_select_ctl_put( err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_INPUT_SELECT_SWITCH, 0, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static int scarlett2_input_select_ctl_info( @@ -3958,43 +3917,38 @@ static int scarlett2_input_select_ctl_info( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int inputs = private->info->gain_input_count; int i, err; - char **values = kcalloc(inputs, sizeof(char *), GFP_KERNEL); + char **values __free(kfree) = NULL; + values = kcalloc(inputs, sizeof(char *), GFP_KERNEL); if (!values) return -ENOMEM; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_autogain_updated(mixer); if (err < 0) - goto unlock; + return err; /* Loop through each input */ for (i = 0; i < inputs; i++) { values[i] = kasprintf(GFP_KERNEL, "Input %d", i + 1); if (!values[i]) { err = -ENOMEM; - goto unlock; + goto clear; } } err = snd_ctl_enum_info(uinfo, 1, i, (const char * const *)values); -unlock: - mutex_unlock(&private->data_mutex); - +clear: for (i = 0; i < inputs; i++) kfree(values[i]); - kfree(values); return err; } @@ -4020,22 +3974,16 @@ static int scarlett2_autogain_disables_ctl_info(struct snd_kcontrol *kctl, struct scarlett2_data *private = mixer->private_data; int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_autogain_updated(mixer); if (err < 0) - goto unlock; - - err = snd_ctl_boolean_mono_info(kctl, uinfo); + return err; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return snd_ctl_boolean_mono_info(kctl, uinfo); } static int scarlett2_input_link_ctl_get( @@ -4044,26 +3992,21 @@ static int scarlett2_input_link_ctl_get( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->input_select_updated) { err = scarlett2_update_input_select(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.enumerated.item[0] = private->input_link_switch[elem->control]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_input_link_ctl_put( @@ -4072,37 +4015,30 @@ static int scarlett2_input_link_ctl_put( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int index = elem->control; int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_put_during_autogain(mixer); if (err < 0) - goto unlock; + return err; oval = private->input_link_switch[index]; val = !!ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->input_link_switch[index] = val; err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_INPUT_LINK_SWITCH, index, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_input_link_ctl = { @@ -4138,16 +4074,14 @@ static int scarlett2_input_gain_ctl_info(struct snd_kcontrol *kctl, struct scarlett2_data *private = mixer->private_data; int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_autogain_updated(mixer); if (err < 0) - goto unlock; + return err; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = elem->channels; @@ -4155,9 +4089,7 @@ static int scarlett2_input_gain_ctl_info(struct snd_kcontrol *kctl, uinfo->value.integer.max = SCARLETT2_MAX_GAIN_VALUE; uinfo->value.integer.step = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_input_gain_ctl_get(struct snd_kcontrol *kctl, @@ -4166,26 +4098,21 @@ static int scarlett2_input_gain_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->input_gain_updated) { err = scarlett2_update_input_gain(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->gain[elem->control]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_input_gain_ctl_put(struct snd_kcontrol *kctl, @@ -4194,38 +4121,31 @@ static int scarlett2_input_gain_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int index = elem->control; int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_put_during_autogain(mixer); if (err < 0) - goto unlock; + return err; oval = private->gain[index]; val = ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->gain[index] = val; /* Send gain change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_INPUT_GAIN, index, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_input_gain_ctl = { @@ -4262,26 +4182,21 @@ static int scarlett2_safe_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->input_safe_updated) { err = scarlett2_update_input_safe(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->safe_switch[elem->control]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_safe_ctl_put(struct snd_kcontrol *kctl, @@ -4290,38 +4205,31 @@ static int scarlett2_safe_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int index = elem->control; int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_put_during_autogain(mixer); if (err < 0) - goto unlock; + return err; oval = private->safe_switch[index]; val = !!ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->safe_switch[index] = val; /* Send switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SAFE_SWITCH, index, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_safe_ctl = { @@ -4356,20 +4264,17 @@ static int scarlett2_pcm_input_switch_ctl_get( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = elem->head.mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); if (private->pcm_input_switch_updated) { err = scarlett2_update_pcm_input_switch(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.enumerated.item[0] = private->pcm_input_switch; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_pcm_input_switch_ctl_put( @@ -4378,21 +4283,18 @@ static int scarlett2_pcm_input_switch_ctl_put( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; + int oval, val, err; - int oval, val, err = 0; - - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->pcm_input_switch; val = !!ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->pcm_input_switch = val; @@ -4400,12 +4302,8 @@ static int scarlett2_pcm_input_switch_ctl_put( err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_PCM_INPUT_SWITCH, 0, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static int scarlett2_pcm_input_switch_ctl_info( @@ -4492,25 +4390,20 @@ static int scarlett2_master_volume_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->vol_updated) { err = scarlett2_update_volumes(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->master_vol; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_headphone_volume_ctl_get( @@ -4520,25 +4413,20 @@ static int scarlett2_headphone_volume_ctl_get( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->vol_updated) { err = scarlett2_update_volumes(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->headphone_vol; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int line_out_remap(struct scarlett2_data *private, int index) @@ -4561,25 +4449,20 @@ static int scarlett2_volume_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; int index = line_out_remap(private, elem->control); - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->vol_updated) { err = scarlett2_update_volumes(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->vol[index]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_volume_ctl_put(struct snd_kcontrol *kctl, @@ -4589,30 +4472,24 @@ static int scarlett2_volume_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; int index = line_out_remap(private, elem->control); - int oval, val, err = 0; + int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->vol[index]; val = ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->vol[index] = val; err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME, index, val - SCARLETT2_VOLUME_BIAS); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const DECLARE_TLV_DB_MINMAX( @@ -4691,25 +4568,20 @@ static int scarlett2_mute_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; int index = line_out_remap(private, elem->control); - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->dim_mute_updated) { err = scarlett2_update_dim_mute(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->mute_switch[index]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_mute_ctl_put(struct snd_kcontrol *kctl, @@ -4719,32 +4591,26 @@ static int scarlett2_mute_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; int index = line_out_remap(private, elem->control); - int oval, val, err = 0; + int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->mute_switch[index]; val = !!ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->mute_switch[index] = val; /* Send mute change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_MUTE_SWITCH, index, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_mute_ctl = { @@ -4863,28 +4729,22 @@ static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, struct scarlett2_data *private = mixer->private_data; int ctl_index = elem->control; int index = line_out_remap(private, ctl_index); - int oval, val, err = 0; + int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->vol_sw_hw_switch[index]; val = !!ucontrol->value.enumerated.item[0]; if (oval == val) - goto unlock; + return 0; err = scarlett2_sw_hw_change(mixer, ctl_index, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_sw_hw_enum_ctl = { @@ -4924,22 +4784,16 @@ static int scarlett2_level_enum_ctl_info(struct snd_kcontrol *kctl, struct scarlett2_data *private = mixer->private_data; int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_autogain_updated(mixer); if (err < 0) - goto unlock; - - err = snd_ctl_enum_info(uinfo, 1, 2, values); + return err; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return snd_ctl_enum_info(uinfo, 1, 2, values); } static int scarlett2_level_enum_ctl_get(struct snd_kcontrol *kctl, @@ -4949,28 +4803,22 @@ static int scarlett2_level_enum_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - int index = elem->control + info->level_input_first; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->input_level_updated) { err = scarlett2_update_input_level(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.enumerated.item[0] = scarlett2_decode_muteable( private->level_switch[index]); - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_level_enum_ctl_put(struct snd_kcontrol *kctl, @@ -4980,26 +4828,23 @@ static int scarlett2_level_enum_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - int index = elem->control + info->level_input_first; int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_put_during_autogain(mixer); if (err < 0) - goto unlock; + return err; oval = private->level_switch[index]; val = !!ucontrol->value.enumerated.item[0]; if (oval == val) - goto unlock; + return 0; private->level_switch[index] = val; @@ -5010,12 +4855,8 @@ static int scarlett2_level_enum_ctl_put(struct snd_kcontrol *kctl, /* Send switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_LEVEL_SWITCH, index, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_level_enum_ctl = { @@ -5049,26 +4890,21 @@ static int scarlett2_pad_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->input_pad_updated) { err = scarlett2_update_input_pad(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->pad_switch[elem->control]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_pad_ctl_put(struct snd_kcontrol *kctl, @@ -5077,34 +4913,27 @@ static int scarlett2_pad_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int index = elem->control; - int oval, val, err = 0; + int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->pad_switch[index]; val = !!ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->pad_switch[index] = val; /* Send switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_PAD_SWITCH, index, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_pad_ctl = { @@ -5138,25 +4967,20 @@ static int scarlett2_air_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->input_air_updated) { err = scarlett2_update_input_air(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->air_switch[elem->control]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_air_ctl_put(struct snd_kcontrol *kctl, @@ -5165,38 +4989,31 @@ static int scarlett2_air_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int index = elem->control; int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_put_during_autogain(mixer); if (err < 0) - goto unlock; + return err; oval = private->air_switch[index]; val = ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->air_switch[index] = val; /* Send switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_AIR_SWITCH, index, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static int scarlett2_air_with_drive_ctl_info( @@ -5210,22 +5027,16 @@ static int scarlett2_air_with_drive_ctl_info( struct scarlett2_data *private = mixer->private_data; int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_autogain_updated(mixer); if (err < 0) - goto unlock; - - err = snd_ctl_enum_info(uinfo, 1, 3, values); + return err; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return snd_ctl_enum_info(uinfo, 1, 3, values); } static const struct snd_kcontrol_new scarlett2_air_ctl[2] = { @@ -5268,25 +5079,20 @@ static int scarlett2_dsp_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->input_dsp_updated) { err = scarlett2_update_input_dsp(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->dsp_switch[elem->control]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_dsp_ctl_put(struct snd_kcontrol *kctl, @@ -5295,38 +5101,31 @@ static int scarlett2_dsp_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int index = elem->control; int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_put_during_autogain(mixer); if (err < 0) - goto unlock; + return err; oval = private->dsp_switch[index]; val = ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->dsp_switch[index] = val; /* Send switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_DSP_SWITCH, index, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_dsp_ctl = { @@ -5389,30 +5188,26 @@ static int scarlett2_compressor_ctl_put( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int index = elem->control; int channel = index / SCARLETT2_COMPRESSOR_PARAM_COUNT; int param_index = index % SCARLETT2_COMPRESSOR_PARAM_COUNT; const struct compressor_param *param = &compressor_params[param_index]; - int oval, val, err; s32 scaled_val; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_put_during_autogain(mixer); if (err < 0) - goto unlock; + return err; oval = private->compressor_values[index]; val = ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->compressor_values[index] = val; @@ -5427,19 +5222,12 @@ static int scarlett2_compressor_ctl_put( err = scarlett2_usb_set_data( mixer, private->config_set->param_buf_addr + 1, 1, channel); if (err < 0) - goto unlock; + return err; err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_COMPRESSOR_PARAMS, index, scaled_val); - if (err < 0) - goto unlock; - if (err == 0) - err = 1; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static int scarlett2_compressor_ctl_info( @@ -5495,20 +5283,18 @@ static int scarlett2_precomp_flt_switch_ctl_put( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int oval, val, err = 0; + int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->precomp_flt_switch[elem->control]; val = ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->precomp_flt_switch[elem->control] = val; @@ -5516,12 +5302,8 @@ static int scarlett2_precomp_flt_switch_ctl_put( err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_PRECOMP_FLT_SWITCH, elem->control, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static int scarlett2_peq_flt_switch_ctl_put( @@ -5530,20 +5312,18 @@ static int scarlett2_peq_flt_switch_ctl_put( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int oval, val, err = 0; + int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->peq_flt_switch[elem->control]; val = ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->peq_flt_switch[elem->control] = val; @@ -5551,12 +5331,8 @@ static int scarlett2_peq_flt_switch_ctl_put( err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_PEQ_FLT_SWITCH, elem->control, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_precomp_flt_switch_ctl = { @@ -5677,20 +5453,17 @@ static int scarlett2_precomp_flt_ctl_put( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int index = elem->control * SCARLETT2_BIQUAD_COEFFS; int i, oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_put_during_autogain(mixer); if (err < 0) - goto unlock; + return err; /* Check if any of the values have changed; if not, return */ for (i = 0; i < SCARLETT2_BIQUAD_COEFFS; i++) { @@ -5701,7 +5474,7 @@ static int scarlett2_precomp_flt_ctl_put( } if (i == SCARLETT2_BIQUAD_COEFFS) - goto unlock; + return 0; /* Update the values */ for (i = 0; i < SCARLETT2_BIQUAD_COEFFS; i++) @@ -5712,19 +5485,14 @@ static int scarlett2_precomp_flt_ctl_put( err = scarlett2_usb_set_data( mixer, private->config_set->param_buf_addr, 1, index); if (err < 0) - goto unlock; + return err; err = scarlett2_usb_set_config_buf( mixer, SCARLETT2_CONFIG_PRECOMP_FLT_PARAMS, index, SCARLETT2_BIQUAD_COEFFS, &private->precomp_flt_values[index]); - if (err == 0) - err = 1; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static int scarlett2_peq_flt_ctl_put( @@ -5734,7 +5502,6 @@ static int scarlett2_peq_flt_ctl_put( struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - int src_index = elem->control * SCARLETT2_BIQUAD_COEFFS; int dst_index = ( elem->control / @@ -5744,16 +5511,14 @@ static int scarlett2_peq_flt_ctl_put( ) * SCARLETT2_BIQUAD_COEFFS; int i, oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_put_during_autogain(mixer); if (err < 0) - goto unlock; + return err; /* Check if any of the values have changed; if not, return */ for (i = 0; i < SCARLETT2_BIQUAD_COEFFS; i++) { @@ -5764,7 +5529,7 @@ static int scarlett2_peq_flt_ctl_put( } if (i == SCARLETT2_BIQUAD_COEFFS) - goto unlock; + return 0; /* Update the values */ for (i = 0; i < SCARLETT2_BIQUAD_COEFFS; i++) @@ -5775,19 +5540,14 @@ static int scarlett2_peq_flt_ctl_put( err = scarlett2_usb_set_data( mixer, private->config_set->param_buf_addr, 1, dst_index); if (err < 0) - goto unlock; + return err; err = scarlett2_usb_set_config_buf( mixer, SCARLETT2_CONFIG_PEQ_FLT_PARAMS, dst_index, SCARLETT2_BIQUAD_COEFFS, &private->peq_flt_values[src_index]); - if (err == 0) - err = 1; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static int scarlett2_flt_ctl_info( @@ -5840,26 +5600,21 @@ static int scarlett2_input_mute_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->input_mute_updated) { err = scarlett2_update_input_mute(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->input_mute_switch[elem->control]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_input_mute_ctl_put(struct snd_kcontrol *kctl, @@ -5868,26 +5623,23 @@ static int scarlett2_input_mute_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int index = elem->control; int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_put_during_autogain(mixer); if (err < 0) - goto unlock; + return err; oval = private->input_mute_switch[index]; val = ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->input_mute_switch[index] = val; @@ -5895,12 +5647,8 @@ static int scarlett2_input_mute_ctl_put(struct snd_kcontrol *kctl, err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_INPUT_MUTE_SWITCH, index, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_input_mute_ctl = { @@ -6011,23 +5759,18 @@ static int scarlett2_phantom_ctl_get(struct snd_kcontrol *kctl, struct scarlett2_data *private = mixer->private_data; int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_input_phantom_updated(mixer); if (err < 0) - goto unlock; + return err; ucontrol->value.integer.value[0] = scarlett2_decode_muteable( private->phantom_switch[elem->control]); - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_phantom_ctl_put(struct snd_kcontrol *kctl, @@ -6037,26 +5780,23 @@ static int scarlett2_phantom_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - int index = elem->control; int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_check_put_during_autogain(mixer); if (err < 0) - goto unlock; + return err; oval = private->phantom_switch[index]; val = !!ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->phantom_switch[index] = val; @@ -6067,15 +5807,10 @@ static int scarlett2_phantom_ctl_put(struct snd_kcontrol *kctl, /* Send switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_PHANTOM_SWITCH, index + info->phantom_first, val); - if (err == 0) - err = 1; - scarlett2_phantom_update_access(mixer); scarlett2_phantom_notify_access(mixer); -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_phantom_ctl = { @@ -6104,34 +5839,27 @@ static int scarlett2_phantom_persistence_ctl_put( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int index = elem->control; - int oval, val, err = 0; + int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->phantom_persistence; val = !!ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->phantom_persistence = val; /* Send switch change to the device */ err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_PHANTOM_PERSISTENCE, index, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_phantom_persistence_ctl = { @@ -6222,25 +5950,20 @@ static int scarlett2_speaker_switch_enum_ctl_get( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->monitor_other_updated) { err = scarlett2_update_monitor_other(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.enumerated.item[0] = private->speaker_switching_switch; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } /* when speaker switching gets enabled, switch the main/alt speakers @@ -6306,21 +6029,18 @@ static int scarlett2_speaker_switch_enum_ctl_put( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; + int oval, val, err; - int oval, val, err = 0; - - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->speaker_switching_switch; val = min(ucontrol->value.enumerated.item[0], 2U); if (oval == val) - goto unlock; + return 0; private->speaker_switching_switch = val; @@ -6329,14 +6049,14 @@ static int scarlett2_speaker_switch_enum_ctl_put( mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE, 0, !!val); if (err < 0) - goto unlock; + return err; /* if speaker switching is enabled, select main or alt */ err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH, 0, val == 2); if (err < 0) - goto unlock; + return err; /* update controls if speaker switching gets enabled or disabled */ if (!oval && val) @@ -6344,12 +6064,7 @@ static int scarlett2_speaker_switch_enum_ctl_put( else if (oval && !val) scarlett2_speaker_switch_disable(mixer); - if (err == 0) - err = 1; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_speaker_switch_enum_ctl = { @@ -6392,25 +6107,20 @@ static int scarlett2_talkback_enum_ctl_get( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->monitor_other_updated) { err = scarlett2_update_monitor_other(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.enumerated.item[0] = private->talkback_switch; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_talkback_enum_ctl_put( @@ -6419,21 +6129,18 @@ static int scarlett2_talkback_enum_ctl_put( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; + int oval, val, err; - int oval, val, err = 0; - - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->talkback_switch; val = min(ucontrol->value.enumerated.item[0], 2U); if (oval == val) - goto unlock; + return 0; private->talkback_switch = val; @@ -6442,18 +6149,14 @@ static int scarlett2_talkback_enum_ctl_put( mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE, 1, !!val); if (err < 0) - goto unlock; + return err; /* if talkback is enabled, select main or alt */ err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH, 1, val == 2); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_talkback_enum_ctl = { @@ -6484,21 +6187,19 @@ static int scarlett2_talkback_map_ctl_put( struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; int index = elem->control; - int oval, val, err = 0, i; + int oval, val, err, i; u16 bitmap = 0; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->talkback_map[index]; val = !!ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->talkback_map[index] = val; @@ -6508,12 +6209,8 @@ static int scarlett2_talkback_map_ctl_put( /* Send updated bitmap to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_TALKBACK_MAP, 0, bitmap); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_talkback_map_ctl = { @@ -6561,25 +6258,20 @@ static int scarlett2_dim_mute_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->dim_mute_updated) { err = scarlett2_update_dim_mute(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->dim_mute[elem->control]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl, @@ -6589,29 +6281,24 @@ static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; int index = elem->control; - int oval, val, err = 0, i; + int oval, val, err, i; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->dim_mute[index]; val = !!ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->dim_mute[index] = val; /* Send switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_DIM_MUTE, index, val); - if (err == 0) - err = 1; - if (index == SCARLETT2_BUTTON_MUTE) for (i = 0; i < private->num_line_out; i++) { int line_index = line_out_remap(private, i); @@ -6624,9 +6311,7 @@ static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl, } } -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_dim_mute_ctl = { @@ -6637,6 +6322,61 @@ static const struct snd_kcontrol_new scarlett2_dim_mute_ctl = { .put = scarlett2_dim_mute_ctl_put }; +/*** Vocaster Speaker/Headphone Mute Controls ***/ + +static int scarlett2_sp_hp_mute_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct scarlett2_data *private = elem->head.mixer->private_data; + + ucontrol->value.integer.value[0] = + !!(private->sp_hp_mute & (1 << elem->control)); + + return 0; +} + +static int scarlett2_sp_hp_mute_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + int index = elem->control; + int val, err; + + guard(mutex)(&private->data_mutex); + + if (private->hwdep_in_use) + return -EBUSY; + + val = private->sp_hp_mute; + + if (ucontrol->value.integer.value[0]) + val |= (1 << index); + else + val &= ~(1 << index); + + if (val == private->sp_hp_mute) + return 0; + + private->sp_hp_mute = val; + + /* Send change to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SP_HP_MUTE, + 0, val); + + return err < 0 ? err : 1; +} + +static const struct snd_kcontrol_new scarlett2_sp_hp_mute_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_sp_hp_mute_ctl_get, + .put = scarlett2_sp_hp_mute_ctl_put +}; + /*** Create the analogue output controls ***/ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) @@ -6669,6 +6409,17 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) return err; } + /* Add Vocaster speaker/headphone mute controls */ + if (private->info->sp_hp_mute_names) + for (i = 0; private->info->sp_hp_mute_names[i]; i++) { + err = scarlett2_add_new_ctl( + mixer, &scarlett2_sp_hp_mute_ctl, + i, 1, private->info->sp_hp_mute_names[i], + NULL); + if (err < 0) + return err; + } + /* Remaining controls are only applicable if the device * has per-channel line-out volume controls. */ @@ -7038,25 +6789,20 @@ static int scarlett2_mixer_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->mix_updated) { err = scarlett2_update_mix(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->mix[elem->control]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_mixer_ctl_put(struct snd_kcontrol *kctl, @@ -7065,15 +6811,13 @@ static int scarlett2_mixer_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int oval, val, mix_num, err = 0; + int oval, val, mix_num, err; int index = elem->control; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->mix[index]; val = clamp(ucontrol->value.integer.value[0], @@ -7081,16 +6825,12 @@ static int scarlett2_mixer_ctl_put(struct snd_kcontrol *kctl, mix_num = index / private->num_mix_in; if (oval == val) - goto unlock; + return 0; private->mix[index] = val; err = scarlett2_usb_set_mix(mixer, mix_num); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const DECLARE_TLV_DB_MINMAX( @@ -7177,25 +6917,20 @@ static int scarlett2_direct_monitor_ctl_get( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->direct_monitor_updated) { err = scarlett2_update_direct_monitor(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.enumerated.item[0] = private->direct_monitor_switch; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_direct_monitor_ctl_put( @@ -7204,34 +6939,27 @@ static int scarlett2_direct_monitor_ctl_put( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int index = elem->control; - int oval, val, err = 0; + int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->direct_monitor_switch; val = min(ucontrol->value.enumerated.item[0], 2U); if (oval == val) - goto unlock; + return 0; private->direct_monitor_switch = val; /* Send switch change to the device */ err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_DIRECT_MONITOR, index, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static int scarlett2_direct_monitor_stereo_enum_ctl_info( @@ -7281,33 +7009,27 @@ static int scarlett2_monitor_mix_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int oval, val, err = 0; + int oval, val, err; int index = elem->control; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->monitor_mix[index]; val = clamp(ucontrol->value.integer.value[0], 0L, (long)SCARLETT2_MIXER_MAX_VALUE); if (oval == val) - goto unlock; + return 0; private->monitor_mix[index] = val; err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN, index, scarlett2_mixer_values[val]); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_monitor_mix_ctl = { @@ -7433,25 +7155,20 @@ static int scarlett2_mux_src_enum_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; int index = line_out_remap(private, elem->control); - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->mux_updated) { err = scarlett2_usb_get_mux(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.enumerated.item[0] = private->mux[index]; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_mux_src_enum_ctl_put(struct snd_kcontrol *kctl, @@ -7461,30 +7178,24 @@ static int scarlett2_mux_src_enum_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; int index = line_out_remap(private, elem->control); - int oval, val, err = 0; + int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->mux[index]; val = min(ucontrol->value.enumerated.item[0], private->num_mux_srcs - 1U); if (oval == val) - goto unlock; + return 0; private->mux[index] = val; err = scarlett2_usb_set_mux(mixer); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_mux_src_enum_ctl = { @@ -7561,17 +7272,15 @@ static int scarlett2_meter_ctl_get(struct snd_kcontrol *kctl, u16 meter_levels[SCARLETT2_MAX_METERS]; int i, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; err = scarlett2_usb_get_meter_levels(mixer, elem->channels, meter_levels); if (err < 0) - goto unlock; + return err; /* copy & translate from meter_levels[] using meter_level_map[] */ for (i = 0; i < elem->channels; i++) { @@ -7586,10 +7295,7 @@ static int scarlett2_meter_ctl_get(struct snd_kcontrol *kctl, ucontrol->value.integer.value[i] = value; } -unlock: - mutex_unlock(&private->data_mutex); - - return err; + return 0; } static const struct snd_kcontrol_new scarlett2_meter_ctl = { @@ -7631,33 +7337,26 @@ static int scarlett2_msd_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; + int oval, val, err; - int oval, val, err = 0; - - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->msd_switch; val = !!ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->msd_switch = val; /* Send switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_MSD_SWITCH, 0, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_msd_ctl = { @@ -7702,21 +7401,18 @@ static int scarlett2_standalone_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; + int oval, val, err; - int oval, val, err = 0; - - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->standalone_switch; val = !!ucontrol->value.integer.value[0]; if (oval == val) - goto unlock; + return 0; private->standalone_switch = val; @@ -7724,12 +7420,8 @@ static int scarlett2_standalone_ctl_put(struct snd_kcontrol *kctl, err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_STANDALONE_SWITCH, 0, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_standalone_ctl = { @@ -7789,20 +7481,17 @@ static int scarlett2_power_status_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); if (private->power_status_updated) { err = scarlett2_update_power_status(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->power_status; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_power_status_ctl_info( @@ -7864,25 +7553,20 @@ static int scarlett2_bluetooth_volume_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int err = 0; + int err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; if (private->bluetooth_updated) { err = scarlett2_update_bluetooth_volume(mixer); if (err < 0) - goto unlock; + return err; } ucontrol->value.integer.value[0] = private->bluetooth_volume; - -unlock: - mutex_unlock(&private->data_mutex); - return err; + return 0; } static int scarlett2_bluetooth_volume_ctl_put(struct snd_kcontrol *kctl, @@ -7891,32 +7575,26 @@ static int scarlett2_bluetooth_volume_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int oval, val, err = 0; + int oval, val, err; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); - if (private->hwdep_in_use) { - err = -EBUSY; - goto unlock; - } + if (private->hwdep_in_use) + return -EBUSY; oval = private->bluetooth_volume; val = clamp(ucontrol->value.integer.value[0], 0L, (long)SCARLETT2_MAX_BLUETOOTH_VOLUME); if (oval == val) - goto unlock; + return 0; private->bluetooth_volume = val; err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_BLUETOOTH_VOLUME, 0, val); - if (err == 0) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static int scarlett2_bluetooth_volume_ctl_info( @@ -8011,39 +7689,31 @@ static int scarlett2_spdif_mode_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; - int oval, val, err = 0; + int oval, val, err; int i; - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); oval = private->spdif_mode; val = ucontrol->value.enumerated.item[0]; - if (val < 0) { - err = -EINVAL; - goto unlock; - } + if (val < 0) + return -EINVAL; for (i = 0; i <= val; i++) - if (private->info->spdif_mode_values[i] == 0xff) { - err = -EINVAL; - goto unlock; - } + if (private->info->spdif_mode_values[i] == 0xff) + return -EINVAL; if (oval == val) - goto unlock; + return 0; private->spdif_mode = val; err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_SPDIF_MODE, 0, private->info->spdif_mode_values[val]); - if (!err) - err = 1; -unlock: - mutex_unlock(&private->data_mutex); - return err; + return err < 0 ? err : 1; } static const struct snd_kcontrol_new scarlett2_spdif_mode_ctl = { @@ -9140,9 +8810,8 @@ static int snd_scarlett2_controls_create( */ static void scarlett2_lock(struct scarlett2_data *private) { - mutex_lock(&private->data_mutex); + guard(mutex)(&private->data_mutex); private->hwdep_in_use = 1; - mutex_unlock(&private->data_mutex); } /* Call SCARLETT2_USB_GET_ERASE to get the erase progress */ @@ -9414,7 +9083,7 @@ static long scarlett2_hwdep_read(struct snd_hwdep *hw, __le32 len; } __packed req; - u8 *resp; + u8 *resp __free(kfree) = NULL; /* Flash segment must first be selected */ if (private->flash_write_state != SCARLETT2_FLASH_WRITE_STATE_SELECTED) @@ -9460,20 +9129,14 @@ static long scarlett2_hwdep_read(struct snd_hwdep *hw, err = scarlett2_usb(mixer, SCARLETT2_USB_READ_SEGMENT, &req, sizeof(req), resp, count); if (err < 0) - goto error; + return err; /* Copy the response to userspace */ - if (copy_to_user(buf, resp, count)) { - err = -EFAULT; - goto error; - } + if (copy_to_user(buf, resp, count)) + return -EFAULT; *offset += count; - err = count; - -error: - kfree(resp); - return err; + return count; } static long scarlett2_hwdep_write(struct snd_hwdep *hw, @@ -9491,7 +9154,7 @@ static long scarlett2_hwdep_write(struct snd_hwdep *hw, __le32 offset; __le32 pad; u8 data[]; - } __packed *req; + } __packed *req __free(kfree) = NULL; /* Calculate the maximum permitted in data[] */ const size_t max_data_size = SCARLETT2_FLASH_RW_MAX - @@ -9545,22 +9208,16 @@ static long scarlett2_hwdep_write(struct snd_hwdep *hw, req->offset = cpu_to_le32(*offset); req->pad = 0; - if (copy_from_user(req->data, buf, count)) { - err = -EFAULT; - goto error; - } + if (copy_from_user(req->data, buf, count)) + return -EFAULT; err = scarlett2_usb(mixer, SCARLETT2_USB_WRITE_SEGMENT, req, len, NULL, 0); if (err < 0) - goto error; + return err; *offset += count; - err = count; - -error: - kfree(req); - return err; + return count; } static int scarlett2_hwdep_release(struct snd_hwdep *hw, struct file *file) @@ -9610,7 +9267,7 @@ static ssize_t scarlett2_devmap_read( loff_t pos) { struct usb_mixer_interface *mixer = entry->private_data; - u8 *resp_buf; + u8 *resp_buf __free(kfree) = NULL; const size_t block_size = SCARLETT2_DEVMAP_BLOCK_SIZE; size_t copied = 0; @@ -9649,15 +9306,11 @@ static ssize_t scarlett2_devmap_read( req = cpu_to_le32(pos / block_size); err = scarlett2_usb(mixer, SCARLETT2_USB_GET_DEVMAP, &req, sizeof(req), resp_buf, read_size); - if (err < 0) { - kfree(resp_buf); + if (err < 0) return copied ? copied : err; - } - if (copy_to_user(buf, resp_buf + offset, copy_size)) { - kfree(resp_buf); + if (copy_to_user(buf, resp_buf + offset, copy_size)) return -EFAULT; - } buf += copy_size; pos += copy_size; @@ -9665,7 +9318,6 @@ static ssize_t scarlett2_devmap_read( count -= copy_size; } - kfree(resp_buf); return copied; } diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c index 236b69054867..1c5712c31f5e 100644 --- a/sound/usb/mixer_us16x08.c +++ b/sound/usb/mixer_us16x08.c @@ -152,12 +152,11 @@ static int snd_us16x08_recv_urb(struct snd_usb_audio *chip, unsigned char *buf, int size) { - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), SND_US16X08_URB_METER_REQUEST, SND_US16X08_URB_METER_REQUESTTYPE, 0, 0, buf, size); - mutex_unlock(&chip->mutex); return 0; } diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index bff92505e408..54d01dfd820f 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -77,10 +77,10 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream if (atomic_read(&subs->stream->chip->shutdown)) return SNDRV_PCM_POS_XRUN; - spin_lock(&subs->lock); - hwptr_done = subs->hwptr_done; - runtime->delay = snd_usb_pcm_delay(subs, runtime); - spin_unlock(&subs->lock); + scoped_guard(spinlock, &subs->lock) { + hwptr_done = subs->hwptr_done; + runtime->delay = snd_usb_pcm_delay(subs, runtime); + } return bytes_to_frames(runtime, hwptr_done); } @@ -560,9 +560,9 @@ int snd_usb_hw_params(struct snd_usb_substream *subs, subs->sync_endpoint); } - mutex_lock(&chip->mutex); - subs->cur_audiofmt = fmt; - mutex_unlock(&chip->mutex); + scoped_guard(mutex, &chip->mutex) { + subs->cur_audiofmt = fmt; + } if (!subs->data_endpoint->need_setup) goto unlock; @@ -611,14 +611,14 @@ int snd_usb_hw_free(struct snd_usb_substream *subs) struct snd_usb_audio *chip = subs->stream->chip; snd_media_stop_pipeline(subs); - mutex_lock(&chip->mutex); - subs->cur_audiofmt = NULL; - mutex_unlock(&chip->mutex); - if (!snd_usb_lock_shutdown(chip)) { + scoped_guard(mutex, &chip->mutex) { + subs->cur_audiofmt = NULL; + } + CLASS(snd_usb_lock, pm)(chip); + if (!pm.err) { if (stop_endpoints(subs, false)) sync_pending_stops(subs); close_endpoints(chip, subs); - snd_usb_unlock_shutdown(chip); } return 0; @@ -675,28 +675,26 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) int retry = 0; int ret; - ret = snd_usb_lock_shutdown(chip); - if (ret < 0) - return ret; - if (snd_BUG_ON(!subs->data_endpoint)) { - ret = -EIO; - goto unlock; - } + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) + return pm.err; + if (snd_BUG_ON(!subs->data_endpoint)) + return -EIO; ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0); if (ret < 0) - goto unlock; + return ret; again: if (subs->sync_endpoint) { ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); if (ret < 0) - goto unlock; + return ret; } ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint); if (ret < 0) - goto unlock; + return ret; else if (ret > 0) snd_usb_set_format_quirk(subs, subs->cur_audiofmt); ret = 0; @@ -722,8 +720,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) goto again; } } - unlock: - snd_usb_unlock_shutdown(chip); + return ret; } @@ -1244,13 +1241,11 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream) struct snd_usb_audio *chip = subs->stream->chip; int ret; - mutex_lock(&chip->mutex); - if (subs->opened) { - mutex_unlock(&chip->mutex); - return -EBUSY; + scoped_guard(mutex, &chip->mutex) { + if (subs->opened) + return -EBUSY; + subs->opened = 1; } - subs->opened = 1; - mutex_unlock(&chip->mutex); runtime->hw = snd_usb_hardware; /* need an explicit sync to catch applptr update in low-latency mode */ @@ -1281,9 +1276,9 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream) err_resume: snd_usb_autosuspend(subs->stream->chip); err_open: - mutex_lock(&chip->mutex); - subs->opened = 0; - mutex_unlock(&chip->mutex); + scoped_guard(mutex, &chip->mutex) { + subs->opened = 0; + } return ret; } @@ -1298,18 +1293,20 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream) snd_media_stop_pipeline(subs); - if (!snd_usb_lock_shutdown(subs->stream->chip)) { + { + CLASS(snd_usb_lock, pm)(subs->stream->chip); + if (pm.err) + return pm.err; ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D1); - snd_usb_unlock_shutdown(subs->stream->chip); if (ret < 0) return ret; } subs->pcm_substream = NULL; snd_usb_autosuspend(subs->stream->chip); - mutex_lock(&chip->mutex); - subs->opened = 0; - mutex_unlock(&chip->mutex); + scoped_guard(mutex, &chip->mutex) { + subs->opened = 0; + } return 0; } @@ -1325,7 +1322,6 @@ static void retire_capture_urb(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; unsigned int stride, frames, bytes, oldptr; int i, period_elapsed = 0; - unsigned long flags; unsigned char *cp; int current_frame_number; @@ -1358,22 +1354,21 @@ static void retire_capture_urb(struct snd_usb_substream *subs, oldbytes, bytes); } /* update the current pointer */ - spin_lock_irqsave(&subs->lock, flags); - oldptr = subs->hwptr_done; - subs->hwptr_done += bytes; - if (subs->hwptr_done >= subs->buffer_bytes) - subs->hwptr_done -= subs->buffer_bytes; - frames = (bytes + (oldptr % stride)) / stride; - subs->transfer_done += frames; - if (subs->transfer_done >= runtime->period_size) { - subs->transfer_done -= runtime->period_size; - period_elapsed = 1; - } - - /* realign last_frame_number */ - subs->last_frame_number = current_frame_number; + scoped_guard(spinlock_irqsave, &subs->lock) { + oldptr = subs->hwptr_done; + subs->hwptr_done += bytes; + if (subs->hwptr_done >= subs->buffer_bytes) + subs->hwptr_done -= subs->buffer_bytes; + frames = (bytes + (oldptr % stride)) / stride; + subs->transfer_done += frames; + if (subs->transfer_done >= runtime->period_size) { + subs->transfer_done -= runtime->period_size; + period_elapsed = 1; + } - spin_unlock_irqrestore(&subs->lock, flags); + /* realign last_frame_number */ + subs->last_frame_number = current_frame_number; + } /* copy a data chunk */ if (oldptr + bytes > subs->buffer_bytes) { unsigned int bytes1 = subs->buffer_bytes - oldptr; @@ -1533,8 +1528,6 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, int counts; unsigned int transfer_done, frame_limit, avail = 0; int i, stride, period_elapsed = 0; - unsigned long flags; - int err = 0; stride = ep->stride; @@ -1542,106 +1535,101 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, ctx->queued = 0; urb->number_of_packets = 0; - spin_lock_irqsave(&subs->lock, flags); - frame_limit = subs->frame_limit + ep->max_urb_frames; - transfer_done = subs->transfer_done; - - if (subs->lowlatency_playback && - runtime->state != SNDRV_PCM_STATE_DRAINING) { - unsigned int hwptr = subs->hwptr_done / stride; + scoped_guard(spinlock_irqsave, &subs->lock) { + frame_limit = subs->frame_limit + ep->max_urb_frames; + transfer_done = subs->transfer_done; - /* calculate the byte offset-in-buffer of the appl_ptr */ - avail = (runtime->control->appl_ptr - runtime->hw_ptr_base) - % runtime->buffer_size; - if (avail <= hwptr) - avail += runtime->buffer_size; - avail -= hwptr; - } + if (subs->lowlatency_playback && + runtime->state != SNDRV_PCM_STATE_DRAINING) { + unsigned int hwptr = subs->hwptr_done / stride; + + /* calculate the byte offset-in-buffer of the appl_ptr */ + avail = (runtime->control->appl_ptr - runtime->hw_ptr_base) + % runtime->buffer_size; + if (avail <= hwptr) + avail += runtime->buffer_size; + avail -= hwptr; + } - for (i = 0; i < ctx->packets; i++) { - counts = snd_usb_endpoint_next_packet_size(ep, ctx, i, avail); - if (counts < 0) - break; - /* set up descriptor */ - urb->iso_frame_desc[i].offset = frames * stride; - urb->iso_frame_desc[i].length = counts * stride; - frames += counts; - avail -= counts; - urb->number_of_packets++; - transfer_done += counts; - if (transfer_done >= runtime->period_size) { - transfer_done -= runtime->period_size; - frame_limit = 0; - period_elapsed = 1; - if (subs->fmt_type == UAC_FORMAT_TYPE_II) { - if (transfer_done > 0) { - /* FIXME: fill-max mode is not - * supported yet */ - frames -= transfer_done; - counts -= transfer_done; - urb->iso_frame_desc[i].length = - counts * stride; - transfer_done = 0; - } - i++; - if (i < ctx->packets) { - /* add a transfer delimiter */ - urb->iso_frame_desc[i].offset = - frames * stride; - urb->iso_frame_desc[i].length = 0; - urb->number_of_packets++; - } + for (i = 0; i < ctx->packets; i++) { + counts = snd_usb_endpoint_next_packet_size(ep, ctx, i, avail); + if (counts < 0) break; + /* set up descriptor */ + urb->iso_frame_desc[i].offset = frames * stride; + urb->iso_frame_desc[i].length = counts * stride; + frames += counts; + avail -= counts; + urb->number_of_packets++; + transfer_done += counts; + if (transfer_done >= runtime->period_size) { + transfer_done -= runtime->period_size; + frame_limit = 0; + period_elapsed = 1; + if (subs->fmt_type == UAC_FORMAT_TYPE_II) { + if (transfer_done > 0) { + /* FIXME: fill-max mode is not + * supported yet */ + frames -= transfer_done; + counts -= transfer_done; + urb->iso_frame_desc[i].length = + counts * stride; + transfer_done = 0; + } + i++; + if (i < ctx->packets) { + /* add a transfer delimiter */ + urb->iso_frame_desc[i].offset = + frames * stride; + urb->iso_frame_desc[i].length = 0; + urb->number_of_packets++; + } + break; + } } + /* finish at the period boundary or after enough frames */ + if ((period_elapsed || transfer_done >= frame_limit) && + !snd_usb_endpoint_implicit_feedback_sink(ep)) + break; } - /* finish at the period boundary or after enough frames */ - if ((period_elapsed || transfer_done >= frame_limit) && - !snd_usb_endpoint_implicit_feedback_sink(ep)) - break; - } - if (!frames) { - err = -EAGAIN; - goto unlock; - } - - bytes = frames * stride; - subs->transfer_done = transfer_done; - subs->frame_limit = frame_limit; - if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE && - subs->cur_audiofmt->dsd_dop)) { - fill_playback_urb_dsd_dop(subs, urb, bytes); - } else if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U8 && - subs->cur_audiofmt->dsd_bitrev)) { - fill_playback_urb_dsd_bitrev(subs, urb, bytes); - } else { - /* usual PCM */ - if (!subs->tx_length_quirk) - copy_to_urb(subs, urb, 0, stride, bytes); - else - bytes = copy_to_urb_quirk(subs, urb, stride, bytes); + if (!frames) + return -EAGAIN; + + bytes = frames * stride; + subs->transfer_done = transfer_done; + subs->frame_limit = frame_limit; + if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE && + subs->cur_audiofmt->dsd_dop)) { + fill_playback_urb_dsd_dop(subs, urb, bytes); + } else if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U8 && + subs->cur_audiofmt->dsd_bitrev)) { + fill_playback_urb_dsd_bitrev(subs, urb, bytes); + } else { + /* usual PCM */ + if (!subs->tx_length_quirk) + copy_to_urb(subs, urb, 0, stride, bytes); + else + bytes = copy_to_urb_quirk(subs, urb, stride, bytes); /* bytes is now amount of outgoing data */ - } + } - subs->last_frame_number = usb_get_current_frame_number(subs->dev); + subs->last_frame_number = usb_get_current_frame_number(subs->dev); - if (subs->trigger_tstamp_pending_update) { - /* this is the first actual URB submitted, - * update trigger timestamp to reflect actual start time - */ - snd_pcm_gettime(runtime, &runtime->trigger_tstamp); - subs->trigger_tstamp_pending_update = false; - } + if (subs->trigger_tstamp_pending_update) { + /* this is the first actual URB submitted, + * update trigger timestamp to reflect actual start time + */ + snd_pcm_gettime(runtime, &runtime->trigger_tstamp); + subs->trigger_tstamp_pending_update = false; + } - if (period_elapsed && !subs->running && subs->lowlatency_playback) { - subs->period_elapsed_pending = 1; - period_elapsed = 0; + if (period_elapsed && !subs->running && subs->lowlatency_playback) { + subs->period_elapsed_pending = 1; + period_elapsed = 0; + } } - unlock: - spin_unlock_irqrestore(&subs->lock, flags); - if (err < 0) - return err; urb->transfer_buffer_length = bytes; if (period_elapsed) { if (in_stream_lock) @@ -1659,24 +1647,23 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, static void retire_playback_urb(struct snd_usb_substream *subs, struct urb *urb) { - unsigned long flags; struct snd_urb_ctx *ctx = urb->context; bool period_elapsed = false; - spin_lock_irqsave(&subs->lock, flags); - if (ctx->queued) { - if (subs->inflight_bytes >= ctx->queued) - subs->inflight_bytes -= ctx->queued; - else - subs->inflight_bytes = 0; - } + scoped_guard(spinlock_irqsave, &subs->lock) { + if (ctx->queued) { + if (subs->inflight_bytes >= ctx->queued) + subs->inflight_bytes -= ctx->queued; + else + subs->inflight_bytes = 0; + } - subs->last_frame_number = usb_get_current_frame_number(subs->dev); - if (subs->running) { - period_elapsed = subs->period_elapsed_pending; - subs->period_elapsed_pending = 0; + subs->last_frame_number = usb_get_current_frame_number(subs->dev); + if (subs->running) { + period_elapsed = subs->period_elapsed_pending; + subs->period_elapsed_pending = 0; + } } - spin_unlock_irqrestore(&subs->lock, flags); if (period_elapsed) snd_pcm_period_elapsed(subs->pcm_substream); } diff --git a/sound/usb/proc.c b/sound/usb/proc.c index c8b967bd7065..f4b7a7ff3203 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -193,7 +193,7 @@ static void proc_dump_substream_status(struct snd_usb_audio *chip, struct snd_usb_substream *subs, struct snd_info_buffer *buffer) { - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); if (subs->running) { snd_iprintf(buffer, " Status: Running\n"); if (subs->cur_audiofmt) { @@ -204,7 +204,6 @@ static void proc_dump_substream_status(struct snd_usb_audio *chip, } else { snd_iprintf(buffer, " Status: Stop\n"); } - mutex_unlock(&chip->mutex); } static void proc_pcm_format_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c index 9ad76fff741b..cfb30a195364 100644 --- a/sound/usb/qcom/qc_audio_offload.c +++ b/sound/usb/qcom/qc_audio_offload.c @@ -755,7 +755,7 @@ static void qmi_stop_session(void) int if_idx; int idx; - mutex_lock(&qdev_mutex); + guard(mutex)(&qdev_mutex); /* find all active intf for set alt 0 and cleanup usb audio dev */ for (idx = 0; idx < SNDRV_CARDS; idx++) { if (!atomic_read(&uadev[idx].in_use)) @@ -791,11 +791,9 @@ static void qmi_stop_session(void) disable_audio_stream(subs); } atomic_set(&uadev[idx].in_use, 0); - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); uaudio_dev_cleanup(&uadev[idx]); - mutex_unlock(&chip->mutex); } - mutex_unlock(&qdev_mutex); } /** @@ -821,8 +819,8 @@ static int uaudio_sideband_notifier(struct usb_interface *intf, chip = usb_get_intfdata(intf); - mutex_lock(&qdev_mutex); - mutex_lock(&chip->mutex); + guard(mutex)(&qdev_mutex); + guard(mutex)(&chip->mutex); dev = &uadev[chip->card->number]; @@ -836,9 +834,6 @@ static int uaudio_sideband_notifier(struct usb_interface *intf, } } - mutex_unlock(&chip->mutex); - mutex_unlock(&qdev_mutex); - return 0; } @@ -972,21 +967,21 @@ static int enable_audio_stream(struct snd_usb_substream *subs, goto put_suspend; if (!atomic_read(&chip->shutdown)) { - ret = snd_usb_lock_shutdown(chip); - if (ret < 0) + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) { + ret = pm.err; goto detach_ep; + } if (subs->sync_endpoint) { ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); if (ret < 0) - goto unlock; + goto detach_ep; } ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint); if (ret < 0) - goto unlock; - - snd_usb_unlock_shutdown(chip); + goto detach_ep; dev_dbg(uaudio_qdev->data->dev, "selected %s iface:%d altsetting:%d datainterval:%dus\n", @@ -1000,9 +995,6 @@ static int enable_audio_stream(struct snd_usb_substream *subs, return 0; -unlock: - snd_usb_unlock_shutdown(chip); - detach_ep: snd_usb_hw_free(subs); @@ -1584,17 +1576,15 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle, goto response; } - mutex_lock(&chip->mutex); - if (req_msg->enable) { - if (info_idx < 0 || chip->system_suspend || subs->opened) { - ret = -EBUSY; - mutex_unlock(&chip->mutex); - - goto response; + scoped_guard(mutex, &chip->mutex) { + if (req_msg->enable) { + if (info_idx < 0 || chip->system_suspend || subs->opened) { + ret = -EBUSY; + goto response; + } + subs->opened = 1; } - subs->opened = 1; } - mutex_unlock(&chip->mutex); if (req_msg->service_interval_valid) { ret = get_data_interval_from_si(subs, @@ -1617,9 +1607,8 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle, ret = prepare_qmi_response(subs, req_msg, &resp, info_idx); if (ret < 0) { - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); subs->opened = 0; - mutex_unlock(&chip->mutex); } } else { info = &uadev[pcm_card_num].info[info_idx]; @@ -1650,14 +1639,13 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle, } disable_audio_stream(subs); - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); subs->opened = 0; - mutex_unlock(&chip->mutex); } response: if (!req_msg->enable && ret != -EINVAL && ret != -ENODEV) { - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); if (info_idx >= 0) { info = &uadev[pcm_card_num].info[info_idx]; uaudio_dev_intf_cleanup(uadev[pcm_card_num].udev, @@ -1666,7 +1654,6 @@ response: if (atomic_read(&uadev[pcm_card_num].in_use)) kref_put(&uadev[pcm_card_num].kref, uaudio_dev_release); - mutex_unlock(&chip->mutex); } mutex_unlock(&qdev_mutex); @@ -1769,12 +1756,12 @@ static void qc_usb_audio_offload_probe(struct snd_usb_audio *chip) !usb_qmi_get_pcm_num(chip, 0)) return; - mutex_lock(&qdev_mutex); - mutex_lock(&chip->mutex); + guard(mutex)(&qdev_mutex); + guard(mutex)(&chip->mutex); if (!uadev[chip->card->number].chip) { sdev = kzalloc(sizeof(*sdev), GFP_KERNEL); if (!sdev) - goto exit; + return; sb = xhci_sideband_register(intf, XHCI_SIDEBAND_VENDOR, uaudio_sideband_notifier); @@ -1813,9 +1800,6 @@ static void qc_usb_audio_offload_probe(struct snd_usb_audio *chip) snd_soc_usb_connect(uaudio_qdev->auxdev->dev.parent, sdev); } - mutex_unlock(&chip->mutex); - mutex_unlock(&qdev_mutex); - return; unreg_xhci: @@ -1825,9 +1809,6 @@ free_sdev: kfree(sdev); uadev[chip->card->number].sdev = NULL; uadev[chip->card->number].chip = NULL; -exit: - mutex_unlock(&chip->mutex); - mutex_unlock(&qdev_mutex); } /** @@ -1863,16 +1844,13 @@ static void qc_usb_audio_offload_disconnect(struct snd_usb_audio *chip) if (card_num >= SNDRV_CARDS) return; - mutex_lock(&qdev_mutex); - mutex_lock(&chip->mutex); + guard(mutex)(&qdev_mutex); + guard(mutex)(&chip->mutex); dev = &uadev[card_num]; /* Device has already been cleaned up, or never populated */ - if (!dev->chip) { - mutex_unlock(&chip->mutex); - mutex_unlock(&qdev_mutex); + if (!dev->chip) return; - } /* cleaned up already */ if (!dev->udev) @@ -1893,9 +1871,6 @@ done: kfree(dev->sdev); dev->sdev = NULL; } - mutex_unlock(&chip->mutex); - - mutex_unlock(&qdev_mutex); } /** @@ -1920,13 +1895,10 @@ static void qc_usb_audio_offload_suspend(struct usb_interface *intf, if (card_num >= SNDRV_CARDS) return; - mutex_lock(&qdev_mutex); - mutex_lock(&chip->mutex); + guard(mutex)(&qdev_mutex); + guard(mutex)(&chip->mutex); uaudio_send_disconnect_ind(chip); - - mutex_unlock(&chip->mutex); - mutex_unlock(&qdev_mutex); } static struct snd_usb_platform_ops offload_ops = { diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 766db7d00cbc..634cb4fb586f 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1599,9 +1599,6 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, /* presonus studio 1810c: skip altsets incompatible with device_setup */ if (chip->usb_id == USB_ID(0x194f, 0x010c)) return s1810c_skip_setting_quirk(chip, iface, altno); - /* presonus studio 1824c: skip altsets incompatible with device_setup */ - if (chip->usb_id == USB_ID(0x194f, 0x010d)) - return s1810c_skip_setting_quirk(chip, iface, altno); return 0; } @@ -2200,9 +2197,9 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { DEVICE_FLG(0x0556, 0x0014, /* Phoenix Audio TMX320VC */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x0572, 0x1b08, /* Conexant Systems (Rockwell), Inc. */ - QUIRK_FLAG_MIXER_MIN_MUTE), + QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE), DEVICE_FLG(0x0572, 0x1b09, /* Conexant Systems (Rockwell), Inc. */ - QUIRK_FLAG_MIXER_MIN_MUTE), + QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE), DEVICE_FLG(0x05a3, 0x9420, /* ELP HD USB Camera */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x05a7, 0x1020, /* Bose Companion 5 */ @@ -2243,18 +2240,22 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_IGNORE_CTL_ERROR), DEVICE_FLG(0x0951, 0x16ad, /* Kingston HyperX */ QUIRK_FLAG_CTL_MSG_DELAY_1M), + DEVICE_FLG(0x0b05, 0x18a6, /* ASUSTek Computer, Inc. */ + QUIRK_FLAG_MIXER_CAPTURE_MIN_MUTE), DEVICE_FLG(0x0b0e, 0x0349, /* Jabra 550a */ QUIRK_FLAG_CTL_MSG_DELAY_1M), DEVICE_FLG(0x0bda, 0x498a, /* Realtek Semiconductor Corp. */ - QUIRK_FLAG_MIXER_MIN_MUTE), + QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE | QUIRK_FLAG_MIXER_CAPTURE_MIN_MUTE), DEVICE_FLG(0x0c45, 0x6340, /* Sonix HD USB Camera */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x0c45, 0x636b, /* Microdia JP001 USB Camera */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x0d8c, 0x000c, /* C-Media */ - QUIRK_FLAG_MIXER_MIN_MUTE), + QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE), + DEVICE_FLG(0x0d8c, 0x0012, /* C-Media */ + QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE), DEVICE_FLG(0x0d8c, 0x0014, /* C-Media */ - QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIXER_MIN_MUTE), + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE), DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */ QUIRK_FLAG_FIXED_RATE), DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */ @@ -2264,7 +2265,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { DEVICE_FLG(0x1101, 0x0003, /* Audioengine D1 */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x12d1, 0x3a07, /* Huawei Technologies Co., Ltd. */ - QUIRK_FLAG_MIXER_MIN_MUTE), + QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE | QUIRK_FLAG_MIXER_CAPTURE_MIN_MUTE), DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ @@ -2304,7 +2305,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x19f7, 0x0003, /* RODE NT-USB */ - QUIRK_FLAG_MIXER_MIN_MUTE), + QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE), DEVICE_FLG(0x19f7, 0x0035, /* RODE NT-USB+ */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x1bcf, 0x2281, /* HD Webcam */ @@ -2356,7 +2357,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x2a70, 0x1881, /* OnePlus Technology (Shenzhen) Co., Ltd. BE02T */ - QUIRK_FLAG_MIXER_MIN_MUTE), + QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE | QUIRK_FLAG_MIXER_CAPTURE_MIN_MUTE), DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */ QUIRK_FLAG_GENERIC_IMPLICIT_FB), DEVICE_FLG(0x2b53, 0x0024, /* Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */ @@ -2368,13 +2369,13 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { DEVICE_FLG(0x2d95, 0x8021, /* VIVO USB-C-XE710 HEADSET */ QUIRK_FLAG_CTL_MSG_DELAY_1M), DEVICE_FLG(0x2d99, 0x0026, /* HECATE G2 GAMING HEADSET */ - QUIRK_FLAG_MIXER_MIN_MUTE), + QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE), DEVICE_FLG(0x2fc6, 0xf0b7, /* iBasso DC07 Pro */ QUIRK_FLAG_CTL_MSG_DELAY_1M), DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */ QUIRK_FLAG_IGNORE_CTL_ERROR), DEVICE_FLG(0x339b, 0x3a07, /* Synaptics HONOR USB-C HEADSET */ - QUIRK_FLAG_MIXER_MIN_MUTE), + QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE), DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x534d, 0x0021, /* MacroSilicon MS2100/MS2106 */ @@ -2442,7 +2443,85 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { {} /* terminator */ }; -void snd_usb_init_quirk_flags(struct snd_usb_audio *chip) +#define QUIRK_STRING_ENTRY(x) \ + [QUIRK_TYPE_ ## x] = __stringify(x) + +static const char *const snd_usb_audio_quirk_flag_names[] = { + QUIRK_STRING_ENTRY(GET_SAMPLE_RATE), + QUIRK_STRING_ENTRY(SHARE_MEDIA_DEVICE), + QUIRK_STRING_ENTRY(ALIGN_TRANSFER), + QUIRK_STRING_ENTRY(TX_LENGTH), + QUIRK_STRING_ENTRY(PLAYBACK_FIRST), + QUIRK_STRING_ENTRY(SKIP_CLOCK_SELECTOR), + QUIRK_STRING_ENTRY(IGNORE_CLOCK_SOURCE), + QUIRK_STRING_ENTRY(ITF_USB_DSD_DAC), + QUIRK_STRING_ENTRY(CTL_MSG_DELAY), + QUIRK_STRING_ENTRY(CTL_MSG_DELAY_1M), + QUIRK_STRING_ENTRY(CTL_MSG_DELAY_5M), + QUIRK_STRING_ENTRY(IFACE_DELAY), + QUIRK_STRING_ENTRY(VALIDATE_RATES), + QUIRK_STRING_ENTRY(DISABLE_AUTOSUSPEND), + QUIRK_STRING_ENTRY(IGNORE_CTL_ERROR), + QUIRK_STRING_ENTRY(DSD_RAW), + QUIRK_STRING_ENTRY(SET_IFACE_FIRST), + QUIRK_STRING_ENTRY(GENERIC_IMPLICIT_FB), + QUIRK_STRING_ENTRY(SKIP_IMPLICIT_FB), + QUIRK_STRING_ENTRY(IFACE_SKIP_CLOSE), + QUIRK_STRING_ENTRY(FORCE_IFACE_RESET), + QUIRK_STRING_ENTRY(FIXED_RATE), + QUIRK_STRING_ENTRY(MIC_RES_16), + QUIRK_STRING_ENTRY(MIC_RES_384), + QUIRK_STRING_ENTRY(MIXER_PLAYBACK_MIN_MUTE), + QUIRK_STRING_ENTRY(MIXER_CAPTURE_MIN_MUTE), + NULL +}; + +const char *snd_usb_quirk_flag_find_name(unsigned long index) +{ + if (index >= ARRAY_SIZE(snd_usb_audio_quirk_flag_names)) + return NULL; + + return snd_usb_audio_quirk_flag_names[index]; +} + +u32 snd_usb_quirk_flags_from_name(const char *name) +{ + int i; + + if (!name || !*name) + return 0; + + for (i = 0; snd_usb_audio_quirk_flag_names[i]; i++) { + if (strcasecmp(name, snd_usb_audio_quirk_flag_names[i]) == 0) + return BIT_U32(i); + } + + return 0; +} + +void snd_usb_apply_flag_dbg(const char *reason, + struct snd_usb_audio *chip, + unsigned long flag) +{ + unsigned long bit; + + for_each_set_bit(bit, &flag, BYTES_TO_BITS(sizeof(flag))) { + const char *name = snd_usb_audio_quirk_flag_names[bit]; + + if (name) + usb_audio_dbg(chip, + "From %s apply quirk flag %s for device %04x:%04x\n", + reason, name, USB_ID_VENDOR(chip->usb_id), + USB_ID_PRODUCT(chip->usb_id)); + else + usb_audio_warn(chip, + "From %s apply unknown quirk flag 0x%lx for device %04x:%04x\n", + reason, bit, USB_ID_VENDOR(chip->usb_id), + USB_ID_PRODUCT(chip->usb_id)); + } +} + +void snd_usb_init_quirk_flags_table(struct snd_usb_audio *chip) { const struct usb_audio_quirk_flags_table *p; @@ -2450,12 +2529,97 @@ void snd_usb_init_quirk_flags(struct snd_usb_audio *chip) if (chip->usb_id == p->id || (!USB_ID_PRODUCT(p->id) && USB_ID_VENDOR(chip->usb_id) == USB_ID_VENDOR(p->id))) { - usb_audio_dbg(chip, - "Set quirk_flags 0x%x for device %04x:%04x\n", - p->flags, USB_ID_VENDOR(chip->usb_id), - USB_ID_PRODUCT(chip->usb_id)); + snd_usb_apply_flag_dbg("builtin table", chip, p->flags); chip->quirk_flags |= p->flags; return; } } } + +void snd_usb_init_quirk_flags_parse_string(struct snd_usb_audio *chip, + const char *str) +{ + u16 chip_vid = USB_ID_VENDOR(chip->usb_id); + u16 chip_pid = USB_ID_PRODUCT(chip->usb_id); + u32 mask_flags, unmask_flags, bit; + char *p, *field, *flag; + bool is_unmask; + u16 vid, pid; + + char *val __free(kfree) = kstrdup(str, GFP_KERNEL); + + if (!val) + return; + + for (p = val; p && *p;) { + /* Each entry consists of VID:PID:flags */ + field = strsep(&p, ":"); + if (!field) + break; + + if (strcmp(field, "*") == 0) + vid = 0; + else if (kstrtou16(field, 16, &vid)) + break; + + field = strsep(&p, ":"); + if (!field) + break; + + if (strcmp(field, "*") == 0) + pid = 0; + else if (kstrtou16(field, 16, &pid)) + break; + + field = strsep(&p, ";"); + if (!field || !*field) + break; + + if ((vid != 0 && vid != chip_vid) || + (pid != 0 && pid != chip_pid)) + continue; + + /* Collect the flags */ + mask_flags = 0; + unmask_flags = 0; + while (field && *field) { + flag = strsep(&field, "|"); + + if (!flag) + break; + + if (*flag == '!') { + is_unmask = true; + flag++; + } else { + is_unmask = false; + } + + if (!kstrtou32(flag, 16, &bit)) { + if (is_unmask) + unmask_flags |= bit; + else + mask_flags |= bit; + + break; + } + + bit = snd_usb_quirk_flags_from_name(flag); + + if (bit) { + if (is_unmask) + unmask_flags |= bit; + else + mask_flags |= bit; + } else { + pr_warn("snd_usb_audio: unknown flag %s while parsing param quirk_flags\n", + flag); + } + } + + chip->quirk_flags &= ~unmask_flags; + chip->quirk_flags |= mask_flags; + snd_usb_apply_flag_dbg("module param", chip, + chip->quirk_flags); + } +} diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index f9bfd5ac7bab..f24d6a5a197a 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h @@ -48,6 +48,15 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, struct audioformat *fp, int stream); -void snd_usb_init_quirk_flags(struct snd_usb_audio *chip); +void snd_usb_apply_flag_dbg(const char *reason, + struct snd_usb_audio *chip, + unsigned long flag); + +void snd_usb_init_quirk_flags_table(struct snd_usb_audio *chip); +void snd_usb_init_quirk_flags_parse_string(struct snd_usb_audio *chip, + const char *str); + +const char *snd_usb_quirk_flag_find_name(unsigned long flag); +u32 snd_usb_quirk_flags_from_name(const char *name); #endif /* __USBAUDIO_QUIRKS_H */ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 1ef4d39978df..79978cae9799 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -139,6 +139,29 @@ struct snd_usb_audio_quirk { int snd_usb_lock_shutdown(struct snd_usb_audio *chip); void snd_usb_unlock_shutdown(struct snd_usb_audio *chip); +/* auto-cleanup */ +struct __snd_usb_lock { + struct snd_usb_audio *chip; + int err; +}; + +static inline struct __snd_usb_lock __snd_usb_lock_shutdown(struct snd_usb_audio *chip) +{ + struct __snd_usb_lock T = { .chip = chip }; + T.err = snd_usb_lock_shutdown(chip); + return T; +} + +static inline void __snd_usb_unlock_shutdown(struct __snd_usb_lock *lock) +{ + if (!lock->err) + snd_usb_unlock_shutdown(lock->chip); +} + +DEFINE_CLASS(snd_usb_lock, struct __snd_usb_lock, + __snd_usb_unlock_shutdown(&(_T)), __snd_usb_lock_shutdown(chip), + struct snd_usb_audio *chip) + extern bool snd_usb_use_vmalloc; extern bool snd_usb_skip_validation; @@ -196,35 +219,70 @@ extern bool snd_usb_skip_validation; * for the given endpoint. * QUIRK_FLAG_MIC_RES_16 and QUIRK_FLAG_MIC_RES_384 * Set the fixed resolution for Mic Capture Volume (mostly for webcams) - * QUIRK_FLAG_MIXER_MIN_MUTE + * QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE * Set minimum volume control value as mute for devices where the lowest * playback value represents muted state instead of minimum audible volume + * QUIRK_FLAG_MIXER_CAPTURE_MIN_MUTE + * Similar to QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE, but for capture streams */ -#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) -#define QUIRK_FLAG_SHARE_MEDIA_DEVICE (1U << 1) -#define QUIRK_FLAG_ALIGN_TRANSFER (1U << 2) -#define QUIRK_FLAG_TX_LENGTH (1U << 3) -#define QUIRK_FLAG_PLAYBACK_FIRST (1U << 4) -#define QUIRK_FLAG_SKIP_CLOCK_SELECTOR (1U << 5) -#define QUIRK_FLAG_IGNORE_CLOCK_SOURCE (1U << 6) -#define QUIRK_FLAG_ITF_USB_DSD_DAC (1U << 7) -#define QUIRK_FLAG_CTL_MSG_DELAY (1U << 8) -#define QUIRK_FLAG_CTL_MSG_DELAY_1M (1U << 9) -#define QUIRK_FLAG_CTL_MSG_DELAY_5M (1U << 10) -#define QUIRK_FLAG_IFACE_DELAY (1U << 11) -#define QUIRK_FLAG_VALIDATE_RATES (1U << 12) -#define QUIRK_FLAG_DISABLE_AUTOSUSPEND (1U << 13) -#define QUIRK_FLAG_IGNORE_CTL_ERROR (1U << 14) -#define QUIRK_FLAG_DSD_RAW (1U << 15) -#define QUIRK_FLAG_SET_IFACE_FIRST (1U << 16) -#define QUIRK_FLAG_GENERIC_IMPLICIT_FB (1U << 17) -#define QUIRK_FLAG_SKIP_IMPLICIT_FB (1U << 18) -#define QUIRK_FLAG_IFACE_SKIP_CLOSE (1U << 19) -#define QUIRK_FLAG_FORCE_IFACE_RESET (1U << 20) -#define QUIRK_FLAG_FIXED_RATE (1U << 21) -#define QUIRK_FLAG_MIC_RES_16 (1U << 22) -#define QUIRK_FLAG_MIC_RES_384 (1U << 23) -#define QUIRK_FLAG_MIXER_MIN_MUTE (1U << 24) +enum { + QUIRK_TYPE_GET_SAMPLE_RATE = 0, + QUIRK_TYPE_SHARE_MEDIA_DEVICE = 1, + QUIRK_TYPE_ALIGN_TRANSFER = 2, + QUIRK_TYPE_TX_LENGTH = 3, + QUIRK_TYPE_PLAYBACK_FIRST = 4, + QUIRK_TYPE_SKIP_CLOCK_SELECTOR = 5, + QUIRK_TYPE_IGNORE_CLOCK_SOURCE = 6, + QUIRK_TYPE_ITF_USB_DSD_DAC = 7, + QUIRK_TYPE_CTL_MSG_DELAY = 8, + QUIRK_TYPE_CTL_MSG_DELAY_1M = 9, + QUIRK_TYPE_CTL_MSG_DELAY_5M = 10, + QUIRK_TYPE_IFACE_DELAY = 11, + QUIRK_TYPE_VALIDATE_RATES = 12, + QUIRK_TYPE_DISABLE_AUTOSUSPEND = 13, + QUIRK_TYPE_IGNORE_CTL_ERROR = 14, + QUIRK_TYPE_DSD_RAW = 15, + QUIRK_TYPE_SET_IFACE_FIRST = 16, + QUIRK_TYPE_GENERIC_IMPLICIT_FB = 17, + QUIRK_TYPE_SKIP_IMPLICIT_FB = 18, + QUIRK_TYPE_IFACE_SKIP_CLOSE = 19, + QUIRK_TYPE_FORCE_IFACE_RESET = 20, + QUIRK_TYPE_FIXED_RATE = 21, + QUIRK_TYPE_MIC_RES_16 = 22, + QUIRK_TYPE_MIC_RES_384 = 23, + QUIRK_TYPE_MIXER_PLAYBACK_MIN_MUTE = 24, + QUIRK_TYPE_MIXER_CAPTURE_MIN_MUTE = 25, +/* Please also edit snd_usb_audio_quirk_flag_names */ +}; + +#define QUIRK_FLAG(x) BIT_U32(QUIRK_TYPE_ ## x) + +#define QUIRK_FLAG_GET_SAMPLE_RATE QUIRK_FLAG(GET_SAMPLE_RATE) +#define QUIRK_FLAG_SHARE_MEDIA_DEVICE QUIRK_FLAG(SHARE_MEDIA_DEVICE) +#define QUIRK_FLAG_ALIGN_TRANSFER QUIRK_FLAG(ALIGN_TRANSFER) +#define QUIRK_FLAG_TX_LENGTH QUIRK_FLAG(TX_LENGTH) +#define QUIRK_FLAG_PLAYBACK_FIRST QUIRK_FLAG(PLAYBACK_FIRST) +#define QUIRK_FLAG_SKIP_CLOCK_SELECTOR QUIRK_FLAG(SKIP_CLOCK_SELECTOR) +#define QUIRK_FLAG_IGNORE_CLOCK_SOURCE QUIRK_FLAG(IGNORE_CLOCK_SOURCE) +#define QUIRK_FLAG_ITF_USB_DSD_DAC QUIRK_FLAG(ITF_USB_DSD_DAC) +#define QUIRK_FLAG_CTL_MSG_DELAY QUIRK_FLAG(CTL_MSG_DELAY) +#define QUIRK_FLAG_CTL_MSG_DELAY_1M QUIRK_FLAG(CTL_MSG_DELAY_1M) +#define QUIRK_FLAG_CTL_MSG_DELAY_5M QUIRK_FLAG(CTL_MSG_DELAY_5M) +#define QUIRK_FLAG_IFACE_DELAY QUIRK_FLAG(IFACE_DELAY) +#define QUIRK_FLAG_VALIDATE_RATES QUIRK_FLAG(VALIDATE_RATES) +#define QUIRK_FLAG_DISABLE_AUTOSUSPEND QUIRK_FLAG(DISABLE_AUTOSUSPEND) +#define QUIRK_FLAG_IGNORE_CTL_ERROR QUIRK_FLAG(IGNORE_CTL_ERROR) +#define QUIRK_FLAG_DSD_RAW QUIRK_FLAG(DSD_RAW) +#define QUIRK_FLAG_SET_IFACE_FIRST QUIRK_FLAG(SET_IFACE_FIRST) +#define QUIRK_FLAG_GENERIC_IMPLICIT_FB QUIRK_FLAG(GENERIC_IMPLICIT_FB) +#define QUIRK_FLAG_SKIP_IMPLICIT_FB QUIRK_FLAG(SKIP_IMPLICIT_FB) +#define QUIRK_FLAG_IFACE_SKIP_CLOSE QUIRK_FLAG(IFACE_SKIP_CLOSE) +#define QUIRK_FLAG_FORCE_IFACE_RESET QUIRK_FLAG(FORCE_IFACE_RESET) +#define QUIRK_FLAG_FIXED_RATE QUIRK_FLAG(FIXED_RATE) +#define QUIRK_FLAG_MIC_RES_16 QUIRK_FLAG(MIC_RES_16) +#define QUIRK_FLAG_MIC_RES_384 QUIRK_FLAG(MIC_RES_384) +#define QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE QUIRK_FLAG(MIXER_PLAYBACK_MIN_MUTE) +#define QUIRK_FLAG_MIXER_CAPTURE_MIN_MUTE QUIRK_FLAG(MIXER_CAPTURE_MIN_MUTE) #endif /* __USBAUDIO_H */ diff --git a/sound/usb/usx2y/Makefile b/sound/usb/usx2y/Makefile index fc033aba03a4..9db87ae39ee9 100644 --- a/sound/usb/usx2y/Makefile +++ b/sound/usb/usx2y/Makefile @@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 snd-usb-usx2y-y := usbusx2y.o usX2Yhwdep.o usx2yhwdeppcm.o snd-usb-us122l-y := us122l.o +snd-usb-us144mkii-y := us144mkii.o us144mkii_pcm.o us144mkii_playback.o us144mkii_capture.o us144mkii_midi.o us144mkii_controls.o obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-usx2y.o obj-$(CONFIG_SND_USB_US122L) += snd-usb-us122l.o +obj-$(CONFIG_SND_USB_US144MKII) += snd-usb-us144mkii.o
\ No newline at end of file diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 2ace3ba46091..011ea96e9779 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -97,10 +97,10 @@ static vm_fault_t usb_stream_hwdep_vm_fault(struct vm_fault *vmf) struct us122l *us122l = vmf->vma->vm_private_data; struct usb_stream *s; - mutex_lock(&us122l->mutex); + guard(mutex)(&us122l->mutex); s = us122l->sk.s; if (!s) - goto unlock; + return VM_FAULT_SIGBUS; offset = vmf->pgoff << PAGE_SHIFT; if (offset < PAGE_ALIGN(s->read_size)) { @@ -108,21 +108,17 @@ static vm_fault_t usb_stream_hwdep_vm_fault(struct vm_fault *vmf) } else { offset -= PAGE_ALIGN(s->read_size); if (offset >= PAGE_ALIGN(s->write_size)) - goto unlock; + return VM_FAULT_SIGBUS; vaddr = us122l->sk.write_page + offset; } page = virt_to_page(vaddr); get_page(page); - mutex_unlock(&us122l->mutex); vmf->page = page; return 0; -unlock: - mutex_unlock(&us122l->mutex); - return VM_FAULT_SIGBUS; } @@ -163,12 +159,11 @@ static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file) usb_autopm_put_interface(iface); if (us122l->first == file) us122l->first = NULL; - mutex_lock(&us122l->mutex); + guard(mutex)(&us122l->mutex); if (us122l->master == file) us122l->master = us122l->slave; us122l->slave = NULL; - mutex_unlock(&us122l->mutex); return 0; } @@ -179,23 +174,19 @@ static int usb_stream_hwdep_mmap(struct snd_hwdep *hw, struct us122l *us122l = hw->private_data; unsigned long offset; struct usb_stream *s; - int err = 0; bool read; offset = area->vm_pgoff << PAGE_SHIFT; - mutex_lock(&us122l->mutex); + guard(mutex)(&us122l->mutex); s = us122l->sk.s; read = offset < s->read_size; - if (read && area->vm_flags & VM_WRITE) { - err = -EPERM; - goto out; - } + if (read && area->vm_flags & VM_WRITE) + return -EPERM; /* if userspace tries to mmap beyond end of our buffer, fail */ if (size > PAGE_ALIGN(read ? s->read_size : s->write_size)) { dev_warn(hw->card->dev, "%s: size %lu > %u\n", __func__, size, read ? s->read_size : s->write_size); - err = -EINVAL; - goto out; + return -EINVAL; } area->vm_ops = &usb_stream_hwdep_vm_ops; @@ -203,9 +194,7 @@ static int usb_stream_hwdep_mmap(struct snd_hwdep *hw, if (!read) vm_flags_set(area, VM_DONTEXPAND); area->vm_private_data = us122l; -out: - mutex_unlock(&us122l->mutex); - return err; + return 0; } static __poll_t usb_stream_hwdep_poll(struct snd_hwdep *hw, @@ -361,7 +350,7 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, snd_power_wait(hw->card); - mutex_lock(&us122l->mutex); + guard(mutex)(&us122l->mutex); s = us122l->sk.s; if (!us122l->master) { us122l->master = file; @@ -381,7 +370,6 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, err = 1; } unlock: - mutex_unlock(&us122l->mutex); wake_up_all(&us122l->sk.sleep); return err; } @@ -577,9 +565,9 @@ static void snd_us122l_disconnect(struct usb_interface *intf) snd_card_disconnect(card); us122l = US122L(card); - mutex_lock(&us122l->mutex); - us122l_stop(us122l); - mutex_unlock(&us122l->mutex); + scoped_guard(mutex, &us122l->mutex) { + us122l_stop(us122l); + } /* release the midi resources */ list_for_each(p, &us122l->midi_list) { @@ -611,9 +599,8 @@ static int snd_us122l_suspend(struct usb_interface *intf, pm_message_t message) list_for_each(p, &us122l->midi_list) snd_usbmidi_input_stop(p); - mutex_lock(&us122l->mutex); + guard(mutex)(&us122l->mutex); usb_stream_stop(&us122l->sk); - mutex_unlock(&us122l->mutex); return 0; } @@ -633,7 +620,7 @@ static int snd_us122l_resume(struct usb_interface *intf) if (!us122l) return 0; - mutex_lock(&us122l->mutex); + guard(mutex)(&us122l->mutex); /* needed, doesn't restart without: */ if (us122l->is_us144) { err = usb_set_interface(us122l->dev, 0, 1); @@ -664,7 +651,6 @@ static int snd_us122l_resume(struct usb_interface *intf) list_for_each(p, &us122l->midi_list) snd_usbmidi_input_start(p); unlock: - mutex_unlock(&us122l->mutex); snd_power_change_state(card, SNDRV_CTL_POWER_D0); return err; } @@ -686,12 +672,6 @@ static const struct usb_device_id snd_us122l_usb_id_table[] = { .idVendor = 0x0644, .idProduct = USB_ID_US122MKII }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x0644, - .idProduct = USB_ID_US144MKII, - .driver_info = US122L_FLAG_US144 - }, { /* terminator */ } }; MODULE_DEVICE_TABLE(usb, snd_us122l_usb_id_table); diff --git a/sound/usb/usx2y/us144mkii.c b/sound/usb/usx2y/us144mkii.c new file mode 100644 index 000000000000..f6572a576c15 --- /dev/null +++ b/sound/usb/usx2y/us144mkii.c @@ -0,0 +1,620 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2025 Å erif Rami <ramiserifpersia@gmail.com> +/* + * ALSA Driver for TASCAM US-144MKII Audio Interface + */ + +#include "us144mkii.h" + +MODULE_AUTHOR("Å erif Rami <ramiserifpersia@gmail.com>"); +MODULE_DESCRIPTION("ALSA Driver for TASCAM US-144MKII"); +MODULE_LICENSE("GPL"); + +/** + * @brief Module parameters for ALSA card instantiation. + * + * These parameters allow users to configure how the ALSA sound card + * for the TASCAM US-144MKII is instantiated. + * + * @param index: Array of integers specifying the ALSA card index for each + * device. Defaults to -1 (automatic). + * @param id: Array of strings specifying the ALSA card ID for each device. + * Defaults to "US144MKII". + * @param enable: Array of booleans to enable or disable each device. + * Defaults to {1, 0, ..., 0} (first device enabled). + * @param dev_idx: Internal counter for the number of TASCAM devices probed. + */ +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; +static bool enable[SNDRV_CARDS] = { 1, [1 ...(SNDRV_CARDS - 1)] = 0 }; +static int dev_idx; + +static int tascam_probe(struct usb_interface *intf, + const struct usb_device_id *usb_id); +static void tascam_disconnect(struct usb_interface *intf); +static int tascam_suspend(struct usb_interface *intf, pm_message_t message); +static int tascam_resume(struct usb_interface *intf); + +void tascam_free_urbs(struct tascam_card *tascam) +{ + int i; + + usb_kill_anchored_urbs(&tascam->playback_anchor); + for (i = 0; i < NUM_PLAYBACK_URBS; i++) { + if (tascam->playback_urbs[i]) { + usb_free_coherent( + tascam->dev, tascam->playback_urb_alloc_size, + tascam->playback_urbs[i]->transfer_buffer, + tascam->playback_urbs[i]->transfer_dma); + usb_free_urb(tascam->playback_urbs[i]); + tascam->playback_urbs[i] = NULL; + } + } + + usb_kill_anchored_urbs(&tascam->feedback_anchor); + for (i = 0; i < NUM_FEEDBACK_URBS; i++) { + if (tascam->feedback_urbs[i]) { + usb_free_coherent( + tascam->dev, tascam->feedback_urb_alloc_size, + tascam->feedback_urbs[i]->transfer_buffer, + tascam->feedback_urbs[i]->transfer_dma); + usb_free_urb(tascam->feedback_urbs[i]); + tascam->feedback_urbs[i] = NULL; + } + } + + usb_kill_anchored_urbs(&tascam->capture_anchor); + for (i = 0; i < NUM_CAPTURE_URBS; i++) { + if (tascam->capture_urbs[i]) { + usb_free_coherent( + tascam->dev, tascam->capture_urb_alloc_size, + tascam->capture_urbs[i]->transfer_buffer, + tascam->capture_urbs[i]->transfer_dma); + usb_free_urb(tascam->capture_urbs[i]); + tascam->capture_urbs[i] = NULL; + } + } + + usb_kill_anchored_urbs(&tascam->midi_in_anchor); + for (i = 0; i < NUM_MIDI_IN_URBS; i++) { + if (tascam->midi_in_urbs[i]) { + usb_free_coherent( + tascam->dev, MIDI_IN_BUF_SIZE, + tascam->midi_in_urbs[i]->transfer_buffer, + tascam->midi_in_urbs[i]->transfer_dma); + usb_free_urb(tascam->midi_in_urbs[i]); + tascam->midi_in_urbs[i] = NULL; + } + } + + usb_kill_anchored_urbs(&tascam->midi_out_anchor); + for (i = 0; i < NUM_MIDI_OUT_URBS; i++) { + if (tascam->midi_out_urbs[i]) { + usb_free_coherent( + tascam->dev, MIDI_OUT_BUF_SIZE, + tascam->midi_out_urbs[i]->transfer_buffer, + tascam->midi_out_urbs[i]->transfer_dma); + usb_free_urb(tascam->midi_out_urbs[i]); + tascam->midi_out_urbs[i] = NULL; + } + } + + kfree(tascam->capture_routing_buffer); + tascam->capture_routing_buffer = NULL; + kfree(tascam->capture_decode_dst_block); + tascam->capture_decode_dst_block = NULL; + kfree(tascam->capture_decode_raw_block); + tascam->capture_decode_raw_block = NULL; + kfree(tascam->capture_ring_buffer); + tascam->capture_ring_buffer = NULL; +} + +int tascam_alloc_urbs(struct tascam_card *tascam) +{ + int i; + size_t max_packet_size; + + max_packet_size = ((96000 / 8000) + 2) * BYTES_PER_FRAME; + tascam->playback_urb_alloc_size = + max_packet_size * PLAYBACK_URB_PACKETS; + + for (i = 0; i < NUM_PLAYBACK_URBS; i++) { + struct urb *urb = + usb_alloc_urb(PLAYBACK_URB_PACKETS, GFP_KERNEL); + + if (!urb) + goto error; + tascam->playback_urbs[i] = urb; + + urb->transfer_buffer = usb_alloc_coherent( + tascam->dev, tascam->playback_urb_alloc_size, + GFP_KERNEL, &urb->transfer_dma); + if (!urb->transfer_buffer) + goto error; + + urb->dev = tascam->dev; + urb->pipe = usb_sndisocpipe(tascam->dev, EP_AUDIO_OUT); + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; + urb->interval = 1; + urb->context = tascam; + urb->complete = playback_urb_complete; + } + + tascam->feedback_urb_alloc_size = + FEEDBACK_PACKET_SIZE * FEEDBACK_URB_PACKETS; + + for (i = 0; i < NUM_FEEDBACK_URBS; i++) { + struct urb *f_urb = + usb_alloc_urb(FEEDBACK_URB_PACKETS, GFP_KERNEL); + + if (!f_urb) + goto error; + tascam->feedback_urbs[i] = f_urb; + + f_urb->transfer_buffer = usb_alloc_coherent( + tascam->dev, tascam->feedback_urb_alloc_size, + GFP_KERNEL, &f_urb->transfer_dma); + if (!f_urb->transfer_buffer) + goto error; + + f_urb->dev = tascam->dev; + f_urb->pipe = + usb_rcvisocpipe(tascam->dev, EP_PLAYBACK_FEEDBACK); + f_urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; + f_urb->interval = 4; + f_urb->context = tascam; + f_urb->complete = feedback_urb_complete; + } + + tascam->capture_urb_alloc_size = CAPTURE_URB_SIZE; + for (i = 0; i < NUM_CAPTURE_URBS; i++) { + struct urb *c_urb = usb_alloc_urb(0, GFP_KERNEL); + + if (!c_urb) + goto error; + tascam->capture_urbs[i] = c_urb; + + c_urb->transfer_buffer = usb_alloc_coherent( + tascam->dev, tascam->capture_urb_alloc_size, GFP_KERNEL, + &c_urb->transfer_dma); + if (!c_urb->transfer_buffer) + goto error; + + usb_fill_bulk_urb(c_urb, tascam->dev, + usb_rcvbulkpipe(tascam->dev, EP_AUDIO_IN), + c_urb->transfer_buffer, + tascam->capture_urb_alloc_size, + capture_urb_complete, tascam); + c_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + } + + /* MIDI URB and buffer allocation */ + for (i = 0; i < NUM_MIDI_IN_URBS; i++) { + struct urb *m_urb = usb_alloc_urb(0, GFP_KERNEL); + + if (!m_urb) + goto error; + tascam->midi_in_urbs[i] = m_urb; + m_urb->transfer_buffer = + usb_alloc_coherent(tascam->dev, MIDI_IN_BUF_SIZE, + GFP_KERNEL, &m_urb->transfer_dma); + if (!m_urb->transfer_buffer) + goto error; + usb_fill_bulk_urb(m_urb, tascam->dev, + usb_rcvbulkpipe(tascam->dev, EP_MIDI_IN), + m_urb->transfer_buffer, MIDI_IN_BUF_SIZE, + tascam_midi_in_urb_complete, tascam); + m_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + } + + for (i = 0; i < NUM_MIDI_OUT_URBS; i++) { + struct urb *m_urb = usb_alloc_urb(0, GFP_KERNEL); + + if (!m_urb) + goto error; + tascam->midi_out_urbs[i] = m_urb; + m_urb->transfer_buffer = + usb_alloc_coherent(tascam->dev, MIDI_OUT_BUF_SIZE, + GFP_KERNEL, &m_urb->transfer_dma); + if (!m_urb->transfer_buffer) + goto error; + usb_fill_bulk_urb(m_urb, tascam->dev, + usb_sndbulkpipe(tascam->dev, EP_MIDI_OUT), + m_urb->transfer_buffer, + 0, /* length set later */ + tascam_midi_out_urb_complete, tascam); + m_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + } + + tascam->capture_ring_buffer = + kmalloc(CAPTURE_RING_BUFFER_SIZE, GFP_KERNEL); + if (!tascam->capture_ring_buffer) + goto error; + + tascam->capture_decode_raw_block = + kmalloc(RAW_BYTES_PER_DECODE_BLOCK, GFP_KERNEL); + if (!tascam->capture_decode_raw_block) + goto error; + + tascam->capture_decode_dst_block = + kmalloc(FRAMES_PER_DECODE_BLOCK * DECODED_CHANNELS_PER_FRAME * + DECODED_SAMPLE_SIZE, + GFP_KERNEL); + if (!tascam->capture_decode_dst_block) + goto error; + + tascam->capture_routing_buffer = + kmalloc(FRAMES_PER_DECODE_BLOCK * DECODED_CHANNELS_PER_FRAME * + DECODED_SAMPLE_SIZE, + GFP_KERNEL); + if (!tascam->capture_routing_buffer) + goto error; + + return 0; + +error: + dev_err(tascam->card->dev, "Failed to allocate URBs\n"); + tascam_free_urbs(tascam); + return -ENOMEM; +} + +void tascam_stop_work_handler(struct work_struct *work) +{ + struct tascam_card *tascam = + container_of(work, struct tascam_card, stop_work); + + usb_kill_anchored_urbs(&tascam->playback_anchor); + usb_kill_anchored_urbs(&tascam->feedback_anchor); + usb_kill_anchored_urbs(&tascam->capture_anchor); + atomic_set(&tascam->active_urbs, 0); +} + +/** + * tascam_card_private_free() - Frees private data associated with the sound + * card. + * @card: Pointer to the ALSA sound card instance. + * + * This function is called when the sound card is being freed. It releases + * resources allocated for the tascam_card structure, including the MIDI + * input FIFO and decrements the USB device reference count. + */ +static void tascam_card_private_free(struct snd_card *card) +{ + struct tascam_card *tascam = card->private_data; + + if (tascam) { + kfifo_free(&tascam->midi_in_fifo); + if (tascam->dev) { + usb_put_dev(tascam->dev); + tascam->dev = NULL; + } + } +} + +/** + * tascam_suspend() - Handles device suspension. + * @intf: The USB interface being suspended. + * @message: Power management message. + * + * This function is called when the device is suspended. It stops all active + * streams, kills all URBs, and sends a vendor-specific deep sleep command + * to the device to ensure a stable low-power state. + * + * Return: 0 on success. + */ +static int tascam_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct tascam_card *tascam = usb_get_intfdata(intf); + + if (!tascam) + return 0; + + snd_pcm_suspend_all(tascam->pcm); + + cancel_work_sync(&tascam->stop_work); + cancel_work_sync(&tascam->capture_work); + cancel_work_sync(&tascam->midi_in_work); + cancel_work_sync(&tascam->midi_out_work); + cancel_work_sync(&tascam->stop_pcm_work); + usb_kill_anchored_urbs(&tascam->playback_anchor); + usb_kill_anchored_urbs(&tascam->capture_anchor); + usb_kill_anchored_urbs(&tascam->feedback_anchor); + usb_kill_anchored_urbs(&tascam->midi_in_anchor); + usb_kill_anchored_urbs(&tascam->midi_out_anchor); + + dev_info(&intf->dev, "sending deep sleep command\n"); + int err = usb_control_msg(tascam->dev, usb_sndctrlpipe(tascam->dev, 0), + VENDOR_REQ_DEEP_SLEEP, RT_H2D_VENDOR_DEV, + 0x0000, 0x0000, NULL, 0, USB_CTRL_TIMEOUT_MS); + if (err < 0) + dev_err(&intf->dev, "deep sleep command failed: %d\n", err); + + return 0; +} + +/** + * tascam_resume() - Handles device resumption from suspend. + * @intf: The USB interface being resumed. + * + * This function is called when the device resumes from suspend. It + * re-establishes the active USB interface settings and re-configures the sample + * rate if it was previously active. + * + * Return: 0 on success, or a negative error code on failure. + */ +static int tascam_resume(struct usb_interface *intf) +{ + struct tascam_card *tascam = usb_get_intfdata(intf); + int err; + + if (!tascam) + return 0; + + dev_info(&intf->dev, "resuming TASCAM US-144MKII\n"); + + /* + * The device requires a full re-initialization sequence upon resume. + * First, re-establish the active USB interface settings. + */ + err = usb_set_interface(tascam->dev, 0, 1); + if (err < 0) { + dev_err(&intf->dev, + "resume: failed to set alt setting on intf 0: %d\n", + err); + return err; + } + err = usb_set_interface(tascam->dev, 1, 1); + if (err < 0) { + dev_err(&intf->dev, + "resume: failed to set alt setting on intf 1: %d\n", + err); + return err; + } + + /* Re-configure the sample rate if one was previously active */ + if (tascam->current_rate > 0) + us144mkii_configure_device_for_rate(tascam, + tascam->current_rate); + + return 0; +} + +static void tascam_error_timer(struct timer_list *t) +{ + struct tascam_card *tascam = + container_of(t, struct tascam_card, error_timer); + + if (atomic_read(&tascam->midi_in_active)) + schedule_work(&tascam->midi_in_work); + if (atomic_read(&tascam->midi_out_active)) + schedule_work(&tascam->midi_out_work); +} + +/** + * tascam_probe() - Probes for the TASCAM US-144MKII device. + * @intf: The USB interface being probed. + * @usb_id: The USB device ID. + * + * This function is the entry point for the USB driver when a matching device + * is found. It performs initial device setup, including: + * - Checking for the second interface (MIDI) and associating it. + * - Performing a vendor-specific handshake with the device. + * - Setting alternate settings for USB interfaces. + * - Creating and registering the ALSA sound card, PCM device, and MIDI device. + * - Allocating and initializing URBs for audio and MIDI transfers. + * + * Return: 0 on success, or a negative error code on failure. + */ +static int tascam_probe(struct usb_interface *intf, + const struct usb_device_id *usb_id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct snd_card *card; + struct tascam_card *tascam; + int err; + char *handshake_buf __free(kfree) = NULL; + + if (dev->speed != USB_SPEED_HIGH) + dev_info( + &dev->dev, + "Device is connected to a USB 1.1 port, this is not supported.\n"); + + /* The device has two interfaces; we drive both from this driver. */ + if (intf->cur_altsetting->desc.bInterfaceNumber == 1) { + tascam = usb_get_intfdata(usb_ifnum_to_if(dev, 0)); + if (tascam) { + usb_set_intfdata(intf, tascam); + tascam->iface1 = intf; + } + return 0; /* Let the core handle this interface */ + } + + if (dev_idx >= SNDRV_CARDS) { + dev_err(&dev->dev, "Too many TASCAM devices present"); + return -ENODEV; + } + + if (!enable[dev_idx]) { + dev_info(&dev->dev, "TASCAM US-144MKII device disabled"); + return -ENOENT; + } + + handshake_buf = kmalloc(1, GFP_KERNEL); + if (!handshake_buf) + return -ENOMEM; + + /* Perform vendor-specific handshake */ + err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + VENDOR_REQ_MODE_CONTROL, RT_D2H_VENDOR_DEV, + MODE_VAL_HANDSHAKE_READ, 0x0000, handshake_buf, 1, + USB_CTRL_TIMEOUT_MS); + if (err < 0) { + dev_err(&dev->dev, "Handshake read failed with %d\n", err); + return err; + } + + if (handshake_buf[0] != 0x12 && handshake_buf[0] != 0x16 && + handshake_buf[0] != 0x30 && handshake_buf[0] != 0x32) { + dev_err(&dev->dev, "Unexpected handshake value: 0x%x\n", + handshake_buf[0]); + return -ENODEV; + } + + /* Set alternate settings to enable audio/MIDI endpoints */ + err = usb_set_interface(dev, 0, 1); + if (err < 0) { + dev_err(&dev->dev, + "Failed to set alt setting 1 on interface 0: %d\n", + err); + return err; + } + + err = usb_set_interface(dev, 1, 1); + if (err < 0) { + dev_err(&dev->dev, + "Failed to set alt setting 1 on interface 1: %d\n", + err); + return err; + } + + err = snd_card_new(&dev->dev, index[dev_idx], id[dev_idx], THIS_MODULE, + sizeof(struct tascam_card), &card); + if (err < 0) { + dev_err(&dev->dev, "Failed to create sound card instance\n"); + return err; + } + + tascam = card->private_data; + card->private_free = tascam_card_private_free; + tascam->dev = usb_get_dev(dev); + tascam->card = card; + tascam->iface0 = intf; + tascam->digital_out_source = 1; + tascam->capture_34_source = 1; + + spin_lock_init(&tascam->lock); + spin_lock_init(&tascam->midi_in_lock); + spin_lock_init(&tascam->midi_out_lock); + init_usb_anchor(&tascam->playback_anchor); + init_usb_anchor(&tascam->capture_anchor); + init_usb_anchor(&tascam->feedback_anchor); + init_usb_anchor(&tascam->midi_in_anchor); + init_usb_anchor(&tascam->midi_out_anchor); + + timer_setup(&tascam->error_timer, tascam_error_timer, 0); + + INIT_WORK(&tascam->stop_work, tascam_stop_work_handler); + INIT_WORK(&tascam->stop_pcm_work, tascam_stop_pcm_work_handler); + INIT_WORK(&tascam->capture_work, tascam_capture_work_handler); + init_completion(&tascam->midi_out_drain_completion); + + if (kfifo_alloc(&tascam->midi_in_fifo, MIDI_IN_FIFO_SIZE, GFP_KERNEL)) { + snd_card_free(card); + return -ENOMEM; + } + + strscpy(card->driver, DRIVER_NAME, sizeof(card->driver)); + if (le16_to_cpu(dev->descriptor.idProduct) == USB_PID_TASCAM_US144) { + strscpy(card->shortname, "TASCAM US-144", + sizeof(card->shortname)); + } else if (le16_to_cpu(dev->descriptor.idProduct) == USB_PID_TASCAM_US144MKII) { + strscpy(card->shortname, "TASCAM US-144MKII", + sizeof(card->shortname)); + } else { + strscpy(card->shortname, "TASCAM Unknown", + sizeof(card->shortname)); + } + snprintf(card->longname, sizeof(card->longname), "%s (%04x:%04x) at %s", + card->shortname, USB_VID_TASCAM, dev->descriptor.idProduct, + dev_name(&dev->dev)); + + err = snd_pcm_new(card, "US144MKII PCM", 0, 1, 1, &tascam->pcm); + if (err < 0) + goto free_card; + tascam->pcm->private_data = tascam; + strscpy(tascam->pcm->name, "US144MKII PCM", sizeof(tascam->pcm->name)); + + err = tascam_init_pcm(tascam->pcm); + if (err < 0) + goto free_card; + + err = tascam_create_midi(tascam); + if (err < 0) + goto free_card; + + err = tascam_create_controls(tascam); + if (err < 0) + goto free_card; + + err = tascam_alloc_urbs(tascam); + if (err < 0) + goto free_card; + + err = snd_card_register(card); + if (err < 0) + goto free_card; + + usb_set_intfdata(intf, tascam); + + dev_idx++; + return 0; + +free_card: + tascam_free_urbs(tascam); + snd_card_free(card); + return err; +} + +/** + * tascam_disconnect() - Disconnects the TASCAM US-144MKII device. + * @intf: The USB interface being disconnected. + * + * This function is called when the device is disconnected from the system. + * It cleans up all allocated resources, including killing URBs, freeing + * the sound card, and releasing memory. + */ +static void tascam_disconnect(struct usb_interface *intf) +{ + struct tascam_card *tascam = usb_get_intfdata(intf); + + if (!tascam) + return; + + if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { + /* Ensure all deferred work is complete before freeing resources */ + snd_card_disconnect(tascam->card); + cancel_work_sync(&tascam->stop_work); + cancel_work_sync(&tascam->capture_work); + cancel_work_sync(&tascam->midi_in_work); + cancel_work_sync(&tascam->midi_out_work); + cancel_work_sync(&tascam->stop_pcm_work); + + usb_kill_anchored_urbs(&tascam->playback_anchor); + usb_kill_anchored_urbs(&tascam->capture_anchor); + usb_kill_anchored_urbs(&tascam->feedback_anchor); + usb_kill_anchored_urbs(&tascam->midi_in_anchor); + usb_kill_anchored_urbs(&tascam->midi_out_anchor); + timer_delete_sync(&tascam->error_timer); + tascam_free_urbs(tascam); + snd_card_free(tascam->card); + dev_idx--; + } +} + +static const struct usb_device_id tascam_usb_ids[] = { + { USB_DEVICE(USB_VID_TASCAM, USB_PID_TASCAM_US144) }, + { USB_DEVICE(USB_VID_TASCAM, USB_PID_TASCAM_US144MKII) }, + { /* Terminating entry */ } +}; +MODULE_DEVICE_TABLE(usb, tascam_usb_ids); + +static struct usb_driver tascam_alsa_driver = { + .name = DRIVER_NAME, + .probe = tascam_probe, + .disconnect = tascam_disconnect, + .suspend = tascam_suspend, + .resume = tascam_resume, + .id_table = tascam_usb_ids, +}; + +module_usb_driver(tascam_alsa_driver); diff --git a/sound/usb/usx2y/us144mkii.h b/sound/usb/usx2y/us144mkii.h new file mode 100644 index 000000000000..95c4341f038a --- /dev/null +++ b/sound/usb/usx2y/us144mkii.h @@ -0,0 +1,367 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +// Copyright (c) 2025 Å erif Rami <ramiserifpersia@gmail.com> + +#ifndef __US144MKII_H +#define __US144MKII_H + +#include <linux/kfifo.h> +#include <linux/timer.h> +#include <linux/usb.h> +#include <linux/workqueue.h> +#include <sound/control.h> +#include <sound/core.h> +#include <sound/initval.h> +#include <sound/pcm.h> +#include <sound/rawmidi.h> + +#define DRIVER_NAME "us144mkii" + +/* --- USB Device Identification --- */ +#define USB_VID_TASCAM 0x0644 +#define USB_PID_TASCAM_US144 0x800f +#define USB_PID_TASCAM_US144MKII 0x8020 + +/* --- USB Endpoints (Alternate Setting 1) --- */ +#define EP_PLAYBACK_FEEDBACK 0x81 +#define EP_AUDIO_OUT 0x02 +#define EP_MIDI_IN 0x83 +#define EP_MIDI_OUT 0x04 +#define EP_AUDIO_IN 0x86 + +/* --- USB Control Message Protocol --- */ +#define RT_H2D_CLASS_EP (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT) +#define RT_D2H_CLASS_EP (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT) +#define RT_H2D_VENDOR_DEV (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE) +#define RT_D2H_VENDOR_DEV (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE) + +enum uac_request { + UAC_SET_CUR = 0x01, + UAC_GET_CUR = 0x81, +}; + +enum uac_control_selector { + UAC_SAMPLING_FREQ_CONTROL = 0x0100, +}; + +enum tascam_vendor_request { + VENDOR_REQ_REGISTER_WRITE = 0x41, + VENDOR_REQ_DEEP_SLEEP = 0x44, + VENDOR_REQ_MODE_CONTROL = 0x49, +}; + +enum tascam_mode_value { + MODE_VAL_HANDSHAKE_READ = 0x0000, + MODE_VAL_CONFIG = 0x0010, + MODE_VAL_STREAM_START = 0x0030, +}; + +#define HANDSHAKE_SUCCESS_VAL 0x12 + +enum tascam_register { + REG_ADDR_UNKNOWN_0D = 0x0d04, + REG_ADDR_UNKNOWN_0E = 0x0e00, + REG_ADDR_UNKNOWN_0F = 0x0f00, + REG_ADDR_RATE_44100 = 0x1000, + REG_ADDR_RATE_48000 = 0x1002, + REG_ADDR_RATE_88200 = 0x1008, + REG_ADDR_RATE_96000 = 0x100a, + REG_ADDR_UNKNOWN_11 = 0x110b, +}; + +#define REG_VAL_ENABLE 0x0101 + +/* --- URB Configuration --- */ +#define NUM_PLAYBACK_URBS 4 +#define PLAYBACK_URB_PACKETS 8 +#define NUM_FEEDBACK_URBS 4 +#define FEEDBACK_URB_PACKETS 1 +#define FEEDBACK_PACKET_SIZE 3 +#define NUM_CAPTURE_URBS 8 +#define CAPTURE_URB_SIZE 512 +#define CAPTURE_RING_BUFFER_SIZE (CAPTURE_URB_SIZE * NUM_CAPTURE_URBS * 4) +#define NUM_MIDI_IN_URBS 4 +#define MIDI_IN_BUF_SIZE 64 +#define MIDI_IN_FIFO_SIZE (MIDI_IN_BUF_SIZE * NUM_MIDI_IN_URBS) +#define MIDI_OUT_BUF_SIZE 64 +#define NUM_MIDI_OUT_URBS 4 +#define USB_CTRL_TIMEOUT_MS 1000 +#define FEEDBACK_SYNC_LOSS_THRESHOLD 41 + +/* --- Audio Format Configuration --- */ +#define BYTES_PER_SAMPLE 3 +#define NUM_CHANNELS 4 +#define BYTES_PER_FRAME (NUM_CHANNELS * BYTES_PER_SAMPLE) +#define FEEDBACK_ACCUMULATOR_SIZE 128 + +/* --- Capture Decoding Defines --- */ +#define DECODED_CHANNELS_PER_FRAME 4 +#define DECODED_SAMPLE_SIZE 4 +#define FRAMES_PER_DECODE_BLOCK 8 +#define RAW_BYTES_PER_DECODE_BLOCK 512 + +/** + * struct us144mkii_frame_pattern_observer - State for dynamic feedback + * patterns. + * @sample_rate_khz: The current sample rate in kHz. + * @base_feedback_value: The nominal feedback value for the current rate. + * @feedback_offset: An offset to align the feedback value range. + * @full_frame_patterns: A 2D array of pre-calculated packet size patterns. + * @current_index: The current index into the pattern array. + * @previous_index: The previous index, used for state tracking. + * @sync_locked: A flag indicating if the pattern has locked to the stream. + */ +struct us144mkii_frame_pattern_observer { + unsigned int sample_rate_khz; + unsigned int base_feedback_value; + int feedback_offset; + unsigned int full_frame_patterns[5][8]; + unsigned int current_index; + unsigned int previous_index; + bool sync_locked; +}; + +/** + * struct tascam_card - Main driver data structure for the TASCAM US-144MKII. + * @dev: Pointer to the USB device. + * @iface0: Pointer to USB interface 0 (audio). + * @iface1: Pointer to USB interface 1 (MIDI). + * @card: Pointer to the ALSA sound card instance. + * @pcm: Pointer to the ALSA PCM device. + * @rmidi: Pointer to the ALSA rawmidi device. + * + * @playback_substream: Pointer to the active playback PCM substream. + * @playback_urbs: Array of URBs for playback. + * @playback_urb_alloc_size: Size of allocated buffer for each playback URB. + * @feedback_urbs: Array of URBs for feedback. + * @feedback_urb_alloc_size: Size of allocated buffer for each feedback URB. + * @playback_active: Atomic flag indicating if playback is active. + * @playback_frames_consumed: Total frames consumed by playback. + * @driver_playback_pos: Current position in the ALSA playback buffer (frames). + * @last_period_pos: Last reported period position for playback. + * + * @capture_substream: Pointer to the active capture PCM substream. + * @capture_urbs: Array of URBs for capture. + * @capture_urb_alloc_size: Size of allocated buffer for each capture URB. + * @capture_active: Atomic flag indicating if capture is active. + * @driver_capture_pos: Current position in the ALSA capture buffer (frames). + * @capture_frames_processed: Total frames processed for capture. + * @last_capture_period_pos: Last reported period position for capture. + * @capture_ring_buffer: Ring buffer for raw capture data from USB. + * @capture_ring_buffer_read_ptr: Read pointer for the capture ring buffer. + * @capture_ring_buffer_write_ptr: Write pointer for the capture ring buffer. + * @capture_decode_raw_block: Buffer for a raw 512-byte capture block. + * @capture_decode_dst_block: Buffer for decoded 32-bit capture samples. + * @capture_routing_buffer: Intermediate buffer for capture routing. + * @capture_work: Work struct for deferred capture processing. + * @stop_work: Work struct for deferred stream stopping. + * @stop_pcm_work: Work struct for stopping PCM due to a fatal error (e.g. + * xrun). + * + * @midi_in_substream: Pointer to the active MIDI input substream. + * @midi_out_substream: Pointer to the active MIDI output substream. + * @midi_in_urbs: Array of URBs for MIDI input. + * @midi_out_urbs: Array of URBs for MIDI output. + * @midi_in_active: Atomic flag indicating if MIDI input is active. + * @midi_out_active: Atomic flag indicating if MIDI output is active. + * @midi_in_fifo: FIFO for raw MIDI input data. + * @midi_in_work: Work struct for deferred MIDI input processing. + * @midi_out_work: Work struct for deferred MIDI output processing. + * @midi_in_lock: Spinlock for MIDI input FIFO. + * @midi_out_lock: Spinlock for MIDI output. + * @midi_out_urbs_in_flight: Bitmap of MIDI output URBs currently in flight. + * @midi_running_status: Stores the last MIDI status byte for running status. + * @error_timer: Timer for MIDI error retry logic. + * + * @lock: Main spinlock for protecting shared driver state. + * @active_urbs: Atomic counter for active URBs. + * @current_rate: Currently configured sample rate of the device. + * @line_out_source: Source for Line Outputs (0: Playback 1-2, 1: Playback 3-4). + * @digital_out_source: Source for Digital Outputs (0: Playback 1-2, 1: Playback + * 3-4). + * @capture_12_source: Source for Capture channels 1-2 (0: Analog In, 1: Digital + * In). + * @capture_34_source: Source for Capture channels 3-4 (0: Analog In, 1: Digital + * In). + * + * @feedback_accumulator_pattern: Stores the calculated frames per packet for + * feedback. + * @feedback_pattern_out_idx: Read index for feedback_accumulator_pattern. + * @feedback_pattern_in_idx: Write index for feedback_accumulator_pattern. + * @feedback_synced: Flag indicating if feedback is synced. + * @feedback_consecutive_errors: Counter for consecutive feedback errors. + * @feedback_urb_skip_count: Number of feedback URBs to skip initially for + * stabilization. + * @fpo: Holds the state for the dynamic feedback pattern generation. + * + * @playback_anchor: USB anchor for playback URBs. + * @capture_anchor: USB anchor for capture URBs. + * @feedback_anchor: USB anchor for feedback URBs. + * @midi_in_anchor: USB anchor for MIDI input URBs. + * @midi_out_anchor: USB anchor for MIDI output URBs. + */ +struct tascam_card { + /* --- Core device pointers --- */ + struct usb_device *dev; + struct usb_interface *iface0; + struct usb_interface *iface1; + struct snd_card *card; + struct snd_pcm *pcm; + struct snd_rawmidi *rmidi; + + /* --- PCM Substreams --- */ + struct snd_pcm_substream *playback_substream; + struct snd_pcm_substream *capture_substream; + + /* --- URBs and Anchors --- */ + struct urb *playback_urbs[NUM_PLAYBACK_URBS]; + size_t playback_urb_alloc_size; + struct urb *feedback_urbs[NUM_FEEDBACK_URBS]; + size_t feedback_urb_alloc_size; + struct urb *capture_urbs[NUM_CAPTURE_URBS]; + size_t capture_urb_alloc_size; + struct urb *midi_in_urbs[NUM_MIDI_IN_URBS]; + struct urb *midi_out_urbs[NUM_MIDI_OUT_URBS]; + struct usb_anchor playback_anchor; + struct usb_anchor capture_anchor; + struct usb_anchor feedback_anchor; + struct usb_anchor midi_in_anchor; + struct usb_anchor midi_out_anchor; + + /* --- Stream State --- */ + spinlock_t lock; + atomic_t playback_active; + atomic_t capture_active; + atomic_t active_urbs; + int current_rate; + + /* --- Playback State --- */ + u64 playback_frames_consumed; + snd_pcm_uframes_t driver_playback_pos; + u64 last_period_pos; + + /* --- Capture State --- */ + u64 capture_frames_processed; + snd_pcm_uframes_t driver_capture_pos; + u64 last_capture_period_pos; + u8 *capture_ring_buffer; + size_t capture_ring_buffer_read_ptr; + size_t capture_ring_buffer_write_ptr; + u8 *capture_decode_raw_block; + s32 *capture_decode_dst_block; + s32 *capture_routing_buffer; + + /* --- MIDI State --- */ + struct snd_rawmidi_substream *midi_in_substream; + struct snd_rawmidi_substream *midi_out_substream; + atomic_t midi_in_active; + atomic_t midi_out_active; + struct kfifo midi_in_fifo; + spinlock_t midi_in_lock; + spinlock_t midi_out_lock; + unsigned long midi_out_urbs_in_flight; + u8 midi_running_status; + struct timer_list error_timer; + struct completion midi_out_drain_completion; + + /* --- Feedback Sync State --- */ + unsigned int feedback_accumulator_pattern[FEEDBACK_ACCUMULATOR_SIZE]; + unsigned int feedback_pattern_out_idx; + unsigned int feedback_pattern_in_idx; + bool feedback_synced; + unsigned int feedback_consecutive_errors; + unsigned int feedback_urb_skip_count; + struct us144mkii_frame_pattern_observer fpo; + + /* --- Workqueues --- */ + struct work_struct stop_work; + struct work_struct stop_pcm_work; + struct work_struct capture_work; + struct work_struct midi_in_work; + struct work_struct midi_out_work; + + /* --- Mixer/Routing State --- */ + unsigned int line_out_source; + unsigned int digital_out_source; + unsigned int capture_12_source; + unsigned int capture_34_source; +}; + +/* main.c */ +/** + * tascam_free_urbs() - Free all allocated URBs and associated buffers. + * @tascam: the tascam_card instance + * + * This function kills, unlinks, and frees all playback, feedback, capture, + * and MIDI URBs, along with their transfer buffers and the capture + * ring/decode buffers. + */ +void tascam_free_urbs(struct tascam_card *tascam); + +/** + * tascam_alloc_urbs() - Allocate all URBs and associated buffers. + * @tascam: the tascam_card instance + * + * This function allocates and initializes all URBs for playback, feedback, + * capture, and MIDI, as well as the necessary buffers for data processing. + * + * Return: 0 on success, or a negative error code on failure. + */ +int tascam_alloc_urbs(struct tascam_card *tascam); + +/** + * tascam_stop_work_handler() - Work handler to stop all active streams. + * @work: Pointer to the work_struct. + * + * This function is scheduled to stop all active URBs (playback, feedback, + * capture) and reset the active_urbs counter. + */ +void tascam_stop_work_handler(struct work_struct *work); + +/* us144mkii_pcm.h */ +#include "us144mkii_pcm.h" + +/* us144mkii_midi.c */ +/** + * tascam_midi_in_urb_complete() - Completion handler for MIDI IN URBs + * @urb: The completed URB. + * + * This function runs in interrupt context. It places the raw data from the + * USB endpoint into a kfifo and schedules a work item to process it later, + * ensuring the interrupt handler remains fast. + */ +void tascam_midi_in_urb_complete(struct urb *urb); + +/** + * tascam_midi_out_urb_complete() - Completion handler for MIDI OUT bulk URB. + * @urb: The completed URB. + * + * This function runs in interrupt context. It marks the output URB as no + * longer in-flight. It then re-schedules the work handler to check for and + * send any more data waiting in the ALSA buffer. This is a safe, non-blocking + * way to continue the data transmission chain. + */ +void tascam_midi_out_urb_complete(struct urb *urb); + +/** + * tascam_create_midi() - Create and initialize the ALSA rawmidi device. + * @tascam: The driver instance. + * + * Return: 0 on success, or a negative error code on failure. + */ +int tascam_create_midi(struct tascam_card *tascam); + +/* us144mkii_controls.c */ +/** + * tascam_create_controls() - Creates and adds ALSA mixer controls for the + * device. + * @tascam: The driver instance. + * + * This function registers custom ALSA controls for managing audio routing + * (line out source, digital out source, capture 1-2 source, capture 3-4 source) + * and displaying the current sample rate. + * + * Return: 0 on success, or a negative error code on failure. + */ +int tascam_create_controls(struct tascam_card *tascam); + +#endif /* __US144MKII_H */ diff --git a/sound/usb/usx2y/us144mkii_capture.c b/sound/usb/usx2y/us144mkii_capture.c new file mode 100644 index 000000000000..00188ff6cd51 --- /dev/null +++ b/sound/usb/usx2y/us144mkii_capture.c @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2025 Å erif Rami <ramiserifpersia@gmail.com> + +#include "us144mkii.h" + +/** + * tascam_capture_open() - Opens the PCM capture substream. + * @substream: The ALSA PCM substream to open. + * + * This function sets the hardware parameters for the capture substream + * and stores a reference to the substream in the driver's private data. + * + * Return: 0 on success. + */ +static int tascam_capture_open(struct snd_pcm_substream *substream) +{ + struct tascam_card *tascam = snd_pcm_substream_chip(substream); + + substream->runtime->hw = tascam_pcm_hw; + tascam->capture_substream = substream; + atomic_set(&tascam->capture_active, 0); + + return 0; +} + +/** + * tascam_capture_close() - Closes the PCM capture substream. + * @substream: The ALSA PCM substream to close. + * + * This function clears the reference to the capture substream in the + * driver's private data. + * + * Return: 0 on success. + */ +static int tascam_capture_close(struct snd_pcm_substream *substream) +{ + struct tascam_card *tascam = snd_pcm_substream_chip(substream); + + tascam->capture_substream = NULL; + + return 0; +} + +/** + * tascam_capture_prepare() - Prepares the PCM capture substream for use. + * @substream: The ALSA PCM substream to prepare. + * + * This function initializes capture-related counters and ring buffer pointers. + * + * Return: 0 on success. + */ +static int tascam_capture_prepare(struct snd_pcm_substream *substream) +{ + struct tascam_card *tascam = snd_pcm_substream_chip(substream); + + tascam->driver_capture_pos = 0; + tascam->capture_frames_processed = 0; + tascam->last_capture_period_pos = 0; + tascam->capture_ring_buffer_read_ptr = 0; + tascam->capture_ring_buffer_write_ptr = 0; + + return 0; +} + +/** + * tascam_capture_pointer() - Returns the current capture pointer position. + * @substream: The ALSA PCM substream. + * + * This function returns the current position of the capture pointer within + * the ALSA ring buffer, in frames. + * + * Return: The current capture pointer position in frames. + */ +static snd_pcm_uframes_t +tascam_capture_pointer(struct snd_pcm_substream *substream) +{ + struct tascam_card *tascam = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + u64 pos; + + if (!atomic_read(&tascam->capture_active)) + return 0; + + scoped_guard(spinlock_irqsave, &tascam->lock) { + pos = tascam->capture_frames_processed; + } + + if (runtime->buffer_size == 0) + return 0; + + return do_div(pos, runtime->buffer_size); +} + +/** + * tascam_capture_ops - ALSA PCM operations for capture. + * + * This structure defines the callback functions for capture stream operations, + * including open, close, ioctl, hardware parameters, hardware free, prepare, + * trigger, and pointer. + */ +const struct snd_pcm_ops tascam_capture_ops = { + .open = tascam_capture_open, + .close = tascam_capture_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = tascam_pcm_hw_params, + .hw_free = tascam_pcm_hw_free, + .prepare = tascam_capture_prepare, + .trigger = tascam_pcm_trigger, + .pointer = tascam_capture_pointer, +}; + +/** + * decode_tascam_capture_block() - Decodes a raw 512-byte block from the device. + * @src_block: Pointer to the 512-byte raw source block. + * @dst_block: Pointer to the destination buffer for decoded audio frames. + * + * The device sends audio data in a complex, multiplexed format. This function + * demultiplexes the bits from the raw block into 8 frames of 4-channel, + * 24-bit audio (stored in 32-bit containers). + */ +static void decode_tascam_capture_block(const u8 *src_block, s32 *dst_block) +{ + int frame, bit; + + memset(dst_block, 0, + FRAMES_PER_DECODE_BLOCK * DECODED_CHANNELS_PER_FRAME * + DECODED_SAMPLE_SIZE); + + for (frame = 0; frame < FRAMES_PER_DECODE_BLOCK; ++frame) { + const u8 *p_src_frame_base = src_block + frame * 64; + s32 *p_dst_frame = dst_block + frame * 4; + + s32 ch[4] = { 0 }; + + for (bit = 0; bit < 24; ++bit) { + u8 byte1 = p_src_frame_base[bit]; + u8 byte2 = p_src_frame_base[bit + 32]; + + ch[0] = (ch[0] << 1) | (byte1 & 1); + ch[2] = (ch[2] << 1) | ((byte1 >> 1) & 1); + + ch[1] = (ch[1] << 1) | (byte2 & 1); + ch[3] = (ch[3] << 1) | ((byte2 >> 1) & 1); + } + + /* + * The result is a 24-bit sample. Shift left by 8 to align it to + * the most significant bits of a 32-bit integer (S32_LE format). + */ + p_dst_frame[0] = ch[0] << 8; + p_dst_frame[1] = ch[1] << 8; + p_dst_frame[2] = ch[2] << 8; + p_dst_frame[3] = ch[3] << 8; + } +} + +void tascam_capture_work_handler(struct work_struct *work) +{ + struct tascam_card *tascam = + container_of(work, struct tascam_card, capture_work); + struct snd_pcm_substream *substream = tascam->capture_substream; + struct snd_pcm_runtime *runtime; + u8 *raw_block = tascam->capture_decode_raw_block; + s32 *decoded_block = tascam->capture_decode_dst_block; + s32 *routed_block = tascam->capture_routing_buffer; + + if (!substream || !substream->runtime) + return; + runtime = substream->runtime; + + if (!raw_block || !decoded_block || !routed_block) { + dev_err(tascam->card->dev, + "Capture decode/routing buffers not allocated!\n"); + return; + } + + while (atomic_read(&tascam->capture_active)) { + size_t write_ptr, read_ptr, available_data; + bool can_process; + + scoped_guard(spinlock_irqsave, &tascam->lock) { + write_ptr = tascam->capture_ring_buffer_write_ptr; + read_ptr = tascam->capture_ring_buffer_read_ptr; + available_data = (write_ptr >= read_ptr) ? + (write_ptr - read_ptr) : + (CAPTURE_RING_BUFFER_SIZE - + read_ptr + write_ptr); + can_process = + (available_data >= RAW_BYTES_PER_DECODE_BLOCK); + + if (can_process) { + size_t bytes_to_end = + CAPTURE_RING_BUFFER_SIZE - read_ptr; + if (bytes_to_end >= + RAW_BYTES_PER_DECODE_BLOCK) { + memcpy(raw_block, + tascam->capture_ring_buffer + + read_ptr, + RAW_BYTES_PER_DECODE_BLOCK); + } else { + memcpy(raw_block, + tascam->capture_ring_buffer + + read_ptr, + bytes_to_end); + memcpy(raw_block + bytes_to_end, + tascam->capture_ring_buffer, + RAW_BYTES_PER_DECODE_BLOCK - + bytes_to_end); + } + tascam->capture_ring_buffer_read_ptr = + (read_ptr + + RAW_BYTES_PER_DECODE_BLOCK) % + CAPTURE_RING_BUFFER_SIZE; + } + } + + if (!can_process) + break; + + decode_tascam_capture_block(raw_block, decoded_block); + process_capture_routing_us144mkii(tascam, decoded_block, + routed_block); + + scoped_guard(spinlock_irqsave, &tascam->lock) { + if (atomic_read(&tascam->capture_active)) { + int f; + + for (f = 0; f < FRAMES_PER_DECODE_BLOCK; ++f) { + u8 *dst_frame_start = + runtime->dma_area + + frames_to_bytes( + runtime, + tascam->driver_capture_pos); + s32 *routed_frame_start = + routed_block + + (f * NUM_CHANNELS); + int c; + + for (c = 0; c < NUM_CHANNELS; c++) { + u8 *dst_channel = + dst_frame_start + + (c * BYTES_PER_SAMPLE); + s32 *src_channel_s32 = + routed_frame_start + c; + + memcpy(dst_channel, + ((char *)src_channel_s32) + + 1, + 3); + } + + tascam->driver_capture_pos = + (tascam->driver_capture_pos + + 1) % + runtime->buffer_size; + } + } + } + } +} + +void capture_urb_complete(struct urb *urb) +{ + struct tascam_card *tascam = urb->context; + int ret; + + if (urb->status) { + if (urb->status != -ENOENT && urb->status != -ECONNRESET && + urb->status != -ESHUTDOWN && urb->status != -ENODEV && + urb->status != -EPROTO) + dev_err_ratelimited(tascam->card->dev, + "Capture URB failed: %d\n", + urb->status); + goto out; + } + if (!tascam || !atomic_read(&tascam->capture_active)) + goto out; + + if (urb->actual_length > 0) { + scoped_guard(spinlock_irqsave, &tascam->lock) { + size_t write_ptr = tascam->capture_ring_buffer_write_ptr; + size_t bytes_to_end = CAPTURE_RING_BUFFER_SIZE - write_ptr; + + if (urb->actual_length > bytes_to_end) { + memcpy(tascam->capture_ring_buffer + write_ptr, + urb->transfer_buffer, bytes_to_end); + memcpy(tascam->capture_ring_buffer, + urb->transfer_buffer + bytes_to_end, + urb->actual_length - bytes_to_end); + } else { + memcpy(tascam->capture_ring_buffer + write_ptr, + urb->transfer_buffer, + urb->actual_length); + } + + tascam->capture_ring_buffer_write_ptr = + (write_ptr + urb->actual_length) % + CAPTURE_RING_BUFFER_SIZE; + } + + schedule_work(&tascam->capture_work); + } + + usb_get_urb(urb); + usb_anchor_urb(urb, &tascam->capture_anchor); + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret < 0) { + dev_err_ratelimited(tascam->card->dev, + "Failed to resubmit capture URB: %d\n", + ret); + usb_unanchor_urb(urb); + usb_put_urb(urb); + atomic_dec( + &tascam->active_urbs); /* Decrement on failed resubmission */ + } +out: + usb_put_urb(urb); +} + diff --git a/sound/usb/usx2y/us144mkii_controls.c b/sound/usb/usx2y/us144mkii_controls.c new file mode 100644 index 000000000000..5d69441ef414 --- /dev/null +++ b/sound/usb/usx2y/us144mkii_controls.c @@ -0,0 +1,444 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2025 Å erif Rami <ramiserifpersia@gmail.com> + +#include "us144mkii.h" + +/** + * @brief Text descriptions for playback output source options. + * + * Used by ALSA kcontrol elements to provide user-friendly names for + * the playback routing options (e.g., "Playback 1-2", "Playback 3-4"). + */ +static const char *const playback_source_texts[] = { "Playback 1-2", + "Playback 3-4" }; + +/** + * @brief Text descriptions for capture input source options. + * + * Used by ALSA kcontrol elements to provide user-friendly names for + * the capture routing options (e.g., "Analog In", "Digital In"). + */ +static const char *const capture_source_texts[] = { "Analog In", "Digital In" }; + +/** + * tascam_playback_source_info() - ALSA control info callback for playback + * source. + * @kcontrol: The ALSA kcontrol instance. + * @uinfo: The ALSA control element info structure to fill. + * + * This function provides information about the enumerated playback source + * control, including its type, count, and available items (Playback 1-2, + * Playback 3-4). + * + * Return: 0 on success. + */ +static int tascam_playback_source_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + return snd_ctl_enum_info(uinfo, 1, 2, playback_source_texts); +} + +/** + * tascam_line_out_get() - ALSA control get callback for Line Outputs Source. + * @kcontrol: The ALSA kcontrol instance. + * @ucontrol: The ALSA control element value structure to fill. + * + * This function retrieves the current selection for the Line Outputs source + * (Playback 1-2 or Playback 3-4) from the driver's private data and populates + * the ALSA control element value. + * + * Return: 0 on success. + */ +static int tascam_line_out_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); + + scoped_guard(spinlock_irqsave, &tascam->lock) { + ucontrol->value.enumerated.item[0] = tascam->line_out_source; + } + return 0; +} + +/** + * tascam_line_out_put() - ALSA control put callback for Line Outputs Source. + * @kcontrol: The ALSA kcontrol instance. + * @ucontrol: The ALSA control element value structure containing the new value. + * + * This function sets the Line Outputs source (Playback 1-2 or Playback 3-4) + * based on the user's selection from the ALSA control element. It validates + * the input and updates the driver's private data. + * + * Return: 1 if the value was changed, 0 if unchanged, or a negative error code. + */ +static int tascam_line_out_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); + int changed = 0; + + if (ucontrol->value.enumerated.item[0] > 1) + return -EINVAL; + + scoped_guard(spinlock_irqsave, &tascam->lock) { + if (tascam->line_out_source != ucontrol->value.enumerated.item[0]) { + tascam->line_out_source = ucontrol->value.enumerated.item[0]; + changed = 1; + } + } + return changed; +} + +/** + * tascam_line_out_control - ALSA kcontrol definition for Line Outputs Source. + * + * This defines a new ALSA mixer control named "Line OUTPUTS Source" that allows + * the user to select between "Playback 1-2" and "Playback 3-4" for the analog + * line outputs of the device. It uses the `tascam_playback_source_info` for + * information and `tascam_line_out_get`/`tascam_line_out_put` for value + * handling. + */ +static const struct snd_kcontrol_new tascam_line_out_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Line Playback Source", + .info = tascam_playback_source_info, + .get = tascam_line_out_get, + .put = tascam_line_out_put, +}; + +/** + * tascam_digital_out_get() - ALSA control get callback for Digital Outputs + * Source. + * @kcontrol: The ALSA kcontrol instance. + * @ucontrol: The ALSA control element value structure to fill. + * + * This function retrieves the current selection for the Digital Outputs source + * (Playback 1-2 or Playback 3-4) from the driver's private data and populates + * the ALSA control element value. + * + * Return: 0 on success. + */ +static int tascam_digital_out_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); + + scoped_guard(spinlock_irqsave, &tascam->lock) { + ucontrol->value.enumerated.item[0] = tascam->digital_out_source; + } + return 0; +} + +/** + * tascam_digital_out_put() - ALSA control put callback for Digital Outputs + * Source. + * @kcontrol: The ALSA kcontrol instance. + * @ucontrol: The ALSA control element value structure containing the new value. + * + * This function sets the Digital Outputs source (Playback 1-2 or Playback 3-4) + * based on the user's selection from the ALSA control element. It validates + * the input and updates the driver's private data. + * + * Return: 1 if the value was changed, 0 if unchanged, or a negative error code. + */ +static int tascam_digital_out_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); + int changed = 0; + + if (ucontrol->value.enumerated.item[0] > 1) + return -EINVAL; + + scoped_guard(spinlock_irqsave, &tascam->lock) { + if (tascam->digital_out_source != ucontrol->value.enumerated.item[0]) { + tascam->digital_out_source = ucontrol->value.enumerated.item[0]; + changed = 1; + } + } + return changed; +} + +/** + * tascam_digital_out_control - ALSA kcontrol definition for Digital Outputs + * Source. + * + * This defines a new ALSA mixer control named "Digital OUTPUTS Source" that + * allows the user to select between "Playback 1-2" and "Playback 3-4" for the + * digital outputs of the device. It uses the `tascam_playback_source_info` for + * information and `tascam_digital_out_get`/`tascam_digital_out_put` for value + * handling. + */ +static const struct snd_kcontrol_new tascam_digital_out_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Digital Playback Source", + .info = tascam_playback_source_info, + .get = tascam_digital_out_get, + .put = tascam_digital_out_put, +}; + +/** + * tascam_capture_source_info() - ALSA control info callback for capture source. + * @kcontrol: The ALSA kcontrol instance. + * @uinfo: The ALSA control element info structure to fill. + * + * This function provides information about the enumerated capture source + * control, including its type, count, and available items (Analog In, Digital + * In). + * + * Return: 0 on success. + */ +static int tascam_capture_source_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + return snd_ctl_enum_info(uinfo, 1, 2, capture_source_texts); +} + +/** + * tascam_capture_12_get() - ALSA control get callback for Capture channels 1 + * and 2 Source. + * @kcontrol: The ALSA kcontrol instance. + * @ucontrol: The ALSA control element value structure to fill. + * + * This function retrieves the current selection for the Capture channels 1 and + * 2 source (Analog In or Digital In) from the driver's private data and + * populates the ALSA control element value. + * + * Return: 0 on success. + */ +static int tascam_capture_12_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); + + scoped_guard(spinlock_irqsave, &tascam->lock) { + ucontrol->value.enumerated.item[0] = tascam->capture_12_source; + } + return 0; +} + +/** + * tascam_capture_12_put() - ALSA control put callback for Capture channels 1 + * and 2 Source. + * @kcontrol: The ALSA kcontrol instance. + * @ucontrol: The ALSA control element value structure containing the new value. + * + * This function sets the Capture channels 1 and 2 source (Analog In or Digital + * In) based on the user's selection from the ALSA control element. It validates + * the input and updates the driver's private data. + * + * Return: 1 if the value was changed, 0 if unchanged, or a negative error code. + */ +static int tascam_capture_12_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); + int changed = 0; + + if (ucontrol->value.enumerated.item[0] > 1) + return -EINVAL; + + scoped_guard(spinlock_irqsave, &tascam->lock) { + if (tascam->capture_12_source != ucontrol->value.enumerated.item[0]) { + tascam->capture_12_source = ucontrol->value.enumerated.item[0]; + changed = 1; + } + } + return changed; +} + +/** + * tascam_capture_12_control - ALSA kcontrol definition for Capture channels 1 + * and 2 Source. + * + * This defines a new ALSA mixer control named "ch1 and ch2 Source" that allows + * the user to select between "Analog In" and "Digital In" for the first two + * capture channels of the device. It uses the `tascam_capture_source_info` for + * information and `tascam_capture_12_get`/`tascam_capture_12_put` for value + * handling. + */ +static const struct snd_kcontrol_new tascam_capture_12_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Ch1/2 Capture Source", + .info = tascam_capture_source_info, + .get = tascam_capture_12_get, + .put = tascam_capture_12_put, +}; + +/** + * tascam_capture_34_get() - ALSA control get callback for Capture channels 3 + * and 4 Source. + * @kcontrol: The ALSA kcontrol instance. + * @ucontrol: The ALSA control element value structure to fill. + * + * This function retrieves the current selection for the Capture channels 3 and + * 4 source (Analog In or Digital In) from the driver's private data and + * populates the ALSA control element value. + * + * Return: 0 on success. + */ +static int tascam_capture_34_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); + + scoped_guard(spinlock_irqsave, &tascam->lock) { + ucontrol->value.enumerated.item[0] = tascam->capture_34_source; + } + return 0; +} + +/** + * tascam_capture_34_put() - ALSA control put callback for Capture channels 3 + * and 4 Source. + * @kcontrol: The ALSA kcontrol instance. + * @ucontrol: The ALSA control element value structure containing the new value. + * + * This function sets the Capture channels 3 and 4 source (Analog In or Digital + * In) based on the user's selection from the ALSA control element. It validates + * the input and updates the driver's private data. + * + * Return: 1 if the value was changed, 0 if unchanged, or a negative error code. + */ +static int tascam_capture_34_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); + int changed = 0; + + if (ucontrol->value.enumerated.item[0] > 1) + return -EINVAL; + + scoped_guard(spinlock_irqsave, &tascam->lock) { + if (tascam->capture_34_source != ucontrol->value.enumerated.item[0]) { + tascam->capture_34_source = ucontrol->value.enumerated.item[0]; + changed = 1; + } + } + return changed; +} + +/** + * tascam_capture_34_control - ALSA kcontrol definition for Capture channels 3 + * and 4 Source. + * + * This defines a new ALSA mixer control named "ch3 and ch4 Source" that allows + * the user to select between "Analog In" and "Digital In" for the third and + * fourth capture channels of the device. It uses the + * `tascam_capture_source_info` for information and + * `tascam_capture_34_get`/`tascam_capture_34_put` for value handling. + */ +static const struct snd_kcontrol_new tascam_capture_34_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Ch3/4 Capture Source", + .info = tascam_capture_source_info, + .get = tascam_capture_34_get, + .put = tascam_capture_34_put, +}; + +/** + * tascam_samplerate_info() - ALSA control info callback for Sample Rate. + * @kcontrol: The ALSA kcontrol instance. + * @uinfo: The ALSA control element info structure to fill. + * + * This function provides information about the Sample Rate control, defining + * it as an integer type with a minimum value of 0 and a maximum of 96000. + * + * Return: 0 on success. + */ +static int tascam_samplerate_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 96000; + return 0; +} + +/** + * tascam_samplerate_get() - ALSA control get callback for Sample Rate. + * @kcontrol: The ALSA kcontrol instance. + * @ucontrol: The ALSA control element value structure to fill. + * + * This function retrieves the current sample rate from the device via a USB + * control message and populates the ALSA control element value. If the rate + * is already known (i.e., `current_rate` is set), it returns that value + * directly. + * + * Return: 0 on success, or a negative error code on failure. + */ +static int tascam_samplerate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tascam_card *tascam = + (struct tascam_card *)snd_kcontrol_chip(kcontrol); + u8 *buf __free(kfree) = NULL; + int err; + u32 rate = 0; + + scoped_guard(spinlock_irqsave, &tascam->lock) { + if (tascam->current_rate > 0) { + ucontrol->value.integer.value[0] = tascam->current_rate; + return 0; + } + } + + buf = kmalloc(3, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + err = usb_control_msg(tascam->dev, usb_rcvctrlpipe(tascam->dev, 0), + UAC_GET_CUR, RT_D2H_CLASS_EP, + UAC_SAMPLING_FREQ_CONTROL, EP_AUDIO_IN, buf, 3, + USB_CTRL_TIMEOUT_MS); + + if (err >= 3) + rate = buf[0] | (buf[1] << 8) | (buf[2] << 16); + + ucontrol->value.integer.value[0] = rate; + return 0; +} + +/** + * tascam_samplerate_control - ALSA kcontrol definition for Sample Rate. + * + * This defines a new ALSA mixer control named "Sample Rate" that displays + * the current sample rate of the device. It is a read-only control. + */ +static const struct snd_kcontrol_new tascam_samplerate_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Sample Rate", + .info = tascam_samplerate_info, + .get = tascam_samplerate_get, + .access = SNDRV_CTL_ELEM_ACCESS_READ, +}; + +int tascam_create_controls(struct tascam_card *tascam) +{ + int err; + + err = snd_ctl_add(tascam->card, + snd_ctl_new1(&tascam_line_out_control, tascam)); + if (err < 0) + return err; + err = snd_ctl_add(tascam->card, + snd_ctl_new1(&tascam_digital_out_control, tascam)); + if (err < 0) + return err; + err = snd_ctl_add(tascam->card, + snd_ctl_new1(&tascam_capture_12_control, tascam)); + if (err < 0) + return err; + err = snd_ctl_add(tascam->card, + snd_ctl_new1(&tascam_capture_34_control, tascam)); + if (err < 0) + return err; + + err = snd_ctl_add(tascam->card, + snd_ctl_new1(&tascam_samplerate_control, tascam)); + if (err < 0) + return err; + + return 0; +} diff --git a/sound/usb/usx2y/us144mkii_midi.c b/sound/usb/usx2y/us144mkii_midi.c new file mode 100644 index 000000000000..ed2afec2a89a --- /dev/null +++ b/sound/usb/usx2y/us144mkii_midi.c @@ -0,0 +1,403 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2025 Å erif Rami <ramiserifpersia@gmail.com> + +#include "us144mkii.h" + +/** + * tascam_midi_in_work_handler() - Deferred work for processing MIDI input. + * @work: The work_struct instance. + * + * This function runs in a thread context. It safely reads raw USB data from + * the kfifo, processes it by stripping protocol-specific padding bytes, and + * passes the clean MIDI data to the ALSA rawmidi subsystem. + */ +static void tascam_midi_in_work_handler(struct work_struct *work) +{ + struct tascam_card *tascam = + container_of(work, struct tascam_card, midi_in_work); + u8 buf[9]; + u8 clean_buf[8]; + unsigned int count, clean_count; + + if (!tascam->midi_in_substream) + return; + + while (kfifo_out_spinlocked(&tascam->midi_in_fifo, buf, sizeof(buf), + &tascam->midi_in_lock) == sizeof(buf)) { + clean_count = 0; + for (count = 0; count < 8; ++count) { + if (buf[count] != 0xfd) + clean_buf[clean_count++] = buf[count]; + } + + if (clean_count > 0) + snd_rawmidi_receive(tascam->midi_in_substream, + clean_buf, clean_count); + } +} + +void tascam_midi_in_urb_complete(struct urb *urb) +{ + struct tascam_card *tascam = urb->context; + int ret; + + if (!tascam) + goto out; + + if (urb->status) { + if (urb->status != -ENOENT && urb->status != -ECONNRESET && + urb->status != -ESHUTDOWN && urb->status != -EPROTO) { + dev_err_ratelimited(tascam->card->dev, + "MIDI IN URB failed: status %d\n", + urb->status); + } + goto out; + } + + if (atomic_read(&tascam->midi_in_active) && + urb->actual_length > 0) { + kfifo_in_spinlocked(&tascam->midi_in_fifo, urb->transfer_buffer, + urb->actual_length, &tascam->midi_in_lock); + schedule_work(&tascam->midi_in_work); + } + + usb_get_urb(urb); + usb_anchor_urb(urb, &tascam->midi_in_anchor); + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret < 0) { + dev_err(tascam->card->dev, + "Failed to resubmit MIDI IN URB: error %d\n", ret); + usb_unanchor_urb(urb); + goto out; + } + +out: + usb_put_urb(urb); +} + +/** + * tascam_midi_in_open() - Opens the MIDI input substream. + * @substream: The ALSA rawmidi substream to open. + * + * This function stores a reference to the MIDI input substream in the + * driver's private data. + * + * Return: 0 on success. + */ +static int tascam_midi_in_open(struct snd_rawmidi_substream *substream) +{ + struct tascam_card *tascam = substream->rmidi->private_data; + + tascam->midi_in_substream = substream; + return 0; +} + +/** + * tascam_midi_in_close() - Closes the MIDI input substream. + * @substream: The ALSA rawmidi substream to close. + * + * Return: 0 on success. + */ +static int tascam_midi_in_close(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +/** + * tascam_midi_in_trigger() - Triggers MIDI input stream activity. + * @substream: The ALSA rawmidi substream. + * @up: Boolean indicating whether to start (1) or stop (0) the stream. + * + * This function starts or stops the MIDI input URBs based on the 'up' + * parameter. When starting, it resets the kfifo and submits all MIDI input + * URBs. When stopping, it kills all anchored MIDI input URBs and cancels the + * associated workqueue. + */ +static void tascam_midi_in_trigger(struct snd_rawmidi_substream *substream, + int up) +{ + struct tascam_card *tascam = substream->rmidi->private_data; + int i, err; + + if (up) { + if (atomic_xchg(&tascam->midi_in_active, 1) == 0) { + scoped_guard(spinlock_irqsave, &tascam->midi_in_lock) + { + kfifo_reset(&tascam->midi_in_fifo); + } + + for (i = 0; i < NUM_MIDI_IN_URBS; i++) { + usb_get_urb(tascam->midi_in_urbs[i]); + usb_anchor_urb(tascam->midi_in_urbs[i], + &tascam->midi_in_anchor); + err = usb_submit_urb(tascam->midi_in_urbs[i], + GFP_KERNEL); + if (err < 0) { + dev_err(tascam->card->dev, + "Failed to submit MIDI IN URB %d: %d\n", + i, err); + usb_unanchor_urb( + tascam->midi_in_urbs[i]); + usb_put_urb(tascam->midi_in_urbs[i]); + } + } + } + } else { + if (atomic_xchg(&tascam->midi_in_active, 0) == 1) { + usb_kill_anchored_urbs(&tascam->midi_in_anchor); + cancel_work_sync(&tascam->midi_in_work); + } + } +} + +/** + * tascam_midi_in_ops - ALSA rawmidi operations for MIDI input. + * + * This structure defines the callback functions for MIDI input stream + * operations, including open, close, and trigger. + */ +static const struct snd_rawmidi_ops tascam_midi_in_ops = { + .open = tascam_midi_in_open, + .close = tascam_midi_in_close, + .trigger = tascam_midi_in_trigger, +}; + +void tascam_midi_out_urb_complete(struct urb *urb) +{ + struct tascam_card *tascam = urb->context; + int i, urb_index = -1; + + if (urb->status) { + if (urb->status != -ENOENT && urb->status != -ECONNRESET && + urb->status != -ESHUTDOWN) { + dev_err_ratelimited(tascam->card->dev, + "MIDI OUT URB failed: %d\n", + urb->status); + } + goto out; + } + + if (!tascam) + goto out; + + for (i = 0; i < NUM_MIDI_OUT_URBS; i++) { + if (tascam->midi_out_urbs[i] == urb) { + urb_index = i; + break; + } + } + + if (urb_index < 0) { + dev_err_ratelimited(tascam->card->dev, + "Unknown MIDI OUT URB completed!\n"); + goto out; + } + + scoped_guard(spinlock_irqsave, &tascam->midi_out_lock) + { + clear_bit(urb_index, &tascam->midi_out_urbs_in_flight); + } + + if (atomic_read(&tascam->midi_out_active)) + schedule_work(&tascam->midi_out_work); + +out: + usb_put_urb(urb); +} + +/** + * tascam_midi_out_work_handler() - Deferred work for sending MIDI data + * @work: The work_struct instance. + * + * This function handles the proprietary output protocol: take the raw MIDI + * message bytes from the application, place them at the start of a 9-byte + * buffer, pad the rest with 0xFD, and add a terminator byte (0x00). + * This function pulls as many bytes as will fit into one packet from the + * ALSA buffer and sends them. + */ +static void tascam_midi_out_work_handler(struct work_struct *work) +{ + struct tascam_card *tascam = + container_of(work, struct tascam_card, midi_out_work); + struct snd_rawmidi_substream *substream = tascam->midi_out_substream; + int i; + + if (!substream || !atomic_read(&tascam->midi_out_active)) + return; + + while (snd_rawmidi_transmit_peek(substream, (u8[]){ 0 }, 1) == 1) { + int urb_index; + struct urb *urb; + u8 *buf; + int bytes_to_send; + + scoped_guard(spinlock_irqsave, &tascam->midi_out_lock) { + urb_index = -1; + for (i = 0; i < NUM_MIDI_OUT_URBS; i++) { + if (!test_bit( + i, + &tascam->midi_out_urbs_in_flight)) { + urb_index = i; + break; + } + } + + if (urb_index < 0) + return; /* No free URBs, will be rescheduled by + * completion handler + */ + + urb = tascam->midi_out_urbs[urb_index]; + buf = urb->transfer_buffer; + bytes_to_send = snd_rawmidi_transmit(substream, buf, 8); + + if (bytes_to_send <= 0) + break; /* No more data */ + + if (bytes_to_send < 9) + memset(buf + bytes_to_send, 0xfd, + 9 - bytes_to_send); + buf[8] = 0xe0; + + set_bit(urb_index, &tascam->midi_out_urbs_in_flight); + urb->transfer_buffer_length = 9; + } + + usb_get_urb(urb); + usb_anchor_urb(urb, &tascam->midi_out_anchor); + if (usb_submit_urb(urb, GFP_KERNEL) < 0) { + dev_err_ratelimited( + tascam->card->dev, + "Failed to submit MIDI OUT URB %d\n", + urb_index); + scoped_guard(spinlock_irqsave, &tascam->midi_out_lock) + { + clear_bit(urb_index, + &tascam->midi_out_urbs_in_flight); + } + usb_unanchor_urb(urb); + usb_put_urb(urb); + break; /* Stop on error */ + } + } +} + +/** + * tascam_midi_out_open() - Opens the MIDI output substream. + * @substream: The ALSA rawmidi substream to open. + * + * This function stores a reference to the MIDI output substream in the + * driver's private data and initializes the MIDI running status. + * + * Return: 0 on success. + */ +static int tascam_midi_out_open(struct snd_rawmidi_substream *substream) +{ + struct tascam_card *tascam = substream->rmidi->private_data; + + tascam->midi_out_substream = substream; + /* Initialize the running status state for the packet packer. */ + tascam->midi_running_status = 0; + return 0; +} + +/** + * tascam_midi_out_close() - Closes the MIDI output substream. + * @substream: The ALSA rawmidi substream to close. + * + * Return: 0 on success. + */ +static int tascam_midi_out_close(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +/** + * tascam_midi_out_drain() - Drains the MIDI output stream. + * @substream: The ALSA rawmidi substream. + * + * This function cancels any pending MIDI output work and kills all + * anchored MIDI output URBs, ensuring all data is sent or discarded. + */ +static void tascam_midi_out_drain(struct snd_rawmidi_substream *substream) +{ + struct tascam_card *tascam = substream->rmidi->private_data; + bool in_flight = true; + + while (in_flight) { + in_flight = false; + for (int i = 0; i < NUM_MIDI_OUT_URBS; i++) { + if (test_bit(i, &tascam->midi_out_urbs_in_flight)) { + in_flight = true; + break; + } + } + if (in_flight) + schedule_timeout_uninterruptible(1); + } + + cancel_work_sync(&tascam->midi_out_work); + usb_kill_anchored_urbs(&tascam->midi_out_anchor); +} + +/** + * tascam_midi_out_trigger() - Triggers MIDI output stream activity. + * @substream: The ALSA rawmidi substream. + * @up: Boolean indicating whether to start (1) or stop (0) the stream. + * + * This function starts or stops the MIDI output workqueue based on the + * 'up' parameter. + */ +static void tascam_midi_out_trigger(struct snd_rawmidi_substream *substream, + int up) +{ + struct tascam_card *tascam = substream->rmidi->private_data; + + if (up) { + atomic_set(&tascam->midi_out_active, 1); + schedule_work(&tascam->midi_out_work); + } else { + atomic_set(&tascam->midi_out_active, 0); + } +} + +/** + * tascam_midi_out_ops - ALSA rawmidi operations for MIDI output. + * + * This structure defines the callback functions for MIDI output stream + * operations, including open, close, trigger, and drain. + */ +static const struct snd_rawmidi_ops tascam_midi_out_ops = { + .open = tascam_midi_out_open, + .close = tascam_midi_out_close, + .trigger = tascam_midi_out_trigger, + .drain = tascam_midi_out_drain, +}; + +int tascam_create_midi(struct tascam_card *tascam) +{ + int err; + + err = snd_rawmidi_new(tascam->card, "US144MKII MIDI", 0, 1, 1, + &tascam->rmidi); + if (err < 0) + return err; + + strscpy(tascam->rmidi->name, "US144MKII MIDI", + sizeof(tascam->rmidi->name)); + tascam->rmidi->private_data = tascam; + + snd_rawmidi_set_ops(tascam->rmidi, SNDRV_RAWMIDI_STREAM_INPUT, + &tascam_midi_in_ops); + snd_rawmidi_set_ops(tascam->rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, + &tascam_midi_out_ops); + + tascam->rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT | + SNDRV_RAWMIDI_INFO_OUTPUT | + SNDRV_RAWMIDI_INFO_DUPLEX; + + INIT_WORK(&tascam->midi_in_work, tascam_midi_in_work_handler); + INIT_WORK(&tascam->midi_out_work, tascam_midi_out_work_handler); + + return 0; +} diff --git a/sound/usb/usx2y/us144mkii_pcm.c b/sound/usb/usx2y/us144mkii_pcm.c new file mode 100644 index 000000000000..0c84304d4624 --- /dev/null +++ b/sound/usb/usx2y/us144mkii_pcm.c @@ -0,0 +1,370 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2025 Å erif Rami <ramiserifpersia@gmail.com> + +#include "us144mkii.h" + +/** + * fpo_init_pattern() - Generates a packet distribution pattern. + * @size: The number of elements in the pattern array (e.g., 8). + * @pattern_array: Pointer to the array to be populated. + * @initial_value: The base value to initialize each element with. + * @target_sum: The desired sum of all elements in the final array. + * + * This function initializes an array with a base value and then iteratively + * adjusts the elements to match a target sum, distributing the difference + * as evenly as possible. + */ +static void fpo_init_pattern(unsigned int size, unsigned int *pattern_array, + unsigned int initial_value, int target_sum) +{ + int diff, i; + + if (!size) + return; + + for (i = 0; i < size; ++i) + pattern_array[i] = initial_value; + + diff = target_sum - (size * initial_value); + for (i = 0; i < abs(diff); ++i) { + if (diff > 0) + pattern_array[i]++; + else + pattern_array[i]--; + } +} + +const struct snd_pcm_hardware tascam_pcm_hw = { + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000), + .rate_min = 44100, + .rate_max = 96000, + .channels_min = NUM_CHANNELS, + .channels_max = NUM_CHANNELS, + .buffer_bytes_max = 1024 * 1024, + .period_bytes_min = 48 * BYTES_PER_FRAME, + .period_bytes_max = 1024 * BYTES_PER_FRAME, + .periods_min = 2, + .periods_max = 1024, +}; + +void process_playback_routing_us144mkii(struct tascam_card *tascam, + const u8 *src_buffer, u8 *dst_buffer, + size_t frames) +{ + size_t f; + const u8 *src_12, *src_34; + u8 *dst_line, *dst_digital; + + for (f = 0; f < frames; ++f) { + src_12 = src_buffer + f * BYTES_PER_FRAME; + src_34 = src_12 + (2 * BYTES_PER_SAMPLE); + dst_line = dst_buffer + f * BYTES_PER_FRAME; + dst_digital = dst_line + (2 * BYTES_PER_SAMPLE); + + /* LINE OUTPUTS (ch1/2 on device) */ + if (tascam->line_out_source == 0) /* "ch1 and ch2" */ + memcpy(dst_line, src_12, 2 * BYTES_PER_SAMPLE); + else /* "ch3 and ch4" */ + memcpy(dst_line, src_34, 2 * BYTES_PER_SAMPLE); + + /* DIGITAL OUTPUTS (ch3/4 on device) */ + if (tascam->digital_out_source == 0) /* "ch1 and ch2" */ + memcpy(dst_digital, src_12, 2 * BYTES_PER_SAMPLE); + else /* "ch3 and ch4" */ + memcpy(dst_digital, src_34, 2 * BYTES_PER_SAMPLE); + } +} + +void process_capture_routing_us144mkii(struct tascam_card *tascam, + const s32 *decoded_block, + s32 *routed_block) +{ + int f; + const s32 *src_frame; + s32 *dst_frame; + + for (f = 0; f < FRAMES_PER_DECODE_BLOCK; f++) { + src_frame = decoded_block + (f * DECODED_CHANNELS_PER_FRAME); + dst_frame = routed_block + (f * DECODED_CHANNELS_PER_FRAME); + + /* ch1 and ch2 Source */ + if (tascam->capture_12_source == 0) { /* analog inputs */ + dst_frame[0] = src_frame[0]; /* Analog L */ + dst_frame[1] = src_frame[1]; /* Analog R */ + } else { /* digital inputs */ + dst_frame[0] = src_frame[2]; /* Digital L */ + dst_frame[1] = src_frame[3]; /* Digital R */ + } + + /* ch3 and ch4 Source */ + if (tascam->capture_34_source == 0) { /* analog inputs */ + dst_frame[2] = src_frame[0]; /* Analog L (Duplicate) */ + dst_frame[3] = src_frame[1]; /* Analog R (Duplicate) */ + } else { /* digital inputs */ + dst_frame[2] = src_frame[2]; /* Digital L */ + dst_frame[3] = src_frame[3]; /* Digital R */ + } + } +} + +int us144mkii_configure_device_for_rate(struct tascam_card *tascam, int rate) +{ + struct usb_device *dev = tascam->dev; + u8 *rate_payload_buf __free(kfree) = NULL; + u16 rate_vendor_wValue; + int err = 0; + const u8 *current_payload_src; + + static const u8 payload_44100[] = { 0x44, 0xac, 0x00 }; + static const u8 payload_48000[] = { 0x80, 0xbb, 0x00 }; + static const u8 payload_88200[] = { 0x88, 0x58, 0x01 }; + static const u8 payload_96000[] = { 0x00, 0x77, 0x01 }; + + switch (rate) { + case 44100: + current_payload_src = payload_44100; + rate_vendor_wValue = REG_ADDR_RATE_44100; + break; + case 48000: + current_payload_src = payload_48000; + rate_vendor_wValue = REG_ADDR_RATE_48000; + break; + case 88200: + current_payload_src = payload_88200; + rate_vendor_wValue = REG_ADDR_RATE_88200; + break; + case 96000: + current_payload_src = payload_96000; + rate_vendor_wValue = REG_ADDR_RATE_96000; + break; + default: + dev_err(&dev->dev, + "Unsupported sample rate %d for configuration\n", rate); + return -EINVAL; + } + + rate_payload_buf = kmemdup(current_payload_src, 3, GFP_KERNEL); + if (!rate_payload_buf) + return -ENOMEM; + + dev_info(&dev->dev, "Configuring device for %d Hz\n", rate); + + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + VENDOR_REQ_MODE_CONTROL, RT_H2D_VENDOR_DEV, + MODE_VAL_CONFIG, 0x0000, NULL, 0, + USB_CTRL_TIMEOUT_MS); + if (err < 0) + goto fail; + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, + RT_H2D_CLASS_EP, UAC_SAMPLING_FREQ_CONTROL, + EP_AUDIO_IN, rate_payload_buf, 3, + USB_CTRL_TIMEOUT_MS); + if (err < 0) + goto fail; + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, + RT_H2D_CLASS_EP, UAC_SAMPLING_FREQ_CONTROL, + EP_AUDIO_OUT, rate_payload_buf, 3, + USB_CTRL_TIMEOUT_MS); + if (err < 0) + goto fail; + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, + REG_ADDR_UNKNOWN_0D, REG_VAL_ENABLE, NULL, 0, + USB_CTRL_TIMEOUT_MS); + if (err < 0) + goto fail; + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, + REG_ADDR_UNKNOWN_0E, REG_VAL_ENABLE, NULL, 0, + USB_CTRL_TIMEOUT_MS); + if (err < 0) + goto fail; + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, + REG_ADDR_UNKNOWN_0F, REG_VAL_ENABLE, NULL, 0, + USB_CTRL_TIMEOUT_MS); + if (err < 0) + goto fail; + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, + rate_vendor_wValue, REG_VAL_ENABLE, NULL, 0, + USB_CTRL_TIMEOUT_MS); + if (err < 0) + goto fail; + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, + REG_ADDR_UNKNOWN_11, REG_VAL_ENABLE, NULL, 0, + USB_CTRL_TIMEOUT_MS); + if (err < 0) + goto fail; + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + VENDOR_REQ_MODE_CONTROL, RT_H2D_VENDOR_DEV, + MODE_VAL_STREAM_START, 0x0000, NULL, 0, + USB_CTRL_TIMEOUT_MS); + if (err < 0) + goto fail; + return 0; + +fail: + dev_err(&dev->dev, + "Device configuration failed at rate %d with error %d\n", rate, + err); + return err; +} + +int tascam_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct tascam_card *tascam = snd_pcm_substream_chip(substream); + int err; + unsigned int rate = params_rate(params); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + tascam->fpo.sample_rate_khz = rate / 1000; + tascam->fpo.base_feedback_value = tascam->fpo.sample_rate_khz; + tascam->fpo.feedback_offset = 2; + tascam->fpo.current_index = 0; + tascam->fpo.previous_index = 0; + tascam->fpo.sync_locked = false; + + unsigned int initial_value = tascam->fpo.sample_rate_khz / 8; + + for (int i = 0; i < 5; i++) { + int target_sum = tascam->fpo.sample_rate_khz - + tascam->fpo.feedback_offset + i; + fpo_init_pattern(8, tascam->fpo.full_frame_patterns[i], + initial_value, target_sum); + } + } + + if (tascam->current_rate != rate) { + err = us144mkii_configure_device_for_rate(tascam, rate); + if (err < 0) { + tascam->current_rate = 0; + return err; + } + tascam->current_rate = rate; + } + + return 0; +} + +int tascam_pcm_hw_free(struct snd_pcm_substream *substream) +{ + return 0; +} + +int tascam_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct tascam_card *tascam = snd_pcm_substream_chip(substream); + int err = 0; + int i; + bool do_start = false; + bool do_stop = false; + + scoped_guard(spinlock_irqsave, &tascam->lock) { + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + if (!atomic_read(&tascam->playback_active)) { + atomic_set(&tascam->playback_active, 1); + atomic_set(&tascam->capture_active, 1); + do_start = true; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (atomic_read(&tascam->playback_active)) { + atomic_set(&tascam->playback_active, 0); + atomic_set(&tascam->capture_active, 0); + do_stop = true; + } + break; + default: + err = -EINVAL; + break; + } + } + + if (do_start) { + if (atomic_read(&tascam->active_urbs) > 0) { + dev_warn(tascam->card->dev, + "Cannot start, URBs still active.\n"); + return -EAGAIN; + } + + for (i = 0; i < NUM_FEEDBACK_URBS; i++) { + usb_get_urb(tascam->feedback_urbs[i]); + usb_anchor_urb(tascam->feedback_urbs[i], + &tascam->feedback_anchor); + err = usb_submit_urb(tascam->feedback_urbs[i], + GFP_ATOMIC); + if (err < 0) { + usb_unanchor_urb(tascam->feedback_urbs[i]); + usb_put_urb(tascam->feedback_urbs[i]); + atomic_dec(&tascam->active_urbs); + goto start_rollback; + } + atomic_inc(&tascam->active_urbs); + } + for (i = 0; i < NUM_PLAYBACK_URBS; i++) { + usb_get_urb(tascam->playback_urbs[i]); + usb_anchor_urb(tascam->playback_urbs[i], + &tascam->playback_anchor); + err = usb_submit_urb(tascam->playback_urbs[i], + GFP_ATOMIC); + if (err < 0) { + usb_unanchor_urb(tascam->playback_urbs[i]); + usb_put_urb(tascam->playback_urbs[i]); + atomic_dec(&tascam->active_urbs); + goto start_rollback; + } + atomic_inc(&tascam->active_urbs); + } + for (i = 0; i < NUM_CAPTURE_URBS; i++) { + usb_get_urb(tascam->capture_urbs[i]); + usb_anchor_urb(tascam->capture_urbs[i], + &tascam->capture_anchor); + err = usb_submit_urb(tascam->capture_urbs[i], + GFP_ATOMIC); + if (err < 0) { + usb_unanchor_urb(tascam->capture_urbs[i]); + usb_put_urb(tascam->capture_urbs[i]); + atomic_dec(&tascam->active_urbs); + goto start_rollback; + } + atomic_inc(&tascam->active_urbs); + } + + return 0; +start_rollback: + dev_err(tascam->card->dev, + "Failed to submit URBs to start stream: %d\n", err); + do_stop = true; + } + + if (do_stop) + schedule_work(&tascam->stop_work); + + return err; +} + +int tascam_init_pcm(struct snd_pcm *pcm) +{ + struct tascam_card *tascam = pcm->private_data; + + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &tascam_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &tascam_capture_ops); + + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, + tascam->dev->dev.parent, 64 * 1024, + tascam_pcm_hw.buffer_bytes_max); + + return 0; +} diff --git a/sound/usb/usx2y/us144mkii_pcm.h b/sound/usb/usx2y/us144mkii_pcm.h new file mode 100644 index 000000000000..74da8564431b --- /dev/null +++ b/sound/usb/usx2y/us144mkii_pcm.h @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +// Copyright (c) 2025 Å erif Rami <ramiserifpersia@gmail.com> + +#ifndef __US144MKII_PCM_H +#define __US144MKII_PCM_H + +#include "us144mkii.h" + +/** + * tascam_pcm_hw - Hardware capabilities for TASCAM US-144MKII PCM. + * + * Defines the supported PCM formats, rates, channels, and buffer/period sizes + * for the TASCAM US-144MKII audio interface. + */ +extern const struct snd_pcm_hardware tascam_pcm_hw; + +/** + * tascam_playback_ops - ALSA PCM operations for playback. + * + * This structure defines the callback functions for playback stream operations. + */ +extern const struct snd_pcm_ops tascam_playback_ops; + +/** + * tascam_capture_ops - ALSA PCM operations for capture. + * + * This structure defines the callback functions for capture stream operations. + */ +extern const struct snd_pcm_ops tascam_capture_ops; + +/** + * playback_urb_complete() - Completion handler for playback isochronous URBs. + * @urb: the completed URB + * + * This function runs in interrupt context. It calculates the number of bytes + * to send in the next set of packets based on the feedback-driven clock, + * copies the audio data from the ALSA ring buffer, and resubmits the URB. + */ +void playback_urb_complete(struct urb *urb); + +/** + * feedback_urb_complete() - Completion handler for feedback isochronous URBs. + * @urb: the completed URB + * + * This is the master clock for the driver. It runs in interrupt context. + * It reads the feedback value from the device, which indicates how many + * samples the device has consumed. This information is used to adjust the + * playback rate and to advance the capture stream pointer, keeping both + * streams in sync. It then calls snd_pcm_period_elapsed if necessary and + * resubmits itself. + */ +void feedback_urb_complete(struct urb *urb); + +/** + * capture_urb_complete() - Completion handler for capture bulk URBs. + * @urb: the completed URB + * + * This function runs in interrupt context. It copies the received raw data + * into an intermediate ring buffer and then schedules the workqueue to process + * it. It then resubmits the URB to receive more data. + */ +void capture_urb_complete(struct urb *urb); + +/** + * tascam_stop_pcm_work_handler() - Work handler to stop PCM streams. + * @work: Pointer to the work_struct. + * + * This function is scheduled to stop PCM streams (playback and capture) + * from a workqueue context, avoiding blocking operations in interrupt context. + */ +void tascam_stop_pcm_work_handler(struct work_struct *work); + +/** + * tascam_init_pcm() - Initializes the ALSA PCM device. + * @pcm: Pointer to the ALSA PCM device to initialize. + * + * This function sets up the PCM operations, adds ALSA controls for routing + * and sample rate, and preallocates pages for the PCM buffer. + * + * Return: 0 on success, or a negative error code on failure. + */ +int tascam_init_pcm(struct snd_pcm *pcm); + +/** + * us144mkii_configure_device_for_rate() - Set sample rate via USB control msgs + * @tascam: the tascam_card instance + * @rate: the target sample rate (e.g., 44100, 96000) + * + * This function sends a sequence of vendor-specific and UAC control messages + * to configure the device hardware for the specified sample rate. + * + * Return: 0 on success, or a negative error code on failure. + */ +int us144mkii_configure_device_for_rate(struct tascam_card *tascam, int rate); + +/** + * process_playback_routing_us144mkii() - Apply playback routing matrix + * @tascam: The driver instance. + * @src_buffer: Buffer containing 4 channels of S24_3LE audio from ALSA. + * @dst_buffer: Buffer to be filled for the USB device. + * @frames: Number of frames to process. + */ +void process_playback_routing_us144mkii(struct tascam_card *tascam, + const u8 *src_buffer, u8 *dst_buffer, + size_t frames); + +/** + * process_capture_routing_us144mkii() - Apply capture routing matrix + * @tascam: The driver instance. + * @decoded_block: Buffer containing 4 channels of S32LE decoded audio. + * @routed_block: Buffer to be filled for ALSA. + */ +void process_capture_routing_us144mkii(struct tascam_card *tascam, + const s32 *decoded_block, + s32 *routed_block); + +/** + * tascam_pcm_hw_params() - Configures hardware parameters for PCM streams. + * @substream: The ALSA PCM substream. + * @params: The hardware parameters to apply. + * + * This function allocates pages for the PCM buffer and, for playback streams, + * selects the appropriate feedback patterns based on the requested sample rate. + * It also configures the device hardware for the selected sample rate if it + * has changed. + * + * Return: 0 on success, or a negative error code on failure. + */ +int tascam_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); + +/** + * tascam_pcm_hw_free() - Frees hardware parameters for PCM streams. + * @substream: The ALSA PCM substream. + * + * This function is a stub for freeing hardware-related resources. + * + * Return: 0 on success. + */ +int tascam_pcm_hw_free(struct snd_pcm_substream *substream); + +/** + * tascam_pcm_trigger() - Triggers the start or stop of PCM streams. + * @substream: The ALSA PCM substream. + * @cmd: The trigger command (e.g., SNDRV_PCM_TRIGGER_START). + * + * This function handles starting and stopping of playback and capture streams + * by submitting or killing the associated URBs. + * + * Return: 0 on success, or a negative error code on failure. + */ +int tascam_pcm_trigger(struct snd_pcm_substream *substream, int cmd); + +/** + * tascam_capture_work_handler() - Deferred work for processing capture data. + * @work: the work_struct instance + * + * This function runs in a kernel thread context, not an IRQ context. It reads + * raw data from the capture ring buffer, decodes it, applies routing, and + * copies the final audio data into the ALSA capture ring buffer. This offloads + * the CPU-intensive decoding from the time-sensitive URB completion handlers. + */ +void tascam_capture_work_handler(struct work_struct *work); + +#endif /* __US144MKII_PCM_H */ diff --git a/sound/usb/usx2y/us144mkii_playback.c b/sound/usb/usx2y/us144mkii_playback.c new file mode 100644 index 000000000000..0cb9699ec211 --- /dev/null +++ b/sound/usb/usx2y/us144mkii_playback.c @@ -0,0 +1,456 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2025 Å erif Rami <ramiserifpersia@gmail.com> + +#include "us144mkii.h" + +/** + * tascam_playback_open() - Opens the PCM playback substream. + * @substream: The ALSA PCM substream to open. + * + * This function sets the hardware parameters for the playback substream + * and stores a reference to the substream in the driver's private data. + * + * Return: 0 on success. + */ +static int tascam_playback_open(struct snd_pcm_substream *substream) +{ + struct tascam_card *tascam = snd_pcm_substream_chip(substream); + + substream->runtime->hw = tascam_pcm_hw; + tascam->playback_substream = substream; + atomic_set(&tascam->playback_active, 0); + + return 0; +} + +/** + * tascam_playback_close() - Closes the PCM playback substream. + * @substream: The ALSA PCM substream to close. + * + * This function clears the reference to the playback substream in the + * driver's private data. + * + * Return: 0 on success. + */ +static int tascam_playback_close(struct snd_pcm_substream *substream) +{ + struct tascam_card *tascam = snd_pcm_substream_chip(substream); + + tascam->playback_substream = NULL; + + return 0; +} + +/** + * tascam_playback_prepare() - Prepares the PCM playback substream for use. + * @substream: The ALSA PCM substream to prepare. + * + * This function initializes playback-related counters and flags, and configures + * the playback URBs with appropriate packet sizes based on the nominal frame + * rate. + * + * Return: 0 on success. + */ +static int tascam_playback_prepare(struct snd_pcm_substream *substream) +{ + struct tascam_card *tascam = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int i, u; + size_t nominal_frames_per_packet, nominal_bytes_per_packet; + size_t total_bytes_in_urb; + + tascam->driver_playback_pos = 0; + tascam->playback_frames_consumed = 0; + tascam->last_period_pos = 0; + tascam->feedback_pattern_in_idx = 0; + tascam->feedback_pattern_out_idx = 0; + tascam->feedback_synced = false; + tascam->feedback_consecutive_errors = 0; + tascam->feedback_urb_skip_count = NUM_FEEDBACK_URBS; + + nominal_frames_per_packet = runtime->rate / 8000; + for (i = 0; i < FEEDBACK_ACCUMULATOR_SIZE; i++) + tascam->feedback_accumulator_pattern[i] = + nominal_frames_per_packet; + + for (i = 0; i < NUM_FEEDBACK_URBS; i++) { + struct urb *f_urb = tascam->feedback_urbs[i]; + int j; + + f_urb->number_of_packets = FEEDBACK_URB_PACKETS; + f_urb->transfer_buffer_length = + FEEDBACK_URB_PACKETS * FEEDBACK_PACKET_SIZE; + for (j = 0; j < FEEDBACK_URB_PACKETS; j++) { + f_urb->iso_frame_desc[j].offset = + j * FEEDBACK_PACKET_SIZE; + f_urb->iso_frame_desc[j].length = FEEDBACK_PACKET_SIZE; + } + } + + nominal_bytes_per_packet = nominal_frames_per_packet * BYTES_PER_FRAME; + total_bytes_in_urb = nominal_bytes_per_packet * PLAYBACK_URB_PACKETS; + + for (u = 0; u < NUM_PLAYBACK_URBS; u++) { + struct urb *urb = tascam->playback_urbs[u]; + + memset(urb->transfer_buffer, 0, + tascam->playback_urb_alloc_size); + urb->transfer_buffer_length = total_bytes_in_urb; + urb->number_of_packets = PLAYBACK_URB_PACKETS; + for (i = 0; i < PLAYBACK_URB_PACKETS; i++) { + urb->iso_frame_desc[i].offset = + i * nominal_bytes_per_packet; + urb->iso_frame_desc[i].length = + nominal_bytes_per_packet; + } + } + + return 0; +} + +/** + * tascam_playback_pointer() - Returns the current playback pointer position. + * @substream: The ALSA PCM substream. + * + * This function returns the current position of the playback pointer within + * the ALSA ring buffer, in frames. + * + * Return: The current playback pointer position in frames. + */ +static snd_pcm_uframes_t +tascam_playback_pointer(struct snd_pcm_substream *substream) +{ + struct tascam_card *tascam = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + u64 pos; + + if (!atomic_read(&tascam->playback_active)) + return 0; + + scoped_guard(spinlock_irqsave, &tascam->lock) { + pos = tascam->playback_frames_consumed; + } + + if (runtime->buffer_size == 0) + return 0; + + return do_div(pos, runtime->buffer_size); +} + +/** + * tascam_playback_ops - ALSA PCM operations for playback. + * + * This structure defines the callback functions for playback stream operations, + * including open, close, ioctl, hardware parameters, hardware free, prepare, + * trigger, and pointer. + */ +const struct snd_pcm_ops tascam_playback_ops = { + .open = tascam_playback_open, + .close = tascam_playback_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = tascam_pcm_hw_params, + .hw_free = tascam_pcm_hw_free, + .prepare = tascam_playback_prepare, + .trigger = tascam_pcm_trigger, + .pointer = tascam_playback_pointer, +}; + +void playback_urb_complete(struct urb *urb) +{ + struct tascam_card *tascam = urb->context; + struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; + size_t total_bytes_for_urb = 0; + snd_pcm_uframes_t offset_frames; + snd_pcm_uframes_t frames_to_copy; + int ret, i; + + if (urb->status) { + if (urb->status != -ENOENT && urb->status != -ECONNRESET && + urb->status != -ESHUTDOWN && urb->status != -ENODEV) + dev_err_ratelimited(tascam->card->dev, + "Playback URB failed: %d\n", + urb->status); + goto out; + } + if (!tascam || !atomic_read(&tascam->playback_active)) + goto out; + + substream = tascam->playback_substream; + if (!substream || !substream->runtime) + goto out; + runtime = substream->runtime; + + scoped_guard(spinlock_irqsave, &tascam->lock) { + for (i = 0; i < urb->number_of_packets; i++) { + unsigned int frames_for_packet; + size_t bytes_for_packet; + + if (tascam->feedback_synced) { + frames_for_packet = + tascam->feedback_accumulator_pattern + [tascam->feedback_pattern_out_idx]; + tascam->feedback_pattern_out_idx = + (tascam->feedback_pattern_out_idx + 1) % + FEEDBACK_ACCUMULATOR_SIZE; + } else { + frames_for_packet = runtime->rate / 8000; + } + bytes_for_packet = frames_for_packet * BYTES_PER_FRAME; + + urb->iso_frame_desc[i].offset = total_bytes_for_urb; + urb->iso_frame_desc[i].length = bytes_for_packet; + total_bytes_for_urb += bytes_for_packet; + } + urb->transfer_buffer_length = total_bytes_for_urb; + + offset_frames = tascam->driver_playback_pos; + frames_to_copy = bytes_to_frames(runtime, total_bytes_for_urb); + tascam->driver_playback_pos = + (offset_frames + frames_to_copy) % runtime->buffer_size; + } + + if (total_bytes_for_urb > 0) { + u8 *dst_buf = urb->transfer_buffer; + + /* Handle ring buffer wrap-around */ + if (offset_frames + frames_to_copy > runtime->buffer_size) { + size_t first_chunk_bytes = frames_to_bytes( + runtime, runtime->buffer_size - offset_frames); + size_t second_chunk_bytes = + total_bytes_for_urb - first_chunk_bytes; + + memcpy(dst_buf, + runtime->dma_area + + frames_to_bytes(runtime, offset_frames), + first_chunk_bytes); + memcpy(dst_buf + first_chunk_bytes, runtime->dma_area, + second_chunk_bytes); + } else { + memcpy(dst_buf, + runtime->dma_area + + frames_to_bytes(runtime, offset_frames), + total_bytes_for_urb); + } + + process_playback_routing_us144mkii(tascam, dst_buf, dst_buf, + frames_to_copy); + } + + urb->dev = tascam->dev; + usb_get_urb(urb); + usb_anchor_urb(urb, &tascam->playback_anchor); + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret < 0) { + dev_err_ratelimited(tascam->card->dev, + "Failed to resubmit playback URB: %d\n", + ret); + usb_unanchor_urb(urb); + usb_put_urb(urb); + atomic_dec( + &tascam->active_urbs); /* Decrement on failed resubmission */ + } +out: + usb_put_urb(urb); +} + +void feedback_urb_complete(struct urb *urb) +{ + struct tascam_card *tascam = urb->context; + struct snd_pcm_substream *playback_ss, *capture_ss; + struct snd_pcm_runtime *playback_rt, *capture_rt; + u64 total_frames_in_urb = 0; + int ret, p; + unsigned int old_in_idx, new_in_idx; + bool playback_period_elapsed = false; + bool capture_period_elapsed = false; + + if (urb->status) { + if (urb->status != -ENOENT && urb->status != -ECONNRESET && + urb->status != -ESHUTDOWN && urb->status != -ENODEV) { + dev_err_ratelimited(tascam->card->dev, + "Feedback URB failed: %d\n", + urb->status); + atomic_dec( + &tascam->active_urbs); /* Decrement on failed resubmission */ + } + goto out; + } + if (!tascam || !atomic_read(&tascam->playback_active)) + goto out; + + playback_ss = tascam->playback_substream; + if (!playback_ss || !playback_ss->runtime) + goto out; + playback_rt = playback_ss->runtime; + + capture_ss = tascam->capture_substream; + capture_rt = capture_ss ? capture_ss->runtime : NULL; + + scoped_guard(spinlock_irqsave, &tascam->lock) { + if (tascam->feedback_urb_skip_count > 0) { + tascam->feedback_urb_skip_count--; + break; + } + + old_in_idx = tascam->feedback_pattern_in_idx; + + for (p = 0; p < urb->number_of_packets; p++) { + u8 feedback_value = 0; + const unsigned int *pattern; + bool packet_ok = + (urb->iso_frame_desc[p].status == 0 && + urb->iso_frame_desc[p].actual_length >= 1); + + if (packet_ok) + feedback_value = + *((u8 *)urb->transfer_buffer + + urb->iso_frame_desc[p].offset); + + if (packet_ok) { + int delta = feedback_value - + tascam->fpo.base_feedback_value + + tascam->fpo.feedback_offset; + int pattern_idx; + + if (delta < 0) { + pattern_idx = + 0; // Clamp to the lowest pattern + } else if (delta >= 5) { + pattern_idx = + 4; // Clamp to the highest pattern + } else { + pattern_idx = delta; + } + + pattern = + tascam->fpo + .full_frame_patterns[pattern_idx]; + tascam->feedback_consecutive_errors = 0; + int i; + + for (i = 0; i < 8; i++) { + unsigned int in_idx = + (tascam->feedback_pattern_in_idx + + i) % + FEEDBACK_ACCUMULATOR_SIZE; + + tascam->feedback_accumulator_pattern + [in_idx] = pattern[i]; + total_frames_in_urb += pattern[i]; + } + } else { + unsigned int nominal_frames = + playback_rt->rate / 8000; + int i; + + if (tascam->feedback_synced) { + tascam->feedback_consecutive_errors++; + if (tascam->feedback_consecutive_errors > + FEEDBACK_SYNC_LOSS_THRESHOLD) { + dev_err(tascam->card->dev, + "Fatal: Feedback sync lost. Stopping stream.\n"); + schedule_work( + &tascam->stop_pcm_work); + tascam->feedback_synced = false; + break; + } + } + for (i = 0; i < 8; i++) { + unsigned int in_idx = + (tascam->feedback_pattern_in_idx + + i) % + FEEDBACK_ACCUMULATOR_SIZE; + + tascam->feedback_accumulator_pattern + [in_idx] = nominal_frames; + total_frames_in_urb += nominal_frames; + } + } + tascam->feedback_pattern_in_idx = + (tascam->feedback_pattern_in_idx + 8) % + FEEDBACK_ACCUMULATOR_SIZE; + } + + new_in_idx = tascam->feedback_pattern_in_idx; + + if (!tascam->feedback_synced) { + unsigned int out_idx = tascam->feedback_pattern_out_idx; + bool is_ahead = (new_in_idx - out_idx) % + FEEDBACK_ACCUMULATOR_SIZE < + (FEEDBACK_ACCUMULATOR_SIZE / 2); + bool was_behind = (old_in_idx - out_idx) % + FEEDBACK_ACCUMULATOR_SIZE >= + (FEEDBACK_ACCUMULATOR_SIZE / 2); + + if (is_ahead && was_behind) { + dev_dbg(tascam->card->dev, + "Sync Acquired! (in: %u, out: %u)\n", + new_in_idx, out_idx); + tascam->feedback_synced = true; + tascam->feedback_consecutive_errors = 0; + } + } + + if (total_frames_in_urb > 0) { + tascam->playback_frames_consumed += total_frames_in_urb; + if (atomic_read(&tascam->capture_active)) + tascam->capture_frames_processed += + total_frames_in_urb; + } + + if (playback_rt->period_size > 0) { + u64 current_period = + div_u64(tascam->playback_frames_consumed, + playback_rt->period_size); + + if (current_period > tascam->last_period_pos) { + tascam->last_period_pos = current_period; + playback_period_elapsed = true; + } + } + + if (atomic_read(&tascam->capture_active) && capture_rt && + capture_rt->period_size > 0) { + u64 current_capture_period = + div_u64(tascam->capture_frames_processed, + capture_rt->period_size); + + if (current_capture_period > + tascam->last_capture_period_pos) { + tascam->last_capture_period_pos = + current_capture_period; + capture_period_elapsed = true; + } + } + } + if (playback_period_elapsed) + snd_pcm_period_elapsed(playback_ss); + if (capture_period_elapsed) + snd_pcm_period_elapsed(capture_ss); + + urb->dev = tascam->dev; + usb_get_urb(urb); + usb_anchor_urb(urb, &tascam->feedback_anchor); + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret < 0) { + dev_err_ratelimited(tascam->card->dev, + "Failed to resubmit feedback URB: %d\n", + ret); + usb_unanchor_urb(urb); + usb_put_urb(urb); + } +out: + usb_put_urb(urb); +} + +void tascam_stop_pcm_work_handler(struct work_struct *work) +{ + struct tascam_card *tascam = + container_of(work, struct tascam_card, stop_pcm_work); + + if (tascam->playback_substream) + snd_pcm_stop(tascam->playback_substream, SNDRV_PCM_STATE_XRUN); + if (tascam->capture_substream) + snd_pcm_stop(tascam->capture_substream, SNDRV_PCM_STATE_XRUN); +} diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index acca8bead82e..c7c7ec9c228b 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -751,7 +751,6 @@ static int usx2y_format_set(struct usx2ydev *usx2y, snd_pcm_format_t format) static int snd_usx2y_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - int err = 0; unsigned int rate = params_rate(hw_params); snd_pcm_format_t format = params_format(hw_params); struct snd_card *card = substream->pstr->pcm->card; @@ -760,7 +759,7 @@ static int snd_usx2y_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_substream *test_substream; int i; - mutex_lock(&usx2y(card)->pcm_mutex); + guard(mutex)(&usx2y(card)->pcm_mutex); dev_dbg(&dev->dev->dev, "%s(%p, %p)\n", __func__, substream, hw_params); /* all pcm substreams off one usx2y have to operate at the same * rate & format @@ -777,14 +776,11 @@ static int snd_usx2y_pcm_hw_params(struct snd_pcm_substream *substream, test_substream->runtime->format != format) || (test_substream->runtime->rate && test_substream->runtime->rate != rate)) { - err = -EINVAL; - goto error; + return -EINVAL; } } - error: - mutex_unlock(&usx2y(card)->pcm_mutex); - return err; + return 0; } /* @@ -796,7 +792,7 @@ static int snd_usx2y_pcm_hw_free(struct snd_pcm_substream *substream) struct snd_usx2y_substream *subs = runtime->private_data; struct snd_usx2y_substream *cap_subs, *playback_subs; - mutex_lock(&subs->usx2y->pcm_mutex); + guard(mutex)(&subs->usx2y->pcm_mutex); dev_dbg(&subs->usx2y->dev->dev, "%s(%p)\n", __func__, substream); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -816,7 +812,6 @@ static int snd_usx2y_pcm_hw_free(struct snd_pcm_substream *substream) usx2y_urbs_release(subs); } } - mutex_unlock(&subs->usx2y->pcm_mutex); return 0; } @@ -835,7 +830,7 @@ static int snd_usx2y_pcm_prepare(struct snd_pcm_substream *substream) dev_dbg(&usx2y->dev->dev, "%s(%p)\n", __func__, substream); - mutex_lock(&usx2y->pcm_mutex); + guard(mutex)(&usx2y->pcm_mutex); usx2y_subs_prepare(subs); // Start hardware streams // SyncStream first.... @@ -843,25 +838,23 @@ static int snd_usx2y_pcm_prepare(struct snd_pcm_substream *substream) if (usx2y->format != runtime->format) { err = usx2y_format_set(usx2y, runtime->format); if (err < 0) - goto up_prepare_mutex; + return err; } if (usx2y->rate != runtime->rate) { err = usx2y_rate_set(usx2y, runtime->rate); if (err < 0) - goto up_prepare_mutex; + return err; } dev_dbg(&usx2y->dev->dev, "%s: starting capture pipe for %s\n", __func__, subs == capsubs ? "self" : "playpipe"); err = usx2y_urbs_start(capsubs); if (err < 0) - goto up_prepare_mutex; + return err; } if (subs != capsubs && atomic_read(&subs->state) < STATE_PREPARED) err = usx2y_urbs_start(subs); - up_prepare_mutex: - mutex_unlock(&usx2y->pcm_mutex); return err; } diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 1b1496adb47e..7c90214485d9 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -365,7 +365,7 @@ static int snd_usx2y_usbpcm_hw_free(struct snd_pcm_substream *substream) struct snd_usx2y_substream *playback_subs; struct snd_usx2y_substream *cap_subs2; - mutex_lock(&subs->usx2y->pcm_mutex); + guard(mutex)(&subs->usx2y->pcm_mutex); dev_dbg(&subs->usx2y->dev->dev, "%s(%p)\n", __func__, substream); cap_subs2 = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; @@ -394,7 +394,6 @@ static int snd_usx2y_usbpcm_hw_free(struct snd_pcm_substream *substream) usx2y_usbpcm_urbs_release(cap_subs2); } } - mutex_unlock(&subs->usx2y->pcm_mutex); return 0; } @@ -504,15 +503,13 @@ static int snd_usx2y_usbpcm_prepare(struct snd_pcm_substream *substream) dev_dbg(&usx2y->dev->dev, "snd_usx2y_pcm_prepare(%p)\n", substream); - mutex_lock(&usx2y->pcm_mutex); + guard(mutex)(&usx2y->pcm_mutex); if (!usx2y->hwdep_pcm_shm) { usx2y->hwdep_pcm_shm = alloc_pages_exact(USX2Y_HWDEP_PCM_PAGES, GFP_KERNEL); - if (!usx2y->hwdep_pcm_shm) { - err = -ENOMEM; - goto up_prepare_mutex; - } + if (!usx2y->hwdep_pcm_shm) + return -ENOMEM; memset(usx2y->hwdep_pcm_shm, 0, USX2Y_HWDEP_PCM_PAGES); } @@ -523,19 +520,19 @@ static int snd_usx2y_usbpcm_prepare(struct snd_pcm_substream *substream) if (usx2y->format != runtime->format) { err = usx2y_format_set(usx2y, runtime->format); if (err < 0) - goto up_prepare_mutex; + return err; } if (usx2y->rate != runtime->rate) { err = usx2y_rate_set(usx2y, runtime->rate); if (err < 0) - goto up_prepare_mutex; + return err; } dev_dbg(&usx2y->dev->dev, "starting capture pipe for %s\n", subs == capsubs ? "self" : "playpipe"); err = usx2y_usbpcm_urbs_start(capsubs); if (err < 0) - goto up_prepare_mutex; + return err; } if (subs != capsubs) { @@ -547,14 +544,12 @@ static int snd_usx2y_usbpcm_prepare(struct snd_pcm_substream *substream) "Wait: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", usx2y_iso_frames_per_buffer(runtime, usx2y), usx2y->hwdep_pcm_shm->captured_iso_frames); - if (msleep_interruptible(10)) { - err = -ERESTARTSYS; - goto up_prepare_mutex; - } + if (msleep_interruptible(10)) + return -ERESTARTSYS; } err = usx2y_usbpcm_urbs_start(subs); if (err < 0) - goto up_prepare_mutex; + return err; } dev_dbg(&usx2y->dev->dev, "Ready: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", @@ -564,8 +559,6 @@ static int snd_usx2y_usbpcm_prepare(struct snd_pcm_substream *substream) usx2y->hwdep_pcm_shm->capture_iso_start = -1; } - up_prepare_mutex: - mutex_unlock(&usx2y->pcm_mutex); return err; } @@ -646,11 +639,10 @@ static int snd_usx2y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) struct snd_card *card = hw->card; int err; - mutex_lock(&usx2y(card)->pcm_mutex); + guard(mutex)(&usx2y(card)->pcm_mutex); err = usx2y_pcms_busy_check(card); if (!err) usx2y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS; - mutex_unlock(&usx2y(card)->pcm_mutex); return err; } @@ -659,11 +651,10 @@ static int snd_usx2y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file) struct snd_card *card = hw->card; int err; - mutex_lock(&usx2y(card)->pcm_mutex); + guard(mutex)(&usx2y(card)->pcm_mutex); err = usx2y_pcms_busy_check(card); if (!err) usx2y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS; - mutex_unlock(&usx2y(card)->pcm_mutex); return err; } diff --git a/sound/usb/validate.c b/sound/usb/validate.c index a0d55b77c994..4bb4893f6e74 100644 --- a/sound/usb/validate.c +++ b/sound/usb/validate.c @@ -266,7 +266,11 @@ static const struct usb_desc_validator audio_validators[] = { FUNC(UAC_VERSION_2, UAC_MIXER_UNIT, validate_mixer_unit), FUNC(UAC_VERSION_2, UAC_SELECTOR_UNIT, validate_selector_unit), FUNC(UAC_VERSION_2, UAC_FEATURE_UNIT, validate_uac2_feature_unit), - /* UAC_VERSION_2, UAC2_EFFECT_UNIT: not implemented yet */ + /* just a stop-gap, it should be a proper function for the array + * once if the unit is really parsed/used + */ + FIXED(UAC_VERSION_2, UAC2_EFFECT_UNIT, + struct uac2_effect_unit_descriptor), FUNC(UAC_VERSION_2, UAC2_PROCESSING_UNIT_V2, validate_processing_unit), FUNC(UAC_VERSION_2, UAC2_EXTENSION_UNIT_V2, validate_processing_unit), FIXED(UAC_VERSION_2, UAC2_CLOCK_SOURCE, @@ -286,7 +290,8 @@ static const struct usb_desc_validator audio_validators[] = { FUNC(UAC_VERSION_3, UAC3_MIXER_UNIT, validate_mixer_unit), FUNC(UAC_VERSION_3, UAC3_SELECTOR_UNIT, validate_selector_unit), FUNC(UAC_VERSION_3, UAC3_FEATURE_UNIT, validate_uac3_feature_unit), - /* UAC_VERSION_3, UAC3_EFFECT_UNIT: not implemented yet */ + FIXED(UAC_VERSION_3, UAC3_EFFECT_UNIT, + struct uac2_effect_unit_descriptor), /* sharing the same struct */ FUNC(UAC_VERSION_3, UAC3_PROCESSING_UNIT, validate_processing_unit), FUNC(UAC_VERSION_3, UAC3_EXTENSION_UNIT, validate_processing_unit), FIXED(UAC_VERSION_3, UAC3_CLOCK_SOURCE, diff --git a/sound/virtio/virtio_card.c b/sound/virtio/virtio_card.c index 965209e1d872..52c5757585c6 100644 --- a/sound/virtio/virtio_card.c +++ b/sound/virtio/virtio_card.c @@ -85,9 +85,8 @@ static void virtsnd_event_notify_cb(struct virtqueue *vqueue) struct virtio_snd_queue *queue = virtsnd_event_queue(snd); struct virtio_snd_event *event; u32 length; - unsigned long flags; - spin_lock_irqsave(&queue->lock, flags); + guard(spinlock_irqsave)(&queue->lock); do { virtqueue_disable_cb(vqueue); while ((event = virtqueue_get_buf(vqueue, &length))) { @@ -95,7 +94,6 @@ static void virtsnd_event_notify_cb(struct virtqueue *vqueue) virtsnd_event_send(vqueue, event, true, GFP_ATOMIC); } } while (!virtqueue_enable_cb(vqueue)); - spin_unlock_irqrestore(&queue->lock, flags); } /** @@ -176,14 +174,12 @@ static void virtsnd_disable_event_vq(struct virtio_snd *snd) struct virtio_snd_queue *queue = virtsnd_event_queue(snd); struct virtio_snd_event *event; u32 length; - unsigned long flags; if (queue->vqueue) { - spin_lock_irqsave(&queue->lock, flags); + guard(spinlock_irqsave)(&queue->lock); virtqueue_disable_cb(queue->vqueue); while ((event = virtqueue_get_buf(queue->vqueue, &length))) virtsnd_event_dispatch(snd, event); - spin_unlock_irqrestore(&queue->lock, flags); } } diff --git a/sound/virtio/virtio_ctl_msg.c b/sound/virtio/virtio_ctl_msg.c index 9dabea01277f..6433c870f271 100644 --- a/sound/virtio/virtio_ctl_msg.c +++ b/sound/virtio/virtio_ctl_msg.c @@ -131,7 +131,6 @@ int virtsnd_ctl_msg_send(struct virtio_snd *snd, struct virtio_snd_msg *msg, unsigned int nins = 0; struct scatterlist *psgs[4]; bool notify = false; - unsigned long flags; int rc; virtsnd_ctl_msg_ref(msg); @@ -147,15 +146,15 @@ int virtsnd_ctl_msg_send(struct virtio_snd *snd, struct virtio_snd_msg *msg, if (in_sgs) psgs[nouts + nins++] = in_sgs; - spin_lock_irqsave(&queue->lock, flags); - rc = virtqueue_add_sgs(queue->vqueue, psgs, nouts, nins, msg, - GFP_ATOMIC); - if (!rc) { - notify = virtqueue_kick_prepare(queue->vqueue); + scoped_guard(spinlock_irqsave, &queue->lock) { + rc = virtqueue_add_sgs(queue->vqueue, psgs, nouts, nins, msg, + GFP_ATOMIC); + if (!rc) { + notify = virtqueue_kick_prepare(queue->vqueue); - list_add_tail(&msg->list, &snd->ctl_msgs); + list_add_tail(&msg->list, &snd->ctl_msgs); + } } - spin_unlock_irqrestore(&queue->lock, flags); if (rc) { dev_err(&vdev->dev, "failed to send control message (0x%08x)\n", @@ -233,9 +232,8 @@ void virtsnd_ctl_msg_complete(struct virtio_snd_msg *msg) void virtsnd_ctl_msg_cancel_all(struct virtio_snd *snd) { struct virtio_snd_queue *queue = virtsnd_control_queue(snd); - unsigned long flags; - spin_lock_irqsave(&queue->lock, flags); + guard(spinlock_irqsave)(&queue->lock); while (!list_empty(&snd->ctl_msgs)) { struct virtio_snd_msg *msg = list_first_entry(&snd->ctl_msgs, struct virtio_snd_msg, @@ -243,7 +241,6 @@ void virtsnd_ctl_msg_cancel_all(struct virtio_snd *snd) virtsnd_ctl_msg_complete(msg); } - spin_unlock_irqrestore(&queue->lock, flags); } /** @@ -296,13 +293,11 @@ void virtsnd_ctl_notify_cb(struct virtqueue *vqueue) struct virtio_snd_queue *queue = virtsnd_control_queue(snd); struct virtio_snd_msg *msg; u32 length; - unsigned long flags; - spin_lock_irqsave(&queue->lock, flags); + guard(spinlock_irqsave)(&queue->lock); do { virtqueue_disable_cb(vqueue); while ((msg = virtqueue_get_buf(vqueue, &length))) virtsnd_ctl_msg_complete(msg); } while (!virtqueue_enable_cb(vqueue)); - spin_unlock_irqrestore(&queue->lock, flags); } diff --git a/sound/virtio/virtio_pcm.c b/sound/virtio/virtio_pcm.c index 2f7c5e709f07..3602b6690fcd 100644 --- a/sound/virtio/virtio_pcm.c +++ b/sound/virtio/virtio_pcm.c @@ -515,10 +515,10 @@ void virtsnd_pcm_event(struct virtio_snd *snd, struct virtio_snd_event *event) /* TODO: deal with shmem elapsed period */ break; case VIRTIO_SND_EVT_PCM_XRUN: - spin_lock(&vss->lock); - if (vss->xfer_enabled) - vss->xfer_xrun = true; - spin_unlock(&vss->lock); + scoped_guard(spinlock, &vss->lock) { + if (vss->xfer_enabled) + vss->xfer_xrun = true; + } break; } } diff --git a/sound/virtio/virtio_pcm_msg.c b/sound/virtio/virtio_pcm_msg.c index 8c32efaf4c52..9778020a7ba8 100644 --- a/sound/virtio/virtio_pcm_msg.c +++ b/sound/virtio/virtio_pcm_msg.c @@ -272,14 +272,8 @@ int virtsnd_pcm_msg_send(struct virtio_pcm_substream *vss, unsigned long offset, */ unsigned int virtsnd_pcm_msg_pending_num(struct virtio_pcm_substream *vss) { - unsigned int num; - unsigned long flags; - - spin_lock_irqsave(&vss->lock, flags); - num = vss->msg_count; - spin_unlock_irqrestore(&vss->lock, flags); - - return num; + guard(spinlock_irqsave)(&vss->lock); + return vss->msg_count; } /** @@ -308,7 +302,7 @@ static void virtsnd_pcm_msg_complete(struct virtio_pcm_msg *msg, * in the virtqueue. Therefore, on each completion of an I/O message, * the hw_ptr value is unconditionally advanced. */ - spin_lock(&vss->lock); + guard(spinlock)(&vss->lock); /* * If the capture substream returned an incorrect status, then just * increase the hw_ptr by the message size. @@ -338,7 +332,6 @@ static void virtsnd_pcm_msg_complete(struct virtio_pcm_msg *msg, } else if (!vss->msg_count) { wake_up_all(&vss->msg_empty); } - spin_unlock(&vss->lock); } /** @@ -351,15 +344,13 @@ static inline void virtsnd_pcm_notify_cb(struct virtio_snd_queue *queue) { struct virtio_pcm_msg *msg; u32 written_bytes; - unsigned long flags; - spin_lock_irqsave(&queue->lock, flags); + guard(spinlock_irqsave)(&queue->lock); do { virtqueue_disable_cb(queue->vqueue); while ((msg = virtqueue_get_buf(queue->vqueue, &written_bytes))) virtsnd_pcm_msg_complete(msg, written_bytes); } while (!virtqueue_enable_cb(queue->vqueue)); - spin_unlock_irqrestore(&queue->lock, flags); } /** diff --git a/sound/virtio/virtio_pcm_ops.c b/sound/virtio/virtio_pcm_ops.c index ad12aae52fc3..6297a9c61e70 100644 --- a/sound/virtio/virtio_pcm_ops.c +++ b/sound/virtio/virtio_pcm_ops.c @@ -327,7 +327,6 @@ static int virtsnd_pcm_trigger(struct snd_pcm_substream *substream, int command) struct virtio_snd *snd = vss->snd; struct virtio_snd_queue *queue; struct virtio_snd_msg *msg; - unsigned long flags; int rc = 0; switch (command) { @@ -335,23 +334,20 @@ static int virtsnd_pcm_trigger(struct snd_pcm_substream *substream, int command) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: queue = virtsnd_pcm_queue(vss); - spin_lock_irqsave(&queue->lock, flags); - spin_lock(&vss->lock); - if (vss->direction == SNDRV_PCM_STREAM_CAPTURE) - rc = virtsnd_pcm_msg_send(vss, 0, vss->buffer_bytes); - if (!rc) + scoped_guard(spinlock_irqsave, &queue->lock) { + guard(spinlock)(&vss->lock); + if (vss->direction == SNDRV_PCM_STREAM_CAPTURE) + rc = virtsnd_pcm_msg_send(vss, 0, vss->buffer_bytes); + if (rc) + return rc; vss->xfer_enabled = true; - spin_unlock(&vss->lock); - spin_unlock_irqrestore(&queue->lock, flags); - if (rc) - return rc; + } msg = virtsnd_pcm_ctl_msg_alloc(vss, VIRTIO_SND_R_PCM_START, GFP_KERNEL); if (!msg) { - spin_lock_irqsave(&vss->lock, flags); + guard(spinlock_irqsave)(&vss->lock); vss->xfer_enabled = false; - spin_unlock_irqrestore(&vss->lock, flags); return -ENOMEM; } @@ -364,9 +360,9 @@ static int virtsnd_pcm_trigger(struct snd_pcm_substream *substream, int command) vss->stopped = true; fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - spin_lock_irqsave(&vss->lock, flags); - vss->xfer_enabled = false; - spin_unlock_irqrestore(&vss->lock, flags); + scoped_guard(spinlock_irqsave, &vss->lock) { + vss->xfer_enabled = false; + } msg = virtsnd_pcm_ctl_msg_alloc(vss, VIRTIO_SND_R_PCM_STOP, GFP_KERNEL); @@ -480,38 +476,24 @@ static int virtsnd_pcm_pb_ack(struct snd_pcm_substream *substream) { struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream); struct virtio_snd_queue *queue = virtsnd_pcm_queue(vss); - unsigned long flags; - int rc; - spin_lock_irqsave(&queue->lock, flags); - spin_lock(&vss->lock); + guard(spinlock_irqsave)(&queue->lock); + guard(spinlock)(&vss->lock); - rc = snd_pcm_indirect_playback_transfer(substream, &vss->pcm_indirect, - virtsnd_pcm_trans_copy); - - spin_unlock(&vss->lock); - spin_unlock_irqrestore(&queue->lock, flags); - - return rc; + return snd_pcm_indirect_playback_transfer(substream, &vss->pcm_indirect, + virtsnd_pcm_trans_copy); } static int virtsnd_pcm_cp_ack(struct snd_pcm_substream *substream) { struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream); struct virtio_snd_queue *queue = virtsnd_pcm_queue(vss); - unsigned long flags; - int rc; - - spin_lock_irqsave(&queue->lock, flags); - spin_lock(&vss->lock); - - rc = snd_pcm_indirect_capture_transfer(substream, &vss->pcm_indirect, - virtsnd_pcm_trans_copy); - spin_unlock(&vss->lock); - spin_unlock_irqrestore(&queue->lock, flags); + guard(spinlock_irqsave)(&queue->lock); + guard(spinlock)(&vss->lock); - return rc; + return snd_pcm_indirect_capture_transfer(substream, &vss->pcm_indirect, + virtsnd_pcm_trans_copy); } /* PCM substream operators map. */ diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index 01f49555c5f6..8e2a007311d3 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c @@ -171,13 +171,11 @@ static struct snd_pcm_substream * had_substream_get(struct snd_intelhad *intelhaddata) { struct snd_pcm_substream *substream; - unsigned long flags; - spin_lock_irqsave(&intelhaddata->had_spinlock, flags); + guard(spinlock_irqsave)(&intelhaddata->had_spinlock); substream = intelhaddata->stream_info.substream; if (substream) intelhaddata->stream_info.substream_refcount++; - spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags); return substream; } @@ -186,11 +184,8 @@ had_substream_get(struct snd_intelhad *intelhaddata) */ static void had_substream_put(struct snd_intelhad *intelhaddata) { - unsigned long flags; - - spin_lock_irqsave(&intelhaddata->had_spinlock, flags); + guard(spinlock_irqsave)(&intelhaddata->had_spinlock); intelhaddata->stream_info.substream_refcount--; - spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags); } static u32 had_config_offset(int pipe) @@ -554,16 +549,13 @@ static int had_chmap_ctl_get(struct snd_kcontrol *kcontrol, memset(ucontrol->value.integer.value, 0, sizeof(long) * HAD_MAX_CHANNEL); - mutex_lock(&intelhaddata->mutex); - if (!intelhaddata->chmap->chmap) { - mutex_unlock(&intelhaddata->mutex); + guard(mutex)(&intelhaddata->mutex); + if (!intelhaddata->chmap->chmap) return 0; - } chmap = intelhaddata->chmap->chmap; for (i = 0; i < chmap->channels; i++) ucontrol->value.integer.value[i] = chmap->map[i]; - mutex_unlock(&intelhaddata->mutex); return 0; } @@ -949,10 +941,9 @@ static int had_process_ringbuf(struct snd_pcm_substream *substream, struct snd_intelhad *intelhaddata) { int len, processed; - unsigned long flags; processed = 0; - spin_lock_irqsave(&intelhaddata->had_spinlock, flags); + guard(spinlock_irqsave)(&intelhaddata->had_spinlock); for (;;) { /* get the remaining bytes on the buffer */ had_read_register(intelhaddata, @@ -961,25 +952,20 @@ static int had_process_ringbuf(struct snd_pcm_substream *substream, if (len < 0 || len > intelhaddata->period_bytes) { dev_dbg(intelhaddata->dev, "Invalid buf length %d\n", len); - len = -EPIPE; - goto out; + return -EPIPE; } if (len > 0) /* OK, this is the current buffer */ break; /* len=0 => already empty, check the next buffer */ - if (++processed >= intelhaddata->num_bds) { - len = -EPIPE; /* all empty? - report underrun */ - goto out; - } + if (++processed >= intelhaddata->num_bds) + return -EPIPE; /* all empty? - report underrun */ had_advance_ringbuf(substream, intelhaddata); } len = intelhaddata->period_bytes - len; len += intelhaddata->period_bytes * intelhaddata->pcmbuf_head; - out: - spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags); return len; } @@ -1095,10 +1081,10 @@ static int had_pcm_open(struct snd_pcm_substream *substream) goto error; /* expose PCM substream */ - spin_lock_irq(&intelhaddata->had_spinlock); - intelhaddata->stream_info.substream = substream; - intelhaddata->stream_info.substream_refcount++; - spin_unlock_irq(&intelhaddata->had_spinlock); + scoped_guard(spinlock_irq, &intelhaddata->had_spinlock) { + intelhaddata->stream_info.substream = substream; + intelhaddata->stream_info.substream_refcount++; + } return retval; error: @@ -1156,7 +1142,7 @@ static int had_pcm_trigger(struct snd_pcm_substream *substream, int cmd) intelhaddata = snd_pcm_substream_chip(substream); - spin_lock(&intelhaddata->had_spinlock); + guard(spinlock)(&intelhaddata->had_spinlock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: @@ -1175,7 +1161,6 @@ static int had_pcm_trigger(struct snd_pcm_substream *substream, int cmd) default: retval = -EINVAL; } - spin_unlock(&intelhaddata->had_spinlock); return retval; } @@ -1314,21 +1299,20 @@ static void had_process_hot_plug(struct snd_intelhad *intelhaddata) { struct snd_pcm_substream *substream; - spin_lock_irq(&intelhaddata->had_spinlock); - if (intelhaddata->connected) { - dev_dbg(intelhaddata->dev, "Device already connected\n"); - spin_unlock_irq(&intelhaddata->had_spinlock); - return; - } + scoped_guard(spinlock_irq, &intelhaddata->had_spinlock) { + if (intelhaddata->connected) { + dev_dbg(intelhaddata->dev, "Device already connected\n"); + return; + } - /* Disable Audio */ - had_enable_audio(intelhaddata, false); + /* Disable Audio */ + had_enable_audio(intelhaddata, false); - intelhaddata->connected = true; - dev_dbg(intelhaddata->dev, - "%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_CONNECTED\n", + intelhaddata->connected = true; + dev_dbg(intelhaddata->dev, + "%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_CONNECTED\n", __func__, __LINE__); - spin_unlock_irq(&intelhaddata->had_spinlock); + } had_build_channel_allocation_map(intelhaddata); @@ -1347,22 +1331,20 @@ static void had_process_hot_unplug(struct snd_intelhad *intelhaddata) { struct snd_pcm_substream *substream; - spin_lock_irq(&intelhaddata->had_spinlock); - if (!intelhaddata->connected) { - dev_dbg(intelhaddata->dev, "Device already disconnected\n"); - spin_unlock_irq(&intelhaddata->had_spinlock); - return; - - } + scoped_guard(spinlock_irq, &intelhaddata->had_spinlock) { + if (!intelhaddata->connected) { + dev_dbg(intelhaddata->dev, "Device already disconnected\n"); + return; + } - /* Disable Audio */ - had_enable_audio(intelhaddata, false); + /* Disable Audio */ + had_enable_audio(intelhaddata, false); - intelhaddata->connected = false; - dev_dbg(intelhaddata->dev, - "%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_DISCONNECTED\n", + intelhaddata->connected = false; + dev_dbg(intelhaddata->dev, + "%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_DISCONNECTED\n", __func__, __LINE__); - spin_unlock_irq(&intelhaddata->had_spinlock); + } kfree(intelhaddata->chmap->chmap); intelhaddata->chmap->chmap = NULL; @@ -1394,14 +1376,13 @@ static int had_iec958_get(struct snd_kcontrol *kcontrol, { struct snd_intelhad *intelhaddata = snd_kcontrol_chip(kcontrol); - mutex_lock(&intelhaddata->mutex); + guard(mutex)(&intelhaddata->mutex); ucontrol->value.iec958.status[0] = (intelhaddata->aes_bits >> 0) & 0xff; ucontrol->value.iec958.status[1] = (intelhaddata->aes_bits >> 8) & 0xff; ucontrol->value.iec958.status[2] = (intelhaddata->aes_bits >> 16) & 0xff; ucontrol->value.iec958.status[3] = (intelhaddata->aes_bits >> 24) & 0xff; - mutex_unlock(&intelhaddata->mutex); return 0; } @@ -1426,12 +1407,11 @@ static int had_iec958_put(struct snd_kcontrol *kcontrol, (ucontrol->value.iec958.status[1] << 8) | (ucontrol->value.iec958.status[2] << 16) | (ucontrol->value.iec958.status[3] << 24); - mutex_lock(&intelhaddata->mutex); + guard(mutex)(&intelhaddata->mutex); if (intelhaddata->aes_bits != val) { intelhaddata->aes_bits = val; changed = 1; } - mutex_unlock(&intelhaddata->mutex); return changed; } @@ -1448,10 +1428,9 @@ static int had_ctl_eld_get(struct snd_kcontrol *kcontrol, { struct snd_intelhad *intelhaddata = snd_kcontrol_chip(kcontrol); - mutex_lock(&intelhaddata->mutex); + guard(mutex)(&intelhaddata->mutex); memcpy(ucontrol->value.bytes.data, intelhaddata->eld, HDMI_MAX_ELD_BYTES); - mutex_unlock(&intelhaddata->mutex); return 0; } @@ -1642,9 +1621,9 @@ static void hdmi_lpe_audio_free(struct snd_card *card) struct intel_hdmi_lpe_audio_pdata *pdata = card_ctx->dev->platform_data; int port; - spin_lock_irq(&pdata->lpe_audio_slock); - pdata->notify_audio_lpe = NULL; - spin_unlock_irq(&pdata->lpe_audio_slock); + scoped_guard(spinlock_irq, &pdata->lpe_audio_slock) { + pdata->notify_audio_lpe = NULL; + } for_each_port(card_ctx, port) { struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; @@ -1805,9 +1784,9 @@ static int __hdmi_lpe_audio_probe(struct platform_device *pdev) if (ret) return ret; - spin_lock_irq(&pdata->lpe_audio_slock); - pdata->notify_audio_lpe = notify_audio_lpe; - spin_unlock_irq(&pdata->lpe_audio_slock); + scoped_guard(spinlock_irq, &pdata->lpe_audio_slock) { + pdata->notify_audio_lpe = notify_audio_lpe; + } pm_runtime_set_autosuspend_delay(&pdev->dev, INTEL_HDMI_AUDIO_SUSPEND_DELAY_MS); pm_runtime_use_autosuspend(&pdev->dev); diff --git a/sound/xen/xen_snd_front.c b/sound/xen/xen_snd_front.c index b66e037710d0..c56d17479f05 100644 --- a/sound/xen/xen_snd_front.c +++ b/sound/xen/xen_snd_front.c @@ -62,12 +62,12 @@ int xen_snd_front_stream_query_hw_param(struct xen_snd_front_evtchnl *evtchnl, struct xensnd_req *req; int ret; - mutex_lock(&evtchnl->u.req.req_io_lock); + guard(mutex)(&evtchnl->u.req.req_io_lock); - mutex_lock(&evtchnl->ring_io_lock); - req = be_stream_prepare_req(evtchnl, XENSND_OP_HW_PARAM_QUERY); - req->op.hw_param = *hw_param_req; - mutex_unlock(&evtchnl->ring_io_lock); + scoped_guard(mutex, &evtchnl->ring_io_lock) { + req = be_stream_prepare_req(evtchnl, XENSND_OP_HW_PARAM_QUERY); + req->op.hw_param = *hw_param_req; + } ret = be_stream_do_io(evtchnl); @@ -77,7 +77,6 @@ int xen_snd_front_stream_query_hw_param(struct xen_snd_front_evtchnl *evtchnl, if (ret == 0) *hw_param_resp = evtchnl->u.req.resp.hw_param; - mutex_unlock(&evtchnl->u.req.req_io_lock); return ret; } @@ -90,25 +89,24 @@ int xen_snd_front_stream_prepare(struct xen_snd_front_evtchnl *evtchnl, struct xensnd_req *req; int ret; - mutex_lock(&evtchnl->u.req.req_io_lock); - - mutex_lock(&evtchnl->ring_io_lock); - req = be_stream_prepare_req(evtchnl, XENSND_OP_OPEN); - req->op.open.pcm_format = format; - req->op.open.pcm_channels = channels; - req->op.open.pcm_rate = rate; - req->op.open.buffer_sz = buffer_sz; - req->op.open.period_sz = period_sz; - req->op.open.gref_directory = - xen_front_pgdir_shbuf_get_dir_start(shbuf); - mutex_unlock(&evtchnl->ring_io_lock); + guard(mutex)(&evtchnl->u.req.req_io_lock); + + scoped_guard(mutex, &evtchnl->ring_io_lock) { + req = be_stream_prepare_req(evtchnl, XENSND_OP_OPEN); + req->op.open.pcm_format = format; + req->op.open.pcm_channels = channels; + req->op.open.pcm_rate = rate; + req->op.open.buffer_sz = buffer_sz; + req->op.open.period_sz = period_sz; + req->op.open.gref_directory = + xen_front_pgdir_shbuf_get_dir_start(shbuf); + } ret = be_stream_do_io(evtchnl); if (ret == 0) ret = be_stream_wait_io(evtchnl); - mutex_unlock(&evtchnl->u.req.req_io_lock); return ret; } @@ -117,18 +115,17 @@ int xen_snd_front_stream_close(struct xen_snd_front_evtchnl *evtchnl) __always_unused struct xensnd_req *req; int ret; - mutex_lock(&evtchnl->u.req.req_io_lock); + guard(mutex)(&evtchnl->u.req.req_io_lock); - mutex_lock(&evtchnl->ring_io_lock); - req = be_stream_prepare_req(evtchnl, XENSND_OP_CLOSE); - mutex_unlock(&evtchnl->ring_io_lock); + scoped_guard(mutex, &evtchnl->ring_io_lock) { + req = be_stream_prepare_req(evtchnl, XENSND_OP_CLOSE); + } ret = be_stream_do_io(evtchnl); if (ret == 0) ret = be_stream_wait_io(evtchnl); - mutex_unlock(&evtchnl->u.req.req_io_lock); return ret; } @@ -138,20 +135,19 @@ int xen_snd_front_stream_write(struct xen_snd_front_evtchnl *evtchnl, struct xensnd_req *req; int ret; - mutex_lock(&evtchnl->u.req.req_io_lock); + guard(mutex)(&evtchnl->u.req.req_io_lock); - mutex_lock(&evtchnl->ring_io_lock); - req = be_stream_prepare_req(evtchnl, XENSND_OP_WRITE); - req->op.rw.length = count; - req->op.rw.offset = pos; - mutex_unlock(&evtchnl->ring_io_lock); + scoped_guard(mutex, &evtchnl->ring_io_lock) { + req = be_stream_prepare_req(evtchnl, XENSND_OP_WRITE); + req->op.rw.length = count; + req->op.rw.offset = pos; + } ret = be_stream_do_io(evtchnl); if (ret == 0) ret = be_stream_wait_io(evtchnl); - mutex_unlock(&evtchnl->u.req.req_io_lock); return ret; } @@ -161,20 +157,19 @@ int xen_snd_front_stream_read(struct xen_snd_front_evtchnl *evtchnl, struct xensnd_req *req; int ret; - mutex_lock(&evtchnl->u.req.req_io_lock); + guard(mutex)(&evtchnl->u.req.req_io_lock); - mutex_lock(&evtchnl->ring_io_lock); - req = be_stream_prepare_req(evtchnl, XENSND_OP_READ); - req->op.rw.length = count; - req->op.rw.offset = pos; - mutex_unlock(&evtchnl->ring_io_lock); + scoped_guard(mutex, &evtchnl->ring_io_lock) { + req = be_stream_prepare_req(evtchnl, XENSND_OP_READ); + req->op.rw.length = count; + req->op.rw.offset = pos; + } ret = be_stream_do_io(evtchnl); if (ret == 0) ret = be_stream_wait_io(evtchnl); - mutex_unlock(&evtchnl->u.req.req_io_lock); return ret; } @@ -184,19 +179,18 @@ int xen_snd_front_stream_trigger(struct xen_snd_front_evtchnl *evtchnl, struct xensnd_req *req; int ret; - mutex_lock(&evtchnl->u.req.req_io_lock); + guard(mutex)(&evtchnl->u.req.req_io_lock); - mutex_lock(&evtchnl->ring_io_lock); - req = be_stream_prepare_req(evtchnl, XENSND_OP_TRIGGER); - req->op.trigger.type = type; - mutex_unlock(&evtchnl->ring_io_lock); + scoped_guard(mutex, &evtchnl->ring_io_lock) { + req = be_stream_prepare_req(evtchnl, XENSND_OP_TRIGGER); + req->op.trigger.type = type; + } ret = be_stream_do_io(evtchnl); if (ret == 0) ret = be_stream_wait_io(evtchnl); - mutex_unlock(&evtchnl->u.req.req_io_lock); return ret; } diff --git a/sound/xen/xen_snd_front_evtchnl.c b/sound/xen/xen_snd_front_evtchnl.c index 26d1b3987887..2fbed8e4a490 100644 --- a/sound/xen/xen_snd_front_evtchnl.c +++ b/sound/xen/xen_snd_front_evtchnl.c @@ -28,7 +28,7 @@ static irqreturn_t evtchnl_interrupt_req(int irq, void *dev_id) if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED)) return IRQ_HANDLED; - mutex_lock(&channel->ring_io_lock); + guard(mutex)(&channel->ring_io_lock); again: rp = channel->u.req.ring.sring->rsp_prod; @@ -80,7 +80,6 @@ again: channel->u.req.ring.sring->rsp_event = i + 1; } - mutex_unlock(&channel->ring_io_lock); return IRQ_HANDLED; } @@ -93,13 +92,13 @@ static irqreturn_t evtchnl_interrupt_evt(int irq, void *dev_id) if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED)) return IRQ_HANDLED; - mutex_lock(&channel->ring_io_lock); + guard(mutex)(&channel->ring_io_lock); prod = page->in_prod; /* Ensure we see ring contents up to prod. */ virt_rmb(); if (prod == page->in_cons) - goto out; + return IRQ_HANDLED; /* * Assume that the backend is trusted to always write sane values @@ -125,8 +124,6 @@ static irqreturn_t evtchnl_interrupt_evt(int irq, void *dev_id) /* Ensure ring contents. */ virt_wmb(); -out: - mutex_unlock(&channel->ring_io_lock); return IRQ_HANDLED; } @@ -444,23 +441,23 @@ void xen_snd_front_evtchnl_pair_set_connected(struct xen_snd_front_evtchnl_pair else state = EVTCHNL_STATE_DISCONNECTED; - mutex_lock(&evt_pair->req.ring_io_lock); - evt_pair->req.state = state; - mutex_unlock(&evt_pair->req.ring_io_lock); + scoped_guard(mutex, &evt_pair->req.ring_io_lock) { + evt_pair->req.state = state; + } - mutex_lock(&evt_pair->evt.ring_io_lock); - evt_pair->evt.state = state; - mutex_unlock(&evt_pair->evt.ring_io_lock); + scoped_guard(mutex, &evt_pair->evt.ring_io_lock) { + evt_pair->evt.state = state; + } } void xen_snd_front_evtchnl_pair_clear(struct xen_snd_front_evtchnl_pair *evt_pair) { - mutex_lock(&evt_pair->req.ring_io_lock); - evt_pair->req.evt_next_id = 0; - mutex_unlock(&evt_pair->req.ring_io_lock); + scoped_guard(mutex, &evt_pair->req.ring_io_lock) { + evt_pair->req.evt_next_id = 0; + } - mutex_lock(&evt_pair->evt.ring_io_lock); - evt_pair->evt.evt_next_id = 0; - mutex_unlock(&evt_pair->evt.ring_io_lock); + scoped_guard(mutex, &evt_pair->evt.ring_io_lock) { + evt_pair->evt.evt_next_id = 0; + } } |