Commit 10d74107 authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'for-linus' into for-next

Merge back for-linus branch for the badness table adjustment for VIA codecs

* for-linus:
  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
parents f390dad4 55a63d4d
...@@ -3141,7 +3141,7 @@ static unsigned int convert_to_spdif_status(unsigned short val) ...@@ -3141,7 +3141,7 @@ static unsigned int convert_to_spdif_status(unsigned short val)
if (val & AC_DIG1_PROFESSIONAL) if (val & AC_DIG1_PROFESSIONAL)
sbits |= IEC958_AES0_PROFESSIONAL; sbits |= IEC958_AES0_PROFESSIONAL;
if (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; sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
} else { } else {
if (val & AC_DIG1_EMPHASIS) if (val & AC_DIG1_EMPHASIS)
......
...@@ -1006,6 +1006,8 @@ enum { ...@@ -1006,6 +1006,8 @@ enum {
BAD_NO_EXTRA_SURR_DAC = 0x101, BAD_NO_EXTRA_SURR_DAC = 0x101,
/* Primary DAC shared with main surrounds */ /* Primary DAC shared with main surrounds */
BAD_SHARED_SURROUND = 0x100, BAD_SHARED_SURROUND = 0x100,
/* No independent HP possible */
BAD_NO_INDEP_HP = 0x40,
/* Primary DAC shared with main CLFE */ /* Primary DAC shared with main CLFE */
BAD_SHARED_CLFE = 0x10, BAD_SHARED_CLFE = 0x10,
/* Primary DAC shared with extra surrounds */ /* Primary DAC shared with extra surrounds */
...@@ -1403,6 +1405,43 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx) ...@@ -1403,6 +1405,43 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
return snd_hda_get_path_idx(codec, path); 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 /* fill the empty entries in the dac array for speaker/hp with the
* shared dac pointed by the paths * shared dac pointed by the paths
*/ */
...@@ -1556,6 +1595,9 @@ static int fill_and_eval_dacs(struct hda_codec *codec, ...@@ -1556,6 +1595,9 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
badness += BAD_MULTI_IO; 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 */ /* re-fill the shared DAC for speaker / headphone */
if (cfg->line_out_type != AUTO_PIN_HP_OUT) if (cfg->line_out_type != AUTO_PIN_HP_OUT)
refill_shared_dacs(codec, cfg->hp_outs, refill_shared_dacs(codec, cfg->hp_outs,
...@@ -1769,6 +1811,10 @@ static int parse_output_paths(struct hda_codec *codec) ...@@ -1769,6 +1811,10 @@ static int parse_output_paths(struct hda_codec *codec)
cfg->speaker_pins, val); 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); kfree(best_cfg);
return 0; return 0;
} }
......
...@@ -415,6 +415,8 @@ struct azx_dev { ...@@ -415,6 +415,8 @@ struct azx_dev {
unsigned int opened :1; unsigned int opened :1;
unsigned int running :1; unsigned int running :1;
unsigned int irq_pending :1; unsigned int irq_pending :1;
unsigned int prepared:1;
unsigned int locked:1;
/* /*
* For VIA: * For VIA:
* A flag to ensure DMA position is 0 * A flag to ensure DMA position is 0
...@@ -426,8 +428,25 @@ struct azx_dev { ...@@ -426,8 +428,25 @@ struct azx_dev {
struct timecounter azx_tc; struct timecounter azx_tc;
struct cyclecounter azx_cc; 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 */ /* CORB/RIRB */
struct azx_rb { struct azx_rb {
u32 *buf; /* CORB/RIRB buffer u32 *buf; /* CORB/RIRB buffer
...@@ -527,6 +546,10 @@ struct azx { ...@@ -527,6 +546,10 @@ struct azx {
/* card list (for power_save trigger) */ /* card list (for power_save trigger) */
struct list_head list; struct list_head list;
#ifdef CONFIG_SND_HDA_DSP_LOADER
struct azx_dev saved_azx_dev;
#endif
}; };
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
...@@ -1793,15 +1816,25 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) ...@@ -1793,15 +1816,25 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream)
dev = chip->capture_index_offset; dev = chip->capture_index_offset;
nums = chip->capture_streams; nums = chip->capture_streams;
} }
for (i = 0; i < nums; i++, dev++) for (i = 0; i < nums; i++, dev++) {
if (!chip->azx_dev[dev].opened) { struct azx_dev *azx_dev = &chip->azx_dev[dev];
res = &chip->azx_dev[dev]; dsp_lock(azx_dev);
if (res->assigned_key == key) if (!azx_dev->opened && !dsp_is_locked(azx_dev)) {
break; 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) { if (res) {
dsp_lock(res);
res->opened = 1; res->opened = 1;
res->assigned_key = key; res->assigned_key = key;
dsp_unlock(res);
} }
return res; return res;
} }
...@@ -2009,6 +2042,12 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -2009,6 +2042,12 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
struct azx_dev *azx_dev = get_azx_dev(substream); struct azx_dev *azx_dev = get_azx_dev(substream);
int ret; int ret;
dsp_lock(azx_dev);
if (dsp_is_locked(azx_dev)) {
ret = -EBUSY;
goto unlock;
}
mark_runtime_wc(chip, azx_dev, substream, false); mark_runtime_wc(chip, azx_dev, substream, false);
azx_dev->bufsize = 0; azx_dev->bufsize = 0;
azx_dev->period_bytes = 0; azx_dev->period_bytes = 0;
...@@ -2016,8 +2055,10 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -2016,8 +2055,10 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
ret = snd_pcm_lib_malloc_pages(substream, ret = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params)); params_buffer_bytes(hw_params));
if (ret < 0) if (ret < 0)
return ret; goto unlock;
mark_runtime_wc(chip, azx_dev, substream, true); mark_runtime_wc(chip, azx_dev, substream, true);
unlock:
dsp_unlock(azx_dev);
return ret; return ret;
} }
...@@ -2029,16 +2070,21 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) ...@@ -2029,16 +2070,21 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
/* reset BDL address */ /* reset BDL address */
dsp_lock(azx_dev);
if (!dsp_is_locked(azx_dev)) {
azx_sd_writel(azx_dev, SD_BDLPL, 0); azx_sd_writel(azx_dev, SD_BDLPL, 0);
azx_sd_writel(azx_dev, SD_BDLPU, 0); azx_sd_writel(azx_dev, SD_BDLPU, 0);
azx_sd_writel(azx_dev, SD_CTL, 0); azx_sd_writel(azx_dev, SD_CTL, 0);
azx_dev->bufsize = 0; azx_dev->bufsize = 0;
azx_dev->period_bytes = 0; azx_dev->period_bytes = 0;
azx_dev->format_val = 0; azx_dev->format_val = 0;
}
snd_hda_codec_cleanup(apcm->codec, hinfo, substream); snd_hda_codec_cleanup(apcm->codec, hinfo, substream);
mark_runtime_wc(chip, azx_dev, substream, false); mark_runtime_wc(chip, azx_dev, substream, false);
azx_dev->prepared = 0;
dsp_unlock(azx_dev);
return snd_pcm_lib_free_pages(substream); return snd_pcm_lib_free_pages(substream);
} }
...@@ -2055,6 +2101,12 @@ static int azx_pcm_prepare(struct snd_pcm_substream *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); snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid);
unsigned short ctls = spdif ? spdif->ctls : 0; 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); azx_stream_reset(chip, azx_dev);
format_val = snd_hda_calc_stream_format(runtime->rate, format_val = snd_hda_calc_stream_format(runtime->rate,
runtime->channels, runtime->channels,
...@@ -2065,7 +2117,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -2065,7 +2117,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
snd_printk(KERN_ERR SFX snd_printk(KERN_ERR SFX
"%s: invalid format_val, rate=%d, ch=%d, format=%d\n", "%s: invalid format_val, rate=%d, ch=%d, format=%d\n",
pci_name(chip->pci), runtime->rate, runtime->channels, runtime->format); pci_name(chip->pci), runtime->rate, runtime->channels, runtime->format);
return -EINVAL; err = -EINVAL;
goto unlock;
} }
bufsize = snd_pcm_lib_buffer_bytes(substream); bufsize = snd_pcm_lib_buffer_bytes(substream);
...@@ -2084,7 +2137,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -2084,7 +2137,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
azx_dev->no_period_wakeup = runtime->no_period_wakeup; azx_dev->no_period_wakeup = runtime->no_period_wakeup;
err = azx_setup_periods(chip, substream, azx_dev); err = azx_setup_periods(chip, substream, azx_dev);
if (err < 0) if (err < 0)
return err; goto unlock;
} }
/* wallclk has 24Mhz clock source */ /* wallclk has 24Mhz clock source */
...@@ -2101,8 +2154,14 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -2101,8 +2154,14 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) && if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) &&
stream_tag > chip->capture_streams) stream_tag > chip->capture_streams)
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); 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) 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) ...@@ -2117,6 +2176,9 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
azx_dev = get_azx_dev(substream); azx_dev = get_azx_dev(substream);
trace_azx_pcm_trigger(chip, azx_dev, cmd); trace_azx_pcm_trigger(chip, azx_dev, cmd);
if (dsp_is_locked(azx_dev) || !azx_dev->prepared)
return -EPIPE;
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
rstart = 1; rstart = 1;
...@@ -2621,17 +2683,27 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, ...@@ -2621,17 +2683,27 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
struct azx_dev *azx_dev; struct azx_dev *azx_dev;
int err; int err;
if (snd_hda_lock_devices(bus)) azx_dev = azx_get_dsp_loader_dev(chip);
return -EBUSY;
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, err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG,
snd_dma_pci_data(chip->pci), snd_dma_pci_data(chip->pci),
byte_size, bufp); byte_size, bufp);
if (err < 0) if (err < 0)
goto unlock; goto err_alloc;
mark_pages_wc(chip, bufp, true); mark_pages_wc(chip, bufp, true);
azx_dev = azx_get_dsp_loader_dev(chip);
azx_dev->bufsize = byte_size; azx_dev->bufsize = byte_size;
azx_dev->period_bytes = byte_size; azx_dev->period_bytes = byte_size;
azx_dev->format_val = format; azx_dev->format_val = format;
...@@ -2649,13 +2721,20 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, ...@@ -2649,13 +2721,20 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
goto error; goto error;
azx_setup_controller(chip, azx_dev); azx_setup_controller(chip, azx_dev);
dsp_unlock(azx_dev);
return azx_dev->stream_tag; return azx_dev->stream_tag;
error: error:
mark_pages_wc(chip, bufp, false); mark_pages_wc(chip, bufp, false);
snd_dma_free_pages(bufp); snd_dma_free_pages(bufp);
unlock: err_alloc:
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);
unlock:
dsp_unlock(azx_dev);
return err; return err;
} }
...@@ -2677,9 +2756,10 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus, ...@@ -2677,9 +2756,10 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus,
struct azx *chip = bus->private_data; struct azx *chip = bus->private_data;
struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);
if (!dmab->area) if (!dmab->area || !azx_dev->locked)
return; return;
dsp_lock(azx_dev);
/* reset BDL address */ /* reset BDL address */
azx_sd_writel(azx_dev, SD_BDLPL, 0); azx_sd_writel(azx_dev, SD_BDLPL, 0);
azx_sd_writel(azx_dev, SD_BDLPU, 0); azx_sd_writel(azx_dev, SD_BDLPU, 0);
...@@ -2692,7 +2772,12 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus, ...@@ -2692,7 +2772,12 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus,
snd_dma_free_pages(dmab); snd_dma_free_pages(dmab);
dmab->area = NULL; 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 */ #endif /* CONFIG_SND_HDA_DSP_LOADER */
...@@ -3481,6 +3566,7 @@ static int azx_first_init(struct azx *chip) ...@@ -3481,6 +3566,7 @@ static int azx_first_init(struct azx *chip)
} }
for (i = 0; i < chip->num_streams; i++) { for (i = 0; i < chip->num_streams; i++) {
dsp_lock_init(&chip->azx_dev[i]);
/* allocate memory for the BDL for each stream */ /* allocate memory for the BDL for each stream */
err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(chip->pci), snd_dma_pci_data(chip->pci),
......
...@@ -168,10 +168,10 @@ static void cs_automute(struct hda_codec *codec) ...@@ -168,10 +168,10 @@ static void cs_automute(struct hda_codec *codec)
snd_hda_gen_update_outputs(codec); snd_hda_gen_update_outputs(codec);
if (spec->gpio_eapd_hp) { 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; spec->gpio_eapd_hp : spec->gpio_eapd_speaker;
snd_hda_codec_write(codec, 0x01, 0, snd_hda_codec_write(codec, 0x01, 0,
AC_VERB_SET_GPIO_DATA, gpio); AC_VERB_SET_GPIO_DATA, spec->gpio_data);
} }
} }
......
...@@ -715,8 +715,9 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_ ...@@ -715,8 +715,9 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
case UAC2_CLOCK_SELECTOR: { case UAC2_CLOCK_SELECTOR: {
struct uac_selector_unit_descriptor *d = p1; struct uac_selector_unit_descriptor *d = p1;
/* call recursively to retrieve the channel info */ /* call recursively to retrieve the channel info */
if (check_input_term(state, d->baSourceID[0], term) < 0) err = check_input_term(state, d->baSourceID[0], term);
return -ENODEV; if (err < 0)
return err;
term->type = d->bDescriptorSubtype << 16; /* virtual type */ term->type = d->bDescriptorSubtype << 16; /* virtual type */
term->id = id; term->id = id;
term->name = uac_selector_unit_iSelector(d); 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_ ...@@ -725,7 +726,8 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
case UAC1_PROCESSING_UNIT: case UAC1_PROCESSING_UNIT:
case UAC1_EXTENSION_UNIT: case UAC1_EXTENSION_UNIT:
/* UAC2_PROCESSING_UNIT_V2 */ /* UAC2_PROCESSING_UNIT_V2 */
/* UAC2_EFFECT_UNIT */ { /* UAC2_EFFECT_UNIT */
case UAC2_EXTENSION_UNIT_V2: {
struct uac_processing_unit_descriptor *d = p1; struct uac_processing_unit_descriptor *d = p1;
if (state->mixer->protocol == UAC_VERSION_2 && if (state->mixer->protocol == UAC_VERSION_2 &&
...@@ -1356,8 +1358,9 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void ...@@ -1356,8 +1358,9 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
return err; return err;
/* determine the input source type and name */ /* determine the input source type and name */
if (check_input_term(state, hdr->bSourceID, &iterm) < 0) err = check_input_term(state, hdr->bSourceID, &iterm);
return -EINVAL; if (err < 0)
return err;
master_bits = snd_usb_combine_bytes(bmaControls, csize); master_bits = snd_usb_combine_bytes(bmaControls, csize);
/* master configuration quirks */ /* master configuration quirks */
...@@ -2052,6 +2055,8 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) ...@@ -2052,6 +2055,8 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
return parse_audio_extension_unit(state, unitid, p1); return parse_audio_extension_unit(state, unitid, p1);
else /* UAC_VERSION_2 */ else /* UAC_VERSION_2 */
return parse_audio_processing_unit(state, unitid, p1); return parse_audio_processing_unit(state, unitid, p1);
case UAC2_EXTENSION_UNIT_V2:
return parse_audio_extension_unit(state, unitid, p1);
default: default:
snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]); snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
return -EINVAL; return -EINVAL;
...@@ -2118,7 +2123,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) ...@@ -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.type = le16_to_cpu(desc->wTerminalType);
state.oterm.name = desc->iTerminal; state.oterm.name = desc->iTerminal;
err = parse_audio_unit(&state, desc->bSourceID); err = parse_audio_unit(&state, desc->bSourceID);
if (err < 0) if (err < 0 && err != -EINVAL)
return err; return err;
} else { /* UAC_VERSION_2 */ } else { /* UAC_VERSION_2 */
struct uac2_output_terminal_descriptor *desc = p; struct uac2_output_terminal_descriptor *desc = p;
...@@ -2130,12 +2135,12 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) ...@@ -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.type = le16_to_cpu(desc->wTerminalType);
state.oterm.name = desc->iTerminal; state.oterm.name = desc->iTerminal;
err = parse_audio_unit(&state, desc->bSourceID); err = parse_audio_unit(&state, desc->bSourceID);
if (err < 0) if (err < 0 && err != -EINVAL)
return err; return err;
/* for UAC2, use the same approach to also add the clock selectors */ /* for UAC2, use the same approach to also add the clock selectors */
err = parse_audio_unit(&state, desc->bCSourceID); err = parse_audio_unit(&state, desc->bCSourceID);
if (err < 0) if (err < 0 && err != -EINVAL)
return err; return err;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment