mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 13:44:15 +08:00
Sound fixes for 3.9-rc4
Mostly HD-audio and USB-audio regression fixes: - Oops fix at unloading of snd-hda-codec-conexant module - A few trivial regression fixes for Cirrus and Conexant HD-audio codecs - Relax the USB-audio descriptor parse errors as non-fatal - Fix locking of HD-audio CA0132 DSP loader - Fix the generic HD-audio parser for VIA codecs -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABAgAGBQJRTGiuAAoJEGwxgFQ9KSmk65wP/0kpwdOuNt/U24qYPE8F/F93 SSM7CY124Pyx5Q8/W6044IUkl11YRBvy3Qp8REp43mNw+/VBC+CfSORltVP0BMUr B9Az38a2t7ViV0FYFNxu+AskQNVL8nrQjVASw6kqi8NEk/sJmE+5mmvaAAuv0GHy GLxG6bMqIUnUlys4xy/kgyrtMmGjU1RfX8D5DGZoggFzXHKVY+U7c4NXcwV6C7VB z/5gG4SRVB3av6mGO37Kn/PDAUVYH55dhnHdYulkU5/yDfoi5OyqG9dWXhiKrPFP MAruKWY2n3x6dsvd+LJ1a72Y4DUtPHQANs5gtO9JeCm8xJHbUrGGwn9yaXfN1uRN 2arpUwp3kLoDve27EpFfJJ69f0wQvZoL/GafN8slRzIB8/+UE5tCicvZn3/X7svk 6cyQbi8iGA8wYKXNLnunmsf3jaeoXoFjwdIgA8liNfSwqJcllJ/0Pl/U+FN9Y4NK xVh2K78BR1pOgmYBufkLXoiG+LKZsnN8qmJauQQ8dUXLxm3JcXTIvm2v9vP6Hs7b HDjPvpNYS8WAjfNu6QzVhOovJ4JJj+OipGmAUh6x1kjlRq2g+HJwb4TeI2zYX8J+ o07ZbRVPo9ctl3+oNO0vq9R7yn8QlcgScjfNylWpFmwLpcrWErRrL1nnRxjT+jEr hjL6RNQ5lNODEd5i07+4 =EBFM -----END PGP SIGNATURE----- Merge tag 'sound-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "Mostly HD-audio and USB-audio regression fixes: - Oops fix at unloading of snd-hda-codec-conexant module - A few trivial regression fixes for Cirrus and Conexant HD-audio codecs - Relax the USB-audio descriptor parse errors as non-fatal - Fix locking of HD-audio CA0132 DSP loader - Fix the generic HD-audio parser for VIA codecs" * tag 'sound-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: hda - Fix DAC assignment for independent HP ALSA: hda - Fix abuse of snd_hda_lock_devices() for DSP loader ALSA: hda - Fix typo in checking IEC958 emphasis bit ALSA: snd-usb: mixer: ignore -EINVAL in snd_usb_mixer_controls() ALSA: snd-usb: mixer: propagate errors up the call chain ALSA: usb: Parse UAC2 extension unit like for UAC1 ALSA: hda - Fix yet missing GPIO/EAPD setup in cirrus driver ALSA: hda/cirrus - Fix the digital beep registration ALSA: hda - Fix missing beep detach in patch_conexant.c ALSA: documentation: Fix typo in Documentation/sound
This commit is contained in:
commit
70dc52faae
@ -912,7 +912,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
models depending on the codec chip. The list of available models
|
||||
is found in HD-Audio-Models.txt
|
||||
|
||||
The model name "genric" is treated as a special case. When this
|
||||
The model name "generic" is treated as a special case. When this
|
||||
model is given, the driver uses the generic codec parser without
|
||||
"codec-patch". It's sometimes good for testing and debugging.
|
||||
|
||||
|
@ -285,7 +285,7 @@ sample data.
|
||||
<H4>
|
||||
7.2.4 Close Callback</H4>
|
||||
The <TT>close</TT> callback is called when this device is closed by the
|
||||
applicaion. If any private data was allocated in open callback, it must
|
||||
application. If any private data was allocated in open callback, it must
|
||||
be released in the close callback. The deletion of ALSA port should be
|
||||
done here, too. This callback must not be NULL.
|
||||
<H4>
|
||||
|
@ -3144,7 +3144,7 @@ static unsigned int convert_to_spdif_status(unsigned short val)
|
||||
if (val & AC_DIG1_PROFESSIONAL)
|
||||
sbits |= IEC958_AES0_PROFESSIONAL;
|
||||
if (sbits & IEC958_AES0_PROFESSIONAL) {
|
||||
if (sbits & AC_DIG1_EMPHASIS)
|
||||
if (val & AC_DIG1_EMPHASIS)
|
||||
sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
|
||||
} else {
|
||||
if (val & AC_DIG1_EMPHASIS)
|
||||
|
@ -995,6 +995,8 @@ enum {
|
||||
BAD_NO_EXTRA_SURR_DAC = 0x101,
|
||||
/* Primary DAC shared with main surrounds */
|
||||
BAD_SHARED_SURROUND = 0x100,
|
||||
/* No independent HP possible */
|
||||
BAD_NO_INDEP_HP = 0x40,
|
||||
/* Primary DAC shared with main CLFE */
|
||||
BAD_SHARED_CLFE = 0x10,
|
||||
/* Primary DAC shared with extra surrounds */
|
||||
@ -1392,6 +1394,43 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
|
||||
return snd_hda_get_path_idx(codec, path);
|
||||
}
|
||||
|
||||
/* check whether the independent HP is available with the current config */
|
||||
static bool indep_hp_possible(struct hda_codec *codec)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
struct auto_pin_cfg *cfg = &spec->autocfg;
|
||||
struct nid_path *path;
|
||||
int i, idx;
|
||||
|
||||
if (cfg->line_out_type == AUTO_PIN_HP_OUT)
|
||||
idx = spec->out_paths[0];
|
||||
else
|
||||
idx = spec->hp_paths[0];
|
||||
path = snd_hda_get_path_from_idx(codec, idx);
|
||||
if (!path)
|
||||
return false;
|
||||
|
||||
/* assume no path conflicts unless aamix is involved */
|
||||
if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
|
||||
return true;
|
||||
|
||||
/* check whether output paths contain aamix */
|
||||
for (i = 0; i < cfg->line_outs; i++) {
|
||||
if (spec->out_paths[i] == idx)
|
||||
break;
|
||||
path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
|
||||
if (path && is_nid_contained(path, spec->mixer_nid))
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < cfg->speaker_outs; i++) {
|
||||
path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
|
||||
if (path && is_nid_contained(path, spec->mixer_nid))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* fill the empty entries in the dac array for speaker/hp with the
|
||||
* shared dac pointed by the paths
|
||||
*/
|
||||
@ -1545,6 +1584,9 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
|
||||
badness += BAD_MULTI_IO;
|
||||
}
|
||||
|
||||
if (spec->indep_hp && !indep_hp_possible(codec))
|
||||
badness += BAD_NO_INDEP_HP;
|
||||
|
||||
/* re-fill the shared DAC for speaker / headphone */
|
||||
if (cfg->line_out_type != AUTO_PIN_HP_OUT)
|
||||
refill_shared_dacs(codec, cfg->hp_outs,
|
||||
@ -1758,6 +1800,10 @@ static int parse_output_paths(struct hda_codec *codec)
|
||||
cfg->speaker_pins, val);
|
||||
}
|
||||
|
||||
/* clear indep_hp flag if not available */
|
||||
if (spec->indep_hp && !indep_hp_possible(codec))
|
||||
spec->indep_hp = 0;
|
||||
|
||||
kfree(best_cfg);
|
||||
return 0;
|
||||
}
|
||||
|
@ -415,6 +415,8 @@ struct azx_dev {
|
||||
unsigned int opened :1;
|
||||
unsigned int running :1;
|
||||
unsigned int irq_pending :1;
|
||||
unsigned int prepared:1;
|
||||
unsigned int locked:1;
|
||||
/*
|
||||
* For VIA:
|
||||
* A flag to ensure DMA position is 0
|
||||
@ -426,8 +428,25 @@ struct azx_dev {
|
||||
|
||||
struct timecounter azx_tc;
|
||||
struct cyclecounter azx_cc;
|
||||
|
||||
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
||||
struct mutex dsp_mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* DSP lock helpers */
|
||||
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
||||
#define dsp_lock_init(dev) mutex_init(&(dev)->dsp_mutex)
|
||||
#define dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex)
|
||||
#define dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex)
|
||||
#define dsp_is_locked(dev) ((dev)->locked)
|
||||
#else
|
||||
#define dsp_lock_init(dev) do {} while (0)
|
||||
#define dsp_lock(dev) do {} while (0)
|
||||
#define dsp_unlock(dev) do {} while (0)
|
||||
#define dsp_is_locked(dev) 0
|
||||
#endif
|
||||
|
||||
/* CORB/RIRB */
|
||||
struct azx_rb {
|
||||
u32 *buf; /* CORB/RIRB buffer
|
||||
@ -527,6 +546,10 @@ struct azx {
|
||||
|
||||
/* card list (for power_save trigger) */
|
||||
struct list_head list;
|
||||
|
||||
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
||||
struct azx_dev saved_azx_dev;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
@ -1793,15 +1816,25 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream)
|
||||
dev = chip->capture_index_offset;
|
||||
nums = chip->capture_streams;
|
||||
}
|
||||
for (i = 0; i < nums; i++, dev++)
|
||||
if (!chip->azx_dev[dev].opened) {
|
||||
res = &chip->azx_dev[dev];
|
||||
if (res->assigned_key == key)
|
||||
break;
|
||||
for (i = 0; i < nums; i++, dev++) {
|
||||
struct azx_dev *azx_dev = &chip->azx_dev[dev];
|
||||
dsp_lock(azx_dev);
|
||||
if (!azx_dev->opened && !dsp_is_locked(azx_dev)) {
|
||||
res = azx_dev;
|
||||
if (res->assigned_key == key) {
|
||||
res->opened = 1;
|
||||
res->assigned_key = key;
|
||||
dsp_unlock(azx_dev);
|
||||
return azx_dev;
|
||||
}
|
||||
}
|
||||
dsp_unlock(azx_dev);
|
||||
}
|
||||
if (res) {
|
||||
dsp_lock(res);
|
||||
res->opened = 1;
|
||||
res->assigned_key = key;
|
||||
dsp_unlock(res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -2009,6 +2042,12 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct azx_dev *azx_dev = get_azx_dev(substream);
|
||||
int ret;
|
||||
|
||||
dsp_lock(azx_dev);
|
||||
if (dsp_is_locked(azx_dev)) {
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
mark_runtime_wc(chip, azx_dev, substream, false);
|
||||
azx_dev->bufsize = 0;
|
||||
azx_dev->period_bytes = 0;
|
||||
@ -2016,8 +2055,10 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
ret = snd_pcm_lib_malloc_pages(substream,
|
||||
params_buffer_bytes(hw_params));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto unlock;
|
||||
mark_runtime_wc(chip, azx_dev, substream, true);
|
||||
unlock:
|
||||
dsp_unlock(azx_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2029,16 +2070,21 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
|
||||
|
||||
/* reset BDL address */
|
||||
azx_sd_writel(azx_dev, SD_BDLPL, 0);
|
||||
azx_sd_writel(azx_dev, SD_BDLPU, 0);
|
||||
azx_sd_writel(azx_dev, SD_CTL, 0);
|
||||
azx_dev->bufsize = 0;
|
||||
azx_dev->period_bytes = 0;
|
||||
azx_dev->format_val = 0;
|
||||
dsp_lock(azx_dev);
|
||||
if (!dsp_is_locked(azx_dev)) {
|
||||
azx_sd_writel(azx_dev, SD_BDLPL, 0);
|
||||
azx_sd_writel(azx_dev, SD_BDLPU, 0);
|
||||
azx_sd_writel(azx_dev, SD_CTL, 0);
|
||||
azx_dev->bufsize = 0;
|
||||
azx_dev->period_bytes = 0;
|
||||
azx_dev->format_val = 0;
|
||||
}
|
||||
|
||||
snd_hda_codec_cleanup(apcm->codec, hinfo, substream);
|
||||
|
||||
mark_runtime_wc(chip, azx_dev, substream, false);
|
||||
azx_dev->prepared = 0;
|
||||
dsp_unlock(azx_dev);
|
||||
return snd_pcm_lib_free_pages(substream);
|
||||
}
|
||||
|
||||
@ -2055,6 +2101,12 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid);
|
||||
unsigned short ctls = spdif ? spdif->ctls : 0;
|
||||
|
||||
dsp_lock(azx_dev);
|
||||
if (dsp_is_locked(azx_dev)) {
|
||||
err = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
azx_stream_reset(chip, azx_dev);
|
||||
format_val = snd_hda_calc_stream_format(runtime->rate,
|
||||
runtime->channels,
|
||||
@ -2065,7 +2117,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
snd_printk(KERN_ERR SFX
|
||||
"%s: invalid format_val, rate=%d, ch=%d, format=%d\n",
|
||||
pci_name(chip->pci), runtime->rate, runtime->channels, runtime->format);
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
bufsize = snd_pcm_lib_buffer_bytes(substream);
|
||||
@ -2084,7 +2137,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
azx_dev->no_period_wakeup = runtime->no_period_wakeup;
|
||||
err = azx_setup_periods(chip, substream, azx_dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* wallclk has 24Mhz clock source */
|
||||
@ -2101,8 +2154,14 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) &&
|
||||
stream_tag > chip->capture_streams)
|
||||
stream_tag -= chip->capture_streams;
|
||||
return snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag,
|
||||
err = snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag,
|
||||
azx_dev->format_val, substream);
|
||||
|
||||
unlock:
|
||||
if (!err)
|
||||
azx_dev->prepared = 1;
|
||||
dsp_unlock(azx_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
@ -2117,6 +2176,9 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
azx_dev = get_azx_dev(substream);
|
||||
trace_azx_pcm_trigger(chip, azx_dev, cmd);
|
||||
|
||||
if (dsp_is_locked(azx_dev) || !azx_dev->prepared)
|
||||
return -EPIPE;
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
rstart = 1;
|
||||
@ -2621,17 +2683,27 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
|
||||
struct azx_dev *azx_dev;
|
||||
int err;
|
||||
|
||||
if (snd_hda_lock_devices(bus))
|
||||
return -EBUSY;
|
||||
azx_dev = azx_get_dsp_loader_dev(chip);
|
||||
|
||||
dsp_lock(azx_dev);
|
||||
spin_lock_irq(&chip->reg_lock);
|
||||
if (azx_dev->running || azx_dev->locked) {
|
||||
spin_unlock_irq(&chip->reg_lock);
|
||||
err = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
azx_dev->prepared = 0;
|
||||
chip->saved_azx_dev = *azx_dev;
|
||||
azx_dev->locked = 1;
|
||||
spin_unlock_irq(&chip->reg_lock);
|
||||
|
||||
err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG,
|
||||
snd_dma_pci_data(chip->pci),
|
||||
byte_size, bufp);
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
goto err_alloc;
|
||||
|
||||
mark_pages_wc(chip, bufp, true);
|
||||
azx_dev = azx_get_dsp_loader_dev(chip);
|
||||
azx_dev->bufsize = byte_size;
|
||||
azx_dev->period_bytes = byte_size;
|
||||
azx_dev->format_val = format;
|
||||
@ -2649,13 +2721,20 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
|
||||
goto error;
|
||||
|
||||
azx_setup_controller(chip, azx_dev);
|
||||
dsp_unlock(azx_dev);
|
||||
return azx_dev->stream_tag;
|
||||
|
||||
error:
|
||||
mark_pages_wc(chip, bufp, false);
|
||||
snd_dma_free_pages(bufp);
|
||||
unlock:
|
||||
snd_hda_unlock_devices(bus);
|
||||
err_alloc:
|
||||
spin_lock_irq(&chip->reg_lock);
|
||||
if (azx_dev->opened)
|
||||
*azx_dev = chip->saved_azx_dev;
|
||||
azx_dev->locked = 0;
|
||||
spin_unlock_irq(&chip->reg_lock);
|
||||
unlock:
|
||||
dsp_unlock(azx_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -2677,9 +2756,10 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus,
|
||||
struct azx *chip = bus->private_data;
|
||||
struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);
|
||||
|
||||
if (!dmab->area)
|
||||
if (!dmab->area || !azx_dev->locked)
|
||||
return;
|
||||
|
||||
dsp_lock(azx_dev);
|
||||
/* reset BDL address */
|
||||
azx_sd_writel(azx_dev, SD_BDLPL, 0);
|
||||
azx_sd_writel(azx_dev, SD_BDLPU, 0);
|
||||
@ -2692,7 +2772,12 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus,
|
||||
snd_dma_free_pages(dmab);
|
||||
dmab->area = NULL;
|
||||
|
||||
snd_hda_unlock_devices(bus);
|
||||
spin_lock_irq(&chip->reg_lock);
|
||||
if (azx_dev->opened)
|
||||
*azx_dev = chip->saved_azx_dev;
|
||||
azx_dev->locked = 0;
|
||||
spin_unlock_irq(&chip->reg_lock);
|
||||
dsp_unlock(azx_dev);
|
||||
}
|
||||
#endif /* CONFIG_SND_HDA_DSP_LOADER */
|
||||
|
||||
@ -3481,6 +3566,7 @@ static int azx_first_init(struct azx *chip)
|
||||
}
|
||||
|
||||
for (i = 0; i < chip->num_streams; i++) {
|
||||
dsp_lock_init(&chip->azx_dev[i]);
|
||||
/* allocate memory for the BDL for each stream */
|
||||
err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
|
||||
snd_dma_pci_data(chip->pci),
|
||||
|
@ -168,10 +168,10 @@ static void cs_automute(struct hda_codec *codec)
|
||||
snd_hda_gen_update_outputs(codec);
|
||||
|
||||
if (spec->gpio_eapd_hp) {
|
||||
unsigned int gpio = spec->gen.hp_jack_present ?
|
||||
spec->gpio_data = spec->gen.hp_jack_present ?
|
||||
spec->gpio_eapd_hp : spec->gpio_eapd_speaker;
|
||||
snd_hda_codec_write(codec, 0x01, 0,
|
||||
AC_VERB_SET_GPIO_DATA, gpio);
|
||||
AC_VERB_SET_GPIO_DATA, spec->gpio_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1142,7 +1142,7 @@ static int patch_cxt5045(struct hda_codec *codec)
|
||||
}
|
||||
|
||||
if (spec->beep_amp)
|
||||
snd_hda_attach_beep_device(codec, spec->beep_amp);
|
||||
snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1921,7 +1921,7 @@ static int patch_cxt5051(struct hda_codec *codec)
|
||||
}
|
||||
|
||||
if (spec->beep_amp)
|
||||
snd_hda_attach_beep_device(codec, spec->beep_amp);
|
||||
snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3099,7 +3099,7 @@ static int patch_cxt5066(struct hda_codec *codec)
|
||||
}
|
||||
|
||||
if (spec->beep_amp)
|
||||
snd_hda_attach_beep_device(codec, spec->beep_amp);
|
||||
snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3191,11 +3191,17 @@ static int cx_auto_build_controls(struct hda_codec *codec)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cx_auto_free(struct hda_codec *codec)
|
||||
{
|
||||
snd_hda_detach_beep_device(codec);
|
||||
snd_hda_gen_free(codec);
|
||||
}
|
||||
|
||||
static const struct hda_codec_ops cx_auto_patch_ops = {
|
||||
.build_controls = cx_auto_build_controls,
|
||||
.build_pcms = snd_hda_gen_build_pcms,
|
||||
.init = snd_hda_gen_init,
|
||||
.free = snd_hda_gen_free,
|
||||
.free = cx_auto_free,
|
||||
.unsol_event = snd_hda_jack_unsol_event,
|
||||
#ifdef CONFIG_PM
|
||||
.check_power_status = snd_hda_gen_check_power_status,
|
||||
@ -3391,7 +3397,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
||||
|
||||
codec->patch_ops = cx_auto_patch_ops;
|
||||
if (spec->beep_amp)
|
||||
snd_hda_attach_beep_device(codec, spec->beep_amp);
|
||||
snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
|
||||
|
||||
/* Some laptops with Conexant chips show stalls in S3 resume,
|
||||
* which falls into the single-cmd mode.
|
||||
|
@ -715,8 +715,9 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
|
||||
case UAC2_CLOCK_SELECTOR: {
|
||||
struct uac_selector_unit_descriptor *d = p1;
|
||||
/* call recursively to retrieve the channel info */
|
||||
if (check_input_term(state, d->baSourceID[0], term) < 0)
|
||||
return -ENODEV;
|
||||
err = check_input_term(state, d->baSourceID[0], term);
|
||||
if (err < 0)
|
||||
return err;
|
||||
term->type = d->bDescriptorSubtype << 16; /* virtual type */
|
||||
term->id = id;
|
||||
term->name = uac_selector_unit_iSelector(d);
|
||||
@ -725,7 +726,8 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
|
||||
case UAC1_PROCESSING_UNIT:
|
||||
case UAC1_EXTENSION_UNIT:
|
||||
/* UAC2_PROCESSING_UNIT_V2 */
|
||||
/* UAC2_EFFECT_UNIT */ {
|
||||
/* UAC2_EFFECT_UNIT */
|
||||
case UAC2_EXTENSION_UNIT_V2: {
|
||||
struct uac_processing_unit_descriptor *d = p1;
|
||||
|
||||
if (state->mixer->protocol == UAC_VERSION_2 &&
|
||||
@ -1356,8 +1358,9 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
|
||||
return err;
|
||||
|
||||
/* determine the input source type and name */
|
||||
if (check_input_term(state, hdr->bSourceID, &iterm) < 0)
|
||||
return -EINVAL;
|
||||
err = check_input_term(state, hdr->bSourceID, &iterm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
master_bits = snd_usb_combine_bytes(bmaControls, csize);
|
||||
/* master configuration quirks */
|
||||
@ -2052,6 +2055,8 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
|
||||
return parse_audio_extension_unit(state, unitid, p1);
|
||||
else /* UAC_VERSION_2 */
|
||||
return parse_audio_processing_unit(state, unitid, p1);
|
||||
case UAC2_EXTENSION_UNIT_V2:
|
||||
return parse_audio_extension_unit(state, unitid, p1);
|
||||
default:
|
||||
snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
|
||||
return -EINVAL;
|
||||
@ -2118,7 +2123,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
|
||||
state.oterm.type = le16_to_cpu(desc->wTerminalType);
|
||||
state.oterm.name = desc->iTerminal;
|
||||
err = parse_audio_unit(&state, desc->bSourceID);
|
||||
if (err < 0)
|
||||
if (err < 0 && err != -EINVAL)
|
||||
return err;
|
||||
} else { /* UAC_VERSION_2 */
|
||||
struct uac2_output_terminal_descriptor *desc = p;
|
||||
@ -2130,12 +2135,12 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
|
||||
state.oterm.type = le16_to_cpu(desc->wTerminalType);
|
||||
state.oterm.name = desc->iTerminal;
|
||||
err = parse_audio_unit(&state, desc->bSourceID);
|
||||
if (err < 0)
|
||||
if (err < 0 && err != -EINVAL)
|
||||
return err;
|
||||
|
||||
/* for UAC2, use the same approach to also add the clock selectors */
|
||||
err = parse_audio_unit(&state, desc->bCSourceID);
|
||||
if (err < 0)
|
||||
if (err < 0 && err != -EINVAL)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user