Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70dc52fa authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 1e0695cb 55a63d4d
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -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
    models depending on the codec chip.  The list of available models
    is found in HD-Audio-Models.txt
    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
    model is given, the driver uses the generic codec parser without
    "codec-patch".  It's sometimes good for testing and debugging.
    "codec-patch".  It's sometimes good for testing and debugging.


+1 −1
Original line number Original line Diff line number Diff line
@@ -285,7 +285,7 @@ sample data.
<H4>
<H4>
7.2.4 Close Callback</H4>
7.2.4 Close Callback</H4>
The <TT>close</TT> callback is called when this device is closed by the
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
be released in the close callback. The deletion of ALSA port should be
done here, too. This callback must not be NULL.
done here, too. This callback must not be NULL.
<H4>
<H4>
+1 −1
Original line number Original line Diff line number Diff line
@@ -3144,7 +3144,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)
+46 −0
Original line number Original line Diff line number Diff line
@@ -995,6 +995,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 */
@@ -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);
	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
 */
 */
@@ -1545,6 +1584,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,
@@ -1758,6 +1800,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;
}
}
+109 −23
Original line number Original line Diff line number Diff line
@@ -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 {


	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 {


	/* 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)
		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,
	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,
	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)
	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)
		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)
		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)
		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)
	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)
	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,
	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,
		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);
 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:
 unlock:
	snd_hda_unlock_devices(bus);
	dsp_unlock(azx_dev);
	return err;
	return err;
}
}


@@ -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,
	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)
	}
	}


	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),
Loading