sound fixes for 6.0-rc5
we received lots of small fixes for various drivers at this time, hopefully it will be the last big bump before 6.0 release. The significant changes are regression fixes for (yet again) HD-audio memory allocations and USB-audio PCM parameter handling, while there are many small ASoC device-specific fixes as well as a few out-of-bounds and race issues spotted by fuzzers. -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmMZ6SMOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE+SBRAAtNWQfYY8Lk3HXWOiAGT2D+/rJE2d9ZbKcOZH cMBunn6NmJ/JP1TOnVzzwSvNB6p4rK9NFAh02rORps+j+B7EeSERYy3ODtTRsofm ilYrKQWWHMEJqreyqDibHyZJCZdTdA9uoAwmv3S8zhV5HhzRq/AO2LRY69L1S8g2 QdA7nReMJtihIIIS4P7LhNgTXdCD07V7Dtex1BCr6IZnCYOzu7UUdcHBwBSaQxjM dsyG5g3jJKtlxal3KZ7wdPvRtNeRz0cs3UHiae5QUy424Q+itj/vUVGzkUygg+SJ 4qNjvEox2wf+SbufkMWvVUxggWLQinU/GL2NhDAa+ggo+PjIRK9l/LOPxmL/Z2bM WR5oub+7ws/8RsvRLLg2GKPJnSwuNEL+KKKXtdbzHWEwllDKR1/HJtdj+UUyeq6/ 2kqPpxsAwxMo8FEScjh0AEllmLUFVclTeQRxQhIkAZ4okKB5Eakp3tVPm+dLLTH9 MQDGr/qPBjdhYzsJr15JZ8aCJdLigi7yPK7RTPgxn/ZWF9wncDUsBnZxb2A3p9ny qc85n2MdAS335kSEuRDDJHVvkjjTO1VuAfSJMx+T5bjAX9ziH6kBAMEHyBaLvI11 aPCiPPcFh/xwIJ7Hchew/1g+4Vr0yOV1hsOpQNE04ULHLNTIwD1CLeu9uZVv/o/K CwzT4ug= =LEyu -----END PGP SIGNATURE----- Merge tag 'sound-6.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "Lots of small fixes for various drivers at this time, hopefully it will be the last big bump before 6.0 release. The significant changes are regression fixes for (yet again) HD-audio memory allocations and USB-audio PCM parameter handling, while there are many small ASoC device-specific fixes as well as a few out-of-bounds and race issues spotted by fuzzers" * tag 'sound-6.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (29 commits) ALSA: usb-audio: Clear fixed clock rate at closing EP ALSA: emu10k1: Fix out of bounds access in snd_emu10k1_pcm_channel_alloc() ALSA: hda: Once again fix regression of page allocations with IOMMU ALSA: usb-audio: Fix an out-of-bounds bug in __snd_usb_parse_audio_interface() ALSA: hda/tegra: Align BDL entry to 4KB boundary ALSA: hda/sigmatel: Fix unused variable warning for beep power change ALSA: pcm: oss: Fix race at SNDCTL_DSP_SYNC ALSA: hda/sigmatel: Keep power up while beep is enabled ALSA: aloop: Fix random zeros in capture data when using jiffies timer ALSA: usb-audio: Split endpoint setups for hw_params and prepare ALSA: usb-audio: Register card again for iface over delayed_register option ALSA: usb-audio: Inform the delayed registration more properly ASoC: fsl_aud2htx: Add error handler for pm_runtime_enable ASoC: fsl_aud2htx: register platform component before registering cpu dai ASoC: SOF: ipc4-topology: fix alh_group_ida max value ASoC: mchp-spdiftx: Fix clang -Wbitfield-constant-conversion ASoC: SOF: Kconfig: Make IPC_MESSAGE_INJECTOR depend on SND_SOC_SOF ASoC: SOF: Kconfig: Make IPC_FLOOD_TEST depend on SND_SOC_SOF ASoC: fsl_mqs: Fix supported clock DAI format ASoC: nau8540: Implement hw constraint for rates ...
This commit is contained in:
commit
83dfc0e2fd
@ -543,10 +543,13 @@ static void *snd_dma_noncontig_alloc(struct snd_dma_buffer *dmab, size_t size)
|
||||
dmab->dev.need_sync = dma_need_sync(dmab->dev.dev,
|
||||
sg_dma_address(sgt->sgl));
|
||||
p = dma_vmap_noncontiguous(dmab->dev.dev, size, sgt);
|
||||
if (p)
|
||||
if (p) {
|
||||
dmab->private_data = sgt;
|
||||
else
|
||||
/* store the first page address for convenience */
|
||||
dmab->addr = snd_sgbuf_get_addr(dmab, 0);
|
||||
} else {
|
||||
dma_free_noncontiguous(dmab->dev.dev, size, sgt, dmab->dev.dir);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -780,6 +783,8 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
|
||||
if (!p)
|
||||
goto error;
|
||||
dmab->private_data = sgbuf;
|
||||
/* store the first page address for convenience */
|
||||
dmab->addr = snd_sgbuf_get_addr(dmab, 0);
|
||||
return p;
|
||||
|
||||
error:
|
||||
|
@ -1672,14 +1672,14 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
|
||||
runtime = substream->runtime;
|
||||
if (atomic_read(&substream->mmap_count))
|
||||
goto __direct;
|
||||
err = snd_pcm_oss_make_ready(substream);
|
||||
if (err < 0)
|
||||
return err;
|
||||
atomic_inc(&runtime->oss.rw_ref);
|
||||
if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
|
||||
atomic_dec(&runtime->oss.rw_ref);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
err = snd_pcm_oss_make_ready_locked(substream);
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
format = snd_pcm_oss_format_from(runtime->oss.format);
|
||||
width = snd_pcm_format_physical_width(format);
|
||||
if (runtime->oss.buffer_used > 0) {
|
||||
|
@ -605,17 +605,18 @@ static unsigned int loopback_jiffies_timer_pos_update
|
||||
cable->streams[SNDRV_PCM_STREAM_PLAYBACK];
|
||||
struct loopback_pcm *dpcm_capt =
|
||||
cable->streams[SNDRV_PCM_STREAM_CAPTURE];
|
||||
unsigned long delta_play = 0, delta_capt = 0;
|
||||
unsigned long delta_play = 0, delta_capt = 0, cur_jiffies;
|
||||
unsigned int running, count1, count2;
|
||||
|
||||
cur_jiffies = jiffies;
|
||||
running = cable->running ^ cable->pause;
|
||||
if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
|
||||
delta_play = jiffies - dpcm_play->last_jiffies;
|
||||
delta_play = cur_jiffies - dpcm_play->last_jiffies;
|
||||
dpcm_play->last_jiffies += delta_play;
|
||||
}
|
||||
|
||||
if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) {
|
||||
delta_capt = jiffies - dpcm_capt->last_jiffies;
|
||||
delta_capt = cur_jiffies - dpcm_capt->last_jiffies;
|
||||
dpcm_capt->last_jiffies += delta_capt;
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voic
|
||||
epcm->voices[0]->epcm = epcm;
|
||||
if (voices > 1) {
|
||||
for (i = 1; i < voices; i++) {
|
||||
epcm->voices[i] = &epcm->emu->voices[epcm->voices[0]->number + i];
|
||||
epcm->voices[i] = &epcm->emu->voices[(epcm->voices[0]->number + i) % NUM_G];
|
||||
epcm->voices[i]->epcm = epcm;
|
||||
}
|
||||
}
|
||||
|
@ -1817,7 +1817,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
|
||||
|
||||
/* use the non-cached pages in non-snoop mode */
|
||||
if (!azx_snoop(chip))
|
||||
azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_WC;
|
||||
azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_WC_SG;
|
||||
|
||||
if (chip->driver_type == AZX_DRIVER_NVIDIA) {
|
||||
dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
|
||||
|
@ -474,7 +474,8 @@ MODULE_DEVICE_TABLE(of, hda_tegra_match);
|
||||
static int hda_tegra_probe(struct platform_device *pdev)
|
||||
{
|
||||
const unsigned int driver_flags = AZX_DCAPS_CORBRP_SELF_CLEAR |
|
||||
AZX_DCAPS_PM_RUNTIME;
|
||||
AZX_DCAPS_PM_RUNTIME |
|
||||
AZX_DCAPS_4K_BDLE_BOUNDARY;
|
||||
struct snd_card *card;
|
||||
struct azx *chip;
|
||||
struct hda_tegra *hda;
|
||||
|
@ -209,6 +209,7 @@ struct sigmatel_spec {
|
||||
|
||||
/* beep widgets */
|
||||
hda_nid_t anabeep_nid;
|
||||
bool beep_power_on;
|
||||
|
||||
/* SPDIF-out mux */
|
||||
const char * const *spdif_labels;
|
||||
@ -4443,6 +4444,28 @@ static int stac_suspend(struct hda_codec *codec)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stac_check_power_status(struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
#ifdef CONFIG_SND_HDA_INPUT_BEEP
|
||||
struct sigmatel_spec *spec = codec->spec;
|
||||
#endif
|
||||
int ret = snd_hda_gen_check_power_status(codec, nid);
|
||||
|
||||
#ifdef CONFIG_SND_HDA_INPUT_BEEP
|
||||
if (nid == spec->gen.beep_nid && codec->beep) {
|
||||
if (codec->beep->enabled != spec->beep_power_on) {
|
||||
spec->beep_power_on = codec->beep->enabled;
|
||||
if (spec->beep_power_on)
|
||||
snd_hda_power_up_pm(codec);
|
||||
else
|
||||
snd_hda_power_down_pm(codec);
|
||||
}
|
||||
ret |= spec->beep_power_on;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#define stac_suspend NULL
|
||||
#endif /* CONFIG_PM */
|
||||
@ -4455,6 +4478,7 @@ static const struct hda_codec_ops stac_patch_ops = {
|
||||
.unsol_event = snd_hda_jack_unsol_event,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = stac_suspend,
|
||||
.check_power_status = stac_check_power_status,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -196,7 +196,7 @@ struct mchp_spdiftx_dev {
|
||||
struct clk *pclk;
|
||||
struct clk *gclk;
|
||||
unsigned int fmt;
|
||||
int gclk_enabled:1;
|
||||
unsigned int gclk_enabled:1;
|
||||
};
|
||||
|
||||
static inline int mchp_spdiftx_is_running(struct mchp_spdiftx_dev *dev)
|
||||
|
@ -1617,7 +1617,6 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
|
||||
unsigned int current_plug_status;
|
||||
unsigned int current_button_status;
|
||||
unsigned int i;
|
||||
int report = 0;
|
||||
|
||||
mutex_lock(&cs42l42->irq_lock);
|
||||
if (cs42l42->suspended) {
|
||||
@ -1711,13 +1710,15 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
|
||||
|
||||
if (current_button_status & CS42L42_M_DETECT_TF_MASK) {
|
||||
dev_dbg(cs42l42->dev, "Button released\n");
|
||||
report = 0;
|
||||
snd_soc_jack_report(cs42l42->jack, 0,
|
||||
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
|
||||
SND_JACK_BTN_2 | SND_JACK_BTN_3);
|
||||
} else if (current_button_status & CS42L42_M_DETECT_FT_MASK) {
|
||||
report = cs42l42_handle_button_press(cs42l42);
|
||||
|
||||
snd_soc_jack_report(cs42l42->jack,
|
||||
cs42l42_handle_button_press(cs42l42),
|
||||
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
|
||||
SND_JACK_BTN_2 | SND_JACK_BTN_3);
|
||||
}
|
||||
snd_soc_jack_report(cs42l42->jack, report, SND_JACK_BTN_0 | SND_JACK_BTN_1 |
|
||||
SND_JACK_BTN_2 | SND_JACK_BTN_3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,17 +357,32 @@ static const struct snd_soc_dapm_route nau8540_dapm_routes[] = {
|
||||
{"AIFTX", NULL, "Digital CH4 Mux"},
|
||||
};
|
||||
|
||||
static int nau8540_clock_check(struct nau8540 *nau8540, int rate, int osr)
|
||||
static const struct nau8540_osr_attr *
|
||||
nau8540_get_osr(struct nau8540 *nau8540)
|
||||
{
|
||||
unsigned int osr;
|
||||
|
||||
regmap_read(nau8540->regmap, NAU8540_REG_ADC_SAMPLE_RATE, &osr);
|
||||
osr &= NAU8540_ADC_OSR_MASK;
|
||||
if (osr >= ARRAY_SIZE(osr_adc_sel))
|
||||
return NULL;
|
||||
return &osr_adc_sel[osr];
|
||||
}
|
||||
|
||||
static int nau8540_dai_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
|
||||
const struct nau8540_osr_attr *osr;
|
||||
|
||||
osr = nau8540_get_osr(nau8540);
|
||||
if (!osr || !osr->osr)
|
||||
return -EINVAL;
|
||||
|
||||
if (rate * osr > CLK_ADC_MAX) {
|
||||
dev_err(nau8540->dev, "exceed the maximum frequency of CLK_ADC\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
0, CLK_ADC_MAX / osr->osr);
|
||||
}
|
||||
|
||||
static int nau8540_hw_params(struct snd_pcm_substream *substream,
|
||||
@ -375,7 +390,8 @@ static int nau8540_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int val_len = 0, osr;
|
||||
unsigned int val_len = 0;
|
||||
const struct nau8540_osr_attr *osr;
|
||||
|
||||
/* CLK_ADC = OSR * FS
|
||||
* ADC clock frequency is defined as Over Sampling Rate (OSR)
|
||||
@ -383,13 +399,14 @@ static int nau8540_hw_params(struct snd_pcm_substream *substream,
|
||||
* values must be selected such that the maximum frequency is less
|
||||
* than 6.144 MHz.
|
||||
*/
|
||||
regmap_read(nau8540->regmap, NAU8540_REG_ADC_SAMPLE_RATE, &osr);
|
||||
osr &= NAU8540_ADC_OSR_MASK;
|
||||
if (nau8540_clock_check(nau8540, params_rate(params), osr))
|
||||
osr = nau8540_get_osr(nau8540);
|
||||
if (!osr || !osr->osr)
|
||||
return -EINVAL;
|
||||
if (params_rate(params) * osr->osr > CLK_ADC_MAX)
|
||||
return -EINVAL;
|
||||
regmap_update_bits(nau8540->regmap, NAU8540_REG_CLOCK_SRC,
|
||||
NAU8540_CLK_ADC_SRC_MASK,
|
||||
osr_adc_sel[osr].clk_src << NAU8540_CLK_ADC_SRC_SFT);
|
||||
osr->clk_src << NAU8540_CLK_ADC_SRC_SFT);
|
||||
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
@ -515,6 +532,7 @@ static int nau8540_set_tdm_slot(struct snd_soc_dai *dai,
|
||||
|
||||
|
||||
static const struct snd_soc_dai_ops nau8540_dai_ops = {
|
||||
.startup = nau8540_dai_startup,
|
||||
.hw_params = nau8540_hw_params,
|
||||
.set_fmt = nau8540_set_fmt,
|
||||
.set_tdm_slot = nau8540_set_tdm_slot,
|
||||
|
@ -670,28 +670,40 @@ static const struct snd_soc_dapm_route nau8821_dapm_routes[] = {
|
||||
{"HPOR", NULL, "Class G"},
|
||||
};
|
||||
|
||||
static int nau8821_clock_check(struct nau8821 *nau8821,
|
||||
int stream, int rate, int osr)
|
||||
static const struct nau8821_osr_attr *
|
||||
nau8821_get_osr(struct nau8821 *nau8821, int stream)
|
||||
{
|
||||
int osrate = 0;
|
||||
unsigned int osr;
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
regmap_read(nau8821->regmap, NAU8821_R2C_DAC_CTRL1, &osr);
|
||||
osr &= NAU8821_DAC_OVERSAMPLE_MASK;
|
||||
if (osr >= ARRAY_SIZE(osr_dac_sel))
|
||||
return -EINVAL;
|
||||
osrate = osr_dac_sel[osr].osr;
|
||||
return NULL;
|
||||
return &osr_dac_sel[osr];
|
||||
} else {
|
||||
regmap_read(nau8821->regmap, NAU8821_R2B_ADC_RATE, &osr);
|
||||
osr &= NAU8821_ADC_SYNC_DOWN_MASK;
|
||||
if (osr >= ARRAY_SIZE(osr_adc_sel))
|
||||
return -EINVAL;
|
||||
osrate = osr_adc_sel[osr].osr;
|
||||
return NULL;
|
||||
return &osr_adc_sel[osr];
|
||||
}
|
||||
}
|
||||
|
||||
if (!osrate || rate * osrate > CLK_DA_AD_MAX) {
|
||||
dev_err(nau8821->dev,
|
||||
"exceed the maximum frequency of CLK_ADC or CLK_DAC");
|
||||
static int nau8821_dai_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct nau8821 *nau8821 = snd_soc_component_get_drvdata(component);
|
||||
const struct nau8821_osr_attr *osr;
|
||||
|
||||
osr = nau8821_get_osr(nau8821, substream->stream);
|
||||
if (!osr || !osr->osr)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
0, CLK_DA_AD_MAX / osr->osr);
|
||||
}
|
||||
|
||||
static int nau8821_hw_params(struct snd_pcm_substream *substream,
|
||||
@ -699,7 +711,8 @@ static int nau8821_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct nau8821 *nau8821 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int val_len = 0, osr, ctrl_val, bclk_fs, clk_div;
|
||||
unsigned int val_len = 0, ctrl_val, bclk_fs, clk_div;
|
||||
const struct nau8821_osr_attr *osr;
|
||||
|
||||
nau8821->fs = params_rate(params);
|
||||
/* CLK_DAC or CLK_ADC = OSR * FS
|
||||
@ -708,27 +721,19 @@ static int nau8821_hw_params(struct snd_pcm_substream *substream,
|
||||
* values must be selected such that the maximum frequency is less
|
||||
* than 6.144 MHz.
|
||||
*/
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
regmap_read(nau8821->regmap, NAU8821_R2C_DAC_CTRL1, &osr);
|
||||
osr &= NAU8821_DAC_OVERSAMPLE_MASK;
|
||||
if (nau8821_clock_check(nau8821, substream->stream,
|
||||
nau8821->fs, osr)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
osr = nau8821_get_osr(nau8821, substream->stream);
|
||||
if (!osr || !osr->osr)
|
||||
return -EINVAL;
|
||||
if (nau8821->fs * osr->osr > CLK_DA_AD_MAX)
|
||||
return -EINVAL;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
regmap_update_bits(nau8821->regmap, NAU8821_R03_CLK_DIVIDER,
|
||||
NAU8821_CLK_DAC_SRC_MASK,
|
||||
osr_dac_sel[osr].clk_src << NAU8821_CLK_DAC_SRC_SFT);
|
||||
} else {
|
||||
regmap_read(nau8821->regmap, NAU8821_R2B_ADC_RATE, &osr);
|
||||
osr &= NAU8821_ADC_SYNC_DOWN_MASK;
|
||||
if (nau8821_clock_check(nau8821, substream->stream,
|
||||
nau8821->fs, osr)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
osr->clk_src << NAU8821_CLK_DAC_SRC_SFT);
|
||||
else
|
||||
regmap_update_bits(nau8821->regmap, NAU8821_R03_CLK_DIVIDER,
|
||||
NAU8821_CLK_ADC_SRC_MASK,
|
||||
osr_adc_sel[osr].clk_src << NAU8821_CLK_ADC_SRC_SFT);
|
||||
}
|
||||
osr->clk_src << NAU8821_CLK_ADC_SRC_SFT);
|
||||
|
||||
/* make BCLK and LRC divde configuration if the codec as master. */
|
||||
regmap_read(nau8821->regmap, NAU8821_R1D_I2S_PCM_CTRL2, &ctrl_val);
|
||||
@ -843,6 +848,7 @@ static int nau8821_digital_mute(struct snd_soc_dai *dai, int mute,
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops nau8821_dai_ops = {
|
||||
.startup = nau8821_dai_startup,
|
||||
.hw_params = nau8821_hw_params,
|
||||
.set_fmt = nau8821_set_dai_fmt,
|
||||
.mute_stream = nau8821_digital_mute,
|
||||
|
@ -1014,27 +1014,42 @@ static irqreturn_t nau8824_interrupt(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int nau8824_clock_check(struct nau8824 *nau8824,
|
||||
int stream, int rate, int osr)
|
||||
static const struct nau8824_osr_attr *
|
||||
nau8824_get_osr(struct nau8824 *nau8824, int stream)
|
||||
{
|
||||
int osrate;
|
||||
unsigned int osr;
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
regmap_read(nau8824->regmap,
|
||||
NAU8824_REG_DAC_FILTER_CTRL_1, &osr);
|
||||
osr &= NAU8824_DAC_OVERSAMPLE_MASK;
|
||||
if (osr >= ARRAY_SIZE(osr_dac_sel))
|
||||
return -EINVAL;
|
||||
osrate = osr_dac_sel[osr].osr;
|
||||
return NULL;
|
||||
return &osr_dac_sel[osr];
|
||||
} else {
|
||||
regmap_read(nau8824->regmap,
|
||||
NAU8824_REG_ADC_FILTER_CTRL, &osr);
|
||||
osr &= NAU8824_ADC_SYNC_DOWN_MASK;
|
||||
if (osr >= ARRAY_SIZE(osr_adc_sel))
|
||||
return -EINVAL;
|
||||
osrate = osr_adc_sel[osr].osr;
|
||||
return NULL;
|
||||
return &osr_adc_sel[osr];
|
||||
}
|
||||
}
|
||||
|
||||
if (!osrate || rate * osr > CLK_DA_AD_MAX) {
|
||||
dev_err(nau8824->dev, "exceed the maximum frequency of CLK_ADC or CLK_DAC\n");
|
||||
static int nau8824_dai_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
|
||||
const struct nau8824_osr_attr *osr;
|
||||
|
||||
osr = nau8824_get_osr(nau8824, substream->stream);
|
||||
if (!osr || !osr->osr)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
0, CLK_DA_AD_MAX / osr->osr);
|
||||
}
|
||||
|
||||
static int nau8824_hw_params(struct snd_pcm_substream *substream,
|
||||
@ -1042,7 +1057,9 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int val_len = 0, osr, ctrl_val, bclk_fs, bclk_div;
|
||||
unsigned int val_len = 0, ctrl_val, bclk_fs, bclk_div;
|
||||
const struct nau8824_osr_attr *osr;
|
||||
int err = -EINVAL;
|
||||
|
||||
nau8824_sema_acquire(nau8824, HZ);
|
||||
|
||||
@ -1053,27 +1070,19 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
|
||||
* than 6.144 MHz.
|
||||
*/
|
||||
nau8824->fs = params_rate(params);
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
regmap_read(nau8824->regmap,
|
||||
NAU8824_REG_DAC_FILTER_CTRL_1, &osr);
|
||||
osr &= NAU8824_DAC_OVERSAMPLE_MASK;
|
||||
if (nau8824_clock_check(nau8824, substream->stream,
|
||||
nau8824->fs, osr))
|
||||
return -EINVAL;
|
||||
osr = nau8824_get_osr(nau8824, substream->stream);
|
||||
if (!osr || !osr->osr)
|
||||
goto error;
|
||||
if (nau8824->fs * osr->osr > CLK_DA_AD_MAX)
|
||||
goto error;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER,
|
||||
NAU8824_CLK_DAC_SRC_MASK,
|
||||
osr_dac_sel[osr].clk_src << NAU8824_CLK_DAC_SRC_SFT);
|
||||
} else {
|
||||
regmap_read(nau8824->regmap,
|
||||
NAU8824_REG_ADC_FILTER_CTRL, &osr);
|
||||
osr &= NAU8824_ADC_SYNC_DOWN_MASK;
|
||||
if (nau8824_clock_check(nau8824, substream->stream,
|
||||
nau8824->fs, osr))
|
||||
return -EINVAL;
|
||||
osr->clk_src << NAU8824_CLK_DAC_SRC_SFT);
|
||||
else
|
||||
regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER,
|
||||
NAU8824_CLK_ADC_SRC_MASK,
|
||||
osr_adc_sel[osr].clk_src << NAU8824_CLK_ADC_SRC_SFT);
|
||||
}
|
||||
osr->clk_src << NAU8824_CLK_ADC_SRC_SFT);
|
||||
|
||||
/* make BCLK and LRC divde configuration if the codec as master. */
|
||||
regmap_read(nau8824->regmap,
|
||||
@ -1090,7 +1099,7 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
|
||||
else if (bclk_fs <= 256)
|
||||
bclk_div = 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
goto error;
|
||||
regmap_update_bits(nau8824->regmap,
|
||||
NAU8824_REG_PORT0_I2S_PCM_CTRL_2,
|
||||
NAU8824_I2S_LRC_DIV_MASK | NAU8824_I2S_BLK_DIV_MASK,
|
||||
@ -1111,15 +1120,17 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
|
||||
val_len |= NAU8824_I2S_DL_32;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_I2S_PCM_CTRL_1,
|
||||
NAU8824_I2S_DL_MASK, val_len);
|
||||
err = 0;
|
||||
|
||||
error:
|
||||
nau8824_sema_release(nau8824);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
@ -1128,8 +1139,6 @@ static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int ctrl1_val = 0, ctrl2_val = 0;
|
||||
|
||||
nau8824_sema_acquire(nau8824, HZ);
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
ctrl2_val |= NAU8824_I2S_MS_MASTER;
|
||||
@ -1171,6 +1180,8 @@ static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nau8824_sema_acquire(nau8824, HZ);
|
||||
|
||||
regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_I2S_PCM_CTRL_1,
|
||||
NAU8824_I2S_DF_MASK | NAU8824_I2S_BP_MASK |
|
||||
NAU8824_I2S_PCMB_EN, ctrl1_val);
|
||||
@ -1547,6 +1558,7 @@ static const struct snd_soc_component_driver nau8824_component_driver = {
|
||||
};
|
||||
|
||||
static const struct snd_soc_dai_ops nau8824_dai_ops = {
|
||||
.startup = nau8824_dai_startup,
|
||||
.hw_params = nau8824_hw_params,
|
||||
.set_fmt = nau8824_set_fmt,
|
||||
.set_tdm_slot = nau8824_set_tdm_slot,
|
||||
|
@ -1247,27 +1247,42 @@ static const struct snd_soc_dapm_route nau8825_dapm_routes[] = {
|
||||
{"HPOR", NULL, "Class G"},
|
||||
};
|
||||
|
||||
static int nau8825_clock_check(struct nau8825 *nau8825,
|
||||
int stream, int rate, int osr)
|
||||
static const struct nau8825_osr_attr *
|
||||
nau8825_get_osr(struct nau8825 *nau8825, int stream)
|
||||
{
|
||||
int osrate;
|
||||
unsigned int osr;
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
regmap_read(nau8825->regmap,
|
||||
NAU8825_REG_DAC_CTRL1, &osr);
|
||||
osr &= NAU8825_DAC_OVERSAMPLE_MASK;
|
||||
if (osr >= ARRAY_SIZE(osr_dac_sel))
|
||||
return -EINVAL;
|
||||
osrate = osr_dac_sel[osr].osr;
|
||||
return NULL;
|
||||
return &osr_dac_sel[osr];
|
||||
} else {
|
||||
regmap_read(nau8825->regmap,
|
||||
NAU8825_REG_ADC_RATE, &osr);
|
||||
osr &= NAU8825_ADC_SYNC_DOWN_MASK;
|
||||
if (osr >= ARRAY_SIZE(osr_adc_sel))
|
||||
return -EINVAL;
|
||||
osrate = osr_adc_sel[osr].osr;
|
||||
return NULL;
|
||||
return &osr_adc_sel[osr];
|
||||
}
|
||||
}
|
||||
|
||||
if (!osrate || rate * osr > CLK_DA_AD_MAX) {
|
||||
dev_err(nau8825->dev, "exceed the maximum frequency of CLK_ADC or CLK_DAC\n");
|
||||
static int nau8825_dai_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct nau8825 *nau8825 = snd_soc_component_get_drvdata(component);
|
||||
const struct nau8825_osr_attr *osr;
|
||||
|
||||
osr = nau8825_get_osr(nau8825, substream->stream);
|
||||
if (!osr || !osr->osr)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
0, CLK_DA_AD_MAX / osr->osr);
|
||||
}
|
||||
|
||||
static int nau8825_hw_params(struct snd_pcm_substream *substream,
|
||||
@ -1276,7 +1291,9 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct nau8825 *nau8825 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int val_len = 0, osr, ctrl_val, bclk_fs, bclk_div;
|
||||
unsigned int val_len = 0, ctrl_val, bclk_fs, bclk_div;
|
||||
const struct nau8825_osr_attr *osr;
|
||||
int err = -EINVAL;
|
||||
|
||||
nau8825_sema_acquire(nau8825, 3 * HZ);
|
||||
|
||||
@ -1286,29 +1303,19 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
|
||||
* values must be selected such that the maximum frequency is less
|
||||
* than 6.144 MHz.
|
||||
*/
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
regmap_read(nau8825->regmap, NAU8825_REG_DAC_CTRL1, &osr);
|
||||
osr &= NAU8825_DAC_OVERSAMPLE_MASK;
|
||||
if (nau8825_clock_check(nau8825, substream->stream,
|
||||
params_rate(params), osr)) {
|
||||
nau8825_sema_release(nau8825);
|
||||
return -EINVAL;
|
||||
}
|
||||
osr = nau8825_get_osr(nau8825, substream->stream);
|
||||
if (!osr || !osr->osr)
|
||||
goto error;
|
||||
if (params_rate(params) * osr->osr > CLK_DA_AD_MAX)
|
||||
goto error;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
|
||||
NAU8825_CLK_DAC_SRC_MASK,
|
||||
osr_dac_sel[osr].clk_src << NAU8825_CLK_DAC_SRC_SFT);
|
||||
} else {
|
||||
regmap_read(nau8825->regmap, NAU8825_REG_ADC_RATE, &osr);
|
||||
osr &= NAU8825_ADC_SYNC_DOWN_MASK;
|
||||
if (nau8825_clock_check(nau8825, substream->stream,
|
||||
params_rate(params), osr)) {
|
||||
nau8825_sema_release(nau8825);
|
||||
return -EINVAL;
|
||||
}
|
||||
osr->clk_src << NAU8825_CLK_DAC_SRC_SFT);
|
||||
else
|
||||
regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
|
||||
NAU8825_CLK_ADC_SRC_MASK,
|
||||
osr_adc_sel[osr].clk_src << NAU8825_CLK_ADC_SRC_SFT);
|
||||
}
|
||||
osr->clk_src << NAU8825_CLK_ADC_SRC_SFT);
|
||||
|
||||
/* make BCLK and LRC divde configuration if the codec as master. */
|
||||
regmap_read(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2, &ctrl_val);
|
||||
@ -1321,10 +1328,8 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
|
||||
bclk_div = 1;
|
||||
else if (bclk_fs <= 128)
|
||||
bclk_div = 0;
|
||||
else {
|
||||
nau8825_sema_release(nau8825);
|
||||
return -EINVAL;
|
||||
}
|
||||
else
|
||||
goto error;
|
||||
regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2,
|
||||
NAU8825_I2S_LRC_DIV_MASK | NAU8825_I2S_BLK_DIV_MASK,
|
||||
((bclk_div + 1) << NAU8825_I2S_LRC_DIV_SFT) | bclk_div);
|
||||
@ -1344,17 +1349,18 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
|
||||
val_len |= NAU8825_I2S_DL_32;
|
||||
break;
|
||||
default:
|
||||
nau8825_sema_release(nau8825);
|
||||
return -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1,
|
||||
NAU8825_I2S_DL_MASK, val_len);
|
||||
err = 0;
|
||||
|
||||
error:
|
||||
/* Release the semaphore. */
|
||||
nau8825_sema_release(nau8825);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
@ -1420,6 +1426,7 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops nau8825_dai_ops = {
|
||||
.startup = nau8825_dai_startup,
|
||||
.hw_params = nau8825_hw_params,
|
||||
.set_fmt = nau8825_set_dai_fmt,
|
||||
};
|
||||
|
@ -234,18 +234,26 @@ static int fsl_aud2htx_probe(struct platform_device *pdev)
|
||||
|
||||
regcache_cache_only(aud2htx->regmap, true);
|
||||
|
||||
/*
|
||||
* Register platform component before registering cpu dai for there
|
||||
* is not defer probe for platform component in snd_soc_add_pcm_runtime().
|
||||
*/
|
||||
ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to pcm register\n");
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_component(&pdev->dev,
|
||||
&fsl_aud2htx_component,
|
||||
&fsl_aud2htx_dai, 1);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register ASoC DAI\n");
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = imx_pcm_dma_init(pdev);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ static int fsl_mqs_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
}
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
|
||||
case SND_SOC_DAIFMT_BP_FP:
|
||||
case SND_SOC_DAIFMT_CBC_CFC:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -1306,7 +1306,7 @@ static int fsl_sai_probe(struct platform_device *pdev)
|
||||
sai->mclk_clk[i] = devm_clk_get(dev, tmp);
|
||||
if (IS_ERR(sai->mclk_clk[i])) {
|
||||
dev_err(dev, "failed to get mclk%d clock: %ld\n",
|
||||
i + 1, PTR_ERR(sai->mclk_clk[i]));
|
||||
i, PTR_ERR(sai->mclk_clk[i]));
|
||||
sai->mclk_clk[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -271,9 +271,6 @@ static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,
|
||||
/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
|
||||
usleep_range(125, 135);
|
||||
mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_ADDA, 1);
|
||||
|
||||
/* reset dmic */
|
||||
afe_priv->mtkaif_dmic = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -270,6 +270,7 @@ static int sm8250_platform_probe(struct platform_device *pdev)
|
||||
if (!card)
|
||||
return -ENOMEM;
|
||||
|
||||
card->owner = THIS_MODULE;
|
||||
/* Allocate the private data */
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
|
@ -196,6 +196,7 @@ config SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE
|
||||
|
||||
config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST
|
||||
tristate "SOF enable IPC flood test"
|
||||
depends on SND_SOC_SOF
|
||||
select SND_SOC_SOF_CLIENT
|
||||
help
|
||||
This option enables a separate client device for IPC flood test
|
||||
@ -214,6 +215,7 @@ config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_NUM
|
||||
|
||||
config SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR
|
||||
tristate "SOF enable IPC message injector"
|
||||
depends on SND_SOC_SOF
|
||||
select SND_SOC_SOF_CLIENT
|
||||
help
|
||||
This option enables the IPC message injector which can be used to send
|
||||
|
@ -771,7 +771,7 @@ static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget)
|
||||
goto err;
|
||||
|
||||
ret = sof_update_ipc_object(scomp, src, SOF_SRC_TOKENS, swidget->tuples,
|
||||
swidget->num_tuples, sizeof(src), 1);
|
||||
swidget->num_tuples, sizeof(*src), 1);
|
||||
if (ret) {
|
||||
dev_err(scomp->dev, "Parsing SRC tokens failed\n");
|
||||
goto err;
|
||||
@ -1251,7 +1251,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
|
||||
if (blob->alh_cfg.count > 1) {
|
||||
int group_id;
|
||||
|
||||
group_id = ida_alloc_max(&alh_group_ida, ALH_MULTI_GTW_COUNT,
|
||||
group_id = ida_alloc_max(&alh_group_ida, ALH_MULTI_GTW_COUNT - 1,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (group_id < 0)
|
||||
|
@ -699,7 +699,7 @@ static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface)
|
||||
if (delayed_register[i] &&
|
||||
sscanf(delayed_register[i], "%x:%x", &id, &inum) == 2 &&
|
||||
id == chip->usb_id)
|
||||
return inum != iface;
|
||||
return iface < inum;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -758,7 +758,8 @@ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
|
||||
* The endpoint needs to be closed via snd_usb_endpoint_close() later.
|
||||
*
|
||||
* Note that this function doesn't configure the endpoint. The substream
|
||||
* needs to set it up later via snd_usb_endpoint_configure().
|
||||
* needs to set it up later via snd_usb_endpoint_set_params() and
|
||||
* snd_usb_endpoint_prepare().
|
||||
*/
|
||||
struct snd_usb_endpoint *
|
||||
snd_usb_endpoint_open(struct snd_usb_audio *chip,
|
||||
@ -924,6 +925,8 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
|
||||
endpoint_set_interface(chip, ep, false);
|
||||
|
||||
if (!--ep->opened) {
|
||||
if (ep->clock_ref && !atomic_read(&ep->clock_ref->locked))
|
||||
ep->clock_ref->rate = 0;
|
||||
ep->iface = 0;
|
||||
ep->altsetting = 0;
|
||||
ep->cur_audiofmt = NULL;
|
||||
@ -1290,12 +1293,13 @@ out_of_memory:
|
||||
/*
|
||||
* snd_usb_endpoint_set_params: configure an snd_usb_endpoint
|
||||
*
|
||||
* It's called either from hw_params callback.
|
||||
* Determine the number of URBs to be used on this endpoint.
|
||||
* An endpoint must be configured before it can be started.
|
||||
* An endpoint that is already running can not be reconfigured.
|
||||
*/
|
||||
static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
|
||||
struct snd_usb_endpoint *ep)
|
||||
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;
|
||||
@ -1378,18 +1382,18 @@ static int init_sample_rate(struct snd_usb_audio *chip,
|
||||
}
|
||||
|
||||
/*
|
||||
* snd_usb_endpoint_configure: Configure the endpoint
|
||||
* snd_usb_endpoint_prepare: Prepare the endpoint
|
||||
*
|
||||
* This function sets up the EP to be fully usable state.
|
||||
* It's called either from hw_params or prepare callback.
|
||||
* It's called either from prepare callback.
|
||||
* The function checks need_setup flag, and performs nothing unless needed,
|
||||
* so it's safe to call this multiple times.
|
||||
*
|
||||
* This returns zero if unchanged, 1 if the configuration has changed,
|
||||
* or a negative error code.
|
||||
*/
|
||||
int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
|
||||
struct snd_usb_endpoint *ep)
|
||||
int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
|
||||
struct snd_usb_endpoint *ep)
|
||||
{
|
||||
bool iface_first;
|
||||
int err = 0;
|
||||
@ -1410,9 +1414,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
}
|
||||
err = snd_usb_endpoint_set_params(chip, ep);
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -1440,10 +1441,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
|
||||
err = snd_usb_endpoint_set_params(chip, ep);
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
|
||||
err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt);
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
|
@ -17,8 +17,10 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
|
||||
bool is_sync_ep);
|
||||
void snd_usb_endpoint_close(struct snd_usb_audio *chip,
|
||||
struct snd_usb_endpoint *ep);
|
||||
int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
|
||||
struct snd_usb_endpoint *ep);
|
||||
int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
|
||||
struct snd_usb_endpoint *ep);
|
||||
int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
|
||||
struct snd_usb_endpoint *ep);
|
||||
int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock);
|
||||
|
||||
bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
|
||||
|
@ -443,17 +443,17 @@ static int configure_endpoints(struct snd_usb_audio *chip,
|
||||
if (stop_endpoints(subs, false))
|
||||
sync_pending_stops(subs);
|
||||
if (subs->sync_endpoint) {
|
||||
err = snd_usb_endpoint_configure(chip, subs->sync_endpoint);
|
||||
err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
err = snd_usb_endpoint_configure(chip, subs->data_endpoint);
|
||||
err = snd_usb_endpoint_prepare(chip, subs->data_endpoint);
|
||||
if (err < 0)
|
||||
return err;
|
||||
snd_usb_set_format_quirk(subs, subs->cur_audiofmt);
|
||||
} else {
|
||||
if (subs->sync_endpoint) {
|
||||
err = snd_usb_endpoint_configure(chip, subs->sync_endpoint);
|
||||
err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
@ -551,7 +551,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
|
||||
subs->cur_audiofmt = fmt;
|
||||
mutex_unlock(&chip->mutex);
|
||||
|
||||
ret = configure_endpoints(chip, subs);
|
||||
if (subs->sync_endpoint) {
|
||||
ret = snd_usb_endpoint_set_params(chip, subs->sync_endpoint);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = snd_usb_endpoint_set_params(chip, subs->data_endpoint);
|
||||
|
||||
unlock:
|
||||
if (ret < 0)
|
||||
|
@ -1764,7 +1764,7 @@ bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface)
|
||||
|
||||
for (q = registration_quirks; q->usb_id; q++)
|
||||
if (chip->usb_id == q->usb_id)
|
||||
return iface != q->interface;
|
||||
return iface < q->interface;
|
||||
|
||||
/* Register as normal */
|
||||
return false;
|
||||
|
@ -495,6 +495,10 @@ static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (chip->card->registered)
|
||||
chip->need_delayed_register = true;
|
||||
|
||||
/* look for an empty stream */
|
||||
list_for_each_entry(as, &chip->pcm_list, list) {
|
||||
if (as->fmt_type != fp->fmt_type)
|
||||
@ -502,9 +506,6 @@ static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
|
||||
subs = &as->substream[stream];
|
||||
if (subs->ep_num)
|
||||
continue;
|
||||
if (snd_device_get_state(chip->card, as->pcm) !=
|
||||
SNDRV_DEV_BUILD)
|
||||
chip->need_delayed_register = true;
|
||||
err = snd_pcm_new_stream(as->pcm, stream, 1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -1105,7 +1106,7 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
|
||||
* Dallas DS4201 workaround: It presents 5 altsettings, but the last
|
||||
* one misses syncpipe, and does not produce any sound.
|
||||
*/
|
||||
if (chip->usb_id == USB_ID(0x04fa, 0x4201))
|
||||
if (chip->usb_id == USB_ID(0x04fa, 0x4201) && num >= 4)
|
||||
num = 4;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user