Commit 750c930b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-5.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "All relatively small changes:

   - a regression fix for PCM link code with CONFIG_REFCOUNT_FULL;
     stumbled on a slight difference between atomic_t and refcount_t

   - a couple of HD-audio stabilization patches addressing the too slow
     PM resume seen on some Intel chips

   - a series of ALSA compress-offload API fixes, including the
     regression by the previous capture stream support

   - trivial LINE6 USB-audio driver fixes, a new Conexant HD-audio chip
     coverage, and a fix in AC97 bus error path"

* tag 'sound-5.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda - Add a conexant codec entry to let mute led work
  ALSA: hda - Fix intermittent CORB/RIRB stall on Intel chips
  ALSA: ac97: Fix double free of ac97_codec_device
  ALSA: compress: Be more restrictive about when a drain is allowed
  ALSA: compress: Don't allow paritial drain operations on capture streams
  ALSA: compress: Prevent bypasses of set_params
  ALSA: compress: Fix regression on compressed capture streams
  ALSA: line6: Fix a typo
  ALSA: pcm: Fix refcount_inc() on zero usage
  ALSA: line6: Fix wrong altsetting for LINE6_PODHD500_1
  ALSA: hda - Optimize resume for codecs without jack detection
parents b381c016 3f880949
...@@ -173,10 +173,7 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream) ...@@ -173,10 +173,7 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
if (snd_BUG_ON(!stream)) if (snd_BUG_ON(!stream))
return; return;
if (stream->direction == SND_COMPRESS_PLAYBACK)
stream->runtime->state = SNDRV_PCM_STATE_SETUP; stream->runtime->state = SNDRV_PCM_STATE_SETUP;
else
stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
wake_up(&stream->runtime->sleep); wake_up(&stream->runtime->sleep);
} }
......
...@@ -122,17 +122,12 @@ static int ac97_codec_add(struct ac97_controller *ac97_ctrl, int idx, ...@@ -122,17 +122,12 @@ static int ac97_codec_add(struct ac97_controller *ac97_ctrl, int idx,
vendor_id); vendor_id);
ret = device_add(&codec->dev); ret = device_add(&codec->dev);
if (ret) if (ret) {
goto err_free_codec;
return 0;
err_free_codec:
of_node_put(codec->dev.of_node);
put_device(&codec->dev); put_device(&codec->dev);
kfree(codec);
ac97_ctrl->codecs[idx] = NULL;
return ret; return ret;
}
return 0;
} }
unsigned int snd_ac97_bus_scan_one(struct ac97_controller *adrv, unsigned int snd_ac97_bus_scan_one(struct ac97_controller *adrv,
......
...@@ -574,10 +574,7 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg) ...@@ -574,10 +574,7 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
stream->metadata_set = false; stream->metadata_set = false;
stream->next_track = false; stream->next_track = false;
if (stream->direction == SND_COMPRESS_PLAYBACK)
stream->runtime->state = SNDRV_PCM_STATE_SETUP; stream->runtime->state = SNDRV_PCM_STATE_SETUP;
else
stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
} else { } else {
return -EPERM; return -EPERM;
} }
...@@ -693,8 +690,17 @@ static int snd_compr_start(struct snd_compr_stream *stream) ...@@ -693,8 +690,17 @@ static int snd_compr_start(struct snd_compr_stream *stream)
{ {
int retval; int retval;
if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED) switch (stream->runtime->state) {
case SNDRV_PCM_STATE_SETUP:
if (stream->direction != SND_COMPRESS_CAPTURE)
return -EPERM;
break;
case SNDRV_PCM_STATE_PREPARED:
break;
default:
return -EPERM; return -EPERM;
}
retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START); retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
if (!retval) if (!retval)
stream->runtime->state = SNDRV_PCM_STATE_RUNNING; stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
...@@ -705,9 +711,15 @@ static int snd_compr_stop(struct snd_compr_stream *stream) ...@@ -705,9 +711,15 @@ static int snd_compr_stop(struct snd_compr_stream *stream)
{ {
int retval; int retval;
if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED || switch (stream->runtime->state) {
stream->runtime->state == SNDRV_PCM_STATE_SETUP) case SNDRV_PCM_STATE_OPEN:
case SNDRV_PCM_STATE_SETUP:
case SNDRV_PCM_STATE_PREPARED:
return -EPERM; return -EPERM;
default:
break;
}
retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
if (!retval) { if (!retval) {
snd_compr_drain_notify(stream); snd_compr_drain_notify(stream);
...@@ -795,9 +807,17 @@ static int snd_compr_drain(struct snd_compr_stream *stream) ...@@ -795,9 +807,17 @@ static int snd_compr_drain(struct snd_compr_stream *stream)
{ {
int retval; int retval;
if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED || switch (stream->runtime->state) {
stream->runtime->state == SNDRV_PCM_STATE_SETUP) case SNDRV_PCM_STATE_OPEN:
case SNDRV_PCM_STATE_SETUP:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
return -EPERM; return -EPERM;
case SNDRV_PCM_STATE_XRUN:
return -EPIPE;
default:
break;
}
retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN); retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
if (retval) { if (retval) {
...@@ -817,6 +837,10 @@ static int snd_compr_next_track(struct snd_compr_stream *stream) ...@@ -817,6 +837,10 @@ static int snd_compr_next_track(struct snd_compr_stream *stream)
if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
return -EPERM; return -EPERM;
/* next track doesn't have any meaning for capture streams */
if (stream->direction == SND_COMPRESS_CAPTURE)
return -EPERM;
/* you can signal next track if this is intended to be a gapless stream /* you can signal next track if this is intended to be a gapless stream
* and current track metadata is set * and current track metadata is set
*/ */
...@@ -834,9 +858,23 @@ static int snd_compr_next_track(struct snd_compr_stream *stream) ...@@ -834,9 +858,23 @@ static int snd_compr_next_track(struct snd_compr_stream *stream)
static int snd_compr_partial_drain(struct snd_compr_stream *stream) static int snd_compr_partial_drain(struct snd_compr_stream *stream)
{ {
int retval; int retval;
if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
stream->runtime->state == SNDRV_PCM_STATE_SETUP) switch (stream->runtime->state) {
case SNDRV_PCM_STATE_OPEN:
case SNDRV_PCM_STATE_SETUP:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
return -EPERM; return -EPERM;
case SNDRV_PCM_STATE_XRUN:
return -EPIPE;
default:
break;
}
/* partial drain doesn't have any meaning for capture streams */
if (stream->direction == SND_COMPRESS_CAPTURE)
return -EPERM;
/* stream can be drained only when next track has been signalled */ /* stream can be drained only when next track has been signalled */
if (stream->next_track == false) if (stream->next_track == false)
return -EPERM; return -EPERM;
......
...@@ -77,7 +77,7 @@ void snd_pcm_group_init(struct snd_pcm_group *group) ...@@ -77,7 +77,7 @@ void snd_pcm_group_init(struct snd_pcm_group *group)
spin_lock_init(&group->lock); spin_lock_init(&group->lock);
mutex_init(&group->mutex); mutex_init(&group->mutex);
INIT_LIST_HEAD(&group->substreams); INIT_LIST_HEAD(&group->substreams);
refcount_set(&group->refs, 0); refcount_set(&group->refs, 1);
} }
/* define group lock helpers */ /* define group lock helpers */
...@@ -1096,8 +1096,7 @@ static void snd_pcm_group_unref(struct snd_pcm_group *group, ...@@ -1096,8 +1096,7 @@ static void snd_pcm_group_unref(struct snd_pcm_group *group,
if (!group) if (!group)
return; return;
do_free = refcount_dec_and_test(&group->refs) && do_free = refcount_dec_and_test(&group->refs);
list_empty(&group->substreams);
snd_pcm_group_unlock(group, substream->pcm->nonatomic); snd_pcm_group_unlock(group, substream->pcm->nonatomic);
if (do_free) if (do_free)
kfree(group); kfree(group);
...@@ -2020,6 +2019,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) ...@@ -2020,6 +2019,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
snd_pcm_group_lock_irq(target_group, nonatomic); snd_pcm_group_lock_irq(target_group, nonatomic);
snd_pcm_stream_lock(substream1); snd_pcm_stream_lock(substream1);
snd_pcm_group_assign(substream1, target_group); snd_pcm_group_assign(substream1, target_group);
refcount_inc(&target_group->refs);
snd_pcm_stream_unlock(substream1); snd_pcm_stream_unlock(substream1);
snd_pcm_group_unlock_irq(target_group, nonatomic); snd_pcm_group_unlock_irq(target_group, nonatomic);
_end: _end:
...@@ -2056,13 +2056,14 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream) ...@@ -2056,13 +2056,14 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream)
snd_pcm_group_lock_irq(group, nonatomic); snd_pcm_group_lock_irq(group, nonatomic);
relink_to_local(substream); relink_to_local(substream);
refcount_dec(&group->refs);
/* detach the last stream, too */ /* detach the last stream, too */
if (list_is_singular(&group->substreams)) { if (list_is_singular(&group->substreams)) {
relink_to_local(list_first_entry(&group->substreams, relink_to_local(list_first_entry(&group->substreams,
struct snd_pcm_substream, struct snd_pcm_substream,
link_list)); link_list));
do_free = !refcount_read(&group->refs); do_free = refcount_dec_and_test(&group->refs);
} }
snd_pcm_group_unlock_irq(group, nonatomic); snd_pcm_group_unlock_irq(group, nonatomic);
......
...@@ -2942,7 +2942,7 @@ static int hda_codec_runtime_resume(struct device *dev) ...@@ -2942,7 +2942,7 @@ static int hda_codec_runtime_resume(struct device *dev)
static int hda_codec_force_resume(struct device *dev) static int hda_codec_force_resume(struct device *dev)
{ {
struct hda_codec *codec = dev_to_hda_codec(dev); struct hda_codec *codec = dev_to_hda_codec(dev);
bool forced_resume = !codec->relaxed_resume; bool forced_resume = !codec->relaxed_resume && codec->jacktbl.used;
int ret; int ret;
/* The get/put pair below enforces the runtime resume even if the /* The get/put pair below enforces the runtime resume even if the
......
...@@ -313,11 +313,10 @@ enum { ...@@ -313,11 +313,10 @@ enum {
#define AZX_DCAPS_INTEL_SKYLAKE \ #define AZX_DCAPS_INTEL_SKYLAKE \
(AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
AZX_DCAPS_SYNC_WRITE |\
AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT) AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT)
#define AZX_DCAPS_INTEL_BROXTON \ #define AZX_DCAPS_INTEL_BROXTON AZX_DCAPS_INTEL_SKYLAKE
(AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT)
/* quirks for ATI SB / AMD Hudson */ /* quirks for ATI SB / AMD Hudson */
#define AZX_DCAPS_PRESET_ATI_SB \ #define AZX_DCAPS_PRESET_ATI_SB \
......
...@@ -1083,6 +1083,7 @@ static int patch_conexant_auto(struct hda_codec *codec) ...@@ -1083,6 +1083,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
*/ */
static const struct hda_device_id snd_hda_id_conexant[] = { static const struct hda_device_id snd_hda_id_conexant[] = {
HDA_CODEC_ENTRY(0x14f11f86, "CX8070", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f12008, "CX8200", patch_conexant_auto), HDA_CODEC_ENTRY(0x14f12008, "CX8200", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f15045, "CX20549 (Venice)", patch_conexant_auto), HDA_CODEC_ENTRY(0x14f15045, "CX20549 (Venice)", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f15047, "CX20551 (Waikiki)", patch_conexant_auto), HDA_CODEC_ENTRY(0x14f15047, "CX20551 (Waikiki)", patch_conexant_auto),
......
...@@ -368,7 +368,7 @@ static const struct line6_properties podhd_properties_table[] = { ...@@ -368,7 +368,7 @@ static const struct line6_properties podhd_properties_table[] = {
.name = "POD HD500", .name = "POD HD500",
.capabilities = LINE6_CAP_PCM .capabilities = LINE6_CAP_PCM
| LINE6_CAP_HWMON, | LINE6_CAP_HWMON,
.altsetting = 1, .altsetting = 0,
.ep_ctrl_r = 0x81, .ep_ctrl_r = 0x81,
.ep_ctrl_w = 0x01, .ep_ctrl_w = 0x01,
.ep_audio_r = 0x86, .ep_audio_r = 0x86,
......
...@@ -244,5 +244,5 @@ static struct usb_driver variax_driver = { ...@@ -244,5 +244,5 @@ static struct usb_driver variax_driver = {
module_usb_driver(variax_driver); module_usb_driver(variax_driver);
MODULE_DESCRIPTION("Vairax Workbench USB driver"); MODULE_DESCRIPTION("Variax Workbench USB driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment