aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/ac97/bus.c2
-rw-r--r--sound/core/Makefile2
-rw-r--r--sound/core/control.c2
-rw-r--r--sound/core/control_compat.c3
-rw-r--r--sound/core/init.c2
-rw-r--r--sound/core/jack.c41
-rw-r--r--sound/core/memalloc.c3
-rw-r--r--sound/core/oss/mixer_oss.c43
-rw-r--r--sound/core/oss/pcm_oss.c71
-rw-r--r--sound/core/oss/pcm_plugin.c5
-rw-r--r--sound/core/pcm.c9
-rw-r--r--sound/core/pcm_lib.c7
-rw-r--r--sound/core/pcm_memory.c11
-rw-r--r--sound/core/pcm_misc.c2
-rw-r--r--sound/core/pcm_native.c123
-rw-r--r--sound/core/rawmidi.c49
-rw-r--r--sound/core/seq/oss/seq_oss.c7
-rw-r--r--sound/core/seq/oss/seq_oss_synth.c3
-rw-r--r--sound/core/seq/seq_ports.c39
-rw-r--r--sound/core/seq/seq_queue.c14
-rw-r--r--sound/core/seq/seq_queue.h8
-rw-r--r--sound/core/seq_device.c8
-rw-r--r--sound/core/timer.c20
-rw-r--r--sound/drivers/aloop.c11
-rw-r--r--sound/drivers/opl3/opl3_midi.c2
-rw-r--r--sound/firewire/Kconfig5
-rw-r--r--sound/firewire/amdtp-stream.c27
-rw-r--r--sound/firewire/bebob/bebob.c5
-rw-r--r--sound/firewire/bebob/bebob_hwdep.c3
-rw-r--r--sound/firewire/bebob/bebob_stream.c12
-rw-r--r--sound/firewire/dice/dice-alesis.c2
-rw-r--r--sound/firewire/dice/dice-stream.c5
-rw-r--r--sound/firewire/dice/dice-tcelectronic.c4
-rw-r--r--sound/firewire/fcp.c4
-rw-r--r--sound/firewire/fireface/ff-transaction.c2
-rw-r--r--sound/firewire/fireworks/fireworks_hwdep.c1
-rw-r--r--sound/firewire/fireworks/fireworks_transaction.c4
-rw-r--r--sound/firewire/oxfw/oxfw.c3
-rw-r--r--sound/firewire/tascam/tascam-transaction.c2
-rw-r--r--sound/hda/ext/hdac_ext_controller.c2
-rw-r--r--sound/hda/ext/hdac_ext_stream.c46
-rw-r--r--sound/hda/hdac_controller.c5
-rw-r--r--sound/hda/hdac_device.c1
-rw-r--r--sound/hda/hdac_stream.c4
-rw-r--r--sound/hda/intel-nhlt.c59
-rw-r--r--sound/isa/Kconfig2
-rw-r--r--sound/isa/cmi8330.c2
-rw-r--r--sound/isa/cs423x/cs4236.c8
-rw-r--r--sound/isa/gus/gus_dma.c2
-rw-r--r--sound/isa/gus/gus_main.c13
-rw-r--r--sound/isa/sb/emu8000.c4
-rw-r--r--sound/isa/sb/sb16_csp.c20
-rw-r--r--sound/isa/sb/sb16_main.c10
-rw-r--r--sound/isa/sb/sb8.c4
-rw-r--r--sound/isa/wavefront/wavefront_synth.c3
-rw-r--r--sound/pci/Kconfig1
-rw-r--r--sound/pci/ac97/ac97_codec.c4
-rw-r--r--sound/pci/cmipci.c3
-rw-r--r--sound/pci/ctxfi/ctamixer.c14
-rw-r--r--sound/pci/ctxfi/ctdaio.c16
-rw-r--r--sound/pci/ctxfi/cthw20k2.c2
-rw-r--r--sound/pci/ctxfi/ctresource.c7
-rw-r--r--sound/pci/ctxfi/ctresource.h4
-rw-r--r--sound/pci/ctxfi/ctsrc.c7
-rw-r--r--sound/pci/hda/hda_bind.c4
-rw-r--r--sound/pci/hda/hda_codec.c5
-rw-r--r--sound/pci/hda/hda_controller.c7
-rw-r--r--sound/pci/hda/hda_controller.h3
-rw-r--r--sound/pci/hda/hda_generic.c40
-rw-r--r--sound/pci/hda/hda_generic.h1
-rw-r--r--sound/pci/hda/hda_intel.c125
-rw-r--r--sound/pci/hda/hda_sysfs.c2
-rw-r--r--sound/pci/hda/hda_tegra.c3
-rw-r--r--sound/pci/hda/patch_ca0132.c29
-rw-r--r--sound/pci/hda/patch_conexant.c26
-rw-r--r--sound/pci/hda/patch_hdmi.c38
-rw-r--r--sound/pci/hda/patch_realtek.c780
-rw-r--r--sound/pci/hda/patch_via.c18
-rw-r--r--sound/pci/intel8x0.c7
-rw-r--r--sound/pci/mixart/mixart_core.c5
-rw-r--r--sound/pci/rme9652/hdsp.c3
-rw-r--r--sound/pci/rme9652/hdspm.c3
-rw-r--r--sound/pci/rme9652/rme9652.c3
-rw-r--r--sound/ppc/powermac.c6
-rw-r--r--sound/soc/amd/acp-da7219-max98357a.c9
-rw-r--r--sound/soc/atmel/Kconfig1
-rw-r--r--sound/soc/atmel/atmel-i2s.c34
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c5
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c62
-rw-r--r--sound/soc/codecs/Kconfig6
-rw-r--r--sound/soc/codecs/ak4458.c23
-rw-r--r--sound/soc/codecs/ak5558.c5
-rw-r--r--sound/soc/codecs/cpcap.c14
-rw-r--r--sound/soc/codecs/cs35l33.c1
-rw-r--r--sound/soc/codecs/cs35l36.c3
-rw-r--r--sound/soc/codecs/cs4265.c3
-rw-r--r--sound/soc/codecs/cs42l42.c125
-rw-r--r--sound/soc/codecs/cs42l42.h15
-rw-r--r--sound/soc/codecs/cs42l51.c22
-rw-r--r--sound/soc/codecs/cs42l52.c8
-rw-r--r--sound/soc/codecs/cs42l56.c7
-rw-r--r--sound/soc/codecs/cs43130.c28
-rw-r--r--sound/soc/codecs/cs53l30.c16
-rw-r--r--sound/soc/codecs/cx2072x.c4
-rw-r--r--sound/soc/codecs/da7219.c14
-rw-r--r--sound/soc/codecs/es8316.c9
-rw-r--r--sound/soc/codecs/es8328.c5
-rw-r--r--sound/soc/codecs/max9759.c3
-rw-r--r--sound/soc/codecs/max98088.c13
-rw-r--r--sound/soc/codecs/max98090.c5
-rw-r--r--sound/soc/codecs/max98373.c2
-rw-r--r--sound/soc/codecs/msm8916-wcd-analog.c22
-rw-r--r--sound/soc/codecs/msm8916-wcd-digital.c14
-rw-r--r--sound/soc/codecs/mt6358.c4
-rw-r--r--sound/soc/codecs/nau8822.c4
-rw-r--r--sound/soc/codecs/nau8822.h3
-rw-r--r--sound/soc/codecs/nau8824.c40
-rw-r--r--sound/soc/codecs/rk3328_codec.c30
-rw-r--r--sound/soc/codecs/rt286.c23
-rw-r--r--sound/soc/codecs/rt5514.c2
-rw-r--r--sound/soc/codecs/rt5631.c2
-rw-r--r--sound/soc/codecs/rt5640.c4
-rw-r--r--sound/soc/codecs/rt5645.c7
-rw-r--r--sound/soc/codecs/rt5651.c4
-rw-r--r--sound/soc/codecs/rt5659.c31
-rw-r--r--sound/soc/codecs/rt5663.c14
-rw-r--r--sound/soc/codecs/rt5668.c12
-rw-r--r--sound/soc/codecs/rt5682.c12
-rw-r--r--sound/soc/codecs/sgtl5000.c2
-rw-r--r--sound/soc/codecs/sti-sas.c1
-rw-r--r--sound/soc/codecs/tlv320aic31xx.h4
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c9
-rw-r--r--sound/soc/codecs/tscs454.c12
-rw-r--r--sound/soc/codecs/wcd9335.c25
-rw-r--r--sound/soc/codecs/wm2000.c6
-rw-r--r--sound/soc/codecs/wm8350.c28
-rw-r--r--sound/soc/codecs/wm8731.c19
-rw-r--r--sound/soc/codecs/wm8958-dsp2.c8
-rw-r--r--sound/soc/codecs/wm8960.c21
-rw-r--r--sound/soc/codecs/wm8962.c1
-rw-r--r--sound/soc/codecs/wm8997.c2
-rw-r--r--sound/soc/codecs/wm8998.c4
-rw-r--r--sound/soc/codecs/wm_adsp.c8
-rw-r--r--sound/soc/fsl/fsl_esai.c8
-rw-r--r--sound/soc/fsl/fsl_sai.c19
-rw-r--r--sound/soc/fsl/fsl_sai.h5
-rw-r--r--sound/soc/fsl/fsl_ssi.c6
-rw-r--r--sound/soc/fsl/imx-es8328.c13
-rw-r--r--sound/soc/fsl/imx-sgtl5000.c14
-rw-r--r--sound/soc/fsl/pcm030-audio-fabric.c11
-rw-r--r--sound/soc/generic/audio-graph-card.c2
-rw-r--r--sound/soc/generic/simple-card.c2
-rw-r--r--sound/soc/hisilicon/hi6210-i2s.c14
-rw-r--r--sound/soc/img/img-i2s-in.c2
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-pcm.c9
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c103
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c13
-rw-r--r--sound/soc/intel/boards/haswell.c1
-rw-r--r--sound/soc/intel/boards/kbl_da7219_max98357a.c4
-rw-r--r--sound/soc/intel/boards/kbl_da7219_max98927.c38
-rw-r--r--sound/soc/intel/boards/kbl_rt5663_max98927.c39
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-kbl-match.c2
-rw-r--r--sound/soc/intel/common/soc-intel-quirks.h25
-rw-r--r--sound/soc/intel/skylake/bxt-sst.c3
-rw-r--r--sound/soc/intel/skylake/cnl-sst.c36
-rw-r--r--sound/soc/intel/skylake/skl-messages.c11
-rw-r--r--sound/soc/intel/skylake/skl-nhlt.c3
-rw-r--r--sound/soc/intel/skylake/skl-pcm.c25
-rw-r--r--sound/soc/intel/skylake/skl-sst-dsp.h2
-rw-r--r--sound/soc/intel/skylake/skl-topology.c204
-rw-r--r--sound/soc/intel/skylake/skl-topology.h1
-rw-r--r--sound/soc/intel/skylake/skl.c29
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c4
-rw-r--r--sound/soc/mediatek/common/mtk-btcvsd.c24
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-wm8960.c9
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-max98090.c8
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c2
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c2
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-rt5650.c2
-rw-r--r--sound/soc/meson/Kconfig2
-rw-r--r--sound/soc/meson/axg-tdm-interface.c14
-rw-r--r--sound/soc/meson/axg-tdmin.c13
-rw-r--r--sound/soc/meson/g12a-tohdmitx.c2
-rw-r--r--sound/soc/mxs/mxs-saif.c6
-rw-r--r--sound/soc/mxs/mxs-sgtl5000.c3
-rw-r--r--sound/soc/qcom/lpass-cpu.c16
-rw-r--r--sound/soc/qcom/lpass-platform.c8
-rw-r--r--sound/soc/qcom/qdsp6/q6routing.c6
-rw-r--r--sound/soc/qcom/sdm845.c2
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c35
-rw-r--r--sound/soc/samsung/idma.c2
-rw-r--r--sound/soc/samsung/tm2_wm5110.c2
-rw-r--r--sound/soc/sh/fsi.c19
-rw-r--r--sound/soc/sh/rcar/adg.c4
-rw-r--r--sound/soc/sh/rcar/core.c69
-rw-r--r--sound/soc/sh/rcar/ssi.c16
-rw-r--r--sound/soc/soc-compress.c5
-rw-r--r--sound/soc/soc-core.c4
-rw-r--r--sound/soc/soc-dapm.c47
-rw-r--r--sound/soc/soc-ops.c74
-rw-r--r--sound/soc/soc-pcm.c2
-rw-r--r--sound/soc/soc-topology.c8
-rw-r--r--sound/soc/sof/debug.c2
-rw-r--r--sound/soc/sof/intel/hda-codec.c3
-rw-r--r--sound/soc/sof/intel/hda-dai.c7
-rw-r--r--sound/soc/sof/intel/hda-dsp.c17
-rw-r--r--sound/soc/sof/intel/hda-loader.c9
-rw-r--r--sound/soc/sof/intel/hda.c1
-rw-r--r--sound/soc/sti/uniperif_player.c6
-rw-r--r--sound/soc/sti/uniperif_reader.c2
-rw-r--r--sound/soc/sunxi/sun4i-codec.c5
-rw-r--r--sound/soc/sunxi/sun4i-i2s.c4
-rw-r--r--sound/soc/tegra/tegra_alc5632.c1
-rw-r--r--sound/soc/tegra/tegra_max98090.c1
-rw-r--r--sound/soc/tegra/tegra_rt5640.c1
-rw-r--r--sound/soc/tegra/tegra_rt5677.c1
-rw-r--r--sound/soc/tegra/tegra_sgtl5000.c1
-rw-r--r--sound/soc/tegra/tegra_wm8753.c1
-rw-r--r--sound/soc/tegra/tegra_wm8903.c1
-rw-r--r--sound/soc/tegra/tegra_wm9712.c1
-rw-r--r--sound/soc/tegra/trimslice.c1
-rw-r--r--sound/soc/ti/davinci-i2s.c5
-rw-r--r--sound/soc/uniphier/Kconfig2
-rw-r--r--sound/soc/xilinx/xlnx_formatter_pcm.c31
-rw-r--r--sound/spi/at73c213.c27
-rw-r--r--sound/synth/emux/emux.c2
-rw-r--r--sound/usb/6fire/comm.c2
-rw-r--r--sound/usb/6fire/firmware.c6
-rw-r--r--sound/usb/card.c14
-rw-r--r--sound/usb/clock.c30
-rw-r--r--sound/usb/format.c4
-rw-r--r--sound/usb/line6/driver.c18
-rw-r--r--sound/usb/line6/driver.h2
-rw-r--r--sound/usb/line6/pod.c5
-rw-r--r--sound/usb/line6/podhd.c6
-rw-r--r--sound/usb/line6/toneport.c2
-rw-r--r--sound/usb/line6/variax.c6
-rw-r--r--sound/usb/midi.c11
-rw-r--r--sound/usb/misc/ua101.c4
-rw-r--r--sound/usb/mixer.c74
-rw-r--r--sound/usb/mixer.h1
-rw-r--r--sound/usb/mixer_maps.c68
-rw-r--r--sound/usb/mixer_quirks.c15
-rw-r--r--sound/usb/mixer_scarlett.c14
-rw-r--r--sound/usb/mixer_scarlett_gen2.c127
-rw-r--r--sound/usb/mixer_scarlett_gen2.h2
-rw-r--r--sound/usb/mixer_us16x08.c2
-rw-r--r--sound/usb/pcm.c8
-rw-r--r--sound/usb/proc.c2
-rw-r--r--sound/usb/quirks-table.h94
-rw-r--r--sound/usb/quirks.c44
-rw-r--r--sound/usb/stream.c10
-rw-r--r--sound/usb/usbaudio.h4
-rw-r--r--sound/usb/usx2y/usb_stream.c7
-rw-r--r--sound/usb/validate.c4
-rw-r--r--sound/x86/intel_hdmi_audio.c2
256 files changed, 3301 insertions, 1210 deletions
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c
index 7985dd8198b6..99e1728b52ae 100644
--- a/sound/ac97/bus.c
+++ b/sound/ac97/bus.c
@@ -520,7 +520,7 @@ static int ac97_bus_remove(struct device *dev)
struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver);
int ret;
- ret = pm_runtime_get_sync(dev);
+ ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
return ret;
diff --git a/sound/core/Makefile b/sound/core/Makefile
index ee4a4a6b99ba..d123587c0fd8 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -9,7 +9,9 @@ ifneq ($(CONFIG_SND_PROC_FS),)
snd-y += info.o
snd-$(CONFIG_SND_OSSEMUL) += info_oss.o
endif
+ifneq ($(CONFIG_M68K),y)
snd-$(CONFIG_ISA_DMA_API) += isadma.o
+endif
snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o
snd-$(CONFIG_SND_VMASTER) += vmaster.o
snd-$(CONFIG_SND_JACK) += ctljack.o jack.o
diff --git a/sound/core/control.c b/sound/core/control.c
index 08ca7666e84c..15efa4b6ea94 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1350,7 +1350,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
unlock:
up_write(&card->controls_rwsem);
- return 0;
+ return err;
}
static int snd_ctl_elem_add_user(struct snd_ctl_file *file,
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index d55be1db1a8a..cca3ed9b0629 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -266,6 +266,7 @@ static int copy_ctl_value_to_user(void __user *userdata,
struct snd_ctl_elem_value *data,
int type, int count)
{
+ struct snd_ctl_elem_value32 __user *data32 = userdata;
int i, size;
if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
@@ -282,6 +283,8 @@ static int copy_ctl_value_to_user(void __user *userdata,
if (copy_to_user(valuep, data->value.bytes.data, size))
return -EFAULT;
}
+ if (copy_to_user(&data32->id, &data->id, sizeof(data32->id)))
+ return -EFAULT;
return 0;
}
diff --git a/sound/core/init.c b/sound/core/init.c
index db99b7fad6ad..45bbc4884ef0 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -384,10 +384,8 @@ int snd_card_disconnect(struct snd_card *card)
return 0;
}
card->shutdown = 1;
- spin_unlock(&card->files_lock);
/* replace file->f_op with special dummy operations */
- spin_lock(&card->files_lock);
list_for_each_entry(mfile, &card->files_list, list) {
/* it's critical part, use endless loop */
/* we have no room to fail */
diff --git a/sound/core/jack.c b/sound/core/jack.c
index fb26196571a7..e7ac82d46821 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -34,8 +34,11 @@ static int snd_jack_dev_disconnect(struct snd_device *device)
#ifdef CONFIG_SND_JACK_INPUT_DEV
struct snd_jack *jack = device->device_data;
- if (!jack->input_dev)
+ mutex_lock(&jack->input_dev_lock);
+ if (!jack->input_dev) {
+ mutex_unlock(&jack->input_dev_lock);
return 0;
+ }
/* If the input device is registered with the input subsystem
* then we need to use a different deallocator. */
@@ -44,6 +47,7 @@ static int snd_jack_dev_disconnect(struct snd_device *device)
else
input_free_device(jack->input_dev);
jack->input_dev = NULL;
+ mutex_unlock(&jack->input_dev_lock);
#endif /* CONFIG_SND_JACK_INPUT_DEV */
return 0;
}
@@ -54,10 +58,13 @@ static int snd_jack_dev_free(struct snd_device *device)
struct snd_card *card = device->card;
struct snd_jack_kctl *jack_kctl, *tmp_jack_kctl;
+ down_write(&card->controls_rwsem);
list_for_each_entry_safe(jack_kctl, tmp_jack_kctl, &jack->kctl_list, list) {
list_del_init(&jack_kctl->list);
snd_ctl_remove(card, jack_kctl->kctl);
}
+ up_write(&card->controls_rwsem);
+
if (jack->private_free)
jack->private_free(jack);
@@ -79,8 +86,11 @@ static int snd_jack_dev_register(struct snd_device *device)
snprintf(jack->name, sizeof(jack->name), "%s %s",
card->shortname, jack->id);
- if (!jack->input_dev)
+ mutex_lock(&jack->input_dev_lock);
+ if (!jack->input_dev) {
+ mutex_unlock(&jack->input_dev_lock);
return 0;
+ }
jack->input_dev->name = jack->name;
@@ -105,6 +115,7 @@ static int snd_jack_dev_register(struct snd_device *device)
if (err == 0)
jack->registered = 1;
+ mutex_unlock(&jack->input_dev_lock);
return err;
}
#endif /* CONFIG_SND_JACK_INPUT_DEV */
@@ -220,10 +231,16 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
return -ENOMEM;
jack->id = kstrdup(id, GFP_KERNEL);
+ if (jack->id == NULL) {
+ kfree(jack);
+ return -ENOMEM;
+ }
- /* don't creat input device for phantom jack */
- if (!phantom_jack) {
#ifdef CONFIG_SND_JACK_INPUT_DEV
+ mutex_init(&jack->input_dev_lock);
+
+ /* don't create input device for phantom jack */
+ if (!phantom_jack) {
int i;
jack->input_dev = input_allocate_device();
@@ -241,8 +258,8 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
input_set_capability(jack->input_dev, EV_SW,
jack_switch_types[i]);
-#endif /* CONFIG_SND_JACK_INPUT_DEV */
}
+#endif /* CONFIG_SND_JACK_INPUT_DEV */
err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
if (err < 0)
@@ -282,10 +299,14 @@ EXPORT_SYMBOL(snd_jack_new);
void snd_jack_set_parent(struct snd_jack *jack, struct device *parent)
{
WARN_ON(jack->registered);
- if (!jack->input_dev)
+ mutex_lock(&jack->input_dev_lock);
+ if (!jack->input_dev) {
+ mutex_unlock(&jack->input_dev_lock);
return;
+ }
jack->input_dev->dev.parent = parent;
+ mutex_unlock(&jack->input_dev_lock);
}
EXPORT_SYMBOL(snd_jack_set_parent);
@@ -333,6 +354,8 @@ EXPORT_SYMBOL(snd_jack_set_key);
/**
* snd_jack_report - Report the current status of a jack
+ * Note: This function uses mutexes and should be called from a
+ * context which can sleep (such as a workqueue).
*
* @jack: The jack to report status for
* @status: The current status of the jack
@@ -352,8 +375,11 @@ void snd_jack_report(struct snd_jack *jack, int status)
status & jack_kctl->mask_bits);
#ifdef CONFIG_SND_JACK_INPUT_DEV
- if (!jack->input_dev)
+ mutex_lock(&jack->input_dev_lock);
+ if (!jack->input_dev) {
+ mutex_unlock(&jack->input_dev_lock);
return;
+ }
for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
int testbit = SND_JACK_BTN_0 >> i;
@@ -372,6 +398,7 @@ void snd_jack_report(struct snd_jack *jack, int status)
}
input_sync(jack->input_dev);
+ mutex_unlock(&jack->input_dev_lock);
#endif /* CONFIG_SND_JACK_INPUT_DEV */
}
EXPORT_SYMBOL(snd_jack_report);
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 6850d13aa98c..fe1ea03582cb 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -76,7 +76,8 @@ static void snd_malloc_dev_iram(struct snd_dma_buffer *dmab, size_t size)
/* Assign the pool into private_data field */
dmab->private_data = pool;
- dmab->area = gen_pool_dma_alloc(pool, size, &dmab->addr);
+ dmab->area = gen_pool_dma_alloc_align(pool, size, &dmab->addr,
+ PAGE_SIZE);
}
/**
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 7eb54df5556d..50ec8b8ff68c 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -130,11 +130,13 @@ static int snd_mixer_oss_devmask(struct snd_mixer_oss_file *fmixer)
if (mixer == NULL)
return -EIO;
+ mutex_lock(&mixer->reg_mutex);
for (chn = 0; chn < 31; chn++) {
pslot = &mixer->slots[chn];
if (pslot->put_volume || pslot->put_recsrc)
result |= 1 << chn;
}
+ mutex_unlock(&mixer->reg_mutex);
return result;
}
@@ -146,11 +148,13 @@ static int snd_mixer_oss_stereodevs(struct snd_mixer_oss_file *fmixer)
if (mixer == NULL)
return -EIO;
+ mutex_lock(&mixer->reg_mutex);
for (chn = 0; chn < 31; chn++) {
pslot = &mixer->slots[chn];
if (pslot->put_volume && pslot->stereo)
result |= 1 << chn;
}
+ mutex_unlock(&mixer->reg_mutex);
return result;
}
@@ -161,6 +165,7 @@ static int snd_mixer_oss_recmask(struct snd_mixer_oss_file *fmixer)
if (mixer == NULL)
return -EIO;
+ mutex_lock(&mixer->reg_mutex);
if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */
result = mixer->mask_recsrc;
} else {
@@ -172,6 +177,7 @@ static int snd_mixer_oss_recmask(struct snd_mixer_oss_file *fmixer)
result |= 1 << chn;
}
}
+ mutex_unlock(&mixer->reg_mutex);
return result;
}
@@ -182,11 +188,12 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer)
if (mixer == NULL)
return -EIO;
+ mutex_lock(&mixer->reg_mutex);
if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */
- int err;
unsigned int index;
- if ((err = mixer->get_recsrc(fmixer, &index)) < 0)
- return err;
+ result = mixer->get_recsrc(fmixer, &index);
+ if (result < 0)
+ goto unlock;
result = 1 << index;
} else {
struct snd_mixer_oss_slot *pslot;
@@ -201,7 +208,10 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer)
}
}
}
- return mixer->oss_recsrc = result;
+ mixer->oss_recsrc = result;
+ unlock:
+ mutex_unlock(&mixer->reg_mutex);
+ return result;
}
static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsrc)
@@ -214,6 +224,7 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr
if (mixer == NULL)
return -EIO;
+ mutex_lock(&mixer->reg_mutex);
if (mixer->get_recsrc && mixer->put_recsrc) { /* exclusive input */
if (recsrc & ~mixer->oss_recsrc)
recsrc &= ~mixer->oss_recsrc;
@@ -239,6 +250,7 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr
}
}
}
+ mutex_unlock(&mixer->reg_mutex);
return result;
}
@@ -250,6 +262,7 @@ static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot)
if (mixer == NULL || slot > 30)
return -EIO;
+ mutex_lock(&mixer->reg_mutex);
pslot = &mixer->slots[slot];
left = pslot->volume[0];
right = pslot->volume[1];
@@ -257,15 +270,21 @@ static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot)
result = pslot->get_volume(fmixer, pslot, &left, &right);
if (!pslot->stereo)
right = left;
- if (snd_BUG_ON(left < 0 || left > 100))
- return -EIO;
- if (snd_BUG_ON(right < 0 || right > 100))
- return -EIO;
+ if (snd_BUG_ON(left < 0 || left > 100)) {
+ result = -EIO;
+ goto unlock;
+ }
+ if (snd_BUG_ON(right < 0 || right > 100)) {
+ result = -EIO;
+ goto unlock;
+ }
if (result >= 0) {
pslot->volume[0] = left;
pslot->volume[1] = right;
result = (left & 0xff) | ((right & 0xff) << 8);
}
+ unlock:
+ mutex_unlock(&mixer->reg_mutex);
return result;
}
@@ -278,6 +297,7 @@ static int snd_mixer_oss_set_volume(struct snd_mixer_oss_file *fmixer,
if (mixer == NULL || slot > 30)
return -EIO;
+ mutex_lock(&mixer->reg_mutex);
pslot = &mixer->slots[slot];
if (left > 100)
left = 100;
@@ -288,10 +308,13 @@ static int snd_mixer_oss_set_volume(struct snd_mixer_oss_file *fmixer,
if (pslot->put_volume)
result = pslot->put_volume(fmixer, pslot, left, right);
if (result < 0)
- return result;
+ goto unlock;
pslot->volume[0] = left;
pslot->volume[1] = right;
- return (left & 0xff) | ((right & 0xff) << 8);
+ result = (left & 0xff) | ((right & 0xff) << 8);
+ unlock:
+ mutex_unlock(&mixer->reg_mutex);
+ return result;
}
static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int cmd, unsigned long arg)
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index f57c610d7523..ad4e0af2d0d0 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -147,7 +147,7 @@ snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
*
* Return the maximum value for field PAR.
*/
-static unsigned int
+static int
snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir)
{
@@ -682,17 +682,25 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *oss_params,
struct snd_pcm_hw_params *slave_params)
{
- size_t s;
- size_t oss_buffer_size, oss_period_size, oss_periods;
- size_t min_period_size, max_period_size;
+ ssize_t s;
+ ssize_t oss_buffer_size;
+ ssize_t oss_period_size, oss_periods;
+ ssize_t min_period_size, max_period_size;
struct snd_pcm_runtime *runtime = substream->runtime;
size_t oss_frame_size;
oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) *
params_channels(oss_params) / 8;
+ oss_buffer_size = snd_pcm_hw_param_value_max(slave_params,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+ NULL);
+ if (oss_buffer_size <= 0)
+ return -EINVAL;
oss_buffer_size = snd_pcm_plug_client_size(substream,
- snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size;
+ oss_buffer_size * oss_frame_size);
+ if (oss_buffer_size <= 0)
+ return -EINVAL;
oss_buffer_size = rounddown_pow_of_two(oss_buffer_size);
if (atomic_read(&substream->mmap_count)) {
if (oss_buffer_size > runtime->oss.mmap_bytes)
@@ -728,17 +736,21 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
min_period_size = snd_pcm_plug_client_size(substream,
snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL));
- min_period_size *= oss_frame_size;
- min_period_size = roundup_pow_of_two(min_period_size);
- if (oss_period_size < min_period_size)
- oss_period_size = min_period_size;
+ if (min_period_size > 0) {
+ min_period_size *= oss_frame_size;
+ min_period_size = roundup_pow_of_two(min_period_size);
+ if (oss_period_size < min_period_size)
+ oss_period_size = min_period_size;
+ }
max_period_size = snd_pcm_plug_client_size(substream,
snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL));
- max_period_size *= oss_frame_size;
- max_period_size = rounddown_pow_of_two(max_period_size);
- if (oss_period_size > max_period_size)
- oss_period_size = max_period_size;
+ if (max_period_size > 0) {
+ max_period_size *= oss_frame_size;
+ max_period_size = rounddown_pow_of_two(max_period_size);
+ if (oss_period_size > max_period_size)
+ oss_period_size = max_period_size;
+ }
oss_periods = oss_buffer_size / oss_period_size;
@@ -746,7 +758,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
oss_periods = substream->oss.setup.periods;
s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL);
- if (runtime->oss.maxfrags && s > runtime->oss.maxfrags)
+ if (s > 0 && runtime->oss.maxfrags && s > runtime->oss.maxfrags)
s = runtime->oss.maxfrags;
if (oss_periods > s)
oss_periods = s;
@@ -762,6 +774,11 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
if (oss_period_size < 16)
return -EINVAL;
+
+ /* don't allocate too large period; 1MB period must be enough */
+ if (oss_period_size > 1024 * 1024)
+ return -ENOMEM;
+
runtime->oss.period_bytes = oss_period_size;
runtime->oss.period_frames = 1;
runtime->oss.periods = oss_periods;
@@ -872,8 +889,15 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
err = -EINVAL;
goto failure;
}
- choose_rate(substream, sparams, runtime->oss.rate);
- snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, NULL);
+
+ err = choose_rate(substream, sparams, runtime->oss.rate);
+ if (err < 0)
+ goto failure;
+ err = snd_pcm_hw_param_near(substream, sparams,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ runtime->oss.channels, NULL);
+ if (err < 0)
+ goto failure;
format = snd_pcm_oss_format_from(runtime->oss.format);
@@ -1026,10 +1050,9 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
goto failure;
}
#endif
- oss_period_size *= oss_frame_size;
-
- oss_buffer_size = oss_period_size * runtime->oss.periods;
- if (oss_buffer_size < 0) {
+ oss_period_size = array_size(oss_period_size, oss_frame_size);
+ oss_buffer_size = array_size(oss_period_size, runtime->oss.periods);
+ if (oss_buffer_size <= 0) {
err = -EINVAL;
goto failure;
}
@@ -1934,11 +1957,15 @@ static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int
static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsigned int val)
{
struct snd_pcm_runtime *runtime;
+ int fragshift;
runtime = substream->runtime;
if (runtime->oss.subdivision || runtime->oss.fragshift)
return -EINVAL;
- runtime->oss.fragshift = val & 0xffff;
+ fragshift = val & 0xffff;
+ if (fragshift >= 25) /* should be large enough */
+ return -EINVAL;
+ runtime->oss.fragshift = fragshift;
runtime->oss.maxfrags = (val >> 16) & 0xffff;
if (runtime->oss.fragshift < 4) /* < 16 */
runtime->oss.fragshift = 4;
@@ -2032,7 +2059,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
int err, cmd;
#ifdef OSS_DEBUG
- pcm_dbg(substream->pcm, "pcm_oss: trigger = 0x%x\n", trigger);
+ pr_debug("pcm_oss: trigger = 0x%x\n", trigger);
#endif
psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index da400da1fafe..8b7bbabeea24 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -61,7 +61,10 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t
}
if ((width = snd_pcm_format_physical_width(format->format)) < 0)
return width;
- size = frames * format->channels * width;
+ size = array3_size(frames, format->channels, width);
+ /* check for too large period size once again */
+ if (size > 1024 * 1024)
+ return -ENOMEM;
if (snd_BUG_ON(size % 8))
return -ENXIO;
size /= 8;
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 9a72d641743d..3561cdceaadc 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -810,7 +810,11 @@ EXPORT_SYMBOL(snd_pcm_new_internal);
static void free_chmap(struct snd_pcm_str *pstr)
{
if (pstr->chmap_kctl) {
- snd_ctl_remove(pstr->pcm->card, pstr->chmap_kctl);
+ struct snd_card *card = pstr->pcm->card;
+
+ down_write(&card->controls_rwsem);
+ snd_ctl_remove(card, pstr->chmap_kctl);
+ up_write(&card->controls_rwsem);
pstr->chmap_kctl = NULL;
}
}
@@ -965,6 +969,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
init_waitqueue_head(&runtime->tsleep);
runtime->status->state = SNDRV_PCM_STATE_OPEN;
+ mutex_init(&runtime->buffer_mutex);
+ atomic_set(&runtime->buffer_accessing, 0);
substream->runtime = runtime;
substream->private_data = pcm->private_data;
@@ -996,6 +1002,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
substream->runtime = NULL;
if (substream->timer)
spin_unlock_irq(&substream->timer->lock);
+ mutex_destroy(&runtime->buffer_mutex);
kfree(runtime);
put_pid(substream->pid);
substream->pid = NULL;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 1662573a4030..1bce55533519 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1736,7 +1736,7 @@ static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream,
channels = params_channels(params);
frame_size = snd_pcm_format_size(format, channels);
if (frame_size > 0)
- params->fifo_size /= (unsigned)frame_size;
+ params->fifo_size /= frame_size;
}
return 0;
}
@@ -2211,10 +2211,15 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
err = -EINVAL;
goto _end_unlock;
}
+ if (!atomic_inc_unless_negative(&runtime->buffer_accessing)) {
+ err = -EBUSY;
+ goto _end_unlock;
+ }
snd_pcm_stream_unlock_irq(substream);
err = writer(substream, appl_ofs, data, offset, frames,
transfer);
snd_pcm_stream_lock_irq(substream);
+ atomic_dec(&runtime->buffer_accessing);
if (err < 0)
goto _end_unlock;
err = pcm_accessible_state(runtime);
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 7600dcdf5fd4..9aea1d6fb054 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -133,19 +133,20 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
size_t size;
struct snd_dma_buffer new_dmab;
+ mutex_lock(&substream->pcm->open_mutex);
if (substream->runtime) {
buffer->error = -EBUSY;
- return;
+ goto unlock;
}
if (!snd_info_get_line(buffer, line, sizeof(line))) {
snd_info_get_str(str, line, sizeof(str));
size = simple_strtoul(str, NULL, 10) * 1024;
if ((size != 0 && size < 8192) || size > substream->dma_max) {
buffer->error = -EINVAL;
- return;
+ goto unlock;
}
if (substream->dma_buffer.bytes == size)
- return;
+ goto unlock;
memset(&new_dmab, 0, sizeof(new_dmab));
new_dmab.dev = substream->dma_buffer.dev;
if (size > 0) {
@@ -153,7 +154,7 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
substream->dma_buffer.dev.dev,
size, &new_dmab) < 0) {
buffer->error = -ENOMEM;
- return;
+ goto unlock;
}
substream->buffer_bytes_max = size;
} else {
@@ -165,6 +166,8 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
} else {
buffer->error = -EINVAL;
}
+ unlock:
+ mutex_unlock(&substream->pcm->open_mutex);
}
static inline void preallocate_info_init(struct snd_pcm_substream *substream)
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index c4eb561d2008..0956be39b035 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -423,7 +423,7 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
return 0;
width = pcm_formats[(INT)format].phys; /* physical width */
pat = pcm_formats[(INT)format].silence;
- if (! width)
+ if (!width || !pat)
return -EINVAL;
/* signed or 1 byte data */
if (pcm_formats[(INT)format].signd == 1 || width <= 8) {
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index ec501fbaabe4..57a4991fa0f3 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -630,6 +630,30 @@ static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
return 0;
}
+/* acquire buffer_mutex; if it's in r/w operation, return -EBUSY, otherwise
+ * block the further r/w operations
+ */
+static int snd_pcm_buffer_access_lock(struct snd_pcm_runtime *runtime)
+{
+ if (!atomic_dec_unless_positive(&runtime->buffer_accessing))
+ return -EBUSY;
+ mutex_lock(&runtime->buffer_mutex);
+ return 0; /* keep buffer_mutex, unlocked by below */
+}
+
+/* release buffer_mutex and clear r/w access flag */
+static void snd_pcm_buffer_access_unlock(struct snd_pcm_runtime *runtime)
+{
+ mutex_unlock(&runtime->buffer_mutex);
+ atomic_inc(&runtime->buffer_accessing);
+}
+
+#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+#define is_oss_stream(substream) ((substream)->oss.oss)
+#else
+#define is_oss_stream(substream) false
+#endif
+
static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -641,22 +665,25 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
+ err = snd_pcm_buffer_access_lock(runtime);
+ if (err < 0)
+ return err;
snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_OPEN:
case SNDRV_PCM_STATE_SETUP:
case SNDRV_PCM_STATE_PREPARED:
+ if (!is_oss_stream(substream) &&
+ atomic_read(&substream->mmap_count))
+ err = -EBADFD;
break;
default:
- snd_pcm_stream_unlock_irq(substream);
- return -EBADFD;
+ err = -EBADFD;
+ break;
}
snd_pcm_stream_unlock_irq(substream);
-#if IS_ENABLED(CONFIG_SND_PCM_OSS)
- if (!substream->oss.oss)
-#endif
- if (atomic_read(&substream->mmap_count))
- return -EBADFD;
+ if (err)
+ goto unlock;
params->rmask = ~0U;
err = snd_pcm_hw_refine(substream, params);
@@ -717,8 +744,13 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
runtime->boundary *= 2;
/* clear the buffer for avoiding possible kernel info leaks */
- if (runtime->dma_area && !substream->ops->copy_user)
- memset(runtime->dma_area, 0, runtime->dma_bytes);
+ if (runtime->dma_area && !substream->ops->copy_user) {
+ size_t size = runtime->dma_bytes;
+
+ if (runtime->info & SNDRV_PCM_INFO_MMAP)
+ size = PAGE_ALIGN(size);
+ memset(runtime->dma_area, 0, size);
+ }
snd_pcm_timer_resolution_change(substream);
snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
@@ -728,14 +760,19 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
if ((usecs = period_to_usecs(runtime)) >= 0)
pm_qos_add_request(&substream->latency_pm_qos_req,
PM_QOS_CPU_DMA_LATENCY, usecs);
- return 0;
+ err = 0;
_error:
- /* hardware might be unusable from this time,
- so we force application to retry to set
- the correct hardware parameter settings */
- snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
- if (substream->ops->hw_free != NULL)
- substream->ops->hw_free(substream);
+ if (err) {
+ /* hardware might be unusable from this time,
+ * so we force application to retry to set
+ * the correct hardware parameter settings
+ */
+ snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
+ if (substream->ops->hw_free != NULL)
+ substream->ops->hw_free(substream);
+ }
+ unlock:
+ snd_pcm_buffer_access_unlock(runtime);
return err;
}
@@ -768,22 +805,29 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
+ result = snd_pcm_buffer_access_lock(runtime);
+ if (result < 0)
+ return result;
snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_SETUP:
case SNDRV_PCM_STATE_PREPARED:
+ if (atomic_read(&substream->mmap_count))
+ result = -EBADFD;
break;
default:
- snd_pcm_stream_unlock_irq(substream);
- return -EBADFD;
+ result = -EBADFD;
+ break;
}
snd_pcm_stream_unlock_irq(substream);
- if (atomic_read(&substream->mmap_count))
- return -EBADFD;
+ if (result)
+ goto unlock;
if (substream->ops->hw_free)
result = substream->ops->hw_free(substream);
snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
pm_qos_remove_request(&substream->latency_pm_qos_req);
+ unlock:
+ snd_pcm_buffer_access_unlock(runtime);
return result;
}
@@ -1020,15 +1064,17 @@ struct action_ops {
*/
static int snd_pcm_action_group(const struct action_ops *ops,
struct snd_pcm_substream *substream,
- int state, int do_lock)
+ int state, int stream_lock)
{
struct snd_pcm_substream *s = NULL;
struct snd_pcm_substream *s1;
int res = 0, depth = 1;
snd_pcm_group_for_each_entry(s, substream) {
- if (do_lock && s != substream) {
- if (s->pcm->nonatomic)
+ if (s != substream) {
+ if (!stream_lock)
+ mutex_lock_nested(&s->runtime->buffer_mutex, depth);
+ else if (s->pcm->nonatomic)
mutex_lock_nested(&s->self_group.mutex, depth);
else
spin_lock_nested(&s->self_group.lock, depth);
@@ -1056,18 +1102,18 @@ static int snd_pcm_action_group(const struct action_ops *ops,
ops->post_action(s, state);
}
_unlock:
- if (do_lock) {
- /* unlock streams */
- snd_pcm_group_for_each_entry(s1, substream) {
- if (s1 != substream) {
- if (s1->pcm->nonatomic)
- mutex_unlock(&s1->self_group.mutex);
- else
- spin_unlock(&s1->self_group.lock);
- }
- if (s1 == s) /* end */
- break;
+ /* unlock streams */
+ snd_pcm_group_for_each_entry(s1, substream) {
+ if (s1 != substream) {
+ if (!stream_lock)
+ mutex_unlock(&s1->runtime->buffer_mutex);
+ else if (s1->pcm->nonatomic)
+ mutex_unlock(&s1->self_group.mutex);
+ else
+ spin_unlock(&s1->self_group.lock);
}
+ if (s1 == s) /* end */
+ break;
}
return res;
}
@@ -1197,10 +1243,15 @@ static int snd_pcm_action_nonatomic(const struct action_ops *ops,
/* Guarantee the group members won't change during non-atomic action */
down_read(&snd_pcm_link_rwsem);
+ res = snd_pcm_buffer_access_lock(substream->runtime);
+ if (res < 0)
+ goto unlock;
if (snd_pcm_stream_linked(substream))
res = snd_pcm_action_group(ops, substream, state, 0);
else
res = snd_pcm_action_single(ops, substream, state);
+ snd_pcm_buffer_access_unlock(substream->runtime);
+ unlock:
up_read(&snd_pcm_link_rwsem);
return res;
}
@@ -1651,21 +1702,25 @@ static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
int err = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL);
if (err < 0)
return err;
+ snd_pcm_stream_lock_irq(substream);
runtime->hw_ptr_base = 0;
runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
runtime->status->hw_ptr % runtime->period_size;
runtime->silence_start = runtime->status->hw_ptr;
runtime->silence_filled = 0;
+ snd_pcm_stream_unlock_irq(substream);
return 0;
}
static void snd_pcm_post_reset(struct snd_pcm_substream *substream, int state)
{
struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_stream_lock_irq(substream);
runtime->control->appl_ptr = runtime->status->hw_ptr;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
runtime->silence_size > 0)
snd_pcm_playback_silence(substream, ULONG_MAX);
+ snd_pcm_stream_unlock_irq(substream);
}
static const struct action_ops snd_pcm_action_reset = {
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 94db4683cfaf..6a3543b8455f 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -72,11 +72,21 @@ static inline unsigned short snd_rawmidi_file_flags(struct file *file)
}
}
-static inline int snd_rawmidi_ready(struct snd_rawmidi_substream *substream)
+static inline bool __snd_rawmidi_ready(struct snd_rawmidi_runtime *runtime)
+{
+ return runtime->avail >= runtime->avail_min;
+}
+
+static bool snd_rawmidi_ready(struct snd_rawmidi_substream *substream)
{
struct snd_rawmidi_runtime *runtime = substream->runtime;
+ unsigned long flags;
+ bool ready;
- return runtime->avail >= runtime->avail_min;
+ spin_lock_irqsave(&runtime->lock, flags);
+ ready = __snd_rawmidi_ready(runtime);
+ spin_unlock_irqrestore(&runtime->lock, flags);
+ return ready;
}
static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substream,
@@ -945,7 +955,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
if (result > 0) {
if (runtime->event)
schedule_work(&runtime->event_work);
- else if (snd_rawmidi_ready(substream))
+ else if (__snd_rawmidi_ready(runtime))
wake_up(&runtime->sleep);
}
spin_unlock_irqrestore(&runtime->lock, flags);
@@ -1024,7 +1034,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
result = 0;
while (count > 0) {
spin_lock_irq(&runtime->lock);
- while (!snd_rawmidi_ready(substream)) {
+ while (!__snd_rawmidi_ready(runtime)) {
wait_queue_entry_t wait;
if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
@@ -1041,9 +1051,11 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
return -ENODEV;
if (signal_pending(current))
return result > 0 ? result : -ERESTARTSYS;
- if (!runtime->avail)
- return result > 0 ? result : -EIO;
spin_lock_irq(&runtime->lock);
+ if (!runtime->avail) {
+ spin_unlock_irq(&runtime->lock);
+ return result > 0 ? result : -EIO;
+ }
}
spin_unlock_irq(&runtime->lock);
count1 = snd_rawmidi_kernel_read1(substream,
@@ -1181,7 +1193,7 @@ int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int coun
runtime->avail += count;
substream->bytes += count;
if (count > 0) {
- if (runtime->drain || snd_rawmidi_ready(substream))
+ if (runtime->drain || __snd_rawmidi_ready(runtime))
wake_up(&runtime->sleep);
}
return count;
@@ -1370,9 +1382,11 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
return -ENODEV;
if (signal_pending(current))
return result > 0 ? result : -ERESTARTSYS;
- if (!runtime->avail && !timeout)
- return result > 0 ? result : -EIO;
spin_lock_irq(&runtime->lock);
+ if (!runtime->avail && !timeout) {
+ spin_unlock_irq(&runtime->lock);
+ return result > 0 ? result : -EIO;
+ }
}
spin_unlock_irq(&runtime->lock);
count1 = snd_rawmidi_kernel_write1(substream, buf, NULL, count);
@@ -1452,6 +1466,7 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
struct snd_rawmidi *rmidi;
struct snd_rawmidi_substream *substream;
struct snd_rawmidi_runtime *runtime;
+ unsigned long buffer_size, avail, xruns;
rmidi = entry->private_data;
snd_iprintf(buffer, "%s\n\n", rmidi->name);
@@ -1470,13 +1485,16 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
" Owner PID : %d\n",
pid_vnr(substream->pid));
runtime = substream->runtime;
+ spin_lock_irq(&runtime->lock);
+ buffer_size = runtime->buffer_size;
+ avail = runtime->avail;
+ spin_unlock_irq(&runtime->lock);
snd_iprintf(buffer,
" Mode : %s\n"
" Buffer size : %lu\n"
" Avail : %lu\n",
runtime->oss ? "OSS compatible" : "native",
- (unsigned long) runtime->buffer_size,
- (unsigned long) runtime->avail);
+ buffer_size, avail);
}
}
}
@@ -1494,13 +1512,16 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
" Owner PID : %d\n",
pid_vnr(substream->pid));
runtime = substream->runtime;
+ spin_lock_irq(&runtime->lock);
+ buffer_size = runtime->buffer_size;
+ avail = runtime->avail;
+ xruns = runtime->xruns;
+ spin_unlock_irq(&runtime->lock);
snd_iprintf(buffer,
" Buffer size : %lu\n"
" Avail : %lu\n"
" Overruns : %lu\n",
- (unsigned long) runtime->buffer_size,
- (unsigned long) runtime->avail,
- (unsigned long) runtime->xruns);
+ buffer_size, avail, xruns);
}
}
}
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index c8b9c0b315d8..250a92b18726 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -174,9 +174,12 @@ odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (snd_BUG_ON(!dp))
return -ENXIO;
- mutex_lock(&register_mutex);
+ if (cmd != SNDCTL_SEQ_SYNC &&
+ mutex_lock_interruptible(&register_mutex))
+ return -ERESTARTSYS;
rc = snd_seq_oss_ioctl(dp, cmd, arg);
- mutex_unlock(&register_mutex);
+ if (cmd != SNDCTL_SEQ_SYNC)
+ mutex_unlock(&register_mutex);
return rc;
}
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 11554d0412f0..1b8409ec2c97 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -611,7 +611,8 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
if (info->is_midi) {
struct midi_info minf;
- snd_seq_oss_midi_make_info(dp, info->midi_mapped, &minf);
+ if (snd_seq_oss_midi_make_info(dp, info->midi_mapped, &minf))
+ return -ENXIO;
inf->synth_type = SYNTH_TYPE_MIDI;
inf->synth_subtype = 0;
inf->nr_voices = 16;
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 83be6b982a87..97e8eb38b096 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -514,10 +514,11 @@ static int check_and_subscribe_port(struct snd_seq_client *client,
return err;
}
-static void delete_and_unsubscribe_port(struct snd_seq_client *client,
- struct snd_seq_client_port *port,
- struct snd_seq_subscribers *subs,
- bool is_src, bool ack)
+/* called with grp->list_mutex held */
+static void __delete_and_unsubscribe_port(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_subscribers *subs,
+ bool is_src, bool ack)
{
struct snd_seq_port_subs_info *grp;
struct list_head *list;
@@ -525,7 +526,6 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client,
grp = is_src ? &port->c_src : &port->c_dest;
list = is_src ? &subs->src_list : &subs->dest_list;
- down_write(&grp->list_mutex);
write_lock_irq(&grp->list_lock);
empty = list_empty(list);
if (!empty)
@@ -535,6 +535,18 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client,
if (!empty)
unsubscribe_port(client, port, grp, &subs->info, ack);
+}
+
+static void delete_and_unsubscribe_port(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_subscribers *subs,
+ bool is_src, bool ack)
+{
+ struct snd_seq_port_subs_info *grp;
+
+ grp = is_src ? &port->c_src : &port->c_dest;
+ down_write(&grp->list_mutex);
+ __delete_and_unsubscribe_port(client, port, subs, is_src, ack);
up_write(&grp->list_mutex);
}
@@ -590,27 +602,30 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector,
struct snd_seq_client_port *dest_port,
struct snd_seq_port_subscribe *info)
{
- struct snd_seq_port_subs_info *src = &src_port->c_src;
+ struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
struct snd_seq_subscribers *subs;
int err = -ENOENT;
- down_write(&src->list_mutex);
+ /* always start from deleting the dest port for avoiding concurrent
+ * deletions
+ */
+ down_write(&dest->list_mutex);
/* look for the connection */
- list_for_each_entry(subs, &src->list_head, src_list) {
+ list_for_each_entry(subs, &dest->list_head, dest_list) {
if (match_subs_info(info, &subs->info)) {
- atomic_dec(&subs->ref_count); /* mark as not ready */
+ __delete_and_unsubscribe_port(dest_client, dest_port,
+ subs, false,
+ connector->number != dest_client->number);
err = 0;
break;
}
}
- up_write(&src->list_mutex);
+ up_write(&dest->list_mutex);
if (err < 0)
return err;
delete_and_unsubscribe_port(src_client, src_port, subs, true,
connector->number != src_client->number);
- delete_and_unsubscribe_port(dest_client, dest_port, subs, false,
- connector->number != dest_client->number);
kfree(subs);
return 0;
}
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 71a6ea62c3be..4ff0b927230c 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -234,12 +234,15 @@ struct snd_seq_queue *snd_seq_queue_find_name(char *name)
/* -------------------------------------------------------- */
+#define MAX_CELL_PROCESSES_IN_QUEUE 1000
+
void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
{
unsigned long flags;
struct snd_seq_event_cell *cell;
snd_seq_tick_time_t cur_tick;
snd_seq_real_time_t cur_time;
+ int processed = 0;
if (q == NULL)
return;
@@ -262,6 +265,8 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
if (!cell)
break;
snd_seq_dispatch_event(cell, atomic, hop);
+ if (++processed >= MAX_CELL_PROCESSES_IN_QUEUE)
+ goto out; /* the rest processed at the next batch */
}
/* Process time queue... */
@@ -271,14 +276,19 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
if (!cell)
break;
snd_seq_dispatch_event(cell, atomic, hop);
+ if (++processed >= MAX_CELL_PROCESSES_IN_QUEUE)
+ goto out; /* the rest processed at the next batch */
}
+ out:
/* free lock */
spin_lock_irqsave(&q->check_lock, flags);
if (q->check_again) {
q->check_again = 0;
- spin_unlock_irqrestore(&q->check_lock, flags);
- goto __again;
+ if (processed < MAX_CELL_PROCESSES_IN_QUEUE) {
+ spin_unlock_irqrestore(&q->check_lock, flags);
+ goto __again;
+ }
}
q->check_blocked = 0;
spin_unlock_irqrestore(&q->check_lock, flags);
diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h
index 9254c8dbe5e3..25d2d6b61007 100644
--- a/sound/core/seq/seq_queue.h
+++ b/sound/core/seq/seq_queue.h
@@ -26,10 +26,10 @@ struct snd_seq_queue {
struct snd_seq_timer *timer; /* time keeper for this queue */
int owner; /* client that 'owns' the timer */
- unsigned int locked:1, /* timer is only accesibble by owner if set */
- klocked:1, /* kernel lock (after START) */
- check_again:1,
- check_blocked:1;
+ bool locked; /* timer is only accesibble by owner if set */
+ bool klocked; /* kernel lock (after START) */
+ bool check_again; /* concurrent access happened during check */
+ bool check_blocked; /* queue being checked */
unsigned int flags; /* status flags */
unsigned int info_flags; /* info for sync */
diff --git a/sound/core/seq_device.c b/sound/core/seq_device.c
index e9dbad93f9d0..c9223049551c 100644
--- a/sound/core/seq_device.c
+++ b/sound/core/seq_device.c
@@ -147,6 +147,8 @@ static int snd_seq_device_dev_free(struct snd_device *device)
struct snd_seq_device *dev = device->device_data;
cancel_autoload_drivers();
+ if (dev->private_free)
+ dev->private_free(dev);
put_device(&dev->dev);
return 0;
}
@@ -174,11 +176,7 @@ static int snd_seq_device_dev_disconnect(struct snd_device *device)
static void snd_seq_dev_release(struct device *dev)
{
- struct snd_seq_device *sdev = to_seq_dev(dev);
-
- if (sdev->private_free)
- sdev->private_free(sdev);
- kfree(sdev);
+ kfree(to_seq_dev(dev));
}
/*
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 013f0e69ff0f..d684aa4150aa 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -491,9 +491,10 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
return;
if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
return;
+ event += 10; /* convert to SNDRV_TIMER_EVENT_MXXX */
list_for_each_entry(ts, &ti->slave_active_head, active_list)
if (ts->ccallback)
- ts->ccallback(ts, event + 100, &tstamp, resolution);
+ ts->ccallback(ts, event, &tstamp, resolution);
}
/* start/continue a master timer */
@@ -594,13 +595,13 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop)
if (!timer)
return -EINVAL;
spin_lock_irqsave(&timer->lock, flags);
+ list_del_init(&timeri->ack_list);
+ list_del_init(&timeri->active_list);
if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
SNDRV_TIMER_IFLG_START))) {
result = -EBUSY;
goto unlock;
}
- list_del_init(&timeri->ack_list);
- list_del_init(&timeri->active_list);
if (timer->card && timer->card->shutdown)
goto unlock;
if (stop) {
@@ -635,23 +636,22 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop)
static int snd_timer_stop_slave(struct snd_timer_instance *timeri, bool stop)
{
unsigned long flags;
+ bool running;
spin_lock_irqsave(&slave_active_lock, flags);
- if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
- spin_unlock_irqrestore(&slave_active_lock, flags);
- return -EBUSY;
- }
+ running = timeri->flags & SNDRV_TIMER_IFLG_RUNNING;
timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
if (timeri->timer) {
spin_lock(&timeri->timer->lock);
list_del_init(&timeri->ack_list);
list_del_init(&timeri->active_list);
- snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP :
- SNDRV_TIMER_EVENT_PAUSE);
+ if (running)
+ snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP :
+ SNDRV_TIMER_EVENT_PAUSE);
spin_unlock(&timeri->timer->lock);
}
spin_unlock_irqrestore(&slave_active_lock, flags);
- return 0;
+ return running ? 0 : -EBUSY;
}
/*
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 9ccdad89c288..452b9eaca815 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -1035,6 +1035,14 @@ static int loopback_mixer_new(struct loopback *loopback, int notify)
return -ENOMEM;
kctl->id.device = dev;
kctl->id.subdevice = substr;
+
+ /* Add the control before copying the id so that
+ * the numid field of the id is set in the copy.
+ */
+ err = snd_ctl_add(card, kctl);
+ if (err < 0)
+ return err;
+
switch (idx) {
case ACTIVE_IDX:
setup->active_id = kctl->id;
@@ -1051,9 +1059,6 @@ static int loopback_mixer_new(struct loopback *loopback, int notify)
default:
break;
}
- err = snd_ctl_add(card, kctl);
- if (err < 0)
- return err;
}
}
}
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
index 280cc79870cf..ce38ec09d408 100644
--- a/sound/drivers/opl3/opl3_midi.c
+++ b/sound/drivers/opl3/opl3_midi.c
@@ -398,7 +398,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)
}
if (instr_4op) {
vp2 = &opl3->voices[voice + 3];
- if (vp->state > 0) {
+ if (vp2->state > 0) {
opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK +
voice_offset + 3);
reg_val = vp->keyon_reg & ~OPL3_KEYON_BIT;
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig
index b0a904cdb932..e469375e2f2a 100644
--- a/sound/firewire/Kconfig
+++ b/sound/firewire/Kconfig
@@ -38,7 +38,7 @@ config SND_OXFW
* Mackie(Loud) Onyx 1640i (former model)
* Mackie(Loud) Onyx Satellite
* Mackie(Loud) Tapco Link.Firewire
- * Mackie(Loud) d.2 pro/d.4 pro
+ * Mackie(Loud) d.2 pro/d.4 pro (built-in FireWire card with OXFW971 ASIC)
* Mackie(Loud) U.420/U.420d
* TASCAM FireOne
* Stanton Controllers & Systems 1 Deck/Mixer
@@ -84,7 +84,7 @@ config SND_BEBOB
* PreSonus FIREBOX/FIREPOD/FP10/Inspire1394
* BridgeCo RDAudio1/Audio5
* Mackie Onyx 1220/1620/1640 (FireWire I/O Card)
- * Mackie d.2 (FireWire Option)
+ * Mackie d.2 (optional FireWire card with DM1000 ASIC)
* Stanton FinalScratch 2 (ScratchAmp)
* Tascam IF-FW/DM
* Behringer XENIX UFX 1204/1604
@@ -110,6 +110,7 @@ config SND_BEBOB
* M-Audio Ozonic/NRV10/ProfireLightBridge
* M-Audio FireWire 1814/ProjectMix IO
* Digidesign Mbox 2 Pro
+ * ToneWeal FW66
To compile this driver as a module, choose M here: the module
will be called snd-bebob.
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index e50e28f77e74..07e58dcad4af 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -617,18 +617,24 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle,
unsigned int *syt, unsigned int index)
{
const __be32 *cip_header;
+ unsigned int cip_header_size;
int err;
*payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT;
- if (*payload_length > s->ctx_data.tx.ctx_header_size +
- s->ctx_data.tx.max_ctx_payload_length) {
+
+ if (!(s->flags & CIP_NO_HEADER))
+ cip_header_size = 8;
+ else
+ cip_header_size = 0;
+
+ if (*payload_length > cip_header_size + s->ctx_data.tx.max_ctx_payload_length) {
dev_err(&s->unit->device,
"Detect jumbo payload: %04x %04x\n",
- *payload_length, s->ctx_data.tx.max_ctx_payload_length);
+ *payload_length, cip_header_size + s->ctx_data.tx.max_ctx_payload_length);
return -EIO;
}
- if (!(s->flags & CIP_NO_HEADER)) {
+ if (cip_header_size > 0) {
cip_header = ctx_header + 2;
err = check_cip_header(s, cip_header, *payload_length,
data_blocks, data_block_counter, syt);
@@ -932,23 +938,22 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
s->ctx_data.rx.last_syt_offset = TICKS_PER_CYCLE;
}
- /* initialize packet buffer */
+ // initialize packet buffer.
+ max_ctx_payload_size = amdtp_stream_get_max_payload(s);
if (s->direction == AMDTP_IN_STREAM) {
dir = DMA_FROM_DEVICE;
type = FW_ISO_CONTEXT_RECEIVE;
- if (!(s->flags & CIP_NO_HEADER))
+ if (!(s->flags & CIP_NO_HEADER)) {
+ max_ctx_payload_size -= 8;
ctx_header_size = IR_CTX_HEADER_SIZE_CIP;
- else
+ } else {
ctx_header_size = IR_CTX_HEADER_SIZE_NO_CIP;
-
- max_ctx_payload_size = amdtp_stream_get_max_payload(s) -
- ctx_header_size;
+ }
} else {
dir = DMA_TO_DEVICE;
type = FW_ISO_CONTEXT_TRANSMIT;
ctx_header_size = 0; // No effect for IT context.
- max_ctx_payload_size = amdtp_stream_get_max_payload(s);
if (!(s->flags & CIP_NO_HEADER))
max_ctx_payload_size -= IT_PKT_HEADER_SIZE_CIP;
}
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c
index 976d8cb9a34f..d58f4fe2be8c 100644
--- a/sound/firewire/bebob/bebob.c
+++ b/sound/firewire/bebob/bebob.c
@@ -59,6 +59,7 @@ static DECLARE_BITMAP(devices_used, SNDRV_CARDS);
#define VEN_MAUDIO1 0x00000d6c
#define VEN_MAUDIO2 0x000007f5
#define VEN_DIGIDESIGN 0x00a07e
+#define OUI_SHOUYO 0x002327
#define MODEL_FOCUSRITE_SAFFIRE_BOTH 0x00000000
#define MODEL_MAUDIO_AUDIOPHILE_BOTH 0x00010060
@@ -387,7 +388,7 @@ static const struct ieee1394_device_id bebob_id_table[] = {
SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010049, &spec_normal),
/* Mackie, Onyx 1220/1620/1640 (Firewire I/O Card) */
SND_BEBOB_DEV_ENTRY(VEN_MACKIE2, 0x00010065, &spec_normal),
- /* Mackie, d.2 (Firewire Option) */
+ // Mackie, d.2 (optional Firewire card with DM1000).
SND_BEBOB_DEV_ENTRY(VEN_MACKIE1, 0x00010067, &spec_normal),
/* Stanton, ScratchAmp */
SND_BEBOB_DEV_ENTRY(VEN_STANTON, 0x00000001, &spec_normal),
@@ -486,6 +487,8 @@ static const struct ieee1394_device_id bebob_id_table[] = {
&maudio_special_spec),
/* Digidesign Mbox 2 Pro */
SND_BEBOB_DEV_ENTRY(VEN_DIGIDESIGN, 0x0000a9, &spec_normal),
+ // Toneweal FW66.
+ SND_BEBOB_DEV_ENTRY(OUI_SHOUYO, 0x020002, &spec_normal),
/* IDs are unknown but able to be supported */
/* Apogee, Mini-ME Firewire */
/* Apogee, Mini-DAC Firewire */
diff --git a/sound/firewire/bebob/bebob_hwdep.c b/sound/firewire/bebob/bebob_hwdep.c
index 45b740f44c45..c362eb38ab90 100644
--- a/sound/firewire/bebob/bebob_hwdep.c
+++ b/sound/firewire/bebob/bebob_hwdep.c
@@ -36,12 +36,11 @@ hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
}
memset(&event, 0, sizeof(event));
+ count = min_t(long, count, sizeof(event.lock_status));
if (bebob->dev_lock_changed) {
event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
event.lock_status.status = (bebob->dev_lock_count > 0);
bebob->dev_lock_changed = false;
-
- count = min_t(long, count, sizeof(event.lock_status));
}
spin_unlock_irq(&bebob->lock);
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c
index ce07ea0d4e71..3935e90c8e8f 100644
--- a/sound/firewire/bebob/bebob_stream.c
+++ b/sound/firewire/bebob/bebob_stream.c
@@ -534,20 +534,22 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob)
static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream,
unsigned int rate, unsigned int index)
{
- struct snd_bebob_stream_formation *formation;
+ unsigned int pcm_channels;
+ unsigned int midi_ports;
struct cmp_connection *conn;
int err;
if (stream == &bebob->tx_stream) {
- formation = bebob->tx_stream_formations + index;
+ pcm_channels = bebob->tx_stream_formations[index].pcm;
+ midi_ports = bebob->midi_input_ports;
conn = &bebob->out_conn;
} else {
- formation = bebob->rx_stream_formations + index;
+ pcm_channels = bebob->rx_stream_formations[index].pcm;
+ midi_ports = bebob->midi_output_ports;
conn = &bebob->in_conn;
}
- err = amdtp_am824_set_parameters(stream, rate, formation->pcm,
- formation->midi, false);
+ err = amdtp_am824_set_parameters(stream, rate, pcm_channels, midi_ports, false);
if (err < 0)
return err;
diff --git a/sound/firewire/dice/dice-alesis.c b/sound/firewire/dice/dice-alesis.c
index f5b325263b67..39a4ef8c8543 100644
--- a/sound/firewire/dice/dice-alesis.c
+++ b/sound/firewire/dice/dice-alesis.c
@@ -16,7 +16,7 @@ alesis_io14_tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT] = {
static const unsigned int
alesis_io26_tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT] = {
{10, 10, 4}, /* Tx0 = Analog + S/PDIF. */
- {16, 8, 0}, /* Tx1 = ADAT1 + ADAT2. */
+ {16, 4, 0}, /* Tx1 = ADAT1 + ADAT2 (available at low rate). */
};
int snd_dice_detect_alesis_formats(struct snd_dice *dice)
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c
index f6a8627ae5a2..0aa3c56cf390 100644
--- a/sound/firewire/dice/dice-stream.c
+++ b/sound/firewire/dice/dice-stream.c
@@ -489,11 +489,10 @@ void snd_dice_stream_stop_duplex(struct snd_dice *dice)
struct reg_params tx_params, rx_params;
if (dice->substreams_counter == 0) {
- if (get_register_params(dice, &tx_params, &rx_params) >= 0) {
- amdtp_domain_stop(&dice->domain);
+ if (get_register_params(dice, &tx_params, &rx_params) >= 0)
finish_session(dice, &tx_params, &rx_params);
- }
+ amdtp_domain_stop(&dice->domain);
release_resources(dice);
}
}
diff --git a/sound/firewire/dice/dice-tcelectronic.c b/sound/firewire/dice/dice-tcelectronic.c
index a8875d24ba2a..43a3bcb15b3d 100644
--- a/sound/firewire/dice/dice-tcelectronic.c
+++ b/sound/firewire/dice/dice-tcelectronic.c
@@ -38,8 +38,8 @@ static const struct dice_tc_spec konnekt_24d = {
};
static const struct dice_tc_spec konnekt_live = {
- .tx_pcm_chs = {{16, 16, 16}, {0, 0, 0} },
- .rx_pcm_chs = {{16, 16, 16}, {0, 0, 0} },
+ .tx_pcm_chs = {{16, 16, 6}, {0, 0, 0} },
+ .rx_pcm_chs = {{16, 16, 6}, {0, 0, 0} },
.has_midi = true,
};
diff --git a/sound/firewire/fcp.c b/sound/firewire/fcp.c
index bbfbebf4affb..df44dd5dc4b2 100644
--- a/sound/firewire/fcp.c
+++ b/sound/firewire/fcp.c
@@ -240,9 +240,7 @@ int fcp_avc_transaction(struct fw_unit *unit,
t.response_match_bytes = response_match_bytes;
t.state = STATE_PENDING;
init_waitqueue_head(&t.wait);
-
- if (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03)
- t.deferrable = true;
+ t.deferrable = (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03);
spin_lock_irq(&transactions_lock);
list_add_tail(&t.list, &transactions);
diff --git a/sound/firewire/fireface/ff-transaction.c b/sound/firewire/fireface/ff-transaction.c
index 7f82762ccc8c..ee7122c461d4 100644
--- a/sound/firewire/fireface/ff-transaction.c
+++ b/sound/firewire/fireface/ff-transaction.c
@@ -88,7 +88,7 @@ static void transmit_midi_msg(struct snd_ff *ff, unsigned int port)
/* Set interval to next transaction. */
ff->next_ktime[port] = ktime_add_ns(ktime_get(),
- ff->rx_bytes[port] * 8 * NSEC_PER_SEC / 31250);
+ ff->rx_bytes[port] * 8 * (NSEC_PER_SEC / 31250));
if (quad_count == 1)
tcode = TCODE_WRITE_QUADLET_REQUEST;
diff --git a/sound/firewire/fireworks/fireworks_hwdep.c b/sound/firewire/fireworks/fireworks_hwdep.c
index e93eb4616c5f..c739173c668f 100644
--- a/sound/firewire/fireworks/fireworks_hwdep.c
+++ b/sound/firewire/fireworks/fireworks_hwdep.c
@@ -34,6 +34,7 @@ hwdep_read_resp_buf(struct snd_efw *efw, char __user *buf, long remained,
type = SNDRV_FIREWIRE_EVENT_EFW_RESPONSE;
if (copy_to_user(buf, &type, sizeof(type)))
return -EFAULT;
+ count += sizeof(type);
remained -= sizeof(type);
buf += sizeof(type);
diff --git a/sound/firewire/fireworks/fireworks_transaction.c b/sound/firewire/fireworks/fireworks_transaction.c
index 0f533f5bd960..9f8c53b39f95 100644
--- a/sound/firewire/fireworks/fireworks_transaction.c
+++ b/sound/firewire/fireworks/fireworks_transaction.c
@@ -123,7 +123,7 @@ copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode)
t = (struct snd_efw_transaction *)data;
length = min_t(size_t, be32_to_cpu(t->length) * sizeof(u32), length);
- spin_lock_irq(&efw->lock);
+ spin_lock(&efw->lock);
if (efw->push_ptr < efw->pull_ptr)
capacity = (unsigned int)(efw->pull_ptr - efw->push_ptr);
@@ -190,7 +190,7 @@ handle_resp_for_user(struct fw_card *card, int generation, int source,
copy_resp_to_buf(efw, data, length, rcode);
end:
- spin_unlock_irq(&instances_lock);
+ spin_unlock(&instances_lock);
}
static void
diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c
index fb6df3fc018e..bebb2b8296cb 100644
--- a/sound/firewire/oxfw/oxfw.c
+++ b/sound/firewire/oxfw/oxfw.c
@@ -350,8 +350,7 @@ static const struct ieee1394_device_id oxfw_id_table[] = {
* Onyx-i series (former models): 0x081216
* Mackie Onyx Satellite: 0x00200f
* Tapco LINK.firewire 4x6: 0x000460
- * d.2 pro: Unknown
- * d.4 pro: Unknown
+ * d.2 pro/d.4 pro (built-in card): Unknown
* U.420: Unknown
* U.420d: Unknown
*/
diff --git a/sound/firewire/tascam/tascam-transaction.c b/sound/firewire/tascam/tascam-transaction.c
index 90288b4b4637..a073cece4a7d 100644
--- a/sound/firewire/tascam/tascam-transaction.c
+++ b/sound/firewire/tascam/tascam-transaction.c
@@ -209,7 +209,7 @@ static void midi_port_work(struct work_struct *work)
/* Set interval to next transaction. */
port->next_ktime = ktime_add_ns(ktime_get(),
- port->consume_bytes * 8 * NSEC_PER_SEC / 31250);
+ port->consume_bytes * 8 * (NSEC_PER_SEC / 31250));
/* Start this transaction. */
port->idling = false;
diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c
index 09ff209df4a3..c87187f63573 100644
--- a/sound/hda/ext/hdac_ext_controller.c
+++ b/sound/hda/ext/hdac_ext_controller.c
@@ -148,6 +148,8 @@ struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_bus *bus,
return NULL;
if (bus->idx != bus_idx)
return NULL;
+ if (addr < 0 || addr > 31)
+ return NULL;
list_for_each_entry(hlink, &bus->hlink_list, list) {
for (i = 0; i < HDA_MAX_CODECS; i++) {
diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c
index 6b1b4b834bae..04f4070fbf36 100644
--- a/sound/hda/ext/hdac_ext_stream.c
+++ b/sound/hda/ext/hdac_ext_stream.c
@@ -106,20 +106,14 @@ void snd_hdac_stream_free_all(struct hdac_bus *bus)
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_free_all);
-/**
- * snd_hdac_ext_stream_decouple - decouple the hdac stream
- * @bus: HD-audio core bus
- * @stream: HD-audio ext core stream object to initialize
- * @decouple: flag to decouple
- */
-void snd_hdac_ext_stream_decouple(struct hdac_bus *bus,
- struct hdac_ext_stream *stream, bool decouple)
+void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus,
+ struct hdac_ext_stream *stream,
+ bool decouple)
{
struct hdac_stream *hstream = &stream->hstream;
u32 val;
int mask = AZX_PPCTL_PROCEN(hstream->index);
- spin_lock_irq(&bus->reg_lock);
val = readw(bus->ppcap + AZX_REG_PP_PPCTL) & mask;
if (decouple && !val)
@@ -128,6 +122,20 @@ void snd_hdac_ext_stream_decouple(struct hdac_bus *bus,
snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, mask, 0);
stream->decoupled = decouple;
+}
+EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_decouple_locked);
+
+/**
+ * snd_hdac_ext_stream_decouple - decouple the hdac stream
+ * @bus: HD-audio core bus
+ * @stream: HD-audio ext core stream object to initialize
+ * @decouple: flag to decouple
+ */
+void snd_hdac_ext_stream_decouple(struct hdac_bus *bus,
+ struct hdac_ext_stream *stream, bool decouple)
+{
+ spin_lock_irq(&bus->reg_lock);
+ snd_hdac_ext_stream_decouple_locked(bus, stream, decouple);
spin_unlock_irq(&bus->reg_lock);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_decouple);
@@ -252,6 +260,7 @@ hdac_ext_link_stream_assign(struct hdac_bus *bus,
return NULL;
}
+ spin_lock_irq(&bus->reg_lock);
list_for_each_entry(stream, &bus->stream_list, list) {
struct hdac_ext_stream *hstream = container_of(stream,
struct hdac_ext_stream,
@@ -266,17 +275,16 @@ hdac_ext_link_stream_assign(struct hdac_bus *bus,
}
if (!hstream->link_locked) {
- snd_hdac_ext_stream_decouple(bus, hstream, true);
+ snd_hdac_ext_stream_decouple_locked(bus, hstream, true);
res = hstream;
break;
}
}
if (res) {
- spin_lock_irq(&bus->reg_lock);
res->link_locked = 1;
res->link_substream = substream;
- spin_unlock_irq(&bus->reg_lock);
}
+ spin_unlock_irq(&bus->reg_lock);
return res;
}
@@ -292,6 +300,7 @@ hdac_ext_host_stream_assign(struct hdac_bus *bus,
return NULL;
}
+ spin_lock_irq(&bus->reg_lock);
list_for_each_entry(stream, &bus->stream_list, list) {
struct hdac_ext_stream *hstream = container_of(stream,
struct hdac_ext_stream,
@@ -301,18 +310,17 @@ hdac_ext_host_stream_assign(struct hdac_bus *bus,
if (!stream->opened) {
if (!hstream->decoupled)
- snd_hdac_ext_stream_decouple(bus, hstream, true);
+ snd_hdac_ext_stream_decouple_locked(bus, hstream, true);
res = hstream;
break;
}
}
if (res) {
- spin_lock_irq(&bus->reg_lock);
res->hstream.opened = 1;
res->hstream.running = 0;
res->hstream.substream = substream;
- spin_unlock_irq(&bus->reg_lock);
}
+ spin_unlock_irq(&bus->reg_lock);
return res;
}
@@ -378,15 +386,17 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *stream, int type)
break;
case HDAC_EXT_STREAM_TYPE_HOST:
+ spin_lock_irq(&bus->reg_lock);
if (stream->decoupled && !stream->link_locked)
- snd_hdac_ext_stream_decouple(bus, stream, false);
+ snd_hdac_ext_stream_decouple_locked(bus, stream, false);
+ spin_unlock_irq(&bus->reg_lock);
snd_hdac_stream_release(&stream->hstream);
break;
case HDAC_EXT_STREAM_TYPE_LINK:
- if (stream->decoupled && !stream->hstream.opened)
- snd_hdac_ext_stream_decouple(bus, stream, false);
spin_lock_irq(&bus->reg_lock);
+ if (stream->decoupled && !stream->hstream.opened)
+ snd_hdac_ext_stream_decouple_locked(bus, stream, false);
stream->link_locked = 0;
stream->link_substream = NULL;
spin_unlock_irq(&bus->reg_lock);
diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c
index 7e7be8e4dcf9..87ba66dcfd47 100644
--- a/sound/hda/hdac_controller.c
+++ b/sound/hda/hdac_controller.c
@@ -395,8 +395,9 @@ int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset)
if (!full_reset)
goto skip_reset;
- /* clear STATESTS */
- snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK);
+ /* clear STATESTS if not in reset */
+ if (snd_hdac_chip_readb(bus, GCTL) & AZX_GCTL_RESET)
+ snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK);
/* reset controller */
snd_hdac_bus_enter_link_reset(bus);
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c
index b84e12f4f804..489f996d86bc 100644
--- a/sound/hda/hdac_device.c
+++ b/sound/hda/hdac_device.c
@@ -656,6 +656,7 @@ static struct hda_vendor_id hda_vendor_ids[] = {
{ 0x14f1, "Conexant" },
{ 0x17e8, "Chrontel" },
{ 0x1854, "LG" },
+ { 0x19e5, "Huawei" },
{ 0x1aec, "Wolfson Microelectronics" },
{ 0x1af4, "QEMU" },
{ 0x434d, "C-Media" },
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c
index 682ed39f79b0..b299b8b7f871 100644
--- a/sound/hda/hdac_stream.c
+++ b/sound/hda/hdac_stream.c
@@ -289,6 +289,7 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus,
int key = (substream->pcm->device << 16) | (substream->number << 2) |
(substream->stream + 1);
+ spin_lock_irq(&bus->reg_lock);
list_for_each_entry(azx_dev, &bus->stream_list, list) {
if (azx_dev->direction != substream->stream)
continue;
@@ -302,13 +303,12 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus,
res = azx_dev;
}
if (res) {
- spin_lock_irq(&bus->reg_lock);
res->opened = 1;
res->running = 0;
res->assigned_key = key;
res->substream = substream;
- spin_unlock_irq(&bus->reg_lock);
}
+ spin_unlock_irq(&bus->reg_lock);
return res;
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_assign);
diff --git a/sound/hda/intel-nhlt.c b/sound/hda/intel-nhlt.c
index daede96f28ee..6ed80a4cba01 100644
--- a/sound/hda/intel-nhlt.c
+++ b/sound/hda/intel-nhlt.c
@@ -64,18 +64,49 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
struct nhlt_endpoint *epnt;
struct nhlt_dmic_array_config *cfg;
struct nhlt_vendor_dmic_array_config *cfg_vendor;
+ struct nhlt_fmt *fmt_configs;
unsigned int dmic_geo = 0;
- u8 j;
+ u16 max_ch = 0;
+ u8 i, j;
if (!nhlt)
return 0;
- epnt = (struct nhlt_endpoint *)nhlt->desc;
+ if (nhlt->header.length <= sizeof(struct acpi_table_header)) {
+ dev_warn(dev, "Invalid DMIC description table\n");
+ return 0;
+ }
+
+ for (j = 0, epnt = nhlt->desc; j < nhlt->endpoint_count; j++,
+ epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length)) {
+
+ if (epnt->linktype != NHLT_LINK_DMIC)
+ continue;
+
+ cfg = (struct nhlt_dmic_array_config *)(epnt->config.caps);
+ fmt_configs = (struct nhlt_fmt *)(epnt->config.caps + epnt->config.size);
+
+ /* find max number of channels based on format_configuration */
+ if (fmt_configs->fmt_count) {
+ dev_dbg(dev, "%s: found %d format definitions\n",
+ __func__, fmt_configs->fmt_count);
+
+ for (i = 0; i < fmt_configs->fmt_count; i++) {
+ struct wav_fmt_ext *fmt_ext;
+
+ fmt_ext = &fmt_configs->fmt_config[i].fmt_ext;
- for (j = 0; j < nhlt->endpoint_count; j++) {
- if (epnt->linktype == NHLT_LINK_DMIC) {
- cfg = (struct nhlt_dmic_array_config *)
- (epnt->config.caps);
+ if (fmt_ext->fmt.channels > max_ch)
+ max_ch = fmt_ext->fmt.channels;
+ }
+ dev_dbg(dev, "%s: max channels found %d\n", __func__, max_ch);
+ } else {
+ dev_dbg(dev, "%s: No format information found\n", __func__);
+ }
+
+ if (cfg->device_config.config_type != NHLT_CONFIG_TYPE_MIC_ARRAY) {
+ dmic_geo = max_ch;
+ } else {
switch (cfg->array_type) {
case NHLT_MIC_ARRAY_2CH_SMALL:
case NHLT_MIC_ARRAY_2CH_BIG:
@@ -92,13 +123,23 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
dmic_geo = cfg_vendor->nb_mics;
break;
default:
- dev_warn(dev, "undefined DMIC array_type 0x%0x\n",
- cfg->array_type);
+ dev_warn(dev, "%s: undefined DMIC array_type 0x%0x\n",
+ __func__, cfg->array_type);
+ }
+
+ if (dmic_geo > 0) {
+ dev_dbg(dev, "%s: Array with %d dmics\n", __func__, dmic_geo);
+ }
+ if (max_ch > dmic_geo) {
+ dev_dbg(dev, "%s: max channels %d exceed dmic number %d\n",
+ __func__, max_ch, dmic_geo);
}
}
- epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
}
+ dev_dbg(dev, "%s: dmic number %d max_ch %d\n",
+ __func__, dmic_geo, max_ch);
+
return dmic_geo;
}
EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo);
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index b690ed937cbe..df2e45c8814e 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -22,7 +22,7 @@ config SND_SB16_DSP
menuconfig SND_ISA
bool "ISA sound devices"
depends on ISA || COMPILE_TEST
- depends on ISA_DMA_API
+ depends on ISA_DMA_API && !M68K
default y
help
Support for sound devices connected via the ISA bus.
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index bb7d4940ac25..281ecd0eea48 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -549,7 +549,7 @@ static int snd_cmi8330_probe(struct snd_card *card, int dev)
}
if (acard->sb->hardware != SB_HW_16) {
snd_printk(KERN_ERR PFX "SB16 not found during probe\n");
- return err;
+ return -ENODEV;
}
snd_wss_out(acard->wss, CS4231_MISC_INFO, 0x40); /* switch on MODE2 */
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index fa3c39cff5f8..9ee3a312c679 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -544,7 +544,7 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
static int dev;
int err;
struct snd_card *card;
- struct pnp_dev *cdev;
+ struct pnp_dev *cdev, *iter;
char cid[PNP_ID_LEN];
if (pnp_device_is_isapnp(pdev))
@@ -560,9 +560,11 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
strcpy(cid, pdev->id[0].id);
cid[5] = '1';
cdev = NULL;
- list_for_each_entry(cdev, &(pdev->protocol->devices), protocol_list) {
- if (!strcmp(cdev->id[0].id, cid))
+ list_for_each_entry(iter, &(pdev->protocol->devices), protocol_list) {
+ if (!strcmp(iter->id[0].id, cid)) {
+ cdev = iter;
break;
+ }
}
err = snd_cs423x_card_new(&pdev->dev, dev, &card);
if (err < 0)
diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c
index a1c770d826dd..6d664dd8dde0 100644
--- a/sound/isa/gus/gus_dma.c
+++ b/sound/isa/gus/gus_dma.c
@@ -126,6 +126,8 @@ static void snd_gf1_dma_interrupt(struct snd_gus_card * gus)
}
block = snd_gf1_dma_next_block(gus);
spin_unlock(&gus->dma_lock);
+ if (!block)
+ return;
snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd);
kfree(block);
#if 0
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index af6b4d89d695..39911a637e80 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -77,17 +77,8 @@ static const struct snd_kcontrol_new snd_gus_joystick_control = {
static void snd_gus_init_control(struct snd_gus_card *gus)
{
- int ret;
-
- if (!gus->ace_flag) {
- ret =
- snd_ctl_add(gus->card,
- snd_ctl_new1(&snd_gus_joystick_control,
- gus));
- if (ret)
- snd_printk(KERN_ERR "gus: snd_ctl_add failed: %d\n",
- ret);
- }
+ if (!gus->ace_flag)
+ snd_ctl_add(gus->card, snd_ctl_new1(&snd_gus_joystick_control, gus));
}
/*
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 433e32e254f9..91c96fad0618 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -1029,8 +1029,10 @@ snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
memset(emu->controls, 0, sizeof(emu->controls));
for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
- if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0)
+ if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0) {
+ emu->controls[i] = NULL;
goto __error;
+ }
}
return 0;
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index 4ad0ff0c4508..30021ab5e0e9 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -814,6 +814,7 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel
mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7);
+ spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
spin_lock(&p->chip->reg_lock);
set_mode_register(p->chip, 0xc0); /* c0 = STOP */
@@ -853,6 +854,7 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel
spin_unlock(&p->chip->reg_lock);
/* restore PCM volume */
+ spin_lock_irqsave(&p->chip->mixer_lock, flags);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR);
spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
@@ -878,6 +880,7 @@ static int snd_sb_csp_stop(struct snd_sb_csp * p)
mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7);
+ spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
spin_lock(&p->chip->reg_lock);
if (p->running & SNDRV_SB_CSP_ST_QSOUND) {
@@ -892,6 +895,7 @@ static int snd_sb_csp_stop(struct snd_sb_csp * p)
spin_unlock(&p->chip->reg_lock);
/* restore PCM volume */
+ spin_lock_irqsave(&p->chip->mixer_lock, flags);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR);
spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
@@ -1045,10 +1049,14 @@ static int snd_sb_qsound_build(struct snd_sb_csp * p)
spin_lock_init(&p->q_lock);
- if ((err = snd_ctl_add(card, p->qsound_switch = snd_ctl_new1(&snd_sb_qsound_switch, p))) < 0)
+ if ((err = snd_ctl_add(card, p->qsound_switch = snd_ctl_new1(&snd_sb_qsound_switch, p))) < 0) {
+ p->qsound_switch = NULL;
goto __error;
- if ((err = snd_ctl_add(card, p->qsound_space = snd_ctl_new1(&snd_sb_qsound_space, p))) < 0)
+ }
+ if ((err = snd_ctl_add(card, p->qsound_space = snd_ctl_new1(&snd_sb_qsound_space, p))) < 0) {
+ p->qsound_space = NULL;
goto __error;
+ }
return 0;
@@ -1068,10 +1076,14 @@ static void snd_sb_qsound_destroy(struct snd_sb_csp * p)
card = p->chip->card;
down_write(&card->controls_rwsem);
- if (p->qsound_switch)
+ if (p->qsound_switch) {
snd_ctl_remove(card, p->qsound_switch);
- if (p->qsound_space)
+ p->qsound_switch = NULL;
+ }
+ if (p->qsound_space) {
snd_ctl_remove(card, p->qsound_space);
+ p->qsound_space = NULL;
+ }
up_write(&card->controls_rwsem);
/* cancel pending transfer of QSound parameters */
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
index 0768bbf8fd71..679f9f48370f 100644
--- a/sound/isa/sb/sb16_main.c
+++ b/sound/isa/sb/sb16_main.c
@@ -864,14 +864,10 @@ int snd_sb16dsp_pcm(struct snd_sb *chip, int device)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb16_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb16_capture_ops);
- if (chip->dma16 >= 0 && chip->dma8 != chip->dma16) {
- err = snd_ctl_add(card, snd_ctl_new1(
- &snd_sb16_dma_control, chip));
- if (err)
- return err;
- } else {
+ if (chip->dma16 >= 0 && chip->dma8 != chip->dma16)
+ snd_ctl_add(card, snd_ctl_new1(&snd_sb16_dma_control, chip));
+ else
pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
- }
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
card->dev,
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index d67eae3988bd..6f1fc8789676 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -96,10 +96,6 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
/* block the 0x388 port to avoid PnP conflicts */
acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
- if (!acard->fm_res) {
- err = -EBUSY;
- goto _err;
- }
if (port[dev] != SNDRV_AUTO_PORT) {
if ((err = snd_sbdsp_create(card, port[dev], irq[dev],
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index d6420d224d09..09b368761cc0 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -1088,7 +1088,8 @@ wavefront_send_sample (snd_wavefront_t *dev,
if (dataptr < data_end) {
- __get_user (sample_short, dataptr);
+ if (get_user(sample_short, dataptr))
+ return -EFAULT;
dataptr += skip;
if (data_is_unsigned) { /* GUS ? */
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 7630f808d087..6edde2f14502 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -279,6 +279,7 @@ config SND_CS46XX_NEW_DSP
config SND_CS5530
tristate "CS5530 Audio"
depends on ISA_DMA_API && (X86_32 || COMPILE_TEST)
+ depends on !M68K
select SND_SB16_DSP
help
Say Y here to include support for audio on Cyrix/NatSemi CS5530 chips.
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 66f6c3bf08e3..6fb192a94762 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -938,8 +938,8 @@ static int snd_ac97_ad18xx_pcm_get_volume(struct snd_kcontrol *kcontrol, struct
int codec = kcontrol->private_value & 3;
mutex_lock(&ac97->page_mutex);
- ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31);
- ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31);
+ ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31);
+ ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31);
mutex_unlock(&ac97->page_mutex);
return 0;
}
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index df720881eb99..db9d89ba3658 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -302,7 +302,6 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#define CM_MICGAINZ 0x01 /* mic boost */
#define CM_MICGAINZ_SHIFT 0
-#define CM_REG_MIXER3 0x24
#define CM_REG_AUX_VOL 0x26
#define CM_VAUXL_MASK 0xf0
#define CM_VAUXR_MASK 0x0f
@@ -3310,7 +3309,7 @@ static void snd_cmipci_remove(struct pci_dev *pci)
*/
static unsigned char saved_regs[] = {
CM_REG_FUNCTRL1, CM_REG_CHFORMAT, CM_REG_LEGACY_CTRL, CM_REG_MISC_CTRL,
- CM_REG_MIXER0, CM_REG_MIXER1, CM_REG_MIXER2, CM_REG_MIXER3, CM_REG_PLL,
+ CM_REG_MIXER0, CM_REG_MIXER1, CM_REG_MIXER2, CM_REG_AUX_VOL, CM_REG_PLL,
CM_REG_CH0_FRAME1, CM_REG_CH0_FRAME2,
CM_REG_CH1_FRAME1, CM_REG_CH1_FRAME2, CM_REG_EXT_MISC,
CM_REG_INT_STATUS, CM_REG_INT_HLDCLR, CM_REG_FUNCTRL0,
diff --git a/sound/pci/ctxfi/ctamixer.c b/sound/pci/ctxfi/ctamixer.c
index d4ff377eb3a3..6d636bdcaa5a 100644
--- a/sound/pci/ctxfi/ctamixer.c
+++ b/sound/pci/ctxfi/ctamixer.c
@@ -23,16 +23,15 @@
#define BLANK_SLOT 4094
-static int amixer_master(struct rsc *rsc)
+static void amixer_master(struct rsc *rsc)
{
rsc->conj = 0;
- return rsc->idx = container_of(rsc, struct amixer, rsc)->idx[0];
+ rsc->idx = container_of(rsc, struct amixer, rsc)->idx[0];
}
-static int amixer_next_conj(struct rsc *rsc)
+static void amixer_next_conj(struct rsc *rsc)
{
rsc->conj++;
- return container_of(rsc, struct amixer, rsc)->idx[rsc->conj];
}
static int amixer_index(const struct rsc *rsc)
@@ -331,16 +330,15 @@ int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr)
/* SUM resource management */
-static int sum_master(struct rsc *rsc)
+static void sum_master(struct rsc *rsc)
{
rsc->conj = 0;
- return rsc->idx = container_of(rsc, struct sum, rsc)->idx[0];
+ rsc->idx = container_of(rsc, struct sum, rsc)->idx[0];
}
-static int sum_next_conj(struct rsc *rsc)
+static void sum_next_conj(struct rsc *rsc)
{
rsc->conj++;
- return container_of(rsc, struct sum, rsc)->idx[rsc->conj];
}
static int sum_index(const struct rsc *rsc)
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c
index 27441d498968..b5e1296af09e 100644
--- a/sound/pci/ctxfi/ctdaio.c
+++ b/sound/pci/ctxfi/ctdaio.c
@@ -51,12 +51,12 @@ static struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
[SPDIFIO] = {.left = 0x05, .right = 0x85},
};
-static int daio_master(struct rsc *rsc)
+static void daio_master(struct rsc *rsc)
{
/* Actually, this is not the resource index of DAIO.
* For DAO, it is the input mapper index. And, for DAI,
* it is the output time-slot index. */
- return rsc->conj = rsc->idx;
+ rsc->conj = rsc->idx;
}
static int daio_index(const struct rsc *rsc)
@@ -64,19 +64,19 @@ static int daio_index(const struct rsc *rsc)
return rsc->conj;
}
-static int daio_out_next_conj(struct rsc *rsc)
+static void daio_out_next_conj(struct rsc *rsc)
{
- return rsc->conj += 2;
+ rsc->conj += 2;
}
-static int daio_in_next_conj_20k1(struct rsc *rsc)
+static void daio_in_next_conj_20k1(struct rsc *rsc)
{
- return rsc->conj += 0x200;
+ rsc->conj += 0x200;
}
-static int daio_in_next_conj_20k2(struct rsc *rsc)
+static void daio_in_next_conj_20k2(struct rsc *rsc)
{
- return rsc->conj += 0x100;
+ rsc->conj += 0x100;
}
static const struct rsc_ops daio_out_rsc_ops = {
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c
index 3cd4b7dad945..b1cc4cdc6c41 100644
--- a/sound/pci/ctxfi/cthw20k2.c
+++ b/sound/pci/ctxfi/cthw20k2.c
@@ -991,7 +991,7 @@ static int daio_mgr_dao_init(void *blk, unsigned int idx, unsigned int conf)
if (idx < 4) {
/* S/PDIF output */
- switch ((conf & 0x7)) {
+ switch ((conf & 0xf)) {
case 1:
set_field(&ctl->txctl[idx], ATXCTL_NUC, 0);
break;
diff --git a/sound/pci/ctxfi/ctresource.c b/sound/pci/ctxfi/ctresource.c
index 0bb5696e44b3..ec5f597b580a 100644
--- a/sound/pci/ctxfi/ctresource.c
+++ b/sound/pci/ctxfi/ctresource.c
@@ -109,18 +109,17 @@ static int audio_ring_slot(const struct rsc *rsc)
return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type];
}
-static int rsc_next_conj(struct rsc *rsc)
+static void rsc_next_conj(struct rsc *rsc)
{
unsigned int i;
for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); )
i++;
rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i);
- return rsc->conj;
}
-static int rsc_master(struct rsc *rsc)
+static void rsc_master(struct rsc *rsc)
{
- return rsc->conj = rsc->idx;
+ rsc->conj = rsc->idx;
}
static const struct rsc_ops rsc_generic_ops = {
diff --git a/sound/pci/ctxfi/ctresource.h b/sound/pci/ctxfi/ctresource.h
index 93e47488a1c1..92146054af58 100644
--- a/sound/pci/ctxfi/ctresource.h
+++ b/sound/pci/ctxfi/ctresource.h
@@ -39,8 +39,8 @@ struct rsc {
};
struct rsc_ops {
- int (*master)(struct rsc *rsc); /* Move to master resource */
- int (*next_conj)(struct rsc *rsc); /* Move to next conjugate resource */
+ void (*master)(struct rsc *rsc); /* Move to master resource */
+ void (*next_conj)(struct rsc *rsc); /* Move to next conjugate resource */
int (*index)(const struct rsc *rsc); /* Return the index of resource */
/* Return the output slot number */
int (*output_slot)(const struct rsc *rsc);
diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c
index 37c18ce84974..7d2bda0c3d3d 100644
--- a/sound/pci/ctxfi/ctsrc.c
+++ b/sound/pci/ctxfi/ctsrc.c
@@ -590,16 +590,15 @@ int src_mgr_destroy(struct src_mgr *src_mgr)
/* SRCIMP resource manager operations */
-static int srcimp_master(struct rsc *rsc)
+static void srcimp_master(struct rsc *rsc)
{
rsc->conj = 0;
- return rsc->idx = container_of(rsc, struct srcimp, rsc)->idx[0];
+ rsc->idx = container_of(rsc, struct srcimp, rsc)->idx[0];
}
-static int srcimp_next_conj(struct rsc *rsc)
+static void srcimp_next_conj(struct rsc *rsc)
{
rsc->conj++;
- return container_of(rsc, struct srcimp, rsc)->idx[rsc->conj];
}
static int srcimp_index(const struct rsc *rsc)
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c
index 6a8564566375..17a25e453f60 100644
--- a/sound/pci/hda/hda_bind.c
+++ b/sound/pci/hda/hda_bind.c
@@ -47,6 +47,10 @@ static void hda_codec_unsol_event(struct hdac_device *dev, unsigned int ev)
if (codec->bus->shutdown)
return;
+ /* ignore unsol events during system suspend/resume */
+ if (codec->core.dev.power.power_state.event != PM_EVENT_ON)
+ return;
+
if (codec->patch_ops.unsol_event)
codec->patch_ops.unsol_event(codec, ev);
}
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 6da296def283..c8847de8388f 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1721,8 +1721,11 @@ void snd_hda_ctls_clear(struct hda_codec *codec)
{
int i;
struct hda_nid_item *items = codec->mixers.list;
+
+ down_write(&codec->card->controls_rwsem);
for (i = 0; i < codec->mixers.used; i++)
snd_ctl_remove(codec->card, items[i].kctl);
+ up_write(&codec->card->controls_rwsem);
snd_array_free(&codec->mixers);
snd_array_free(&codec->nids);
}
@@ -1798,7 +1801,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
return -EBUSY;
/* OK, let it free */
- snd_hdac_device_unregister(&codec->core);
+ device_release_driver(hda_codec_dev(codec));
/* allow device access again */
snd_hda_unlock_devices(bus);
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 5e6081750bd9..6a159c6c2f54 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -613,13 +613,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
20,
178000000);
- /* by some reason, the playback stream stalls on PulseAudio with
- * tsched=1 when a capture stream triggers. Until we figure out the
- * real cause, disable tsched mode by telling the PCM info flag.
- */
- if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND)
- runtime->hw.info |= SNDRV_PCM_INFO_BATCH;
-
if (chip->align_buffer_size)
/* constrain buffer sizes to be multiple of 128
bytes. This is more efficient in terms of memory
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h
index a356fb0e5773..9da7a06d024f 100644
--- a/sound/pci/hda/hda_controller.h
+++ b/sound/pci/hda/hda_controller.h
@@ -41,7 +41,7 @@
/* 24 unused */
#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */
#define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */
-#define AZX_DCAPS_SUSPEND_SPURIOUS_WAKEUP (1 << 27) /* Workaround for spurious wakeups after suspend */
+/* 27 unused */
#define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */
#define AZX_DCAPS_NO_MSI64 (1 << 29) /* Stick to 32-bit MSIs */
#define AZX_DCAPS_SEPARATE_STREAM_TAG (1 << 30) /* capture and playback use separate stream tag */
@@ -143,6 +143,7 @@ struct azx {
unsigned int align_buffer_size:1;
unsigned int region_requested:1;
unsigned int disabled:1; /* disabled by vga_switcheroo */
+ unsigned int pm_prepared:1;
/* GTS present */
unsigned int gts_present:1;
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index e1750bdbe51f..e92fcb150e57 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -1202,11 +1202,17 @@ static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
*index = ch;
return "Headphone";
case AUTO_PIN_LINE_OUT:
- /* This deals with the case where we have two DACs and
- * one LO, one HP and one Speaker */
- if (!ch && cfg->speaker_outs && cfg->hp_outs) {
- bool hp_lo_shared = !path_has_mixer(codec, spec->hp_paths[0], ctl_type);
- bool spk_lo_shared = !path_has_mixer(codec, spec->speaker_paths[0], ctl_type);
+ /* This deals with the case where one HP or one Speaker or
+ * one HP + one Speaker need to share the DAC with LO
+ */
+ if (!ch) {
+ bool hp_lo_shared = false, spk_lo_shared = false;
+
+ if (cfg->speaker_outs)
+ spk_lo_shared = !path_has_mixer(codec,
+ spec->speaker_paths[0], ctl_type);
+ if (cfg->hp_outs)
+ hp_lo_shared = !path_has_mixer(codec, spec->hp_paths[0], ctl_type);
if (hp_lo_shared && spk_lo_shared)
return spec->vmaster_mute.hook ? "PCM" : "Master";
if (hp_lo_shared)
@@ -1364,16 +1370,20 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs,
struct nid_path *path;
hda_nid_t pin = pins[i];
- path = snd_hda_get_path_from_idx(codec, path_idx[i]);
- if (path) {
- badness += assign_out_path_ctls(codec, path);
- continue;
+ if (!spec->obey_preferred_dacs) {
+ path = snd_hda_get_path_from_idx(codec, path_idx[i]);
+ if (path) {
+ badness += assign_out_path_ctls(codec, path);
+ continue;
+ }
}
dacs[i] = get_preferred_dac(codec, pin);
if (dacs[i]) {
if (is_dac_already_used(codec, dacs[i]))
badness += bad->shared_primary;
+ } else if (spec->obey_preferred_dacs) {
+ badness += BAD_NO_PRIMARY_DAC;
}
if (!dacs[i])
@@ -3448,7 +3458,7 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol,
struct hda_gen_spec *spec = codec->spec;
const struct hda_input_mux *imux;
struct nid_path *path;
- int i, adc_idx, err = 0;
+ int i, adc_idx, ret, err = 0;
imux = &spec->input_mux;
adc_idx = kcontrol->id.index;
@@ -3458,9 +3468,13 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol,
if (!path || !path->ctls[type])
continue;
kcontrol->private_value = path->ctls[type];
- err = func(kcontrol, ucontrol);
- if (err < 0)
+ ret = func(kcontrol, ucontrol);
+ if (ret < 0) {
+ err = ret;
break;
+ }
+ if (ret > 0)
+ err = 1;
}
mutex_unlock(&codec->control_mutex);
if (err >= 0 && spec->cap_sync_hook)
@@ -4013,7 +4027,7 @@ int snd_hda_gen_add_micmute_led(struct hda_codec *codec,
spec->micmute_led.led_mode = MICMUTE_LED_FOLLOW_MUTE;
spec->micmute_led.capture = 0;
- spec->micmute_led.led_value = 0;
+ spec->micmute_led.led_value = -1;
spec->micmute_led.old_hook = spec->cap_sync_hook;
spec->micmute_led.update = hook;
spec->cap_sync_hook = update_micmute_led;
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index fb9f1a90238b..e728df6145ad 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -236,6 +236,7 @@ struct hda_gen_spec {
unsigned int power_down_unused:1; /* power down unused widgets */
unsigned int dac_min_mute:1; /* minimal = mute for DACs */
unsigned int suppress_vmaster:1; /* don't create vmaster kctls */
+ unsigned int obey_preferred_dacs:1; /* obey preferred_dacs assignment */
/* other internal flags */
unsigned int no_analog:1; /* digital I/O only */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 590ea262f2e2..b8fe0ec5d624 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -295,8 +295,7 @@ enum {
/* PCH for HSW/BDW; with runtime PM */
/* no i915 binding for this as HSW/BDW has another controller for HDMI */
#define AZX_DCAPS_INTEL_PCH \
- (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
- AZX_DCAPS_SUSPEND_SPURIOUS_WAKEUP)
+ (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME)
/* HSW HDMI */
#define AZX_DCAPS_INTEL_HASWELL \
@@ -672,13 +671,17 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
* the update-IRQ timing. The IRQ is issued before actually the
* data is processed. So, we need to process it afterwords in a
* workqueue.
+ *
+ * Returns 1 if OK to proceed, 0 for delay handling, -1 for skipping update
*/
static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
{
struct snd_pcm_substream *substream = azx_dev->core.substream;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int stream = substream->stream;
u32 wallclk;
unsigned int pos;
+ snd_pcm_uframes_t hwptr, target;
wallclk = azx_readl(chip, WALLCLK) - azx_dev->core.start_wallclk;
if (wallclk < (azx_dev->core.period_wallclk * 2) / 3)
@@ -715,6 +718,24 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
/* NG - it's below the first next period boundary */
return chip->bdl_pos_adj ? 0 : -1;
azx_dev->core.start_wallclk += wallclk;
+
+ if (azx_dev->core.no_period_wakeup)
+ return 1; /* OK, no need to check period boundary */
+
+ if (runtime->hw_ptr_base != runtime->hw_ptr_interrupt)
+ return 1; /* OK, already in hwptr updating process */
+
+ /* check whether the period gets really elapsed */
+ pos = bytes_to_frames(runtime, pos);
+ hwptr = runtime->hw_ptr_base + pos;
+ if (hwptr < runtime->status->hw_ptr)
+ hwptr += runtime->buffer_size;
+ target = runtime->hw_ptr_interrupt + runtime->period_size;
+ if (hwptr < target) {
+ /* too early wakeup, process it later */
+ return chip->bdl_pos_adj ? 0 : -1;
+ }
+
return 1; /* OK, it's fine */
}
@@ -908,11 +929,7 @@ static unsigned int azx_get_pos_skl(struct azx *chip, struct azx_dev *azx_dev)
if (azx_dev->core.substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
return azx_skl_get_dpib_pos(chip, azx_dev);
- /* For capture, we need to read posbuf, but it requires a delay
- * for the possible boundary overlap; the read of DPIB fetches the
- * actual posbuf
- */
- udelay(20);
+ /* read of DPIB fetches the actual posbuf */
azx_skl_get_dpib_pos(chip, azx_dev);
return azx_get_pos_posbuf(chip, azx_dev);
}
@@ -984,7 +1001,7 @@ static void __azx_runtime_suspend(struct azx *chip)
display_power(chip, false);
}
-static void __azx_runtime_resume(struct azx *chip, bool from_rt)
+static void __azx_runtime_resume(struct azx *chip)
{
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
struct hdac_bus *bus = azx_bus(chip);
@@ -1001,12 +1018,15 @@ static void __azx_runtime_resume(struct azx *chip, bool from_rt)
azx_init_pci(chip);
hda_intel_init_chip(chip, true);
- if (status && from_rt) {
- list_for_each_codec(codec, &chip->bus)
- if (!codec->relaxed_resume &&
- (status & (1 << codec->addr)))
- schedule_delayed_work(&codec->jackpoll_work,
- codec->jackpoll_interval);
+ /* Avoid codec resume if runtime resume is for system suspend */
+ if (!chip->pm_prepared) {
+ list_for_each_codec(codec, &chip->bus) {
+ if (codec->relaxed_resume)
+ continue;
+
+ if (codec->forced_resume || (status & (1 << codec->addr)))
+ pm_request_resume(hda_codec_dev(codec));
+ }
}
/* power down again for link-controlled chips */
@@ -1015,6 +1035,39 @@ static void __azx_runtime_resume(struct azx *chip, bool from_rt)
}
#ifdef CONFIG_PM_SLEEP
+static int azx_prepare(struct device *dev)
+{
+ struct snd_card *card = dev_get_drvdata(dev);
+ struct azx *chip;
+
+ if (!azx_is_pm_ready(card))
+ return 0;
+
+ chip = card->private_data;
+ chip->pm_prepared = 1;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+
+ flush_work(&azx_bus(chip)->unsol_work);
+
+ /* HDA controller always requires different WAKEEN for runtime suspend
+ * and system suspend, so don't use direct-complete here.
+ */
+ return 0;
+}
+
+static void azx_complete(struct device *dev)
+{
+ struct snd_card *card = dev_get_drvdata(dev);
+ struct azx *chip;
+
+ if (!azx_is_pm_ready(card))
+ return;
+
+ chip = card->private_data;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ chip->pm_prepared = 0;
+}
+
static int azx_suspend(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
@@ -1026,15 +1079,7 @@ static int azx_suspend(struct device *dev)
chip = card->private_data;
bus = azx_bus(chip);
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- /* An ugly workaround: direct call of __azx_runtime_suspend() and
- * __azx_runtime_resume() for old Intel platforms that suffer from
- * spurious wakeups after S3 suspend
- */
- if (chip->driver_caps & AZX_DCAPS_SUSPEND_SPURIOUS_WAKEUP)
- __azx_runtime_suspend(chip);
- else
- pm_runtime_force_suspend(dev);
+ __azx_runtime_suspend(chip);
if (bus->irq >= 0) {
free_irq(bus->irq, chip);
bus->irq = -1;
@@ -1062,11 +1107,7 @@ static int azx_resume(struct device *dev)
if (azx_acquire_irq(chip, 1) < 0)
return -EIO;
- if (chip->driver_caps & AZX_DCAPS_SUSPEND_SPURIOUS_WAKEUP)
- __azx_runtime_resume(chip, false);
- else
- pm_runtime_force_resume(dev);
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ __azx_runtime_resume(chip);
trace_azx_resume(chip);
return 0;
@@ -1114,10 +1155,7 @@ static int azx_runtime_suspend(struct device *dev)
chip = card->private_data;
/* enable controller wake up event */
- if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0) {
- azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) |
- STATESTS_INT_MASK);
- }
+ azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) | STATESTS_INT_MASK);
__azx_runtime_suspend(chip);
trace_azx_runtime_suspend(chip);
@@ -1128,18 +1166,14 @@ static int azx_runtime_resume(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
struct azx *chip;
- bool from_rt = snd_power_get_state(card) == SNDRV_CTL_POWER_D0;
if (!azx_is_pm_ready(card))
return 0;
chip = card->private_data;
- __azx_runtime_resume(chip, from_rt);
+ __azx_runtime_resume(chip);
/* disable controller Wake Up event*/
- if (from_rt) {
- azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
- ~STATESTS_INT_MASK);
- }
+ azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) & ~STATESTS_INT_MASK);
trace_azx_runtime_resume(chip);
return 0;
@@ -1173,6 +1207,8 @@ static int azx_runtime_idle(struct device *dev)
static const struct dev_pm_ops azx_pm = {
SET_SYSTEM_SLEEP_PM_OPS(azx_suspend, azx_resume)
#ifdef CONFIG_PM_SLEEP
+ .prepare = azx_prepare,
+ .complete = azx_complete,
.freeze_noirq = azx_freeze_noirq,
.thaw_noirq = azx_thaw_noirq,
#endif
@@ -1572,6 +1608,7 @@ static struct snd_pci_quirk probe_mask_list[] = {
/* forced codec slots */
SND_PCI_QUIRK(0x1043, 0x1262, "ASUS W5Fm", 0x103),
SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103),
+ SND_PCI_QUIRK(0x1558, 0x0351, "Schenker Dock 15", 0x105),
/* WinFast VP200 H (Teradici) user reported broken communication */
SND_PCI_QUIRK(0x3a21, 0x040d, "WinFast VP200 H", 0x101),
{}
@@ -1757,8 +1794,6 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
assign_position_fix(chip, check_position_fix(chip, position_fix[dev]));
- check_probe_mask(chip, dev);
-
if (single_cmd < 0) /* allow fallback to single_cmd at errors */
chip->fallback_to_single_cmd = 1;
else /* explicitly set to single_cmd or not */
@@ -1790,6 +1825,8 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
chip->bus.needs_damn_long_delay = 1;
}
+ check_probe_mask(chip, dev);
+
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err < 0) {
dev_err(card->dev, "Error creating device [card]!\n");
@@ -2178,8 +2215,6 @@ static struct snd_pci_quirk power_save_blacklist[] = {
SND_PCI_QUIRK(0x1849, 0x7662, "Asrock H81M-HDS", 0),
/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0),
- /* https://bugzilla.redhat.com/show_bug.cgi?id=1581607 */
- SND_PCI_QUIRK(0x1558, 0x3501, "Clevo W35xSS_370SS", 0),
/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
SND_PCI_QUIRK(0x1558, 0x6504, "Clevo W65_67SB", 0),
/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
@@ -2320,6 +2355,7 @@ static int azx_probe_continue(struct azx *chip)
if (azx_has_pm_runtime(chip)) {
pm_runtime_use_autosuspend(&pci->dev);
+ pm_runtime_allow(&pci->dev);
pm_runtime_put_autosuspend(&pci->dev);
}
@@ -2440,9 +2476,14 @@ static const struct pci_device_id azx_ids[] = {
/* CometLake-H */
{ PCI_DEVICE(0x8086, 0x06C8),
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+ { PCI_DEVICE(0x8086, 0xf1c8),
+ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
/* CometLake-S */
{ PCI_DEVICE(0x8086, 0xa3f0),
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+ /* CometLake-R */
+ { PCI_DEVICE(0x8086, 0xf0c8),
+ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
/* Icelake */
{ PCI_DEVICE(0x8086, 0x34c8),
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c
index 6dbe99131bc4..91b4a29a8c36 100644
--- a/sound/pci/hda/hda_sysfs.c
+++ b/sound/pci/hda/hda_sysfs.c
@@ -139,7 +139,7 @@ static int reconfig_codec(struct hda_codec *codec)
"The codec is being used, can't reconfigure.\n");
goto error;
}
- err = snd_hda_codec_configure(codec);
+ err = device_reprobe(hda_codec_dev(codec));
if (err < 0)
goto error;
err = snd_card_register(codec->card);
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
index e378cb33c69d..2971b34c87c1 100644
--- a/sound/pci/hda/hda_tegra.c
+++ b/sound/pci/hda/hda_tegra.c
@@ -292,6 +292,9 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
const char *sname, *drv_name = "tegra-hda";
struct device_node *np = pdev->dev.of_node;
+ if (irq_id < 0)
+ return irq_id;
+
err = hda_tegra_init_chip(chip, pdev);
if (err)
return err;
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 6aa39339db0a..9412bdda85c8 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -93,7 +93,7 @@ enum {
};
/* Strings for Input Source Enum Control */
-static const char *const in_src_str[3] = {"Rear Mic", "Line", "Front Mic" };
+static const char *const in_src_str[3] = { "Microphone", "Line In", "Front Microphone" };
#define IN_SRC_NUM_OF_INPUTS 3
enum {
REAR_MIC,
@@ -1065,6 +1065,7 @@ enum {
QUIRK_R3DI,
QUIRK_R3D,
QUIRK_AE5,
+ QUIRK_AE7,
};
#ifdef CONFIG_PCI
@@ -1146,7 +1147,7 @@ static const struct hda_pintbl ae5_pincfgs[] = {
{ 0x0e, 0x01c510f0 }, /* SPDIF In */
{ 0x0f, 0x01017114 }, /* Port A -- Rear L/R. */
{ 0x10, 0x01017012 }, /* Port D -- Center/LFE or FP Hp */
- { 0x11, 0x01a170ff }, /* Port B -- LineMicIn2 / Rear Headphone */
+ { 0x11, 0x012170ff }, /* Port B -- LineMicIn2 / Rear Headphone */
{ 0x12, 0x01a170f0 }, /* Port C -- LineIn1 */
{ 0x13, 0x908700f0 }, /* What U Hear In*/
{ 0x18, 0x50d000f0 }, /* N/A */
@@ -1184,6 +1185,8 @@ static const struct snd_pci_quirk ca0132_quirks[] = {
SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D),
SND_PCI_QUIRK(0x1102, 0x0018, "Recon3D", QUIRK_R3D),
SND_PCI_QUIRK(0x1102, 0x0051, "Sound Blaster AE-5", QUIRK_AE5),
+ SND_PCI_QUIRK(0x1102, 0x0191, "Sound Blaster AE-5 Plus", QUIRK_AE5),
+ SND_PCI_QUIRK(0x1102, 0x0081, "Sound Blaster AE-7", QUIRK_AE7),
{}
};
@@ -4674,6 +4677,15 @@ static int ca0132_alt_select_in(struct hda_codec *codec)
ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
tmp = FLOAT_THREE;
break;
+ case QUIRK_AE7:
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
+ tmp = FLOAT_THREE;
+ chipio_set_conn_rate(codec, MEM_CONNID_MICIN2,
+ SR_96_000);
+ chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2,
+ SR_96_000);
+ dspio_set_uint_param(codec, 0x80, 0x01, FLOAT_ZERO);
+ break;
default:
tmp = FLOAT_ONE;
break;
@@ -4719,6 +4731,14 @@ static int ca0132_alt_select_in(struct hda_codec *codec)
case QUIRK_AE5:
ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
break;
+ case QUIRK_AE7:
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x3f);
+ chipio_set_conn_rate(codec, MEM_CONNID_MICIN2,
+ SR_96_000);
+ chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2,
+ SR_96_000);
+ dspio_set_uint_param(codec, 0x80, 0x01, FLOAT_ZERO);
+ break;
default:
break;
}
@@ -4728,7 +4748,10 @@ static int ca0132_alt_select_in(struct hda_codec *codec)
if (ca0132_quirk(spec) == QUIRK_R3DI)
chipio_set_conn_rate(codec, 0x0F, SR_96_000);
- tmp = FLOAT_ZERO;
+ if (ca0132_quirk(spec) == QUIRK_AE7)
+ tmp = FLOAT_THREE;
+ else
+ tmp = FLOAT_ZERO;
dspio_set_uint_param(codec, 0x80, 0x00, tmp);
switch (ca0132_quirk(spec)) {
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 396b5503038a..b81b0a1bada5 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -898,18 +898,18 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x103c, 0x8079, "HP EliteBook 840 G3", CXT_FIXUP_HP_DOCK),
SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK),
SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x828c, "HP EliteBook 840 G4", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x83b2, "HP EliteBook 840 G5", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC),
SND_PCI_QUIRK(0x103c, 0x814f, "HP ZBook 15u G3", CXT_FIXUP_MUTE_LED_GPIO),
+ SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
SND_PCI_QUIRK(0x103c, 0x822e, "HP ProBook 440 G4", CXT_FIXUP_MUTE_LED_GPIO),
- SND_PCI_QUIRK(0x103c, 0x836e, "HP ProBook 455 G5", CXT_FIXUP_MUTE_LED_GPIO),
- SND_PCI_QUIRK(0x103c, 0x837f, "HP ProBook 470 G5", CXT_FIXUP_MUTE_LED_GPIO),
+ SND_PCI_QUIRK(0x103c, 0x828c, "HP EliteBook 840 G4", CXT_FIXUP_HP_DOCK),
SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x103c, 0x836e, "HP ProBook 455 G5", CXT_FIXUP_MUTE_LED_GPIO),
+ SND_PCI_QUIRK(0x103c, 0x837f, "HP ProBook 470 G5", CXT_FIXUP_MUTE_LED_GPIO),
+ SND_PCI_QUIRK(0x103c, 0x83b2, "HP EliteBook 840 G5", CXT_FIXUP_HP_DOCK),
+ SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK),
+ SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK),
SND_PCI_QUIRK(0x103c, 0x8402, "HP ProBook 645 G4", CXT_FIXUP_MUTE_LED_GPIO),
SND_PCI_QUIRK(0x103c, 0x8455, "HP Z2 G4", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x8456, "HP Z2 G4 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
@@ -1012,6 +1012,13 @@ static int patch_conexant_auto(struct hda_codec *codec)
snd_hda_pick_fixup(codec, cxt5051_fixup_models,
cxt5051_fixups, cxt_fixups);
break;
+ case 0x14f15098:
+ codec->pin_amp_workaround = 1;
+ spec->gen.mixer_nid = 0x22;
+ spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
+ snd_hda_pick_fixup(codec, cxt5066_fixup_models,
+ cxt5066_fixups, cxt_fixups);
+ break;
case 0x14f150f2:
codec->power_save_node = 1;
/* Fall through */
@@ -1041,11 +1048,11 @@ static int patch_conexant_auto(struct hda_codec *codec)
if (err < 0)
goto error;
- err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
+ err = cx_auto_parse_beep(codec);
if (err < 0)
goto error;
- err = cx_auto_parse_beep(codec);
+ err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
if (err < 0)
goto error;
@@ -1075,6 +1082,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
static const struct hda_device_id snd_hda_id_conexant[] = {
HDA_CODEC_ENTRY(0x14f11f86, "CX8070", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f12008, "CX8200", patch_conexant_auto),
+ HDA_CODEC_ENTRY(0x14f120d0, "CX11970", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f15045, "CX20549 (Venice)", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f15047, "CX20551 (Waikiki)", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f15051, "CX20561 (Hermosa)", patch_conexant_auto),
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 51798632d334..5128a5df16fd 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1820,6 +1820,7 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
static const struct snd_pci_quirk force_connect_list[] = {
SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1),
SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1),
+ SND_PCI_QUIRK(0x1462, 0xec94, "MS-7C94", 1),
{}
};
@@ -2001,22 +2002,25 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
int pinctl;
int err = 0;
+ mutex_lock(&spec->pcm_lock);
if (hinfo->nid) {
pcm_idx = hinfo_to_pcm_index(codec, hinfo);
- if (snd_BUG_ON(pcm_idx < 0))
- return -EINVAL;
+ if (snd_BUG_ON(pcm_idx < 0)) {
+ err = -EINVAL;
+ goto unlock;
+ }
cvt_idx = cvt_nid_to_cvt_index(codec, hinfo->nid);
- if (snd_BUG_ON(cvt_idx < 0))
- return -EINVAL;
+ if (snd_BUG_ON(cvt_idx < 0)) {
+ err = -EINVAL;
+ goto unlock;
+ }
per_cvt = get_cvt(spec, cvt_idx);
-
snd_BUG_ON(!per_cvt->assigned);
per_cvt->assigned = 0;
hinfo->nid = 0;
azx_stream(get_azx_dev(substream))->stripe = 0;
- mutex_lock(&spec->pcm_lock);
snd_hda_spdif_ctls_unassign(codec, pcm_idx);
clear_bit(pcm_idx, &spec->pcm_in_use);
pin_idx = hinfo_to_pin_index(codec, hinfo);
@@ -2044,10 +2048,11 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
per_pin->setup = false;
per_pin->channels = 0;
mutex_unlock(&per_pin->lock);
- unlock:
- mutex_unlock(&spec->pcm_lock);
}
+unlock:
+ mutex_unlock(&spec->pcm_lock);
+
return err;
}
@@ -2378,6 +2383,18 @@ static void generic_hdmi_free(struct hda_codec *codec)
}
#ifdef CONFIG_PM
+static int generic_hdmi_suspend(struct hda_codec *codec)
+{
+ struct hdmi_spec *spec = codec->spec;
+ int pin_idx;
+
+ for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
+ struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
+ cancel_delayed_work_sync(&per_pin->work);
+ }
+ return 0;
+}
+
static int generic_hdmi_resume(struct hda_codec *codec)
{
struct hdmi_spec *spec = codec->spec;
@@ -2401,6 +2418,7 @@ static const struct hda_codec_ops generic_hdmi_patch_ops = {
.build_controls = generic_hdmi_build_controls,
.unsol_event = hdmi_unsol_event,
#ifdef CONFIG_PM
+ .suspend = generic_hdmi_suspend,
.resume = generic_hdmi_resume,
#endif
};
@@ -2550,7 +2568,7 @@ static void generic_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id)
/* skip notification during system suspend (but not in runtime PM);
* the state will be updated at resume
*/
- if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0)
+ if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND)
return;
/* ditto during suspend/resume process itself */
if (snd_hdac_is_in_pm(&codec->core))
@@ -2755,7 +2773,7 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
/* skip notification during system suspend (but not in runtime PM);
* the state will be updated at resume
*/
- if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0)
+ if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND)
return;
/* ditto during suspend/resume process itself */
if (snd_hdac_is_in_pm(&codec->core))
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 4dfd714f718b..804fc0d331b4 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -375,17 +375,18 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000);
/* fallthrough */
case 0x10ec0215:
+ case 0x10ec0230:
case 0x10ec0233:
case 0x10ec0235:
case 0x10ec0236:
case 0x10ec0245:
case 0x10ec0255:
case 0x10ec0256:
+ case 0x19e58326:
case 0x10ec0257:
case 0x10ec0282:
case 0x10ec0283:
case 0x10ec0286:
- case 0x10ec0287:
case 0x10ec0288:
case 0x10ec0285:
case 0x10ec0298:
@@ -396,6 +397,10 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
case 0x10ec0275:
alc_update_coef_idx(codec, 0xe, 0, 1<<0);
break;
+ case 0x10ec0287:
+ alc_update_coef_idx(codec, 0x10, 1<<9, 0);
+ alc_write_coef_idx(codec, 0x8, 0x4ab7);
+ break;
case 0x10ec0293:
alc_update_coef_idx(codec, 0xa, 1<<13, 0);
break;
@@ -436,6 +441,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
alc_update_coef_idx(codec, 0x7, 1<<5, 0);
break;
case 0x10ec0892:
+ case 0x10ec0897:
alc_update_coef_idx(codec, 0x7, 1<<5, 0);
break;
case 0x10ec0899:
@@ -512,6 +518,9 @@ static void alc_shutup_pins(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
switch (codec->core.vendor_id) {
+ case 0x10ec0236:
+ case 0x10ec0256:
+ case 0x19e58326:
case 0x10ec0283:
case 0x10ec0286:
case 0x10ec0288:
@@ -1141,6 +1150,7 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
codec->single_adc_amp = 1;
/* FIXME: do we need this for all Realtek codec models? */
codec->spdif_status_reset = 1;
+ codec->forced_resume = 1;
codec->patch_ops = alc_patch_ops;
err = alc_codec_rename_from_preset(codec);
@@ -1893,6 +1903,7 @@ enum {
ALC889_FIXUP_FRONT_HP_NO_PRESENCE,
ALC889_FIXUP_VAIO_TT,
ALC888_FIXUP_EEE1601,
+ ALC886_FIXUP_EAPD,
ALC882_FIXUP_EAPD,
ALC883_FIXUP_EAPD,
ALC883_FIXUP_ACER_EAPD,
@@ -1917,9 +1928,13 @@ enum {
ALC887_FIXUP_ASUS_BASS,
ALC887_FIXUP_BASS_CHMAP,
ALC1220_FIXUP_GB_DUAL_CODECS,
+ ALC1220_FIXUP_GB_X570,
ALC1220_FIXUP_CLEVO_P950,
ALC1220_FIXUP_CLEVO_PB51ED,
ALC1220_FIXUP_CLEVO_PB51ED_PINS,
+ ALC887_FIXUP_ASUS_AUDIO,
+ ALC887_FIXUP_ASUS_HMIC,
+ ALCS1200A_FIXUP_MIC_VREF,
};
static void alc889_fixup_coef(struct hda_codec *codec,
@@ -2104,6 +2119,30 @@ static void alc1220_fixup_gb_dual_codecs(struct hda_codec *codec,
}
}
+static void alc1220_fixup_gb_x570(struct hda_codec *codec,
+ const struct hda_fixup *fix,
+ int action)
+{
+ static const hda_nid_t conn1[] = { 0x0c };
+ static const struct coef_fw gb_x570_coefs[] = {
+ WRITE_COEF(0x07, 0x03c0),
+ WRITE_COEF(0x1a, 0x01c1),
+ WRITE_COEF(0x1b, 0x0202),
+ WRITE_COEF(0x43, 0x3005),
+ {}
+ };
+
+ switch (action) {
+ case HDA_FIXUP_ACT_PRE_PROBE:
+ snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1);
+ snd_hda_override_conn_list(codec, 0x1b, ARRAY_SIZE(conn1), conn1);
+ break;
+ case HDA_FIXUP_ACT_INIT:
+ alc_process_coef_fw(codec, gb_x570_coefs);
+ break;
+ }
+}
+
static void alc1220_fixup_clevo_p950(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
@@ -2132,6 +2171,31 @@ static void alc1220_fixup_clevo_pb51ed(struct hda_codec *codec,
alc_fixup_headset_mode_no_hp_mic(codec, fix, action);
}
+static void alc887_asus_hp_automute_hook(struct hda_codec *codec,
+ struct hda_jack_callback *jack)
+{
+ struct alc_spec *spec = codec->spec;
+ unsigned int vref;
+
+ snd_hda_gen_hp_automute(codec, jack);
+
+ if (spec->gen.hp_jack_present)
+ vref = AC_PINCTL_VREF_80;
+ else
+ vref = AC_PINCTL_VREF_HIZ;
+ snd_hda_set_pin_ctl(codec, 0x19, PIN_HP | vref);
+}
+
+static void alc887_fixup_asus_jack(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ if (action != HDA_FIXUP_ACT_PROBE)
+ return;
+ snd_hda_set_pin_ctl_cache(codec, 0x1b, PIN_HP);
+ spec->gen.hp_automute_hook = alc887_asus_hp_automute_hook;
+}
+
static const struct hda_fixup alc882_fixups[] = {
[ALC882_FIXUP_ABIT_AW9D_MAX] = {
.type = HDA_FIXUP_PINS,
@@ -2199,6 +2263,15 @@ static const struct hda_fixup alc882_fixups[] = {
{ }
}
},
+ [ALC886_FIXUP_EAPD] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* change to EAPD mode */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0068 },
+ { }
+ }
+ },
[ALC882_FIXUP_EAPD] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
@@ -2372,6 +2445,10 @@ static const struct hda_fixup alc882_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc1220_fixup_gb_dual_codecs,
},
+ [ALC1220_FIXUP_GB_X570] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc1220_fixup_gb_x570,
+ },
[ALC1220_FIXUP_CLEVO_P950] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc1220_fixup_clevo_p950,
@@ -2389,6 +2466,28 @@ static const struct hda_fixup alc882_fixups[] = {
.chained = true,
.chain_id = ALC1220_FIXUP_CLEVO_PB51ED,
},
+ [ALC887_FIXUP_ASUS_AUDIO] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x15, 0x02a14150 }, /* use as headset mic, without its own jack detect */
+ { 0x19, 0x22219420 },
+ {}
+ },
+ },
+ [ALC887_FIXUP_ASUS_HMIC] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc887_fixup_asus_jack,
+ .chained = true,
+ .chain_id = ALC887_FIXUP_ASUS_AUDIO,
+ },
+ [ALCS1200A_FIXUP_MIC_VREF] = {
+ .type = HDA_FIXUP_PINCTLS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x18, PIN_VREF50 }, /* rear mic */
+ { 0x19, PIN_VREF50 }, /* front mic */
+ {}
+ }
+ },
};
static const struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -2407,13 +2506,13 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
ALC882_FIXUP_ACER_ASPIRE_8930G),
SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
ALC882_FIXUP_ACER_ASPIRE_8930G),
+ SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
+ ALC882_FIXUP_ACER_ASPIRE_4930G),
+ SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
ALC882_FIXUP_ACER_ASPIRE_4930G),
SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
ALC882_FIXUP_ACER_ASPIRE_4930G),
- SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
- ALC882_FIXUP_ACER_ASPIRE_4930G),
- SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
SND_PCI_QUIRK(0x1025, 0x021e, "Acer Aspire 5739G",
ALC882_FIXUP_ACER_ASPIRE_4930G),
SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
@@ -2422,14 +2521,16 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V),
SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC),
+ SND_PCI_QUIRK(0x1043, 0x2390, "Asus D700SA", ALC887_FIXUP_ASUS_HMIC),
SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS),
SND_PCI_QUIRK(0x1043, 0x8691, "ASUS ROG Ranger VIII", ALC882_FIXUP_GPIO3),
+ SND_PCI_QUIRK(0x1043, 0x8797, "ASUS TUF B550M-PLUS", ALCS1200A_FIXUP_MIC_VREF),
+ SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
+ SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP),
SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
SND_PCI_QUIRK(0x104d, 0x9060, "Sony Vaio VPCL14M1R", ALC882_FIXUP_NO_PRIMARY_HP),
- SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
- SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP),
/* All Apple entries are in codec SSIDs */
SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
@@ -2456,29 +2557,50 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
+ SND_PCI_QUIRK(0x13fe, 0x1009, "Advantech MIT-W101", ALC886_FIXUP_EAPD),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
- SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_CLEVO_P950),
+ SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_GB_X570),
+ SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_GB_X570),
+ SND_PCI_QUIRK(0x1458, 0xa0d5, "Gigabyte X570S Aorus Master", ALC1220_FIXUP_GB_X570),
SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950),
+ SND_PCI_QUIRK(0x1462, 0x1229, "MSI-GP73", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x1275, "MSI-GL63", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
+ SND_PCI_QUIRK(0x1462, 0xcc34, "MSI Godlike X570", ALC1220_FIXUP_GB_DUAL_CODECS),
SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
+ SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x65e1, "Clevo PB51[ED][DF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x65e5, "Clevo PC50D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x65f1, "Clevo PC50HS", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x65f5, "Clevo PD50PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x67f1, "Clevo PC70H[PRS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x67f5, "Clevo PD70PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x7715, "Clevo X170KM-G", ALC1220_FIXUP_CLEVO_PB51ED),
SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950),
+ SND_PCI_QUIRK(0x1558, 0x9506, "Clevo P955HQ", ALC1220_FIXUP_CLEVO_P950),
+ SND_PCI_QUIRK(0x1558, 0x950a, "Clevo P955H[PR]", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950),
+ SND_PCI_QUIRK(0x1558, 0x95e3, "Clevo P955[ER]T", ALC1220_FIXUP_CLEVO_P950),
+ SND_PCI_QUIRK(0x1558, 0x95e4, "Clevo P955ER", ALC1220_FIXUP_CLEVO_P950),
+ SND_PCI_QUIRK(0x1558, 0x95e5, "Clevo P955EE6", ALC1220_FIXUP_CLEVO_P950),
+ SND_PCI_QUIRK(0x1558, 0x95e6, "Clevo P950R[CDF]", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x96e1, "Clevo P960[ER][CDFN]-K", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x97e1, "Clevo P970[ER][CDFN]", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x97e2, "Clevo P970RC-M", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
@@ -2517,10 +2639,33 @@ static const struct hda_model_fixup alc882_fixup_models[] = {
{.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"},
{.id = ALC887_FIXUP_ASUS_BASS, .name = "asus-bass"},
{.id = ALC1220_FIXUP_GB_DUAL_CODECS, .name = "dual-codecs"},
+ {.id = ALC1220_FIXUP_GB_X570, .name = "gb-x570"},
{.id = ALC1220_FIXUP_CLEVO_P950, .name = "clevo-p950"},
{}
};
+static const struct snd_hda_pin_quirk alc882_pin_fixup_tbl[] = {
+ SND_HDA_PIN_QUIRK(0x10ec1220, 0x1043, "ASUS", ALC1220_FIXUP_CLEVO_P950,
+ {0x14, 0x01014010},
+ {0x15, 0x01011012},
+ {0x16, 0x01016011},
+ {0x18, 0x01a19040},
+ {0x19, 0x02a19050},
+ {0x1a, 0x0181304f},
+ {0x1b, 0x0221401f},
+ {0x1e, 0x01456130}),
+ SND_HDA_PIN_QUIRK(0x10ec1220, 0x1462, "MS-7C35", ALC1220_FIXUP_CLEVO_P950,
+ {0x14, 0x01015010},
+ {0x15, 0x01011012},
+ {0x16, 0x01011011},
+ {0x18, 0x01a11040},
+ {0x19, 0x02a19050},
+ {0x1a, 0x0181104f},
+ {0x1b, 0x0221401f},
+ {0x1e, 0x01451130}),
+ {}
+};
+
/*
* BIOS auto configuration
*/
@@ -2562,6 +2707,7 @@ static int patch_alc882(struct hda_codec *codec)
snd_hda_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl,
alc882_fixups);
+ snd_hda_pick_pin_fixup(codec, alc882_pin_fixup_tbl, alc882_fixups, true);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
alc_auto_parse_customize_define(codec);
@@ -3040,6 +3186,7 @@ static void alc_disable_headset_jack_key(struct hda_codec *codec)
case 0x10ec0215:
case 0x10ec0225:
case 0x10ec0285:
+ case 0x10ec0287:
case 0x10ec0295:
case 0x10ec0289:
case 0x10ec0299:
@@ -3047,8 +3194,10 @@ static void alc_disable_headset_jack_key(struct hda_codec *codec)
alc_update_coef_idx(codec, 0x49, 0x0045, 0x0);
alc_update_coef_idx(codec, 0x44, 0x0045 << 8, 0x0);
break;
+ case 0x10ec0230:
case 0x10ec0236:
case 0x10ec0256:
+ case 0x19e58326:
alc_write_coef_idx(codec, 0x48, 0x0);
alc_update_coef_idx(codec, 0x49, 0x0045, 0x0);
break;
@@ -3066,6 +3215,7 @@ static void alc_enable_headset_jack_key(struct hda_codec *codec)
case 0x10ec0215:
case 0x10ec0225:
case 0x10ec0285:
+ case 0x10ec0287:
case 0x10ec0295:
case 0x10ec0289:
case 0x10ec0299:
@@ -3073,8 +3223,10 @@ static void alc_enable_headset_jack_key(struct hda_codec *codec)
alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
alc_update_coef_idx(codec, 0x44, 0x007f << 8, 0x0045 << 8);
break;
+ case 0x10ec0230:
case 0x10ec0236:
case 0x10ec0256:
+ case 0x19e58326:
alc_write_coef_idx(codec, 0x48, 0xd011);
alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
break;
@@ -3421,7 +3573,8 @@ static void alc256_shutup(struct hda_codec *codec)
/* If disable 3k pulldown control for alc257, the Mic detection will not work correctly
* when booting with headset plugged. So skip setting it for the codec alc257
*/
- if (codec->core.vendor_id != 0x10ec0257)
+ if (codec->core.vendor_id != 0x10ec0236 &&
+ codec->core.vendor_id != 0x10ec0257)
alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
if (!spec->no_shutup_pins)
@@ -3848,6 +4001,15 @@ static void alc271_fixup_dmic(struct hda_codec *codec,
snd_hda_sequence_write(codec, verbs);
}
+/* Fix the speaker amp after resume, etc */
+static void alc269vb_fixup_aspire_e1_coef(struct hda_codec *codec,
+ const struct hda_fixup *fix,
+ int action)
+{
+ if (action == HDA_FIXUP_ACT_INIT)
+ alc_update_coef_idx(codec, 0x0d, 0x6000, 0x6000);
+}
+
static void alc269_fixup_pcm_44k(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@@ -4135,6 +4297,12 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec,
}
}
+static void alc236_fixup_hp_gpio_led(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ alc_fixup_hp_gpio_led(codec, action, 0x02, 0x01);
+}
+
static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@@ -4524,8 +4692,10 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
case 0x10ec0255:
alc_process_coef_fw(codec, coef0255);
break;
+ case 0x10ec0230:
case 0x10ec0236:
case 0x10ec0256:
+ case 0x19e58326:
alc_process_coef_fw(codec, coef0256);
break;
case 0x10ec0234:
@@ -4638,8 +4808,10 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
alc_process_coef_fw(codec, coef0255);
snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
break;
+ case 0x10ec0230:
case 0x10ec0236:
case 0x10ec0256:
+ case 0x19e58326:
alc_write_coef_idx(codec, 0x45, 0xc489);
snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
alc_process_coef_fw(codec, coef0256);
@@ -4787,8 +4959,10 @@ static void alc_headset_mode_default(struct hda_codec *codec)
case 0x10ec0255:
alc_process_coef_fw(codec, coef0255);
break;
+ case 0x10ec0230:
case 0x10ec0236:
case 0x10ec0256:
+ case 0x19e58326:
alc_write_coef_idx(codec, 0x1b, 0x0e4b);
alc_write_coef_idx(codec, 0x45, 0xc089);
msleep(50);
@@ -4885,8 +5059,10 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
case 0x10ec0255:
alc_process_coef_fw(codec, coef0255);
break;
+ case 0x10ec0230:
case 0x10ec0236:
case 0x10ec0256:
+ case 0x19e58326:
alc_process_coef_fw(codec, coef0256);
break;
case 0x10ec0234:
@@ -4998,8 +5174,10 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
case 0x10ec0255:
alc_process_coef_fw(codec, coef0255);
break;
+ case 0x10ec0230:
case 0x10ec0236:
case 0x10ec0256:
+ case 0x19e58326:
alc_process_coef_fw(codec, coef0256);
break;
case 0x10ec0234:
@@ -5093,8 +5271,10 @@ static void alc_determine_headset_type(struct hda_codec *codec)
val = alc_read_coef_idx(codec, 0x46);
is_ctia = (val & 0x0070) == 0x0070;
break;
+ case 0x10ec0230:
case 0x10ec0236:
case 0x10ec0256:
+ case 0x19e58326:
alc_write_coef_idx(codec, 0x1b, 0x0e4b);
alc_write_coef_idx(codec, 0x06, 0x6104);
alc_write_coefex_idx(codec, 0x57, 0x3, 0x09a3);
@@ -5123,7 +5303,7 @@ static void alc_determine_headset_type(struct hda_codec *codec)
case 0x10ec0274:
case 0x10ec0294:
alc_process_coef_fw(codec, coef0274);
- msleep(80);
+ msleep(850);
val = alc_read_coef_idx(codec, 0x46);
is_ctia = (val & 0x00f0) == 0x00f0;
break;
@@ -5307,6 +5487,7 @@ static void alc_update_headset_jack_cb(struct hda_codec *codec,
struct hda_jack_callback *jack)
{
snd_hda_gen_hp_automute(codec, jack);
+ alc_update_headset_mode(codec);
}
static void alc_probe_headset_mode(struct hda_codec *codec)
@@ -5385,8 +5566,10 @@ static void alc255_set_default_jack_type(struct hda_codec *codec)
case 0x10ec0255:
alc_process_coef_fw(codec, alc255fw);
break;
+ case 0x10ec0230:
case 0x10ec0236:
case 0x10ec0256:
+ case 0x19e58326:
alc_process_coef_fw(codec, alc256fw);
break;
}
@@ -5524,6 +5707,18 @@ static void alc_fixup_tpt470_dacs(struct hda_codec *codec,
spec->gen.preferred_dacs = preferred_pairs;
}
+static void alc295_fixup_asus_dacs(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ static const hda_nid_t preferred_pairs[] = {
+ 0x17, 0x02, 0x21, 0x03, 0
+ };
+ struct alc_spec *spec = codec->spec;
+
+ if (action == HDA_FIXUP_ACT_PRE_PROBE)
+ spec->gen.preferred_dacs = preferred_pairs;
+}
+
static void alc_shutup_dell_xps13(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -5937,6 +6132,21 @@ static void alc274_fixup_bind_dacs(struct hda_codec *codec,
codec->power_save_node = 0;
}
+/* avoid DAC 0x06 for bass speaker 0x17; it has no volume control */
+static void alc289_fixup_asus_ga401(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ static const hda_nid_t preferred_pairs[] = {
+ 0x14, 0x02, 0x17, 0x02, 0x21, 0x03, 0
+ };
+ struct alc_spec *spec = codec->spec;
+
+ if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+ spec->gen.preferred_dacs = preferred_pairs;
+ spec->gen.obey_preferred_dacs = 1;
+ }
+}
+
/* The DAC of NID 0x3 will introduce click/pop noise on headphones, so invalidate it */
static void alc285_fixup_invalidate_dacs(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
@@ -5947,6 +6157,29 @@ static void alc285_fixup_invalidate_dacs(struct hda_codec *codec,
snd_hda_override_wcaps(codec, 0x03, 0);
}
+static void alc_combo_jack_hp_jd_restart(struct hda_codec *codec)
+{
+ switch (codec->core.vendor_id) {
+ case 0x10ec0274:
+ case 0x10ec0294:
+ case 0x10ec0225:
+ case 0x10ec0295:
+ case 0x10ec0299:
+ alc_update_coef_idx(codec, 0x4a, 0x8000, 1 << 15); /* Reset HP JD */
+ alc_update_coef_idx(codec, 0x4a, 0x8000, 0 << 15);
+ break;
+ case 0x10ec0230:
+ case 0x10ec0235:
+ case 0x10ec0236:
+ case 0x10ec0255:
+ case 0x10ec0256:
+ case 0x19e58326:
+ alc_update_coef_idx(codec, 0x1b, 0x8000, 1 << 15); /* Reset HP JD */
+ alc_update_coef_idx(codec, 0x1b, 0x8000, 0 << 15);
+ break;
+ }
+}
+
static void alc295_fixup_chromebook(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@@ -5957,16 +6190,7 @@ static void alc295_fixup_chromebook(struct hda_codec *codec,
spec->ultra_low_power = true;
break;
case HDA_FIXUP_ACT_INIT:
- switch (codec->core.vendor_id) {
- case 0x10ec0295:
- alc_update_coef_idx(codec, 0x4a, 0x8000, 1 << 15); /* Reset HP JD */
- alc_update_coef_idx(codec, 0x4a, 0x8000, 0 << 15);
- break;
- case 0x10ec0236:
- alc_update_coef_idx(codec, 0x1b, 0x8000, 1 << 15); /* Reset HP JD */
- alc_update_coef_idx(codec, 0x1b, 0x8000, 0 << 15);
- break;
- }
+ alc_combo_jack_hp_jd_restart(codec);
break;
}
}
@@ -6012,6 +6236,35 @@ static void alc294_fixup_gx502_hp(struct hda_codec *codec,
}
}
+static void alc294_gu502_toggle_output(struct hda_codec *codec,
+ struct hda_jack_callback *cb)
+{
+ /* Windows sets 0x10 to 0x8420 for Node 0x20 which is
+ * responsible from changes between speakers and headphones
+ */
+ if (snd_hda_jack_detect_state(codec, 0x21) == HDA_JACK_PRESENT)
+ alc_write_coef_idx(codec, 0x10, 0x8420);
+ else
+ alc_write_coef_idx(codec, 0x10, 0x0a20);
+}
+
+static void alc294_fixup_gu502_hp(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ if (!is_jack_detectable(codec, 0x21))
+ return;
+
+ switch (action) {
+ case HDA_FIXUP_ACT_PRE_PROBE:
+ snd_hda_jack_detect_enable_callback(codec, 0x21,
+ alc294_gu502_toggle_output);
+ break;
+ case HDA_FIXUP_ACT_INIT:
+ alc294_gu502_toggle_output(codec, NULL);
+ break;
+ }
+}
+
static void alc285_fixup_hp_gpio_amp_init(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@@ -6022,6 +6275,34 @@ static void alc285_fixup_hp_gpio_amp_init(struct hda_codec *codec,
alc_write_coef_idx(codec, 0x65, 0x0);
}
+static void alc274_fixup_hp_headset_mic(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ switch (action) {
+ case HDA_FIXUP_ACT_INIT:
+ alc_combo_jack_hp_jd_restart(codec);
+ break;
+ }
+}
+
+static void alc285_fixup_hp_spectre_x360(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ static const hda_nid_t conn[] = { 0x02 };
+ static const struct hda_pintbl pincfgs[] = {
+ { 0x14, 0x90170110 }, /* rear speaker */
+ { }
+ };
+
+ switch (action) {
+ case HDA_FIXUP_ACT_PRE_PROBE:
+ snd_hda_apply_pincfgs(codec, pincfgs);
+ /* force front speaker to DAC1 */
+ snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
+ break;
+ }
+}
+
/* for hda_fixup_thinkpad_acpi() */
#include "thinkpad_helper.c"
@@ -6113,6 +6394,7 @@ enum {
ALC283_FIXUP_HEADSET_MIC,
ALC255_FIXUP_MIC_MUTE_LED,
ALC282_FIXUP_ASPIRE_V5_PINS,
+ ALC269VB_FIXUP_ASPIRE_E1_COEF,
ALC280_FIXUP_HP_GPIO4,
ALC286_FIXUP_HP_GPIO_LED,
ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY,
@@ -6142,6 +6424,7 @@ enum {
ALC221_FIXUP_HP_FRONT_MIC,
ALC292_FIXUP_TPT460,
ALC298_FIXUP_SPK_VOLUME,
+ ALC298_FIXUP_LENOVO_SPK_VOLUME,
ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER,
ALC269_FIXUP_ATIV_BOOK_8,
ALC221_FIXUP_HP_MIC_NO_PRESENCE,
@@ -6196,10 +6479,15 @@ enum {
ALC294_FIXUP_ASUS_GX502_HP,
ALC294_FIXUP_ASUS_GX502_PINS,
ALC294_FIXUP_ASUS_GX502_VERBS,
+ ALC294_FIXUP_ASUS_GU502_HP,
+ ALC294_FIXUP_ASUS_GU502_PINS,
+ ALC294_FIXUP_ASUS_GU502_VERBS,
ALC285_FIXUP_HP_GPIO_LED,
ALC285_FIXUP_HP_MUTE_LED,
+ ALC236_FIXUP_HP_GPIO_LED,
ALC236_FIXUP_HP_MUTE_LED,
ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
+ ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS,
ALC269VC_FIXUP_ACER_HEADSET_MIC,
@@ -6214,7 +6502,17 @@ enum {
ALC269_FIXUP_LEMOTE_A1802,
ALC269_FIXUP_LEMOTE_A190X,
ALC256_FIXUP_INTEL_NUC8_RUGGED,
+ ALC233_FIXUP_INTEL_NUC8_DMIC,
+ ALC233_FIXUP_INTEL_NUC8_BOOST,
+ ALC256_FIXUP_INTEL_NUC10,
ALC255_FIXUP_XIAOMI_HEADSET_MIC,
+ ALC274_FIXUP_HP_MIC,
+ ALC274_FIXUP_HP_HEADSET_MIC,
+ ALC256_FIXUP_ASUS_HPE,
+ ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK,
+ ALC295_FIXUP_ASUS_DACS,
+ ALC295_FIXUP_HP_OMEN,
+ ALC285_FIXUP_HP_SPECTRE_X360,
};
static const struct hda_fixup alc269_fixups[] = {
@@ -6777,6 +7075,10 @@ static const struct hda_fixup alc269_fixups[] = {
{ },
},
},
+ [ALC269VB_FIXUP_ASPIRE_E1_COEF] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc269vb_fixup_aspire_e1_coef,
+ },
[ALC280_FIXUP_HP_GPIO4] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc280_fixup_hp_gpio4,
@@ -6916,6 +7218,16 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc233_fixup_lenovo_line2_mic_hotkey,
},
+ [ALC233_FIXUP_INTEL_NUC8_DMIC] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc_fixup_inv_dmic,
+ .chained = true,
+ .chain_id = ALC233_FIXUP_INTEL_NUC8_BOOST,
+ },
+ [ALC233_FIXUP_INTEL_NUC8_BOOST] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc269_fixup_limit_int_mic_boost
+ },
[ALC255_FIXUP_DELL_SPK_NOISE] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_disable_aamix,
@@ -6964,6 +7276,10 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE,
},
+ [ALC298_FIXUP_LENOVO_SPK_VOLUME] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc298_fixup_speaker_volume,
+ },
[ALC295_FIXUP_DISABLE_DAC3] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc295_fixup_disable_dac3,
@@ -7395,6 +7711,35 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc294_fixup_gx502_hp,
},
+ [ALC294_FIXUP_ASUS_GU502_PINS] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x19, 0x01a11050 }, /* rear HP mic */
+ { 0x1a, 0x01a11830 }, /* rear external mic */
+ { 0x21, 0x012110f0 }, /* rear HP out */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC294_FIXUP_ASUS_GU502_VERBS
+ },
+ [ALC294_FIXUP_ASUS_GU502_VERBS] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* set 0x15 to HP-OUT ctrl */
+ { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* unmute the 0x15 amp */
+ { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
+ /* set 0x1b to HP-OUT */
+ { 0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC294_FIXUP_ASUS_GU502_HP
+ },
+ [ALC294_FIXUP_ASUS_GU502_HP] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc294_fixup_gu502_hp,
+ },
[ALC294_FIXUP_ASUS_COEF_1B] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
@@ -7405,6 +7750,8 @@ static const struct hda_fixup alc269_fixups[] = {
{ 0x20, AC_VERB_SET_PROC_COEF, 0x4e4b },
{ }
},
+ .chained = true,
+ .chain_id = ALC289_FIXUP_ASUS_GA401,
},
[ALC285_FIXUP_HP_GPIO_LED] = {
.type = HDA_FIXUP_FUNC,
@@ -7414,6 +7761,10 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc285_fixup_hp_mute_led,
},
+ [ALC236_FIXUP_HP_GPIO_LED] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc236_fixup_hp_gpio_led,
+ },
[ALC236_FIXUP_HP_MUTE_LED] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc236_fixup_hp_mute_led,
@@ -7425,6 +7776,14 @@ static const struct hda_fixup alc269_fixups[] = {
{ }
},
},
+ [ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x08},
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x2fcf},
+ { }
+ },
+ },
[ALC295_FIXUP_ASUS_MIC_NO_PRESENCE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
@@ -7464,11 +7823,10 @@ static const struct hda_fixup alc269_fixups[] = {
.chain_id = ALC269_FIXUP_HEADSET_MIC
},
[ALC289_FIXUP_ASUS_GA401] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11020 }, /* headset mic with jack detect */
- { }
- },
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc289_fixup_asus_ga401,
+ .chained = true,
+ .chain_id = ALC289_FIXUP_ASUS_GA502,
},
[ALC289_FIXUP_ASUS_GA502] = {
.type = HDA_FIXUP_PINS,
@@ -7584,6 +7942,15 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MODE
},
+ [ALC256_FIXUP_INTEL_NUC10] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC269_FIXUP_HEADSET_MODE
+ },
[ALC255_FIXUP_XIAOMI_HEADSET_MIC] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
@@ -7592,7 +7959,66 @@ static const struct hda_fixup alc269_fixups[] = {
{ }
},
.chained = true,
- .chain_id = ALC289_FIXUP_ASUS_GA401
+ .chain_id = ALC289_FIXUP_ASUS_GA502
+ },
+ [ALC274_FIXUP_HP_MIC] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x45 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x5089 },
+ { }
+ },
+ },
+ [ALC274_FIXUP_HP_HEADSET_MIC] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc274_fixup_hp_headset_mic,
+ .chained = true,
+ .chain_id = ALC274_FIXUP_HP_MIC
+ },
+ [ALC256_FIXUP_ASUS_HPE] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* Set EAPD high */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x0f },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x7778 },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC
+ },
+ [ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc_fixup_headset_jack,
+ .chained = true,
+ .chain_id = ALC269_FIXUP_THINKPAD_ACPI
+ },
+ [ALC295_FIXUP_ASUS_DACS] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc295_fixup_asus_dacs,
+ },
+ [ALC295_FIXUP_HP_OMEN] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x12, 0xb7a60130 },
+ { 0x13, 0x40000000 },
+ { 0x14, 0x411111f0 },
+ { 0x16, 0x411111f0 },
+ { 0x17, 0x90170110 },
+ { 0x18, 0x411111f0 },
+ { 0x19, 0x02a11030 },
+ { 0x1a, 0x411111f0 },
+ { 0x1b, 0x04a19030 },
+ { 0x1d, 0x40600001 },
+ { 0x1e, 0x411111f0 },
+ { 0x21, 0x03211020 },
+ {}
+ },
+ .chained = true,
+ .chain_id = ALC269_FIXUP_HP_LINE1_MIC1_LED,
+ },
+ [ALC285_FIXUP_HP_SPECTRE_X360] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc285_fixup_hp_spectre_x360,
},
};
@@ -7602,17 +8028,21 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
SND_PCI_QUIRK(0x1025, 0x072d, "Acer Aspire V5-571G", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
SND_PCI_QUIRK(0x1025, 0x0762, "Acer Aspire E1-472", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
+ SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1025, 0x0840, "Acer Aspire E1", ALC269VB_FIXUP_ASPIRE_E1_COEF),
+ SND_PCI_QUIRK(0x1025, 0x101c, "Acer Veriton N2510G", ALC269_FIXUP_LIFEBOOK),
SND_PCI_QUIRK(0x1025, 0x102b, "Acer Aspire C24-860", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1065, "Acer Aspire C20-820", ALC269VC_FIXUP_ACER_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK),
SND_PCI_QUIRK(0x1025, 0x1099, "Acer Aspire E5-523G", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x110e, "Acer Aspire ES1-432", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1025, 0x1166, "Acer Veriton N4640G", ALC269_FIXUP_LIFEBOOK),
+ SND_PCI_QUIRK(0x1025, 0x1167, "Acer Veriton N6640G", ALC269_FIXUP_LIFEBOOK),
SND_PCI_QUIRK(0x1025, 0x1246, "Acer Predator Helios 500", ALC299_FIXUP_PREDATOR_SPK),
SND_PCI_QUIRK(0x1025, 0x1247, "Acer vCopperbox", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS),
SND_PCI_QUIRK(0x1025, 0x1248, "Acer Veriton N4660G", ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE),
@@ -7622,6 +8052,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1025, 0x141f, "Acer Spin SP513-54N", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1025, 0x142b, "Acer Swift SF314-42", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
@@ -7656,8 +8088,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0738, "Dell Precision 5820", ALC269_FIXUP_NO_SHUTUP),
SND_PCI_QUIRK(0x1028, 0x075c, "Dell XPS 27 7760", ALC298_FIXUP_SPK_VOLUME),
SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME),
- SND_PCI_QUIRK(0x1028, 0x07b0, "Dell Precision 7520", ALC295_FIXUP_DISABLE_DAC3),
SND_PCI_QUIRK(0x1028, 0x0798, "Dell Inspiron 17 7000 Gaming", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER),
+ SND_PCI_QUIRK(0x1028, 0x07b0, "Dell Precision 7520", ALC295_FIXUP_DISABLE_DAC3),
SND_PCI_QUIRK(0x1028, 0x080c, "Dell WYSE", ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x084b, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
SND_PCI_QUIRK(0x1028, 0x084e, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
@@ -7667,8 +8099,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x08ad, "Dell WYSE AIO", ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x08ae, "Dell WYSE NB", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
- SND_PCI_QUIRK(0x1028, 0x097e, "Dell Precision", ALC289_FIXUP_DUAL_SPK),
SND_PCI_QUIRK(0x1028, 0x097d, "Dell Precision", ALC289_FIXUP_DUAL_SPK),
+ SND_PCI_QUIRK(0x1028, 0x097e, "Dell Precision", ALC289_FIXUP_DUAL_SPK),
SND_PCI_QUIRK(0x1028, 0x098d, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x09bf, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -7676,35 +8108,18 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x225f, "HP", ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY),
- /* ALC282 */
SND_PCI_QUIRK(0x103c, 0x21f9, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x2210, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+ SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+ SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+ SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x2237, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x2238, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x2239, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x224b, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x226e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x2271, "HP", ALC286_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC280_FIXUP_HP_DOCK_PINS),
- SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC280_FIXUP_HP_DOCK_PINS),
- SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC280_FIXUP_HP_9480M),
- SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- /* ALC290 */
- SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
@@ -7712,41 +8127,67 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED),
+ SND_PCI_QUIRK(0x103c, 0x225f, "HP", ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY),
SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+ SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+ SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+ SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+ SND_PCI_QUIRK(0x103c, 0x226e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+ SND_PCI_QUIRK(0x103c, 0x2271, "HP", ALC286_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+ SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC280_FIXUP_HP_DOCK_PINS),
SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+ SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC280_FIXUP_HP_DOCK_PINS),
SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x228b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x228e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+ SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+ SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+ SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+ SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+ SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x22c5, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x22c7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x22c8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+ SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+ SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC280_FIXUP_HP_9480M),
+ SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+ SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x2334, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC),
SND_PCI_QUIRK(0x103c, 0x802e, "HP Z240 SFF", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x802f, "HP Z240", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x820d, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC),
SND_PCI_QUIRK(0x103c, 0x827e, "HP x360", ALC295_FIXUP_HP_X360),
+ SND_PCI_QUIRK(0x103c, 0x827f, "HP x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
SND_PCI_QUIRK(0x103c, 0x82bf, "HP G3 mini", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x82c0, "HP G3 mini premium", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+ SND_PCI_QUIRK(0x103c, 0x841c, "HP Pavilion 15-CK0xx", ALC269_FIXUP_HP_MUTE_LED_MIC3),
SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+ SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN),
SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+ SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360),
+ SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+ SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT),
SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
+ SND_PCI_QUIRK(0x103c, 0x8724, "HP EliteBook 850 G7", ALC285_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8728, "HP EliteBook 840 G7", ALC285_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8729, "HP", ALC285_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+ SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED),
+ SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x89aa, "HP EliteBook 630 G9", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -7755,18 +8196,25 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1043, 0x125e, "ASUS Q524UQK", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1043, 0x1271, "ASUS X430UN", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC),
+ SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
+ SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS),
SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
+ SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK),
+ SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE),
+ SND_PCI_QUIRK(0x1043, 0x1970, "ASUS UX550VE", ALC289_FIXUP_ASUS_GA401),
+ SND_PCI_QUIRK(0x1043, 0x1982, "ASUS B1400CEPE", ALC256_FIXUP_ASUS_HPE),
SND_PCI_QUIRK(0x1043, 0x19ce, "ASUS B9450FA", ALC294_FIXUP_ASUS_HPE),
SND_PCI_QUIRK(0x1043, 0x19e1, "ASUS UX581LV", ALC295_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
@@ -7776,46 +8224,109 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
+ SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
+ SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
+ SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
- SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
+ SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
+ SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101),
- SND_PCI_QUIRK(0x104d, 0x90b5, "Sony VAIO Pro 11", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX),
+ SND_PCI_QUIRK(0x104d, 0x90b5, "Sony VAIO Pro 11", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
SND_PCI_QUIRK(0x10cf, 0x159f, "Lifebook E780", ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT),
SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN),
- SND_PCI_QUIRK(0x10cf, 0x1757, "Lifebook E752", ALC269_FIXUP_LIFEBOOK_HP_PIN),
SND_PCI_QUIRK(0x10cf, 0x1629, "Lifebook U7x7", ALC255_FIXUP_LIFEBOOK_U7x7_HEADSET_MIC),
+ SND_PCI_QUIRK(0x10cf, 0x1757, "Lifebook E752", ALC269_FIXUP_LIFEBOOK_HP_PIN),
SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
SND_PCI_QUIRK(0x10ec, 0x10f2, "Intel Reference board", ALC700_FIXUP_INTEL_REFERENCE),
+ SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE),
SND_PCI_QUIRK(0x10ec, 0x1230, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
+ SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
+ SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE),
SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
- SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+ SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+ SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x152d, 0x1082, "Quanta NL3", ALC269_FIXUP_LIFEBOOK),
+ SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x1401, "Clevo L140[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x1403, "Clevo N140CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x1404, "Clevo N150CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x14a1, "Clevo L141MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x4018, "Clevo NV40M[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x4019, "Clevo NV40MZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x4020, "Clevo NV40MB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x40a1, "Clevo NL40GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x40c1, "Clevo NL40[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x40d1, "Clevo NL41DU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x50a3, "Clevo NJ51GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x50b3, "Clevo NK50S[BEZ]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x50b6, "Clevo NK50S5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x50b8, "Clevo NK50SZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x50d5, "Clevo NP50D5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x50f0, "Clevo NH50A[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x50f2, "Clevo NH50E[PR]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x50f3, "Clevo NH58DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x50f5, "Clevo NH55EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x50f6, "Clevo NH55DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x5101, "Clevo S510WU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x5157, "Clevo W517GU1", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x51a1, "Clevo NS50MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x70f2, "Clevo NH79EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x70f3, "Clevo NH77DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x70f4, "Clevo NH77EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x70f6, "Clevo NH77DPQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x8535, "Clevo NH50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x8536, "Clevo NH79D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x8550, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x8551, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x8560, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1558, 0x8561, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1558, 0x8562, "Clevo NH[5|7][0-9]RZ[Q]", ALC269_FIXUP_DMIC),
+ SND_PCI_QUIRK(0x1558, 0x8668, "Clevo NP50B[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x8680, "Clevo NJ50LU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x8686, "Clevo NH50[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x8a20, "Clevo NH55DCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x8a51, "Clevo NH70RCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x8d50, "Clevo NH55RCQ-M", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x951d, "Clevo N950T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x9600, "Clevo N960K[PR]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x961d, "Clevo N960S[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x971d, "Clevo N970T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0xa500, "Clevo NL53RU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0xa600, "Clevo NL5XNU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0xb018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0xb019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0xb022, "Clevo NH77D[DC][QW]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0xc018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0xc019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0xc022, "Clevo NH77[DC][QW]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS),
SND_PCI_QUIRK(0x17aa, 0x1048, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
@@ -7823,9 +8334,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
+ SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK_LIMIT_BOOST),
SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
@@ -7853,6 +8364,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
+ SND_PCI_QUIRK(0x17aa, 0x22c1, "Thinkpad P1 Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK),
+ SND_PCI_QUIRK(0x17aa, 0x22c2, "Thinkpad X1 Extreme Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK),
SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
@@ -7863,9 +8376,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3151, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME),
SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
+ SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC),
SND_PCI_QUIRK(0x17aa, 0x501e, "Thinkpad L440", ALC292_FIXUP_TPT440_DOCK),
@@ -7884,19 +8399,21 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x17aa, 0x511e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
SND_PCI_QUIRK(0x17aa, 0x511f, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20),
SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI),
SND_PCI_QUIRK(0x1b35, 0x1237, "CZC L101", ALC269_FIXUP_CZC_L101),
SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
- SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
- SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
- SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE),
SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802),
SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X),
+ SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
+ SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
SND_PCI_QUIRK(0x8086, 0x2080, "Intel NUC 8 Rugged", ALC256_FIXUP_INTEL_NUC8_RUGGED),
+ SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", ALC256_FIXUP_INTEL_NUC10),
#if 0
/* Below is a quirk table taken from the old code.
@@ -8026,6 +8543,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{.id = ALC283_FIXUP_HEADSET_MIC, .name = "alc283-headset"},
{.id = ALC255_FIXUP_MIC_MUTE_LED, .name = "alc255-dell-mute"},
{.id = ALC282_FIXUP_ASPIRE_V5_PINS, .name = "aspire-v5"},
+ {.id = ALC269VB_FIXUP_ASPIRE_E1_COEF, .name = "aspire-e1-coef"},
{.id = ALC280_FIXUP_HP_GPIO4, .name = "hp-gpio4"},
{.id = ALC286_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
{.id = ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY, .name = "hp-gpio2-hotkey"},
@@ -8069,7 +8587,11 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"},
{.id = ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, .name = "alc256-medion-headset"},
{.id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc298-samsung-headphone"},
+ {.id = ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc256-samsung-headphone"},
{.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
+ {.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},
+ {.id = ALC295_FIXUP_HP_OMEN, .name = "alc295-hp-omen"},
+ {.id = ALC285_FIXUP_HP_SPECTRE_X360, .name = "alc285-hp-spectre-x360"},
{}
};
#define ALC225_STANDARD_PINS \
@@ -8298,6 +8820,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
{0x1a, 0x90a70130},
{0x1b, 0x90170110},
{0x21, 0x03211020}),
+ SND_HDA_PIN_QUIRK(0x10ec0274, 0x103c, "HP", ALC274_FIXUP_HP_HEADSET_MIC,
+ {0x17, 0x90170110},
+ {0x19, 0x03a11030},
+ {0x21, 0x03211020}),
SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
{0x12, 0x90a60130},
{0x14, 0x90170110},
@@ -8353,6 +8879,20 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
{0x14, 0x90170110},
{0x19, 0x04a11040},
{0x21, 0x04211020}),
+ SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE,
+ {0x14, 0x90170110},
+ {0x19, 0x04a11040},
+ {0x1d, 0x40600001},
+ {0x21, 0x04211020}),
+ SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK,
+ {0x14, 0x90170110},
+ {0x19, 0x04a11040},
+ {0x21, 0x04211020}),
+ SND_HDA_PIN_QUIRK(0x10ec0287, 0x17aa, "Lenovo", ALC285_FIXUP_THINKPAD_HEADSET_JACK,
+ {0x14, 0x90170110},
+ {0x17, 0x90170111},
+ {0x19, 0x03a11030},
+ {0x21, 0x03211020}),
SND_HDA_PIN_QUIRK(0x10ec0286, 0x1025, "Acer", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE,
{0x12, 0x90a60130},
{0x17, 0x90170110},
@@ -8416,6 +8956,9 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC292_STANDARD_PINS,
{0x13, 0x90a60140}),
+ SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_HPE,
+ {0x17, 0x90170110},
+ {0x21, 0x04211020}),
SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_MIC,
{0x14, 0x90170110},
{0x1b, 0x90a70130},
@@ -8640,8 +9183,10 @@ static int patch_alc269(struct hda_codec *codec)
spec->shutup = alc256_shutup;
spec->init_hook = alc256_init;
break;
+ case 0x10ec0230:
case 0x10ec0236:
case 0x10ec0256:
+ case 0x19e58326:
spec->codec_variant = ALC269_TYPE_ALC256;
spec->shutup = alc256_shutup;
spec->init_hook = alc256_init;
@@ -8707,6 +9252,16 @@ static int patch_alc269(struct hda_codec *codec)
snd_hda_pick_fixup(codec, alc269_fixup_models,
alc269_fixup_tbl, alc269_fixups);
+ /* FIXME: both TX300 and ROG Strix G17 have the same SSID, and
+ * the quirk breaks the latter (bko#214101).
+ * Clear the wrong entry.
+ */
+ if (codec->fixup_id == ALC282_FIXUP_ASUS_TX300 &&
+ codec->core.vendor_id == 0x10ec0294) {
+ codec_dbg(codec, "Clear wrong fixup for ASUS ROG Strix G17\n");
+ codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
+ }
+
snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups, true);
snd_hda_pick_pin_fixup(codec, alc269_fallback_pin_fixup_tbl, alc269_fixups, false);
snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl,
@@ -8824,8 +9379,7 @@ static const struct snd_pci_quirk alc861_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
- SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F),
- SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F),
+ SND_PCI_QUIRK_VENDOR(0x1584, "Haier/Uniwill", ALC861_FIXUP_AMP_VREF_0F),
SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505),
{}
};
@@ -9149,6 +9703,27 @@ static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec,
}
}
+static void alc897_hp_automute_hook(struct hda_codec *codec,
+ struct hda_jack_callback *jack)
+{
+ struct alc_spec *spec = codec->spec;
+ int vref;
+
+ snd_hda_gen_hp_automute(codec, jack);
+ vref = spec->gen.hp_jack_present ? (PIN_HP | AC_PINCTL_VREF_100) : PIN_HP;
+ snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ vref);
+}
+
+static void alc897_fixup_lenovo_headset_mic(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+ spec->gen.hp_automute_hook = alc897_hp_automute_hook;
+ }
+}
+
static const struct coef_fw alc668_coefs[] = {
WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0),
WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80),
@@ -9226,6 +9801,12 @@ enum {
ALC671_FIXUP_HP_HEADSET_MIC2,
ALC662_FIXUP_ACER_X2660G_HEADSET_MODE,
ALC662_FIXUP_ACER_NITRO_HEADSET_MODE,
+ ALC668_FIXUP_ASUS_NO_HEADSET_MIC,
+ ALC668_FIXUP_HEADSET_MIC,
+ ALC668_FIXUP_MIC_DET_COEF,
+ ALC897_FIXUP_LENOVO_HEADSET_MIC,
+ ALC897_FIXUP_HEADSET_MIC_PIN,
+ ALC897_FIXUP_HP_HSMIC_VERB,
};
static const struct hda_fixup alc662_fixups[] = {
@@ -9609,6 +10190,49 @@ static const struct hda_fixup alc662_fixups[] = {
.chained = true,
.chain_id = ALC662_FIXUP_USI_FUNC
},
+ [ALC668_FIXUP_ASUS_NO_HEADSET_MIC] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x1b, 0x04a1112c },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC668_FIXUP_HEADSET_MIC
+ },
+ [ALC668_FIXUP_HEADSET_MIC] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc269_fixup_headset_mic,
+ .chained = true,
+ .chain_id = ALC668_FIXUP_MIC_DET_COEF
+ },
+ [ALC668_FIXUP_MIC_DET_COEF] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x15 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0d60 },
+ {}
+ },
+ },
+ [ALC897_FIXUP_LENOVO_HEADSET_MIC] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc897_fixup_lenovo_headset_mic,
+ },
+ [ALC897_FIXUP_HEADSET_MIC_PIN] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x1a, 0x03a11050 },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MIC
+ },
+ [ALC897_FIXUP_HP_HSMIC_VERB] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+ { }
+ },
+ },
};
static const struct snd_pci_quirk alc662_fixup_tbl[] = {
@@ -9620,6 +10244,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
+ SND_PCI_QUIRK(0x1025, 0x0566, "Acer Aspire Ethos 8951G", ALC669_FIXUP_ACER_ASPIRE_ETHOS),
SND_PCI_QUIRK(0x1025, 0x123c, "Acer Nitro N50-600", ALC662_FIXUP_ACER_NITRO_HEADSET_MODE),
SND_PCI_QUIRK(0x1025, 0x124e, "Acer 2660G", ALC662_FIXUP_ACER_X2660G_HEADSET_MODE),
SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
@@ -9633,15 +10258,19 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
+ SND_PCI_QUIRK(0x103c, 0x8719, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
+ SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2),
+ SND_PCI_QUIRK(0x103c, 0x885f, "HP 288 Pro G8", ALC671_FIXUP_HP_HEADSET_MIC2),
SND_PCI_QUIRK(0x1043, 0x1080, "Asus UX501VW", ALC668_FIXUP_HEADSET_MODE),
SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50),
- SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A),
SND_PCI_QUIRK(0x1043, 0x129d, "Asus N750", ALC662_FIXUP_ASUS_Nx50),
SND_PCI_QUIRK(0x1043, 0x12ff, "ASUS G751", ALC668_FIXUP_ASUS_G751),
+ SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A),
SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16),
SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51),
SND_PCI_QUIRK(0x1043, 0x17bd, "ASUS N751", ALC668_FIXUP_ASUS_Nx51),
+ SND_PCI_QUIRK(0x1043, 0x185d, "ASUS G551JW", ALC668_FIXUP_ASUS_NO_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71SL", ALC662_FIXUP_ASUS_MODE8),
SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16),
SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
@@ -9650,6 +10279,11 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE),
SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS),
+ SND_PCI_QUIRK(0x17aa, 0x1057, "Lenovo P360", ALC897_FIXUP_HEADSET_MIC_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x32ca, "Lenovo ThinkCentre M80", ALC897_FIXUP_HEADSET_MIC_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO),
@@ -9657,7 +10291,6 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x1b0a, 0x01b8, "ACER Veriton", ALC662_FIXUP_ACER_VERITON),
SND_PCI_QUIRK(0x1b35, 0x1234, "CZC ET26", ALC662_FIXUP_CZC_ET26),
SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
- SND_PCI_QUIRK(0x1025, 0x0566, "Acer Aspire Ethos 8951G", ALC669_FIXUP_ACER_ASPIRE_ETHOS),
#if 0
/* Below is a quirk table taken from the old code.
@@ -9931,6 +10564,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0222, "ALC222", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269),
+ HDA_CODEC_ENTRY(0x10ec0230, "ALC236", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0234, "ALC234", patch_alc269),
@@ -9998,11 +10632,13 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
HDA_CODEC_ENTRY(0x10ec0888, "ALC888", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0889, "ALC889", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662),
+ HDA_CODEC_ENTRY(0x10ec0897, "ALC897", patch_alc662),
HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0b00, "ALCS1200A", patch_alc882),
HDA_CODEC_ENTRY(0x10ec1168, "ALC1220", patch_alc882),
HDA_CODEC_ENTRY(0x10ec1220, "ALC1220", patch_alc882),
+ HDA_CODEC_ENTRY(0x19e58326, "HW8326", patch_alc269),
{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_realtek);
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 7ef8f3105cdb..3edb4e25797d 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -113,6 +113,7 @@ static struct via_spec *via_new_spec(struct hda_codec *codec)
spec->codec_type = VT1708S;
spec->gen.indep_hp = 1;
spec->gen.keep_eapd_on = 1;
+ spec->gen.dac_min_mute = 1;
spec->gen.pcm_playback_hook = via_playback_pcm_hook;
spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
codec->power_save_node = 1;
@@ -519,11 +520,11 @@ static int via_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
- err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
+ err = auto_parse_beep(codec);
if (err < 0)
return err;
- err = auto_parse_beep(codec);
+ err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
if (err < 0)
return err;
@@ -1002,6 +1003,7 @@ static const struct hda_verb vt1802_init_verbs[] = {
enum {
VIA_FIXUP_INTMIC_BOOST,
VIA_FIXUP_ASUS_G75,
+ VIA_FIXUP_POWER_SAVE,
};
static void via_fixup_intmic_boost(struct hda_codec *codec,
@@ -1011,6 +1013,13 @@ static void via_fixup_intmic_boost(struct hda_codec *codec,
override_mic_boost(codec, 0x30, 0, 2, 40);
}
+static void via_fixup_power_save(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ if (action == HDA_FIXUP_ACT_PRE_PROBE)
+ codec->power_save_node = 0;
+}
+
static const struct hda_fixup via_fixups[] = {
[VIA_FIXUP_INTMIC_BOOST] = {
.type = HDA_FIXUP_FUNC,
@@ -1025,11 +1034,16 @@ static const struct hda_fixup via_fixups[] = {
{ }
}
},
+ [VIA_FIXUP_POWER_SAVE] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = via_fixup_power_save,
+ },
};
static const struct snd_pci_quirk vt2002p_fixups[] = {
SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
+ SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", VIA_FIXUP_POWER_SAVE),
{}
};
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 6ff94d8ad86e..5150e8d38975 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -354,6 +354,7 @@ struct ichdev {
unsigned int ali_slot; /* ALI DMA slot */
struct ac97_pcm *pcm;
int pcm_open_flag;
+ unsigned int prepared:1;
unsigned int suspended: 1;
};
@@ -714,6 +715,9 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich
int status, civ, i, step;
int ack = 0;
+ if (!(ichdev->prepared || chip->in_measurement) || ichdev->suspended)
+ return;
+
spin_lock_irqsave(&chip->reg_lock, flags);
status = igetbyte(chip, port + ichdev->roff_sr);
civ = igetbyte(chip, port + ICH_REG_OFF_CIV);
@@ -907,6 +911,7 @@ static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream,
if (ichdev->pcm_open_flag) {
snd_ac97_pcm_close(ichdev->pcm);
ichdev->pcm_open_flag = 0;
+ ichdev->prepared = 0;
}
err = snd_ac97_pcm_open(ichdev->pcm, params_rate(hw_params),
params_channels(hw_params),
@@ -928,6 +933,7 @@ static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream)
if (ichdev->pcm_open_flag) {
snd_ac97_pcm_close(ichdev->pcm);
ichdev->pcm_open_flag = 0;
+ ichdev->prepared = 0;
}
return snd_pcm_lib_free_pages(substream);
}
@@ -1002,6 +1008,7 @@ static int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream)
ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
}
snd_intel8x0_setup_periods(chip, ichdev);
+ ichdev->prepared = 1;
return 0;
}
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c
index 048a2660d18d..363b26e85af5 100644
--- a/sound/pci/mixart/mixart_core.c
+++ b/sound/pci/mixart/mixart_core.c
@@ -70,7 +70,6 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
unsigned int i;
#endif
- mutex_lock(&mgr->msg_lock);
err = 0;
/* copy message descriptor from miXart to driver */
@@ -119,8 +118,6 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD));
_clean_exit:
- mutex_unlock(&mgr->msg_lock);
-
return err;
}
@@ -258,7 +255,9 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int
resp.data = resp_data;
resp.size = max_resp_size;
+ mutex_lock(&mgr->msg_lock);
err = get_msg(mgr, &resp, msg_frame);
+ mutex_unlock(&mgr->msg_lock);
if( request->message_id != resp.message_id )
dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n");
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 5cbdc9be9c7e..c7b3e76ea2d2 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -5326,7 +5326,8 @@ static int snd_hdsp_free(struct hdsp *hdsp)
if (hdsp->port)
pci_release_regions(hdsp->pci);
- pci_disable_device(hdsp->pci);
+ if (pci_is_enabled(hdsp->pci))
+ pci_disable_device(hdsp->pci);
return 0;
}
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 81a6f4b2bd3c..e34f07c9ff47 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -6889,7 +6889,8 @@ static int snd_hdspm_free(struct hdspm * hdspm)
if (hdspm->port)
pci_release_regions(hdspm->pci);
- pci_disable_device(hdspm->pci);
+ if (pci_is_enabled(hdspm->pci))
+ pci_disable_device(hdspm->pci);
return 0;
}
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 4c851f8dcaf8..73ad6e74aac9 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -1745,7 +1745,8 @@ static int snd_rme9652_free(struct snd_rme9652 *rme9652)
if (rme9652->port)
pci_release_regions(rme9652->pci);
- pci_disable_device(rme9652->pci);
+ if (pci_is_enabled(rme9652->pci))
+ pci_disable_device(rme9652->pci);
return 0;
}
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index 96ef55082bf9..b135d114ce89 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -77,7 +77,11 @@ static int snd_pmac_probe(struct platform_device *devptr)
sprintf(card->shortname, "PowerMac %s", name_ext);
sprintf(card->longname, "%s (Dev %d) Sub-frame %d",
card->shortname, chip->device_id, chip->subframe);
- if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0)
+ err = snd_pmac_tumbler_init(chip);
+ if (err < 0)
+ goto __error;
+ err = snd_pmac_tumbler_post_init();
+ if (err < 0)
goto __error;
break;
case PMAC_AWACS:
diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c
index f4ee6798154a..1612ec65aaf6 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -73,8 +73,13 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
- da7219_dai_wclk = clk_get(component->dev, "da7219-dai-wclk");
- da7219_dai_bclk = clk_get(component->dev, "da7219-dai-bclk");
+ da7219_dai_wclk = devm_clk_get(component->dev, "da7219-dai-wclk");
+ if (IS_ERR(da7219_dai_wclk))
+ return PTR_ERR(da7219_dai_wclk);
+
+ da7219_dai_bclk = devm_clk_get(component->dev, "da7219-dai-bclk");
+ if (IS_ERR(da7219_dai_bclk))
+ return PTR_ERR(da7219_dai_bclk);
ret = snd_soc_card_jack_new(card, "Headset Jack",
SND_JACK_HEADSET | SND_JACK_LINEOUT |
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 71f2d42188c4..51e75b781968 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -11,7 +11,6 @@ if SND_ATMEL_SOC
config SND_ATMEL_SOC_PDC
bool
- depends on HAS_DMA
config SND_ATMEL_SOC_DMA
bool
diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c
index bbe2b638abb5..d870f56c44cf 100644
--- a/sound/soc/atmel/atmel-i2s.c
+++ b/sound/soc/atmel/atmel-i2s.c
@@ -200,6 +200,7 @@ struct atmel_i2s_dev {
unsigned int fmt;
const struct atmel_i2s_gck_param *gck_param;
const struct atmel_i2s_caps *caps;
+ int clk_use_no;
};
static irqreturn_t atmel_i2s_interrupt(int irq, void *dev_id)
@@ -321,9 +322,16 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream,
{
struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
- unsigned int mr = 0;
+ unsigned int mr = 0, mr_mask;
int ret;
+ mr_mask = ATMEL_I2SC_MR_FORMAT_MASK | ATMEL_I2SC_MR_MODE_MASK |
+ ATMEL_I2SC_MR_DATALENGTH_MASK;
+ if (is_playback)
+ mr_mask |= ATMEL_I2SC_MR_TXMONO;
+ else
+ mr_mask |= ATMEL_I2SC_MR_RXMONO;
+
switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
mr |= ATMEL_I2SC_MR_FORMAT_I2S;
@@ -402,7 +410,7 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- return regmap_write(dev->regmap, ATMEL_I2SC_MR, mr);
+ return regmap_update_bits(dev->regmap, ATMEL_I2SC_MR, mr_mask, mr);
}
static int atmel_i2s_switch_mck_generator(struct atmel_i2s_dev *dev,
@@ -495,18 +503,28 @@ static int atmel_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
is_master = (mr & ATMEL_I2SC_MR_MODE_MASK) == ATMEL_I2SC_MR_MODE_MASTER;
/* If master starts, enable the audio clock. */
- if (is_master && mck_enabled)
- err = atmel_i2s_switch_mck_generator(dev, true);
- if (err)
- return err;
+ if (is_master && mck_enabled) {
+ if (!dev->clk_use_no) {
+ err = atmel_i2s_switch_mck_generator(dev, true);
+ if (err)
+ return err;
+ }
+ dev->clk_use_no++;
+ }
err = regmap_write(dev->regmap, ATMEL_I2SC_CR, cr);
if (err)
return err;
/* If master stops, disable the audio clock. */
- if (is_master && !mck_enabled)
- err = atmel_i2s_switch_mck_generator(dev, false);
+ if (is_master && !mck_enabled) {
+ if (dev->clk_use_no == 1) {
+ err = atmel_i2s_switch_mck_generator(dev, false);
+ if (err)
+ return err;
+ }
+ dev->clk_use_no--;
+ }
return err;
}
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index ca603397651c..1e0973322cd0 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -280,7 +280,10 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
/* Enable PMC peripheral clock for this SSC */
pr_debug("atmel_ssc_dai: Starting clock\n");
- clk_enable(ssc_p->ssc->clk);
+ ret = clk_enable(ssc_p->ssc->clk);
+ if (ret)
+ return ret;
+
ssc_p->mck_rate = clk_get_rate(ssc_p->ssc->clk);
/* Reset the SSC unless initialized to keep it in a clean state */
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index b1bef2bf142d..d1579896f3a1 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -46,35 +46,6 @@
*/
#undef ENABLE_MIC_INPUT
-static struct clk *mclk;
-
-static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card,
- struct snd_soc_dapm_context *dapm,
- enum snd_soc_bias_level level)
-{
- static int mclk_on;
- int ret = 0;
-
- switch (level) {
- case SND_SOC_BIAS_ON:
- case SND_SOC_BIAS_PREPARE:
- if (!mclk_on)
- ret = clk_enable(mclk);
- if (ret == 0)
- mclk_on = 1;
- break;
-
- case SND_SOC_BIAS_OFF:
- case SND_SOC_BIAS_STANDBY:
- if (mclk_on)
- clk_disable(mclk);
- mclk_on = 0;
- break;
- }
-
- return ret;
-}
-
static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Int Mic", NULL),
SND_SOC_DAPM_SPK("Ext Spk", NULL),
@@ -135,7 +106,6 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = {
.owner = THIS_MODULE,
.dai_link = &at91sam9g20ek_dai,
.num_links = 1,
- .set_bias_level = at91sam9g20ek_set_bias_level,
.dapm_widgets = at91sam9g20ek_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets),
@@ -148,7 +118,6 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *codec_np, *cpu_np;
- struct clk *pllb;
struct snd_soc_card *card = &snd_soc_at91sam9g20ek;
int ret;
@@ -162,31 +131,6 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
return -EINVAL;
}
- /*
- * Codec MCLK is supplied by PCK0 - set it up.
- */
- mclk = clk_get(NULL, "pck0");
- if (IS_ERR(mclk)) {
- dev_err(&pdev->dev, "Failed to get MCLK\n");
- ret = PTR_ERR(mclk);
- goto err;
- }
-
- pllb = clk_get(NULL, "pllb");
- if (IS_ERR(pllb)) {
- dev_err(&pdev->dev, "Failed to get PLLB\n");
- ret = PTR_ERR(pllb);
- goto err_mclk;
- }
- ret = clk_set_parent(mclk, pllb);
- clk_put(pllb);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to set MCLK parent\n");
- goto err_mclk;
- }
-
- clk_set_rate(mclk, MCLK_RATE);
-
card->dev = &pdev->dev;
/* Parse device node info */
@@ -214,6 +158,7 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
if (!cpu_np) {
dev_err(&pdev->dev, "dai and pcm info missing\n");
+ of_node_put(codec_np);
return -EINVAL;
}
at91sam9g20ek_dai.cpus->of_node = cpu_np;
@@ -229,9 +174,6 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
return ret;
-err_mclk:
- clk_put(mclk);
- mclk = NULL;
err:
atmel_ssc_put_audio(0);
return ret;
@@ -241,8 +183,6 @@ static int at91sam9g20ek_audio_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
- clk_disable(mclk);
- mclk = NULL;
snd_soc_unregister_card(card);
atmel_ssc_put_audio(0);
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 229cc89f8c5a..dfc536cd9d2f 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -586,21 +586,26 @@ config SND_SOC_CS4349
config SND_SOC_CS47L15
tristate
+ depends on MFD_CS47L15
config SND_SOC_CS47L24
tristate
config SND_SOC_CS47L35
tristate
+ depends on MFD_CS47L35
config SND_SOC_CS47L85
tristate
+ depends on MFD_CS47L85
config SND_SOC_CS47L90
tristate
+ depends on MFD_CS47L90
config SND_SOC_CS47L92
tristate
+ depends on MFD_CS47L92
# Cirrus Logic Quad-Channel ADC
config SND_SOC_CS53L30
@@ -754,7 +759,6 @@ config SND_SOC_MAX98095
config SND_SOC_MAX98357A
tristate "Maxim MAX98357A CODEC"
- depends on GPIOLIB
config SND_SOC_MAX98371
tristate
diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c
index 71562154c0b1..eca5fc559d69 100644
--- a/sound/soc/codecs/ak4458.c
+++ b/sound/soc/codecs/ak4458.c
@@ -523,18 +523,10 @@ static struct snd_soc_dai_driver ak4497_dai = {
.ops = &ak4458_dai_ops,
};
-static void ak4458_power_off(struct ak4458_priv *ak4458)
+static void ak4458_reset(struct ak4458_priv *ak4458, bool active)
{
if (ak4458->reset_gpiod) {
- gpiod_set_value_cansleep(ak4458->reset_gpiod, 0);
- usleep_range(1000, 2000);
- }
-}
-
-static void ak4458_power_on(struct ak4458_priv *ak4458)
-{
- if (ak4458->reset_gpiod) {
- gpiod_set_value_cansleep(ak4458->reset_gpiod, 1);
+ gpiod_set_value_cansleep(ak4458->reset_gpiod, active);
usleep_range(1000, 2000);
}
}
@@ -548,7 +540,7 @@ static int ak4458_init(struct snd_soc_component *component)
if (ak4458->mute_gpiod)
gpiod_set_value_cansleep(ak4458->mute_gpiod, 1);
- ak4458_power_on(ak4458);
+ ak4458_reset(ak4458, false);
ret = snd_soc_component_update_bits(component, AK4458_00_CONTROL1,
0x80, 0x80); /* ACKS bit = 1; 10000000 */
@@ -571,7 +563,7 @@ static void ak4458_remove(struct snd_soc_component *component)
{
struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
- ak4458_power_off(ak4458);
+ ak4458_reset(ak4458, true);
}
#ifdef CONFIG_PM
@@ -581,7 +573,7 @@ static int __maybe_unused ak4458_runtime_suspend(struct device *dev)
regcache_cache_only(ak4458->regmap, true);
- ak4458_power_off(ak4458);
+ ak4458_reset(ak4458, true);
if (ak4458->mute_gpiod)
gpiod_set_value_cansleep(ak4458->mute_gpiod, 0);
@@ -596,8 +588,8 @@ static int __maybe_unused ak4458_runtime_resume(struct device *dev)
if (ak4458->mute_gpiod)
gpiod_set_value_cansleep(ak4458->mute_gpiod, 1);
- ak4458_power_off(ak4458);
- ak4458_power_on(ak4458);
+ ak4458_reset(ak4458, true);
+ ak4458_reset(ak4458, false);
regcache_cache_only(ak4458->regmap, false);
regcache_mark_dirty(ak4458->regmap);
@@ -715,6 +707,7 @@ static const struct of_device_id ak4458_of_match[] = {
{ .compatible = "asahi-kasei,ak4497", .data = &ak4497_drvdata},
{ },
};
+MODULE_DEVICE_TABLE(of, ak4458_of_match);
static struct i2c_driver ak4458_i2c_driver = {
.driver = {
diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c
index 8179512129d3..e98312a6b840 100644
--- a/sound/soc/codecs/ak5558.c
+++ b/sound/soc/codecs/ak5558.c
@@ -264,7 +264,7 @@ static void ak5558_power_off(struct ak5558_priv *ak5558)
if (!ak5558->reset_gpiod)
return;
- gpiod_set_value_cansleep(ak5558->reset_gpiod, 0);
+ gpiod_set_value_cansleep(ak5558->reset_gpiod, 1);
usleep_range(1000, 2000);
}
@@ -273,7 +273,7 @@ static void ak5558_power_on(struct ak5558_priv *ak5558)
if (!ak5558->reset_gpiod)
return;
- gpiod_set_value_cansleep(ak5558->reset_gpiod, 1);
+ gpiod_set_value_cansleep(ak5558->reset_gpiod, 0);
usleep_range(1000, 2000);
}
@@ -389,6 +389,7 @@ static const struct of_device_id ak5558_i2c_dt_ids[] = {
{ .compatible = "asahi-kasei,ak5558"},
{ }
};
+MODULE_DEVICE_TABLE(of, ak5558_i2c_dt_ids);
static struct i2c_driver ak5558_i2c_driver = {
.driver = {
diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c
index d7f05b384f1f..acd88fe38cd4 100644
--- a/sound/soc/codecs/cpcap.c
+++ b/sound/soc/codecs/cpcap.c
@@ -1263,12 +1263,12 @@ static int cpcap_voice_hw_params(struct snd_pcm_substream *substream,
if (direction == SNDRV_PCM_STREAM_CAPTURE) {
mask = 0x0000;
- mask |= CPCAP_BIT_MIC1_RX_TIMESLOT0;
- mask |= CPCAP_BIT_MIC1_RX_TIMESLOT1;
- mask |= CPCAP_BIT_MIC1_RX_TIMESLOT2;
- mask |= CPCAP_BIT_MIC2_TIMESLOT0;
- mask |= CPCAP_BIT_MIC2_TIMESLOT1;
- mask |= CPCAP_BIT_MIC2_TIMESLOT2;
+ mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0);
+ mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT1);
+ mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT2);
+ mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT0);
+ mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT1);
+ mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT2);
val = 0x0000;
if (channels >= 2)
val = BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0);
@@ -1541,6 +1541,8 @@ static int cpcap_codec_probe(struct platform_device *pdev)
{
struct device_node *codec_node =
of_get_child_by_name(pdev->dev.parent->of_node, "audio-codec");
+ if (!codec_node)
+ return -ENODEV;
pdev->dev.of_node = codec_node;
diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c
index 6042194d95d3..8894369e329a 100644
--- a/sound/soc/codecs/cs35l33.c
+++ b/sound/soc/codecs/cs35l33.c
@@ -1201,6 +1201,7 @@ static int cs35l33_i2c_probe(struct i2c_client *i2c_client,
dev_err(&i2c_client->dev,
"CS35L33 Device ID (%X). Expected ID %X\n",
devid, CS35L33_CHIP_ID);
+ ret = -EINVAL;
goto err_enable;
}
diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c
index e9b5f76f27a8..aa32b8c26578 100644
--- a/sound/soc/codecs/cs35l36.c
+++ b/sound/soc/codecs/cs35l36.c
@@ -444,7 +444,8 @@ static bool cs35l36_volatile_reg(struct device *dev, unsigned int reg)
}
}
-static DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10200, 25, 0);
+static const DECLARE_TLV_DB_RANGE(dig_vol_tlv, 0, 912,
+ TLV_DB_MINMAX_ITEM(-10200, 1200));
static DECLARE_TLV_DB_SCALE(amp_gain_tlv, 0, 1, 1);
static const char * const cs35l36_pcm_sftramp_text[] = {
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c
index 2fb65f246b0c..77af5b67b9bb 100644
--- a/sound/soc/codecs/cs4265.c
+++ b/sound/soc/codecs/cs4265.c
@@ -150,7 +150,6 @@ static const struct snd_kcontrol_new cs4265_snd_controls[] = {
SOC_SINGLE("E to F Buffer Disable Switch", CS4265_SPDIF_CTL1,
6, 1, 0),
SOC_ENUM("C Data Access", cam_mode_enum),
- SOC_SINGLE("SPDIF Switch", CS4265_SPDIF_CTL2, 5, 1, 1),
SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2,
3, 1, 0),
SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum),
@@ -186,7 +185,7 @@ static const struct snd_soc_dapm_widget cs4265_dapm_widgets[] = {
SND_SOC_DAPM_SWITCH("Loopback", SND_SOC_NOPM, 0, 0,
&loopback_ctl),
- SND_SOC_DAPM_SWITCH("SPDIF", SND_SOC_NOPM, 0, 0,
+ SND_SOC_DAPM_SWITCH("SPDIF", CS4265_SPDIF_CTL2, 5, 1,
&spdif_switch),
SND_SOC_DAPM_SWITCH("DAC", CS4265_PWRCTL, 1, 1,
&dac_switch),
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 5125bb9b37b5..ebee58eca4d5 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -91,7 +91,7 @@ static const struct reg_default cs42l42_reg_defaults[] = {
{ CS42L42_ASP_RX_INT_MASK, 0x1F },
{ CS42L42_ASP_TX_INT_MASK, 0x0F },
{ CS42L42_CODEC_INT_MASK, 0x03 },
- { CS42L42_SRCPL_INT_MASK, 0xFF },
+ { CS42L42_SRCPL_INT_MASK, 0x7F },
{ CS42L42_VPMON_INT_MASK, 0x01 },
{ CS42L42_PLL_LOCK_INT_MASK, 0x01 },
{ CS42L42_TSRS_PLUG_INT_MASK, 0x0F },
@@ -128,7 +128,7 @@ static const struct reg_default cs42l42_reg_defaults[] = {
{ CS42L42_MIXER_CHA_VOL, 0x3F },
{ CS42L42_MIXER_ADC_VOL, 0x3F },
{ CS42L42_MIXER_CHB_VOL, 0x3F },
- { CS42L42_EQ_COEF_IN0, 0x22 },
+ { CS42L42_EQ_COEF_IN0, 0x00 },
{ CS42L42_EQ_COEF_IN1, 0x00 },
{ CS42L42_EQ_COEF_IN2, 0x00 },
{ CS42L42_EQ_COEF_IN3, 0x00 },
@@ -398,10 +398,13 @@ static const struct regmap_config cs42l42_regmap = {
.reg_defaults = cs42l42_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(cs42l42_reg_defaults),
.cache_type = REGCACHE_RBTREE,
+
+ .use_single_read = true,
+ .use_single_write = true,
};
-static DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 100, false);
-static DECLARE_TLV_DB_SCALE(mixer_tlv, -6200, 100, false);
+static DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 100, true);
+static DECLARE_TLV_DB_SCALE(mixer_tlv, -6300, 100, true);
static const char * const cs42l42_hpf_freq_text[] = {
"1.86Hz", "120Hz", "235Hz", "466Hz"
@@ -420,34 +423,23 @@ static SOC_ENUM_SINGLE_DECL(cs42l42_wnf3_freq_enum, CS42L42_ADC_WNF_HPF_CTL,
CS42L42_ADC_WNF_CF_SHIFT,
cs42l42_wnf3_freq_text);
-static const char * const cs42l42_wnf05_freq_text[] = {
- "280Hz", "315Hz", "350Hz", "385Hz",
- "420Hz", "455Hz", "490Hz", "525Hz"
-};
-
-static SOC_ENUM_SINGLE_DECL(cs42l42_wnf05_freq_enum, CS42L42_ADC_WNF_HPF_CTL,
- CS42L42_ADC_WNF_CF_SHIFT,
- cs42l42_wnf05_freq_text);
-
static const struct snd_kcontrol_new cs42l42_snd_controls[] = {
/* ADC Volume and Filter Controls */
SOC_SINGLE("ADC Notch Switch", CS42L42_ADC_CTL,
- CS42L42_ADC_NOTCH_DIS_SHIFT, true, false),
+ CS42L42_ADC_NOTCH_DIS_SHIFT, true, true),
SOC_SINGLE("ADC Weak Force Switch", CS42L42_ADC_CTL,
CS42L42_ADC_FORCE_WEAK_VCM_SHIFT, true, false),
SOC_SINGLE("ADC Invert Switch", CS42L42_ADC_CTL,
CS42L42_ADC_INV_SHIFT, true, false),
SOC_SINGLE("ADC Boost Switch", CS42L42_ADC_CTL,
CS42L42_ADC_DIG_BOOST_SHIFT, true, false),
- SOC_SINGLE_SX_TLV("ADC Volume", CS42L42_ADC_VOLUME,
- CS42L42_ADC_VOL_SHIFT, 0xA0, 0x6C, adc_tlv),
+ SOC_SINGLE_S8_TLV("ADC Volume", CS42L42_ADC_VOLUME, -97, 12, adc_tlv),
SOC_SINGLE("ADC WNF Switch", CS42L42_ADC_WNF_HPF_CTL,
CS42L42_ADC_WNF_EN_SHIFT, true, false),
SOC_SINGLE("ADC HPF Switch", CS42L42_ADC_WNF_HPF_CTL,
CS42L42_ADC_HPF_EN_SHIFT, true, false),
SOC_ENUM("HPF Corner Freq", cs42l42_hpf_freq_enum),
SOC_ENUM("WNF 3dB Freq", cs42l42_wnf3_freq_enum),
- SOC_ENUM("WNF 05dB Freq", cs42l42_wnf05_freq_enum),
/* DAC Volume and Filter Controls */
SOC_SINGLE("DACA Invert Switch", CS42L42_DAC_CTL1,
@@ -458,7 +450,7 @@ static const struct snd_kcontrol_new cs42l42_snd_controls[] = {
CS42L42_DAC_HPF_EN_SHIFT, true, false),
SOC_DOUBLE_R_TLV("Mixer Volume", CS42L42_MIXER_CHA_VOL,
CS42L42_MIXER_CHB_VOL, CS42L42_MIXER_CH_VOL_SHIFT,
- 0x3e, 1, mixer_tlv)
+ 0x3f, 1, mixer_tlv)
};
static int cs42l42_hpdrv_evt(struct snd_soc_dapm_widget *w,
@@ -666,15 +658,6 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
CS42L42_FSYNC_PULSE_WIDTH_MASK,
CS42L42_FRAC1_VAL(fsync - 1) <<
CS42L42_FSYNC_PULSE_WIDTH_SHIFT);
- snd_soc_component_update_bits(component,
- CS42L42_ASP_FRM_CFG,
- CS42L42_ASP_5050_MASK,
- CS42L42_ASP_5050_MASK);
- /* Set the frame delay to 1.0 SCLK clocks */
- snd_soc_component_update_bits(component, CS42L42_ASP_FRM_CFG,
- CS42L42_ASP_FSD_MASK,
- CS42L42_ASP_FSD_1_0 <<
- CS42L42_ASP_FSD_SHIFT);
/* Set the sample rates (96k or lower) */
snd_soc_component_update_bits(component, CS42L42_FS_RATE_EN,
CS42L42_FS_EN_MASK,
@@ -691,24 +674,6 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
CS42L42_CLK_OASRC_SEL_MASK,
CS42L42_CLK_OASRC_SEL_12 <<
CS42L42_CLK_OASRC_SEL_SHIFT);
- /* channel 1 on low LRCLK, 32 bit */
- snd_soc_component_update_bits(component,
- CS42L42_ASP_RX_DAI0_CH1_AP_RES,
- CS42L42_ASP_RX_CH_AP_MASK |
- CS42L42_ASP_RX_CH_RES_MASK,
- (CS42L42_ASP_RX_CH_AP_LOW <<
- CS42L42_ASP_RX_CH_AP_SHIFT) |
- (CS42L42_ASP_RX_CH_RES_32 <<
- CS42L42_ASP_RX_CH_RES_SHIFT));
- /* Channel 2 on high LRCLK, 32 bit */
- snd_soc_component_update_bits(component,
- CS42L42_ASP_RX_DAI0_CH2_AP_RES,
- CS42L42_ASP_RX_CH_AP_MASK |
- CS42L42_ASP_RX_CH_RES_MASK,
- (CS42L42_ASP_RX_CH_AP_HI <<
- CS42L42_ASP_RX_CH_AP_SHIFT) |
- (CS42L42_ASP_RX_CH_RES_32 <<
- CS42L42_ASP_RX_CH_RES_SHIFT));
if (pll_ratio_table[i].mclk_src_sel == 0) {
/* Pass the clock straight through */
snd_soc_component_update_bits(component,
@@ -788,7 +753,18 @@ static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
/* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
- case SND_SOC_DAIFMT_LEFT_J:
+ /*
+ * 5050 mode, frame starts on falling edge of LRCLK,
+ * frame delayed by 1.0 SCLKs
+ */
+ snd_soc_component_update_bits(component,
+ CS42L42_ASP_FRM_CFG,
+ CS42L42_ASP_STP_MASK |
+ CS42L42_ASP_5050_MASK |
+ CS42L42_ASP_FSD_MASK,
+ CS42L42_ASP_5050_MASK |
+ (CS42L42_ASP_FSD_1_0 <<
+ CS42L42_ASP_FSD_SHIFT));
break;
default:
return -EINVAL;
@@ -797,27 +773,23 @@ static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
/* Bitclock/frame inversion */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
+ asp_cfg_val |= CS42L42_ASP_SCPOL_NOR << CS42L42_ASP_SCPOL_SHIFT;
break;
case SND_SOC_DAIFMT_NB_IF:
- asp_cfg_val |= CS42L42_ASP_POL_INV <<
- CS42L42_ASP_LCPOL_IN_SHIFT;
+ asp_cfg_val |= CS42L42_ASP_SCPOL_NOR << CS42L42_ASP_SCPOL_SHIFT;
+ asp_cfg_val |= CS42L42_ASP_LCPOL_INV << CS42L42_ASP_LCPOL_SHIFT;
break;
case SND_SOC_DAIFMT_IB_NF:
- asp_cfg_val |= CS42L42_ASP_POL_INV <<
- CS42L42_ASP_SCPOL_IN_DAC_SHIFT;
break;
case SND_SOC_DAIFMT_IB_IF:
- asp_cfg_val |= CS42L42_ASP_POL_INV <<
- CS42L42_ASP_LCPOL_IN_SHIFT;
- asp_cfg_val |= CS42L42_ASP_POL_INV <<
- CS42L42_ASP_SCPOL_IN_DAC_SHIFT;
+ asp_cfg_val |= CS42L42_ASP_LCPOL_INV << CS42L42_ASP_LCPOL_SHIFT;
break;
}
- snd_soc_component_update_bits(component, CS42L42_ASP_CLK_CFG,
- CS42L42_ASP_MODE_MASK |
- CS42L42_ASP_SCPOL_IN_DAC_MASK |
- CS42L42_ASP_LCPOL_IN_MASK, asp_cfg_val);
+ snd_soc_component_update_bits(component, CS42L42_ASP_CLK_CFG, CS42L42_ASP_MODE_MASK |
+ CS42L42_ASP_SCPOL_MASK |
+ CS42L42_ASP_LCPOL_MASK,
+ asp_cfg_val);
return 0;
}
@@ -828,14 +800,29 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_component *component = dai->component;
struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
- int retval;
+ unsigned int width = (params_width(params) / 8) - 1;
+ unsigned int val = 0;
cs42l42->srate = params_rate(params);
- cs42l42->swidth = params_width(params);
- retval = cs42l42_pll_config(component);
+ switch(substream->stream) {
+ case SNDRV_PCM_STREAM_PLAYBACK:
+ val |= width << CS42L42_ASP_RX_CH_RES_SHIFT;
+ /* channel 1 on low LRCLK */
+ snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_CH1_AP_RES,
+ CS42L42_ASP_RX_CH_AP_MASK |
+ CS42L42_ASP_RX_CH_RES_MASK, val);
+ /* Channel 2 on high LRCLK */
+ val |= CS42L42_ASP_RX_CH_AP_HI << CS42L42_ASP_RX_CH_AP_SHIFT;
+ snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_CH2_AP_RES,
+ CS42L42_ASP_RX_CH_AP_MASK |
+ CS42L42_ASP_RX_CH_RES_MASK, val);
+ break;
+ default:
+ break;
+ }
- return retval;
+ return cs42l42_pll_config(component);
}
static int cs42l42_set_sysclk(struct snd_soc_dai *dai,
@@ -900,9 +887,9 @@ static int cs42l42_digital_mute(struct snd_soc_dai *dai, int mute)
return 0;
}
-#define CS42L42_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \
- SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE | \
- SNDRV_PCM_FMTBIT_S32_LE)
+#define CS42L42_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S32_LE )
static const struct snd_soc_dai_ops cs42l42_ops = {
@@ -1803,7 +1790,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
dev_dbg(&i2c_client->dev, "Found reset GPIO\n");
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
}
- mdelay(3);
+ usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
/* Request IRQ */
ret = devm_request_threaded_irq(&i2c_client->dev,
@@ -1811,8 +1798,9 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
NULL, cs42l42_irq_thread,
IRQF_ONESHOT | IRQF_TRIGGER_LOW,
"cs42l42", cs42l42);
-
- if (ret != 0)
+ if (ret == -EPROBE_DEFER)
+ goto err_disable;
+ else if (ret != 0)
dev_err(&i2c_client->dev,
"Failed to request IRQ: %d\n", ret);
@@ -1928,6 +1916,7 @@ static int cs42l42_runtime_resume(struct device *dev)
}
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
+ usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
regcache_cache_only(cs42l42->regmap, false);
regcache_sync(cs42l42->regmap);
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index 9e3cc528dcff..ca2019732013 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -77,7 +77,7 @@
#define CS42L42_HP_PDN_SHIFT 3
#define CS42L42_HP_PDN_MASK (1 << CS42L42_HP_PDN_SHIFT)
#define CS42L42_ADC_PDN_SHIFT 2
-#define CS42L42_ADC_PDN_MASK (1 << CS42L42_HP_PDN_SHIFT)
+#define CS42L42_ADC_PDN_MASK (1 << CS42L42_ADC_PDN_SHIFT)
#define CS42L42_PDN_ALL_SHIFT 0
#define CS42L42_PDN_ALL_MASK (1 << CS42L42_PDN_ALL_SHIFT)
@@ -258,11 +258,12 @@
#define CS42L42_ASP_SLAVE_MODE 0x00
#define CS42L42_ASP_MODE_SHIFT 4
#define CS42L42_ASP_MODE_MASK (1 << CS42L42_ASP_MODE_SHIFT)
-#define CS42L42_ASP_SCPOL_IN_DAC_SHIFT 2
-#define CS42L42_ASP_SCPOL_IN_DAC_MASK (1 << CS42L42_ASP_SCPOL_IN_DAC_SHIFT)
-#define CS42L42_ASP_LCPOL_IN_SHIFT 0
-#define CS42L42_ASP_LCPOL_IN_MASK (1 << CS42L42_ASP_LCPOL_IN_SHIFT)
-#define CS42L42_ASP_POL_INV 1
+#define CS42L42_ASP_SCPOL_SHIFT 2
+#define CS42L42_ASP_SCPOL_MASK (3 << CS42L42_ASP_SCPOL_SHIFT)
+#define CS42L42_ASP_SCPOL_NOR 3
+#define CS42L42_ASP_LCPOL_SHIFT 0
+#define CS42L42_ASP_LCPOL_MASK (3 << CS42L42_ASP_LCPOL_SHIFT)
+#define CS42L42_ASP_LCPOL_INV 3
#define CS42L42_ASP_FRM_CFG (CS42L42_PAGE_12 + 0x08)
#define CS42L42_ASP_STP_SHIFT 4
@@ -739,6 +740,7 @@
#define CS42L42_FRAC2_VAL(val) (((val) & 0xff0000) >> 16)
#define CS42L42_NUM_SUPPLIES 5
+#define CS42L42_BOOT_TIME_US 3000
static const char *const cs42l42_supply_names[CS42L42_NUM_SUPPLIES] = {
"VA",
@@ -756,7 +758,6 @@ struct cs42l42_private {
struct completion pdn_done;
u32 sclk;
u32 srate;
- u32 swidth;
u8 plug_state;
u8 hs_type;
u8 ts_inv;
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index 55408c8fcb4e..cdd7ae90c2b5 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -247,8 +247,28 @@ static const struct snd_soc_dapm_widget cs42l51_dapm_widgets[] = {
&cs42l51_adcr_mux_controls),
};
+static int mclk_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct cs42l51_private *cs42l51 = snd_soc_component_get_drvdata(comp);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ return clk_prepare_enable(cs42l51->mclk_handle);
+ case SND_SOC_DAPM_POST_PMD:
+ /* Delay mclk shutdown to fulfill power-down sequence requirements */
+ msleep(20);
+ clk_disable_unprepare(cs42l51->mclk_handle);
+ break;
+ }
+
+ return 0;
+}
+
static const struct snd_soc_dapm_widget cs42l51_dapm_mclk_widgets[] = {
- SND_SOC_DAPM_CLOCK_SUPPLY("MCLK")
+ SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0, mclk_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
};
static const struct snd_soc_dapm_route cs42l51_routes[] = {
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index 2ea4cba3be2a..6c054b357205 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -137,7 +137,9 @@ static DECLARE_TLV_DB_SCALE(mic_tlv, 1600, 100, 0);
static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0);
-static DECLARE_TLV_DB_SCALE(mix_tlv, -50, 50, 0);
+static DECLARE_TLV_DB_SCALE(pass_tlv, -6000, 50, 0);
+
+static DECLARE_TLV_DB_SCALE(mix_tlv, -5150, 50, 0);
static DECLARE_TLV_DB_SCALE(beep_tlv, -56, 200, 0);
@@ -351,7 +353,7 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
CS42L52_SPKB_VOL, 0, 0x40, 0xC0, hl_tlv),
SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL,
- CS42L52_PASSTHRUB_VOL, 0, 0x88, 0x90, pga_tlv),
+ CS42L52_PASSTHRUB_VOL, 0, 0x88, 0x90, pass_tlv),
SOC_DOUBLE("Bypass Mute", CS42L52_MISC_CTL, 4, 5, 1, 0),
@@ -364,7 +366,7 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
CS42L52_ADCB_VOL, 0, 0xA0, 0x78, ipd_tlv),
SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
CS42L52_ADCA_MIXER_VOL, CS42L52_ADCB_MIXER_VOL,
- 0, 0x19, 0x7F, ipd_tlv),
+ 0, 0x19, 0x7F, mix_tlv),
SOC_DOUBLE("ADC Switch", CS42L52_ADC_MISC_CTL, 0, 1, 1, 0),
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c
index ac569ab3d30f..8be7d83f0ce9 100644
--- a/sound/soc/codecs/cs42l56.c
+++ b/sound/soc/codecs/cs42l56.c
@@ -391,9 +391,9 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = {
SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1),
SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME,
- CS42L56_HPB_VOLUME, 0, 0x84, 0x48, hl_tlv),
+ CS42L56_HPB_VOLUME, 0, 0x44, 0x48, hl_tlv),
SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME,
- CS42L56_LOB_VOLUME, 0, 0x84, 0x48, hl_tlv),
+ CS42L56_LOB_VOLUME, 0, 0x44, 0x48, hl_tlv),
SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL,
0, 0x00, 1, tone_tlv),
@@ -1248,6 +1248,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
dev_err(&i2c_client->dev,
"CS42L56 Device ID (%X). Expected %X\n",
devid, CS42L56_DEVID);
+ ret = -EINVAL;
goto err_enable;
}
alpha_rev = reg & CS42L56_AREV_MASK;
@@ -1305,7 +1306,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
ret = devm_snd_soc_register_component(&i2c_client->dev,
&soc_component_dev_cs42l56, &cs42l56_dai, 1);
if (ret < 0)
- return ret;
+ goto err_enable;
return 0;
diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c
index 7fb34422a2a4..8f70dee95878 100644
--- a/sound/soc/codecs/cs43130.c
+++ b/sound/soc/codecs/cs43130.c
@@ -1735,6 +1735,14 @@ static DEVICE_ATTR(hpload_dc_r, 0444, cs43130_show_dc_r, NULL);
static DEVICE_ATTR(hpload_ac_l, 0444, cs43130_show_ac_l, NULL);
static DEVICE_ATTR(hpload_ac_r, 0444, cs43130_show_ac_r, NULL);
+static struct attribute *hpload_attrs[] = {
+ &dev_attr_hpload_dc_l.attr,
+ &dev_attr_hpload_dc_r.attr,
+ &dev_attr_hpload_ac_l.attr,
+ &dev_attr_hpload_ac_r.attr,
+};
+ATTRIBUTE_GROUPS(hpload);
+
static struct reg_sequence hp_en_cal_seq[] = {
{CS43130_INT_MASK_4, CS43130_INT_MASK_ALL},
{CS43130_HP_MEAS_LOAD_1, 0},
@@ -2302,25 +2310,15 @@ static int cs43130_probe(struct snd_soc_component *component)
cs43130->hpload_done = false;
if (cs43130->dc_meas) {
- ret = device_create_file(component->dev, &dev_attr_hpload_dc_l);
- if (ret < 0)
- return ret;
-
- ret = device_create_file(component->dev, &dev_attr_hpload_dc_r);
- if (ret < 0)
- return ret;
-
- ret = device_create_file(component->dev, &dev_attr_hpload_ac_l);
- if (ret < 0)
- return ret;
-
- ret = device_create_file(component->dev, &dev_attr_hpload_ac_r);
- if (ret < 0)
+ ret = sysfs_create_groups(&component->dev->kobj, hpload_groups);
+ if (ret)
return ret;
cs43130->wq = create_singlethread_workqueue("cs43130_hp");
- if (!cs43130->wq)
+ if (!cs43130->wq) {
+ sysfs_remove_groups(&component->dev->kobj, hpload_groups);
return -ENOMEM;
+ }
INIT_WORK(&cs43130->work, cs43130_imp_meas);
}
diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c
index ed22361b35c1..a5a383b92305 100644
--- a/sound/soc/codecs/cs53l30.c
+++ b/sound/soc/codecs/cs53l30.c
@@ -347,22 +347,22 @@ static const struct snd_kcontrol_new cs53l30_snd_controls[] = {
SOC_ENUM("ADC2 NG Delay", adc2_ng_delay_enum),
SOC_SINGLE_SX_TLV("ADC1A PGA Volume",
- CS53L30_ADC1A_AFE_CTL, 0, 0x34, 0x18, pga_tlv),
+ CS53L30_ADC1A_AFE_CTL, 0, 0x34, 0x24, pga_tlv),
SOC_SINGLE_SX_TLV("ADC1B PGA Volume",
- CS53L30_ADC1B_AFE_CTL, 0, 0x34, 0x18, pga_tlv),
+ CS53L30_ADC1B_AFE_CTL, 0, 0x34, 0x24, pga_tlv),
SOC_SINGLE_SX_TLV("ADC2A PGA Volume",
- CS53L30_ADC2A_AFE_CTL, 0, 0x34, 0x18, pga_tlv),
+ CS53L30_ADC2A_AFE_CTL, 0, 0x34, 0x24, pga_tlv),
SOC_SINGLE_SX_TLV("ADC2B PGA Volume",
- CS53L30_ADC2B_AFE_CTL, 0, 0x34, 0x18, pga_tlv),
+ CS53L30_ADC2B_AFE_CTL, 0, 0x34, 0x24, pga_tlv),
SOC_SINGLE_SX_TLV("ADC1A Digital Volume",
- CS53L30_ADC1A_DIG_VOL, 0, 0xA0, 0x0C, dig_tlv),
+ CS53L30_ADC1A_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),
SOC_SINGLE_SX_TLV("ADC1B Digital Volume",
- CS53L30_ADC1B_DIG_VOL, 0, 0xA0, 0x0C, dig_tlv),
+ CS53L30_ADC1B_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),
SOC_SINGLE_SX_TLV("ADC2A Digital Volume",
- CS53L30_ADC2A_DIG_VOL, 0, 0xA0, 0x0C, dig_tlv),
+ CS53L30_ADC2A_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),
SOC_SINGLE_SX_TLV("ADC2B Digital Volume",
- CS53L30_ADC2B_DIG_VOL, 0, 0xA0, 0x0C, dig_tlv),
+ CS53L30_ADC2B_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),
};
static const struct snd_soc_dapm_widget cs53l30_dapm_widgets[] = {
diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c
index 1c1ba7bea4d8..8ee4b2e1ff68 100644
--- a/sound/soc/codecs/cx2072x.c
+++ b/sound/soc/codecs/cx2072x.c
@@ -1579,7 +1579,7 @@ static struct snd_soc_dai_driver soc_codec_cx2072x_dai[] = {
.id = CX2072X_DAI_DSP,
.probe = cx2072x_dsp_dai_probe,
.playback = {
- .stream_name = "Playback",
+ .stream_name = "DSP Playback",
.channels_min = 2,
.channels_max = 2,
.rates = CX2072X_RATES_DSP,
@@ -1591,7 +1591,7 @@ static struct snd_soc_dai_driver soc_codec_cx2072x_dai[] = {
.name = "cx2072x-aec",
.id = 3,
.capture = {
- .stream_name = "Capture",
+ .stream_name = "AEC Capture",
.channels_min = 2,
.channels_max = 2,
.rates = CX2072X_RATES_DSP,
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index f83a6eaba12c..ef8bd9e04637 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -446,7 +446,7 @@ static int da7219_tonegen_freq_put(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mixer_ctrl =
(struct soc_mixer_control *) kcontrol->private_value;
unsigned int reg = mixer_ctrl->reg;
- __le16 val;
+ __le16 val_new, val_old;
int ret;
/*
@@ -454,13 +454,19 @@ static int da7219_tonegen_freq_put(struct snd_kcontrol *kcontrol,
* Therefore we need to convert to little endian here to align with
* HW registers.
*/
- val = cpu_to_le16(ucontrol->value.integer.value[0]);
+ val_new = cpu_to_le16(ucontrol->value.integer.value[0]);
mutex_lock(&da7219->ctrl_lock);
- ret = regmap_raw_write(da7219->regmap, reg, &val, sizeof(val));
+ ret = regmap_raw_read(da7219->regmap, reg, &val_old, sizeof(val_old));
+ if (ret == 0 && (val_old != val_new))
+ ret = regmap_raw_write(da7219->regmap, reg,
+ &val_new, sizeof(val_new));
mutex_unlock(&da7219->ctrl_lock);
- return ret;
+ if (ret < 0)
+ return ret;
+
+ return val_old != val_new;
}
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index 36eef1fb3d18..b781b28de012 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -63,13 +63,8 @@ static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv,
1, 1, TLV_DB_SCALE_ITEM(0, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(250, 0, 0),
3, 3, TLV_DB_SCALE_ITEM(450, 0, 0),
- 4, 4, TLV_DB_SCALE_ITEM(700, 0, 0),
- 5, 5, TLV_DB_SCALE_ITEM(1000, 0, 0),
- 6, 6, TLV_DB_SCALE_ITEM(1300, 0, 0),
- 7, 7, TLV_DB_SCALE_ITEM(1600, 0, 0),
- 8, 8, TLV_DB_SCALE_ITEM(1800, 0, 0),
- 9, 9, TLV_DB_SCALE_ITEM(2100, 0, 0),
- 10, 10, TLV_DB_SCALE_ITEM(2400, 0, 0),
+ 4, 7, TLV_DB_SCALE_ITEM(700, 300, 0),
+ 8, 10, TLV_DB_SCALE_ITEM(1800, 300, 0),
);
static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpout_vol_tlv,
diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c
index fdf64c29f563..4117ab6e9b6f 100644
--- a/sound/soc/codecs/es8328.c
+++ b/sound/soc/codecs/es8328.c
@@ -161,13 +161,16 @@ static int es8328_put_deemph(struct snd_kcontrol *kcontrol,
if (deemph > 1)
return -EINVAL;
+ if (es8328->deemph == deemph)
+ return 0;
+
ret = es8328_set_deemph(component);
if (ret < 0)
return ret;
es8328->deemph = deemph;
- return 0;
+ return 1;
}
diff --git a/sound/soc/codecs/max9759.c b/sound/soc/codecs/max9759.c
index 00e9d4fd1651..0c261335c8a1 100644
--- a/sound/soc/codecs/max9759.c
+++ b/sound/soc/codecs/max9759.c
@@ -64,7 +64,8 @@ static int speaker_gain_control_put(struct snd_kcontrol *kcontrol,
struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
struct max9759 *priv = snd_soc_component_get_drvdata(c);
- if (ucontrol->value.integer.value[0] > 3)
+ if (ucontrol->value.integer.value[0] < 0 ||
+ ucontrol->value.integer.value[0] > 3)
return -EINVAL;
priv->gain = ucontrol->value.integer.value[0];
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index f031d2caa8b7..fa4cdbfd0b80 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -41,6 +41,7 @@ struct max98088_priv {
enum max98088_type devtype;
struct max98088_pdata *pdata;
struct clk *mclk;
+ unsigned char mclk_prescaler;
unsigned int sysclk;
struct max98088_cdata dai[2];
int eq_textcnt;
@@ -998,13 +999,16 @@ static int max98088_dai1_hw_params(struct snd_pcm_substream *substream,
/* Configure NI when operating as master */
if (snd_soc_component_read32(component, M98088_REG_14_DAI1_FORMAT)
& M98088_DAI_MAS) {
+ unsigned long pclk;
+
if (max98088->sysclk == 0) {
dev_err(component->dev, "Invalid system clock frequency\n");
return -EINVAL;
}
ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL)
* (unsigned long long int)rate;
- do_div(ni, (unsigned long long int)max98088->sysclk);
+ pclk = DIV_ROUND_CLOSEST(max98088->sysclk, max98088->mclk_prescaler);
+ ni = DIV_ROUND_CLOSEST_ULL(ni, pclk);
snd_soc_component_write(component, M98088_REG_12_DAI1_CLKCFG_HI,
(ni >> 8) & 0x7F);
snd_soc_component_write(component, M98088_REG_13_DAI1_CLKCFG_LO,
@@ -1065,13 +1069,16 @@ static int max98088_dai2_hw_params(struct snd_pcm_substream *substream,
/* Configure NI when operating as master */
if (snd_soc_component_read32(component, M98088_REG_1C_DAI2_FORMAT)
& M98088_DAI_MAS) {
+ unsigned long pclk;
+
if (max98088->sysclk == 0) {
dev_err(component->dev, "Invalid system clock frequency\n");
return -EINVAL;
}
ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL)
* (unsigned long long int)rate;
- do_div(ni, (unsigned long long int)max98088->sysclk);
+ pclk = DIV_ROUND_CLOSEST(max98088->sysclk, max98088->mclk_prescaler);
+ ni = DIV_ROUND_CLOSEST_ULL(ni, pclk);
snd_soc_component_write(component, M98088_REG_1A_DAI2_CLKCFG_HI,
(ni >> 8) & 0x7F);
snd_soc_component_write(component, M98088_REG_1B_DAI2_CLKCFG_LO,
@@ -1113,8 +1120,10 @@ static int max98088_dai_set_sysclk(struct snd_soc_dai *dai,
*/
if ((freq >= 10000000) && (freq < 20000000)) {
snd_soc_component_write(component, M98088_REG_10_SYS_CLK, 0x10);
+ max98088->mclk_prescaler = 1;
} else if ((freq >= 20000000) && (freq < 30000000)) {
snd_soc_component_write(component, M98088_REG_10_SYS_CLK, 0x20);
+ max98088->mclk_prescaler = 2;
} else {
dev_err(component->dev, "Invalid master clock frequency\n");
return -EINVAL;
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index 6b9d326e11b0..ce9f99dd3e87 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -413,6 +413,9 @@ static int max98090_put_enab_tlv(struct snd_kcontrol *kcontrol,
val = (val >> mc->shift) & mask;
+ if (sel < 0 || sel > mc->max)
+ return -EINVAL;
+
*select = sel;
/* Setting a volume is only valid if it is already On */
@@ -427,7 +430,7 @@ static int max98090_put_enab_tlv(struct snd_kcontrol *kcontrol,
mask << mc->shift,
sel << mc->shift);
- return 0;
+ return *select != val;
}
static const char *max98090_perf_pwr_text[] =
diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c
index 96718e3a1ad0..16fbc9faed90 100644
--- a/sound/soc/codecs/max98373.c
+++ b/sound/soc/codecs/max98373.c
@@ -410,11 +410,13 @@ static int max98373_dac_event(struct snd_soc_dapm_widget *w,
regmap_update_bits(max98373->regmap,
MAX98373_R20FF_GLOBAL_SHDN,
MAX98373_GLOBAL_EN_MASK, 1);
+ usleep_range(30000, 31000);
break;
case SND_SOC_DAPM_POST_PMD:
regmap_update_bits(max98373->regmap,
MAX98373_R20FF_GLOBAL_SHDN,
MAX98373_GLOBAL_EN_MASK, 0);
+ usleep_range(30000, 31000);
max98373->tdm_mode = false;
break;
default:
diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c
index 337bddb7c2a4..5a8eedea6be0 100644
--- a/sound/soc/codecs/msm8916-wcd-analog.c
+++ b/sound/soc/codecs/msm8916-wcd-analog.c
@@ -1195,8 +1195,10 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
}
irq = platform_get_irq_byname(pdev, "mbhc_switch_int");
- if (irq < 0)
- return irq;
+ if (irq < 0) {
+ ret = irq;
+ goto err_disable_clk;
+ }
ret = devm_request_threaded_irq(dev, irq, NULL,
pm8916_mbhc_switch_irq_handler,
@@ -1208,8 +1210,10 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
if (priv->mbhc_btn_enabled) {
irq = platform_get_irq_byname(pdev, "mbhc_but_press_det");
- if (irq < 0)
- return irq;
+ if (irq < 0) {
+ ret = irq;
+ goto err_disable_clk;
+ }
ret = devm_request_threaded_irq(dev, irq, NULL,
mbhc_btn_press_irq_handler,
@@ -1220,8 +1224,10 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
dev_err(dev, "cannot request mbhc button press irq\n");
irq = platform_get_irq_byname(pdev, "mbhc_but_rel_det");
- if (irq < 0)
- return irq;
+ if (irq < 0) {
+ ret = irq;
+ goto err_disable_clk;
+ }
ret = devm_request_threaded_irq(dev, irq, NULL,
mbhc_btn_release_irq_handler,
@@ -1238,6 +1244,10 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
return devm_snd_soc_register_component(dev, &pm8916_wcd_analog,
pm8916_wcd_analog_dai,
ARRAY_SIZE(pm8916_wcd_analog_dai));
+
+err_disable_clk:
+ clk_disable_unprepare(priv->mclk);
+ return ret;
}
static int pm8916_wcd_analog_spmi_remove(struct platform_device *pdev)
diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c
index 09fccacadd6b..e4cde214b7b2 100644
--- a/sound/soc/codecs/msm8916-wcd-digital.c
+++ b/sound/soc/codecs/msm8916-wcd-digital.c
@@ -1201,14 +1201,24 @@ static int msm8916_wcd_digital_probe(struct platform_device *pdev)
ret = clk_prepare_enable(priv->mclk);
if (ret < 0) {
dev_err(dev, "failed to enable mclk %d\n", ret);
- return ret;
+ goto err_clk;
}
dev_set_drvdata(dev, priv);
- return devm_snd_soc_register_component(dev, &msm8916_wcd_digital,
+ ret = devm_snd_soc_register_component(dev, &msm8916_wcd_digital,
msm8916_wcd_digital_dai,
ARRAY_SIZE(msm8916_wcd_digital_dai));
+ if (ret)
+ goto err_mclk;
+
+ return 0;
+
+err_mclk:
+ clk_disable_unprepare(priv->mclk);
+err_clk:
+ clk_disable_unprepare(priv->ahbclk);
+ return ret;
}
static int msm8916_wcd_digital_remove(struct platform_device *pdev)
diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c
index bb737fd678cc..494ba0eeb433 100644
--- a/sound/soc/codecs/mt6358.c
+++ b/sound/soc/codecs/mt6358.c
@@ -103,6 +103,7 @@ int mt6358_set_mtkaif_protocol(struct snd_soc_component *cmpnt,
priv->mtkaif_protocol = mtkaif_protocol;
return 0;
}
+EXPORT_SYMBOL_GPL(mt6358_set_mtkaif_protocol);
static void playback_gpio_set(struct mt6358_priv *priv)
{
@@ -269,6 +270,7 @@ int mt6358_mtkaif_calibration_enable(struct snd_soc_component *cmpnt)
1 << RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_SFT);
return 0;
}
+EXPORT_SYMBOL_GPL(mt6358_mtkaif_calibration_enable);
int mt6358_mtkaif_calibration_disable(struct snd_soc_component *cmpnt)
{
@@ -292,6 +294,7 @@ int mt6358_mtkaif_calibration_disable(struct snd_soc_component *cmpnt)
capture_gpio_reset(priv);
return 0;
}
+EXPORT_SYMBOL_GPL(mt6358_mtkaif_calibration_disable);
int mt6358_set_mtkaif_calibration_phase(struct snd_soc_component *cmpnt,
int phase_1, int phase_2)
@@ -306,6 +309,7 @@ int mt6358_set_mtkaif_calibration_phase(struct snd_soc_component *cmpnt,
phase_2 << RG_AUD_PAD_TOP_PHASE_MODE2_SFT);
return 0;
}
+EXPORT_SYMBOL_GPL(mt6358_set_mtkaif_calibration_phase);
/* dl pga gain */
enum {
diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c
index 78db3bd0b3bc..cd163978792e 100644
--- a/sound/soc/codecs/nau8822.c
+++ b/sound/soc/codecs/nau8822.c
@@ -741,6 +741,8 @@ static int nau8822_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
pll_param->mclk_scaler, pll_param->pre_factor);
snd_soc_component_update_bits(component,
+ NAU8822_REG_POWER_MANAGEMENT_1, NAU8822_PLL_EN_MASK, NAU8822_PLL_OFF);
+ snd_soc_component_update_bits(component,
NAU8822_REG_PLL_N, NAU8822_PLLMCLK_DIV2 | NAU8822_PLLN_MASK,
(pll_param->pre_factor ? NAU8822_PLLMCLK_DIV2 : 0) |
pll_param->pll_int);
@@ -757,6 +759,8 @@ static int nau8822_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
pll_param->mclk_scaler << NAU8822_MCLKSEL_SFT);
snd_soc_component_update_bits(component,
NAU8822_REG_CLOCKING, NAU8822_CLKM_MASK, NAU8822_CLKM_PLL);
+ snd_soc_component_update_bits(component,
+ NAU8822_REG_POWER_MANAGEMENT_1, NAU8822_PLL_EN_MASK, NAU8822_PLL_ON);
return 0;
}
diff --git a/sound/soc/codecs/nau8822.h b/sound/soc/codecs/nau8822.h
index 489191ff187e..b45d42c15de6 100644
--- a/sound/soc/codecs/nau8822.h
+++ b/sound/soc/codecs/nau8822.h
@@ -90,6 +90,9 @@
#define NAU8822_REFIMP_3K 0x3
#define NAU8822_IOBUF_EN (0x1 << 2)
#define NAU8822_ABIAS_EN (0x1 << 3)
+#define NAU8822_PLL_EN_MASK (0x1 << 5)
+#define NAU8822_PLL_ON (0x1 << 5)
+#define NAU8822_PLL_OFF (0x0 << 5)
/* NAU8822_REG_AUDIO_INTERFACE (0x4) */
#define NAU8822_AIFMT_MASK (0x3 << 3)
diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c
index 15bd8335f667..c8ccfa2fff84 100644
--- a/sound/soc/codecs/nau8824.c
+++ b/sound/soc/codecs/nau8824.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/dmi.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
@@ -27,6 +28,12 @@
#include "nau8824.h"
+#define NAU8824_JD_ACTIVE_HIGH BIT(0)
+
+static int nau8824_quirk;
+static int quirk_override = -1;
+module_param_named(quirk, quirk_override, uint, 0444);
+MODULE_PARM_DESC(quirk, "Board-specific quirk override");
static int nau8824_config_sysclk(struct nau8824 *nau8824,
int clk_id, unsigned int freq);
@@ -1875,6 +1882,34 @@ static int nau8824_read_device_properties(struct device *dev,
return 0;
}
+/* Please keep this list alphabetically sorted */
+static const struct dmi_system_id nau8824_quirk_table[] = {
+ {
+ /* Cyberbook T116 rugged tablet */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "20170531"),
+ },
+ .driver_data = (void *)(NAU8824_JD_ACTIVE_HIGH),
+ },
+ {}
+};
+
+static void nau8824_check_quirks(void)
+{
+ const struct dmi_system_id *dmi_id;
+
+ if (quirk_override != -1) {
+ nau8824_quirk = quirk_override;
+ return;
+ }
+
+ dmi_id = dmi_first_match(nau8824_quirk_table);
+ if (dmi_id)
+ nau8824_quirk = (unsigned long)dmi_id->driver_data;
+}
+
static int nau8824_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -1899,6 +1934,11 @@ static int nau8824_i2c_probe(struct i2c_client *i2c,
nau8824->irq = i2c->irq;
sema_init(&nau8824->jd_sem, 1);
+ nau8824_check_quirks();
+
+ if (nau8824_quirk & NAU8824_JD_ACTIVE_HIGH)
+ nau8824->jkdet_polarity = 0;
+
nau8824_print_device_properties(nau8824);
ret = regmap_read(nau8824->regmap, NAU8824_REG_I2C_DEVICE_ID, &value);
diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c
index 287c962ba00d..4e71ecf54af7 100644
--- a/sound/soc/codecs/rk3328_codec.c
+++ b/sound/soc/codecs/rk3328_codec.c
@@ -472,29 +472,45 @@ static int rk3328_platform_probe(struct platform_device *pdev)
rk3328->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(rk3328->pclk)) {
dev_err(&pdev->dev, "can't get acodec pclk\n");
- return PTR_ERR(rk3328->pclk);
+ ret = PTR_ERR(rk3328->pclk);
+ goto err_unprepare_mclk;
}
ret = clk_prepare_enable(rk3328->pclk);
if (ret < 0) {
dev_err(&pdev->dev, "failed to enable acodec pclk\n");
- return ret;
+ goto err_unprepare_mclk;
}
base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(base))
- return PTR_ERR(base);
+ if (IS_ERR(base)) {
+ ret = PTR_ERR(base);
+ goto err_unprepare_pclk;
+ }
rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,
&rk3328_codec_regmap_config);
- if (IS_ERR(rk3328->regmap))
- return PTR_ERR(rk3328->regmap);
+ if (IS_ERR(rk3328->regmap)) {
+ ret = PTR_ERR(rk3328->regmap);
+ goto err_unprepare_pclk;
+ }
platform_set_drvdata(pdev, rk3328);
- return devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
+ ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
rk3328_dai,
ARRAY_SIZE(rk3328_dai));
+ if (ret)
+ goto err_unprepare_pclk;
+
+ return 0;
+
+err_unprepare_pclk:
+ clk_disable_unprepare(rk3328->pclk);
+
+err_unprepare_mclk:
+ clk_disable_unprepare(rk3328->mclk);
+ return ret;
}
static const struct of_device_id rk3328_codec_of_match[] = {
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
index 9593a9a27bf8..d8ab8af2c786 100644
--- a/sound/soc/codecs/rt286.c
+++ b/sound/soc/codecs/rt286.c
@@ -171,6 +171,9 @@ static bool rt286_readable_register(struct device *dev, unsigned int reg)
case RT286_PROC_COEF:
case RT286_SET_AMP_GAIN_ADC_IN1:
case RT286_SET_AMP_GAIN_ADC_IN2:
+ case RT286_SET_GPIO_MASK:
+ case RT286_SET_GPIO_DIRECTION:
+ case RT286_SET_GPIO_DATA:
case RT286_SET_POWER(RT286_DAC_OUT1):
case RT286_SET_POWER(RT286_DAC_OUT2):
case RT286_SET_POWER(RT286_ADC_IN1):
@@ -1115,12 +1118,11 @@ static const struct dmi_system_id force_combo_jack_table[] = {
{ }
};
-static const struct dmi_system_id dmi_dell_dino[] = {
+static const struct dmi_system_id dmi_dell[] = {
{
- .ident = "Dell Dino",
+ .ident = "Dell",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343")
}
},
{ }
@@ -1131,7 +1133,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
{
struct rt286_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct rt286_priv *rt286;
- int i, ret, val;
+ int i, ret, vendor_id;
rt286 = devm_kzalloc(&i2c->dev, sizeof(*rt286),
GFP_KERNEL);
@@ -1147,14 +1149,15 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
}
ret = regmap_read(rt286->regmap,
- RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val);
+ RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &vendor_id);
if (ret != 0) {
dev_err(&i2c->dev, "I2C error %d\n", ret);
return ret;
}
- if (val != RT286_VENDOR_ID && val != RT288_VENDOR_ID) {
+ if (vendor_id != RT286_VENDOR_ID && vendor_id != RT288_VENDOR_ID) {
dev_err(&i2c->dev,
- "Device with ID register %#x is not rt286\n", val);
+ "Device with ID register %#x is not rt286\n",
+ vendor_id);
return -ENODEV;
}
@@ -1178,8 +1181,8 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
if (pdata)
rt286->pdata = *pdata;
- if (dmi_check_system(force_combo_jack_table) ||
- dmi_check_system(dmi_dell_dino))
+ if ((vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) ||
+ dmi_check_system(force_combo_jack_table))
rt286->pdata.cbj_en = true;
regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3);
@@ -1218,7 +1221,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737);
regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f);
- if (dmi_check_system(dmi_dell_dino)) {
+ if (vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) {
regmap_update_bits(rt286->regmap,
RT286_SET_GPIO_MASK, 0x40, 0x40);
regmap_update_bits(rt286->regmap,
diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c
index 7081142a355e..c444a56df95b 100644
--- a/sound/soc/codecs/rt5514.c
+++ b/sound/soc/codecs/rt5514.c
@@ -419,7 +419,7 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
}
}
- return 0;
+ return 1;
}
static const struct snd_kcontrol_new rt5514_snd_controls[] = {
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
index f70b9f7e68bb..281957a8fa86 100644
--- a/sound/soc/codecs/rt5631.c
+++ b/sound/soc/codecs/rt5631.c
@@ -1691,6 +1691,8 @@ static const struct regmap_config rt5631_regmap_config = {
.reg_defaults = rt5631_reg,
.num_reg_defaults = ARRAY_SIZE(rt5631_reg),
.cache_type = REGCACHE_RBTREE,
+ .use_single_read = true,
+ .use_single_write = true,
};
static int rt5631_i2c_probe(struct i2c_client *i2c,
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 747ca248bf10..3bc63fbcb188 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -339,9 +339,9 @@ static bool rt5640_readable_register(struct device *dev, unsigned int reg)
}
static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
-static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
+static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -6562, 0);
static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
-static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
+static const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -1762, 3000);
static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index c83f7f5da96b..a66e93a3af74 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -4074,9 +4074,14 @@ static int rt5645_i2c_remove(struct i2c_client *i2c)
if (i2c->irq)
free_irq(i2c->irq, rt5645);
+ /*
+ * Since the rt5645_btn_check_callback() can queue jack_detect_work,
+ * the timer need to be delted first
+ */
+ del_timer_sync(&rt5645->btn_check_timer);
+
cancel_delayed_work_sync(&rt5645->jack_detect_work);
cancel_delayed_work_sync(&rt5645->rcclock_work);
- del_timer_sync(&rt5645->btn_check_timer);
regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies);
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index c506c9305043..829cf552fe3e 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -285,9 +285,9 @@ static bool rt5651_readable_register(struct device *dev, unsigned int reg)
}
static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
-static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
+static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -6562, 0);
static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
-static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
+static const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -1762, 3000);
static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c
index e66d08398f74..a28afb480060 100644
--- a/sound/soc/codecs/rt5659.c
+++ b/sound/soc/codecs/rt5659.c
@@ -2470,13 +2470,18 @@ static int set_dmic_power(struct snd_soc_dapm_widget *w,
return 0;
}
-static const struct snd_soc_dapm_widget rt5659_dapm_widgets[] = {
+static const struct snd_soc_dapm_widget rt5659_particular_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("LDO2", RT5659_PWR_ANLG_3, RT5659_PWR_LDO2_BIT, 0,
NULL, 0),
- SND_SOC_DAPM_SUPPLY("PLL", RT5659_PWR_ANLG_3, RT5659_PWR_PLL_BIT, 0,
- NULL, 0),
+ SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5659_PWR_ANLG_2, RT5659_PWR_MB1_BIT,
+ 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5659_PWR_VOL,
RT5659_PWR_MIC_DET_BIT, 0, NULL, 0),
+};
+
+static const struct snd_soc_dapm_widget rt5659_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("PLL", RT5659_PWR_ANLG_3, RT5659_PWR_PLL_BIT, 0,
+ NULL, 0),
SND_SOC_DAPM_SUPPLY("Mono Vref", RT5659_PWR_ANLG_1,
RT5659_PWR_VREF3_BIT, 0, NULL, 0),
@@ -2501,8 +2506,6 @@ static const struct snd_soc_dapm_widget rt5659_dapm_widgets[] = {
RT5659_ADC_MONO_R_ASRC_SFT, 0, NULL, 0),
/* Input Side */
- SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5659_PWR_ANLG_2, RT5659_PWR_MB1_BIT,
- 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS2", RT5659_PWR_ANLG_2, RT5659_PWR_MB2_BIT,
0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS3", RT5659_PWR_ANLG_2, RT5659_PWR_MB3_BIT,
@@ -3463,12 +3466,17 @@ static int rt5659_set_component_sysclk(struct snd_soc_component *component, int
{
struct rt5659_priv *rt5659 = snd_soc_component_get_drvdata(component);
unsigned int reg_val = 0;
+ int ret;
if (freq == rt5659->sysclk && clk_id == rt5659->sysclk_src)
return 0;
switch (clk_id) {
case RT5659_SCLK_S_MCLK:
+ ret = clk_set_rate(rt5659->mclk, freq);
+ if (ret)
+ return ret;
+
reg_val |= RT5659_SCLK_SRC_MCLK;
break;
case RT5659_SCLK_S_PLL1:
@@ -3692,10 +3700,23 @@ static int rt5659_set_bias_level(struct snd_soc_component *component,
static int rt5659_probe(struct snd_soc_component *component)
{
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_component_get_dapm(component);
struct rt5659_priv *rt5659 = snd_soc_component_get_drvdata(component);
rt5659->component = component;
+ switch (rt5659->pdata.jd_src) {
+ case RT5659_JD_HDA_HEADER:
+ break;
+
+ default:
+ snd_soc_dapm_new_controls(dapm,
+ rt5659_particular_dapm_widgets,
+ ARRAY_SIZE(rt5659_particular_dapm_widgets));
+ break;
+ }
+
return 0;
}
diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c
index 2943692f66ed..19e2f622718d 100644
--- a/sound/soc/codecs/rt5663.c
+++ b/sound/soc/codecs/rt5663.c
@@ -3461,6 +3461,7 @@ static void rt5663_calibrate(struct rt5663_priv *rt5663)
static int rt5663_parse_dp(struct rt5663_priv *rt5663, struct device *dev)
{
int table_size;
+ int ret;
device_property_read_u32(dev, "realtek,dc_offset_l_manual",
&rt5663->pdata.dc_offset_l_manual);
@@ -3477,9 +3478,13 @@ static int rt5663_parse_dp(struct rt5663_priv *rt5663, struct device *dev)
table_size = sizeof(struct impedance_mapping_table) *
rt5663->pdata.impedance_sensing_num;
rt5663->imp_table = devm_kzalloc(dev, table_size, GFP_KERNEL);
- device_property_read_u32_array(dev,
+ if (!rt5663->imp_table)
+ return -ENOMEM;
+ ret = device_property_read_u32_array(dev,
"realtek,impedance_sensing_table",
(u32 *)rt5663->imp_table, table_size);
+ if (ret)
+ return ret;
}
return 0;
@@ -3504,8 +3509,11 @@ static int rt5663_i2c_probe(struct i2c_client *i2c,
if (pdata)
rt5663->pdata = *pdata;
- else
- rt5663_parse_dp(rt5663, &i2c->dev);
+ else {
+ ret = rt5663_parse_dp(rt5663, &i2c->dev);
+ if (ret)
+ return ret;
+ }
for (i = 0; i < ARRAY_SIZE(rt5663->supplies); i++)
rt5663->supplies[i].supply = rt5663_supply_names[i];
diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c
index 5716cede99cb..acc2b34ca334 100644
--- a/sound/soc/codecs/rt5668.c
+++ b/sound/soc/codecs/rt5668.c
@@ -1022,11 +1022,13 @@ static void rt5668_jack_detect_handler(struct work_struct *work)
container_of(work, struct rt5668_priv, jack_detect_work.work);
int val, btn_type;
- while (!rt5668->component)
- usleep_range(10000, 15000);
-
- while (!rt5668->component->card->instantiated)
- usleep_range(10000, 15000);
+ if (!rt5668->component || !rt5668->component->card ||
+ !rt5668->component->card->instantiated) {
+ /* card not yet ready, try later */
+ mod_delayed_work(system_power_efficient_wq,
+ &rt5668->jack_detect_work, msecs_to_jiffies(15));
+ return;
+ }
mutex_lock(&rt5668->calibrate_mutex);
diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c
index 05e883a65d7a..a8cf4c745130 100644
--- a/sound/soc/codecs/rt5682.c
+++ b/sound/soc/codecs/rt5682.c
@@ -1052,11 +1052,13 @@ static void rt5682_jack_detect_handler(struct work_struct *work)
container_of(work, struct rt5682_priv, jack_detect_work.work);
int val, btn_type;
- while (!rt5682->component)
- usleep_range(10000, 15000);
-
- while (!rt5682->component->card->instantiated)
- usleep_range(10000, 15000);
+ if (!rt5682->component || !rt5682->component->card ||
+ !rt5682->component->card->instantiated) {
+ /* card not yet ready, try later */
+ mod_delayed_work(system_power_efficient_wq,
+ &rt5682->jack_detect_work, msecs_to_jiffies(15));
+ return;
+ }
mutex_lock(&rt5682->calibrate_mutex);
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index f5b59305c957..8a1e485982d8 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -71,7 +71,7 @@ static const struct reg_default sgtl5000_reg_defaults[] = {
{ SGTL5000_DAP_EQ_BASS_BAND4, 0x002f },
{ SGTL5000_DAP_MAIN_CHAN, 0x8000 },
{ SGTL5000_DAP_MIX_CHAN, 0x0000 },
- { SGTL5000_DAP_AVC_CTRL, 0x0510 },
+ { SGTL5000_DAP_AVC_CTRL, 0x5100 },
{ SGTL5000_DAP_AVC_THRESHOLD, 0x1473 },
{ SGTL5000_DAP_AVC_ATTACK, 0x0028 },
{ SGTL5000_DAP_AVC_DECAY, 0x0050 },
diff --git a/sound/soc/codecs/sti-sas.c b/sound/soc/codecs/sti-sas.c
index ec9933b054ad..423daac9d5a9 100644
--- a/sound/soc/codecs/sti-sas.c
+++ b/sound/soc/codecs/sti-sas.c
@@ -411,6 +411,7 @@ static const struct of_device_id sti_sas_dev_match[] = {
},
{},
};
+MODULE_DEVICE_TABLE(of, sti_sas_dev_match);
static int sti_sas_driver_probe(struct platform_device *pdev)
{
diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h
index cb024955c978..73c5f6c8ed69 100644
--- a/sound/soc/codecs/tlv320aic31xx.h
+++ b/sound/soc/codecs/tlv320aic31xx.h
@@ -151,8 +151,8 @@ struct aic31xx_pdata {
#define AIC31XX_WORD_LEN_24BITS 0x02
#define AIC31XX_WORD_LEN_32BITS 0x03
#define AIC31XX_IFACE1_MASTER_MASK GENMASK(3, 2)
-#define AIC31XX_BCLK_MASTER BIT(2)
-#define AIC31XX_WCLK_MASTER BIT(3)
+#define AIC31XX_BCLK_MASTER BIT(3)
+#define AIC31XX_WCLK_MASTER BIT(2)
/* AIC31XX_DATA_OFFSET */
#define AIC31XX_DATA_OFFSET_MASK GENMASK(7, 0)
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 68165de1c8de..7a1ffbaf48be 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -662,7 +662,7 @@ static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
}
static int aic32x4_setup_clocks(struct snd_soc_component *component,
- unsigned int sample_rate)
+ unsigned int sample_rate, unsigned int channels)
{
u8 aosr;
u16 dosr;
@@ -750,7 +750,9 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component,
dosr);
clk_set_rate(clocks[5].clk,
- sample_rate * 32);
+ sample_rate * 32 *
+ channels);
+
return 0;
}
}
@@ -772,7 +774,8 @@ static int aic32x4_hw_params(struct snd_pcm_substream *substream,
u8 iface1_reg = 0;
u8 dacsetup_reg = 0;
- aic32x4_setup_clocks(component, params_rate(params));
+ aic32x4_setup_clocks(component, params_rate(params),
+ params_channels(params));
switch (params_width(params)) {
case 16:
diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c
index c3587af9985c..3d981441b8d1 100644
--- a/sound/soc/codecs/tscs454.c
+++ b/sound/soc/codecs/tscs454.c
@@ -3128,18 +3128,17 @@ static int set_aif_sample_format(struct snd_soc_component *component,
unsigned int width;
int ret;
- switch (format) {
- case SNDRV_PCM_FORMAT_S16_LE:
+ switch (snd_pcm_format_width(format)) {
+ case 16:
width = FV_WL_16;
break;
- case SNDRV_PCM_FORMAT_S20_3LE:
+ case 20:
width = FV_WL_20;
break;
- case SNDRV_PCM_FORMAT_S24_3LE:
+ case 24:
width = FV_WL_24;
break;
- case SNDRV_PCM_FORMAT_S24_LE:
- case SNDRV_PCM_FORMAT_S32_LE:
+ case 32:
width = FV_WL_32;
break;
default:
@@ -3337,6 +3336,7 @@ static const struct snd_soc_component_driver soc_component_dev_tscs454 = {
.num_dapm_routes = ARRAY_SIZE(tscs454_intercon),
.controls = tscs454_snd_controls,
.num_controls = ARRAY_SIZE(tscs454_snd_controls),
+ .endianness = 1,
};
#define TSCS454_RATES SNDRV_PCM_RATE_8000_96000
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index f318403133e9..016aff97e2fb 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -618,7 +618,7 @@ static const char * const sb_tx8_mux_text[] = {
"ZERO", "RX_MIX_TX8", "DEC8", "DEC8_192"
};
-static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400);
static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
static const DECLARE_TLV_DB_SCALE(ear_pa_gain, 0, 150, 0);
@@ -4076,6 +4076,16 @@ static int wcd9335_setup_irqs(struct wcd9335_codec *wcd)
return ret;
}
+static void wcd9335_teardown_irqs(struct wcd9335_codec *wcd)
+{
+ int i;
+
+ /* disable interrupts on all slave ports */
+ for (i = 0; i < WCD9335_SLIM_NUM_PORT_REG; i++)
+ regmap_write(wcd->if_regmap, WCD9335_SLIM_PGD_PORT_INT_EN0 + i,
+ 0x00);
+}
+
static void wcd9335_cdc_sido_ccl_enable(struct wcd9335_codec *wcd,
bool ccl_flag)
{
@@ -4844,6 +4854,7 @@ static void wcd9335_codec_init(struct snd_soc_component *component)
static int wcd9335_codec_probe(struct snd_soc_component *component)
{
struct wcd9335_codec *wcd = dev_get_drvdata(component->dev);
+ int ret;
int i;
snd_soc_component_init_regmap(component, wcd->regmap);
@@ -4861,7 +4872,15 @@ static int wcd9335_codec_probe(struct snd_soc_component *component)
for (i = 0; i < NUM_CODEC_DAIS; i++)
INIT_LIST_HEAD(&wcd->dai[i].slim_ch_list);
- return wcd9335_setup_irqs(wcd);
+ ret = wcd9335_setup_irqs(wcd);
+ if (ret)
+ goto free_clsh_ctrl;
+
+ return 0;
+
+free_clsh_ctrl:
+ wcd_clsh_ctrl_free(wcd->clsh_ctrl);
+ return ret;
}
static void wcd9335_codec_remove(struct snd_soc_component *comp)
@@ -4869,7 +4888,7 @@ static void wcd9335_codec_remove(struct snd_soc_component *comp)
struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
wcd_clsh_ctrl_free(wcd->clsh_ctrl);
- free_irq(regmap_irq_get_virq(wcd->irq_data, WCD9335_IRQ_SLIMBUS), wcd);
+ wcd9335_teardown_irqs(wcd);
}
static int wcd9335_codec_set_sysclk(struct snd_soc_component *comp,
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 72e165cc6443..97ece3114b3d 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -536,7 +536,7 @@ static int wm2000_anc_transition(struct wm2000_priv *wm2000,
{
struct i2c_client *i2c = wm2000->i2c;
int i, j;
- int ret;
+ int ret = 0;
if (wm2000->anc_mode == mode)
return 0;
@@ -566,13 +566,13 @@ static int wm2000_anc_transition(struct wm2000_priv *wm2000,
ret = anc_transitions[i].step[j](i2c,
anc_transitions[i].analogue);
if (ret != 0)
- return ret;
+ break;
}
if (anc_transitions[i].dest == ANC_OFF)
clk_disable_unprepare(wm2000->mclk);
- return 0;
+ return ret;
}
static int wm2000_anc_set_mode(struct wm2000_priv *wm2000)
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index fe99584c917f..9cd91bb0a902 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1535,18 +1535,38 @@ static int wm8350_component_probe(struct snd_soc_component *component)
wm8350_clear_bits(wm8350, WM8350_JACK_DETECT,
WM8350_JDL_ENA | WM8350_JDR_ENA);
- wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L,
+ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L,
wm8350_hpl_jack_handler, 0, "Left jack detect",
priv);
- wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R,
+ if (ret != 0)
+ goto err;
+
+ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R,
wm8350_hpr_jack_handler, 0, "Right jack detect",
priv);
- wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICSCD,
+ if (ret != 0)
+ goto free_jck_det_l;
+
+ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICSCD,
wm8350_mic_handler, 0, "Microphone short", priv);
- wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD,
+ if (ret != 0)
+ goto free_jck_det_r;
+
+ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD,
wm8350_mic_handler, 0, "Microphone detect", priv);
+ if (ret != 0)
+ goto free_micscd;
return 0;
+
+free_micscd:
+ wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_MICSCD, priv);
+free_jck_det_r:
+ wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv);
+free_jck_det_l:
+ wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv);
+err:
+ return ret;
}
static void wm8350_component_remove(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 6fd1bef848ed..fa55d79b39b6 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -601,7 +601,7 @@ static int wm8731_hw_init(struct device *dev, struct wm8731_priv *wm8731)
ret = wm8731_reset(wm8731->regmap);
if (ret < 0) {
dev_err(dev, "Failed to issue reset: %d\n", ret);
- goto err_regulator_enable;
+ goto err;
}
/* Clear POWEROFF, keep everything else disabled */
@@ -618,10 +618,7 @@ static int wm8731_hw_init(struct device *dev, struct wm8731_priv *wm8731)
regcache_mark_dirty(wm8731->regmap);
-err_regulator_enable:
- /* Regulators will be enabled by bias management */
- regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
-
+err:
return ret;
}
@@ -765,21 +762,27 @@ static int wm8731_i2c_probe(struct i2c_client *i2c,
ret = PTR_ERR(wm8731->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
- return ret;
+ goto err_regulator_enable;
}
ret = wm8731_hw_init(&i2c->dev, wm8731);
if (ret != 0)
- return ret;
+ goto err_regulator_enable;
ret = devm_snd_soc_register_component(&i2c->dev,
&soc_component_dev_wm8731, &wm8731_dai, 1);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
- return ret;
+ goto err_regulator_enable;
}
return 0;
+
+err_regulator_enable:
+ /* Regulators will be enabled by bias management */
+ regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
+
+ return ret;
}
static int wm8731_i2c_remove(struct i2c_client *client)
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index 04f23477039a..c677c068b05e 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -534,7 +534,7 @@ static int wm8958_mbc_put(struct snd_kcontrol *kcontrol,
wm8958_dsp_apply(component, mbc, wm8994->mbc_ena[mbc]);
- return 0;
+ return 1;
}
#define WM8958_MBC_SWITCH(xname, xval) {\
@@ -660,7 +660,7 @@ static int wm8958_vss_put(struct snd_kcontrol *kcontrol,
wm8958_dsp_apply(component, vss, wm8994->vss_ena[vss]);
- return 0;
+ return 1;
}
@@ -734,7 +734,7 @@ static int wm8958_hpf_put(struct snd_kcontrol *kcontrol,
wm8958_dsp_apply(component, hpf % 3, ucontrol->value.integer.value[0]);
- return 0;
+ return 1;
}
#define WM8958_HPF_SWITCH(xname, xval) {\
@@ -828,7 +828,7 @@ static int wm8958_enh_eq_put(struct snd_kcontrol *kcontrol,
wm8958_dsp_apply(component, eq, ucontrol->value.integer.value[0]);
- return 0;
+ return 1;
}
#define WM8958_ENH_EQ_SWITCH(xname, xval) {\
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 6cf0f6612bda..512f8899dcbb 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -707,7 +707,13 @@ int wm8960_configure_pll(struct snd_soc_component *component, int freq_in,
best_freq_out = -EINVAL;
*sysclk_idx = *dac_idx = *bclk_idx = -1;
- for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {
+ /*
+ * From Datasheet, the PLL performs best when f2 is between
+ * 90MHz and 100MHz, the desired sysclk output is 11.2896MHz
+ * or 12.288MHz, then sysclkdiv = 2 is the best choice.
+ * So search sysclk_divs from 2 to 1 other than from 1 to 2.
+ */
+ for (i = ARRAY_SIZE(sysclk_divs) - 1; i >= 0; --i) {
if (sysclk_divs[i] == -1)
continue;
for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) {
@@ -746,9 +752,16 @@ static int wm8960_configure_clocking(struct snd_soc_component *component)
int i, j, k;
int ret;
- if (!(iface1 & (1<<6))) {
- dev_dbg(component->dev,
- "Codec is slave mode, no need to configure clock\n");
+ /*
+ * For Slave mode clocking should still be configured,
+ * so this if statement should be removed, but some platform
+ * may not work if the sysclk is not configured, to avoid such
+ * compatible issue, just add '!wm8960->sysclk' condition in
+ * this if statement.
+ */
+ if (!(iface1 & (1 << 6)) && !wm8960->sysclk) {
+ dev_warn(component->dev,
+ "slave mode, but proceeding with no clock configuration\n");
return 0;
}
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index d9d59f45833f..ebaee468057b 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -3854,6 +3854,7 @@ static int wm8962_runtime_suspend(struct device *dev)
#endif
static const struct dev_pm_ops wm8962_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL)
};
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c
index 37e4bb3dbd8a..229f2986cd96 100644
--- a/sound/soc/codecs/wm8997.c
+++ b/sound/soc/codecs/wm8997.c
@@ -1177,6 +1177,8 @@ static int wm8997_probe(struct platform_device *pdev)
goto err_spk_irqs;
}
+ return ret;
+
err_spk_irqs:
arizona_free_spk_irqs(arizona);
diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c
index 7c1899219573..817ccddd6344 100644
--- a/sound/soc/codecs/wm8998.c
+++ b/sound/soc/codecs/wm8998.c
@@ -1375,7 +1375,7 @@ static int wm8998_probe(struct platform_device *pdev)
ret = arizona_init_spk_irqs(arizona);
if (ret < 0)
- return ret;
+ goto err_pm_disable;
ret = devm_snd_soc_register_component(&pdev->dev,
&soc_component_dev_wm8998,
@@ -1390,6 +1390,8 @@ static int wm8998_probe(struct platform_device *pdev)
err_spk_irqs:
arizona_free_spk_irqs(arizona);
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
return ret;
}
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 9b8bb7bbe945..aedfa6b2895b 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -791,7 +791,7 @@ int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
- int ret = 0;
+ int ret = 1;
if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw)
return 0;
@@ -1496,7 +1496,7 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL);
if (!ctl_work) {
ret = -ENOMEM;
- goto err_ctl_cache;
+ goto err_list_del;
}
ctl_work->dsp = dsp;
@@ -1506,7 +1506,8 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
return 0;
-err_ctl_cache:
+err_list_del:
+ list_del(&ctl->list);
kfree(ctl->cache);
err_ctl_name:
kfree(ctl->name);
@@ -1912,6 +1913,7 @@ static int wm_adsp_load(struct wm_adsp *dsp)
mem = wm_adsp_find_region(dsp, type);
if (!mem) {
adsp_err(dsp, "No region of type: %x\n", type);
+ ret = -EINVAL;
goto out_fw;
}
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 84290be778f0..33ade79fa032 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -494,11 +494,13 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,
ESAI_SAICR_SYNC, esai_priv->synchronous ?
ESAI_SAICR_SYNC : 0);
- /* Set a default slot number -- 2 */
+ /* Set slots count */
regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
- ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2));
+ ESAI_xCCR_xDC_MASK,
+ ESAI_xCCR_xDC(esai_priv->slots));
regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
- ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2));
+ ESAI_xCCR_xDC_MASK,
+ ESAI_xCCR_xDC(esai_priv->slots));
}
return 0;
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 914b75c23d1b..027259695551 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -694,7 +694,7 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
return 0;
}
-static struct snd_soc_dai_driver fsl_sai_dai = {
+static struct snd_soc_dai_driver fsl_sai_dai_template = {
.probe = fsl_sai_dai_probe,
.playback = {
.stream_name = "CPU-Playback",
@@ -965,12 +965,15 @@ static int fsl_sai_probe(struct platform_device *pdev)
return ret;
}
+ memcpy(&sai->cpu_dai_drv, &fsl_sai_dai_template,
+ sizeof(fsl_sai_dai_template));
+
/* Sync Tx with Rx as default by following old DT binding */
sai->synchronous[RX] = true;
sai->synchronous[TX] = false;
- fsl_sai_dai.symmetric_rates = 1;
- fsl_sai_dai.symmetric_channels = 1;
- fsl_sai_dai.symmetric_samplebits = 1;
+ sai->cpu_dai_drv.symmetric_rates = 1;
+ sai->cpu_dai_drv.symmetric_channels = 1;
+ sai->cpu_dai_drv.symmetric_samplebits = 1;
if (of_find_property(np, "fsl,sai-synchronous-rx", NULL) &&
of_find_property(np, "fsl,sai-asynchronous", NULL)) {
@@ -987,9 +990,9 @@ static int fsl_sai_probe(struct platform_device *pdev)
/* Discard all settings for asynchronous mode */
sai->synchronous[RX] = false;
sai->synchronous[TX] = false;
- fsl_sai_dai.symmetric_rates = 0;
- fsl_sai_dai.symmetric_channels = 0;
- fsl_sai_dai.symmetric_samplebits = 0;
+ sai->cpu_dai_drv.symmetric_rates = 0;
+ sai->cpu_dai_drv.symmetric_channels = 0;
+ sai->cpu_dai_drv.symmetric_samplebits = 0;
}
if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) &&
@@ -1018,7 +1021,7 @@ static int fsl_sai_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
- &fsl_sai_dai, 1);
+ &sai->cpu_dai_drv, 1);
if (ret)
goto err_pm_disable;
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index 6aba7d28f5f3..afaef2027234 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -67,8 +67,8 @@
#define FSL_SAI_xCR3(tx, ofs) (tx ? FSL_SAI_TCR3(ofs) : FSL_SAI_RCR3(ofs))
#define FSL_SAI_xCR4(tx, ofs) (tx ? FSL_SAI_TCR4(ofs) : FSL_SAI_RCR4(ofs))
#define FSL_SAI_xCR5(tx, ofs) (tx ? FSL_SAI_TCR5(ofs) : FSL_SAI_RCR5(ofs))
-#define FSL_SAI_xDR(tx, ofs) (tx ? FSL_SAI_TDR(ofs) : FSL_SAI_RDR(ofs))
-#define FSL_SAI_xFR(tx, ofs) (tx ? FSL_SAI_TFR(ofs) : FSL_SAI_RFR(ofs))
+#define FSL_SAI_xDR0(tx) (tx ? FSL_SAI_TDR0 : FSL_SAI_RDR0)
+#define FSL_SAI_xFR0(tx) (tx ? FSL_SAI_TFR0 : FSL_SAI_RFR0)
#define FSL_SAI_xMR(tx) (tx ? FSL_SAI_TMR : FSL_SAI_RMR)
/* SAI Transmit/Receive Control Register */
@@ -180,6 +180,7 @@ struct fsl_sai {
unsigned int bclk_ratio;
const struct fsl_sai_soc_data *soc_data;
+ struct snd_soc_dai_driver cpu_dai_drv;
struct snd_dmaengine_dai_dma_data dma_params_rx;
struct snd_dmaengine_dai_dma_data dma_params_tx;
};
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index a4ebd6ddaba1..ed18bc69e095 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -873,6 +873,7 @@ static int fsl_ssi_hw_free(struct snd_pcm_substream *substream,
static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt)
{
u32 strcr = 0, scr = 0, stcr, srcr, mask;
+ unsigned int slots;
ssi->dai_fmt = fmt;
@@ -904,10 +905,11 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt)
return -EINVAL;
}
+ slots = ssi->slots ? : 2;
regmap_update_bits(ssi->regs, REG_SSI_STCCR,
- SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
+ SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(slots));
regmap_update_bits(ssi->regs, REG_SSI_SRCCR,
- SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
+ SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(slots));
/* Data on rising edge of bclk, frame low, 1clk before data */
strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP | SSI_STCR_TEFS;
diff --git a/sound/soc/fsl/imx-es8328.c b/sound/soc/fsl/imx-es8328.c
index 15a27a2cd0ca..9e602c345619 100644
--- a/sound/soc/fsl/imx-es8328.c
+++ b/sound/soc/fsl/imx-es8328.c
@@ -87,6 +87,7 @@ static int imx_es8328_probe(struct platform_device *pdev)
if (int_port > MUX_PORT_MAX || int_port == 0) {
dev_err(dev, "mux-int-port: hardware only has %d mux ports\n",
MUX_PORT_MAX);
+ ret = -EINVAL;
goto fail;
}
@@ -145,13 +146,13 @@ static int imx_es8328_probe(struct platform_device *pdev)
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
- goto fail;
+ goto put_device;
}
comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL);
if (!comp) {
ret = -ENOMEM;
- goto fail;
+ goto put_device;
}
data->dev = dev;
@@ -182,12 +183,12 @@ static int imx_es8328_probe(struct platform_device *pdev)
ret = snd_soc_of_parse_card_name(&data->card, "model");
if (ret) {
dev_err(dev, "Unable to parse card name\n");
- goto fail;
+ goto put_device;
}
ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
if (ret) {
dev_err(dev, "Unable to parse routing: %d\n", ret);
- goto fail;
+ goto put_device;
}
data->card.num_links = 1;
data->card.owner = THIS_MODULE;
@@ -196,10 +197,12 @@ static int imx_es8328_probe(struct platform_device *pdev)
ret = snd_soc_register_card(&data->card);
if (ret) {
dev_err(dev, "Unable to register: %d\n", ret);
- goto fail;
+ goto put_device;
}
platform_set_drvdata(pdev, data);
+put_device:
+ put_device(&ssi_pdev->dev);
fail:
of_node_put(ssi_np);
of_node_put(codec_np);
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
index 15e8b9343c35..7106d56a3346 100644
--- a/sound/soc/fsl/imx-sgtl5000.c
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -120,19 +120,19 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
- goto fail;
+ goto put_device;
}
comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL);
if (!comp) {
ret = -ENOMEM;
- goto fail;
+ goto put_device;
}
data->codec_clk = clk_get(&codec_dev->dev, NULL);
if (IS_ERR(data->codec_clk)) {
ret = PTR_ERR(data->codec_clk);
- goto fail;
+ goto put_device;
}
data->clk_frequency = clk_get_rate(data->codec_clk);
@@ -158,10 +158,10 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
data->card.dev = &pdev->dev;
ret = snd_soc_of_parse_card_name(&data->card, "model");
if (ret)
- goto fail;
+ goto put_device;
ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
if (ret)
- goto fail;
+ goto put_device;
data->card.num_links = 1;
data->card.owner = THIS_MODULE;
data->card.dai_link = &data->dai;
@@ -176,7 +176,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
ret);
- goto fail;
+ goto put_device;
}
of_node_put(ssi_np);
@@ -184,6 +184,8 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
return 0;
+put_device:
+ put_device(&codec_dev->dev);
fail:
if (data && !IS_ERR(data->codec_clk))
clk_put(data->codec_clk);
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c
index af3c3b90c0ac..83b4a22bf15a 100644
--- a/sound/soc/fsl/pcm030-audio-fabric.c
+++ b/sound/soc/fsl/pcm030-audio-fabric.c
@@ -93,16 +93,21 @@ static int pcm030_fabric_probe(struct platform_device *op)
dev_err(&op->dev, "platform_device_alloc() failed\n");
ret = platform_device_add(pdata->codec_device);
- if (ret)
+ if (ret) {
dev_err(&op->dev, "platform_device_add() failed: %d\n", ret);
+ platform_device_put(pdata->codec_device);
+ }
ret = snd_soc_register_card(card);
- if (ret)
+ if (ret) {
dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret);
+ platform_device_del(pdata->codec_device);
+ platform_device_put(pdata->codec_device);
+ }
platform_set_drvdata(op, pdata);
-
return ret;
+
}
static int pcm030_fabric_remove(struct platform_device *op)
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c
index 6007e6305735..1bc498124689 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -340,7 +340,7 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv,
struct device_node *top = dev->of_node;
struct asoc_simple_dai *cpu_dai;
struct asoc_simple_dai *codec_dai;
- int ret, single_cpu;
+ int ret, single_cpu = 0;
/* Do it only CPU turn */
if (!li->cpu)
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index fc9c753db8dd..4484c40c7a39 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -258,7 +258,7 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv,
struct device_node *plat = NULL;
char prop[128];
char *prefix = "";
- int ret, single_cpu;
+ int ret, single_cpu = 0;
/*
* |CPU |Codec : turn
diff --git a/sound/soc/hisilicon/hi6210-i2s.c b/sound/soc/hisilicon/hi6210-i2s.c
index ab3b76d298b3..03470e8f3008 100644
--- a/sound/soc/hisilicon/hi6210-i2s.c
+++ b/sound/soc/hisilicon/hi6210-i2s.c
@@ -102,18 +102,15 @@ static int hi6210_i2s_startup(struct snd_pcm_substream *substream,
for (n = 0; n < i2s->clocks; n++) {
ret = clk_prepare_enable(i2s->clk[n]);
- if (ret) {
- while (n--)
- clk_disable_unprepare(i2s->clk[n]);
- return ret;
- }
+ if (ret)
+ goto err_unprepare_clk;
}
ret = clk_set_rate(i2s->clk[CLK_I2S_BASE], 49152000);
if (ret) {
dev_err(i2s->dev, "%s: setting 49.152MHz base rate failed %d\n",
__func__, ret);
- return ret;
+ goto err_unprepare_clk;
}
/* enable clock before frequency division */
@@ -165,6 +162,11 @@ static int hi6210_i2s_startup(struct snd_pcm_substream *substream,
hi6210_write_reg(i2s, HII2S_SW_RST_N, val);
return 0;
+
+err_unprepare_clk:
+ while (n--)
+ clk_disable_unprepare(i2s->clk[n]);
+ return ret;
}
static void hi6210_i2s_shutdown(struct snd_pcm_substream *substream,
diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c
index bb668551dd4b..243f916355ee 100644
--- a/sound/soc/img/img-i2s-in.c
+++ b/sound/soc/img/img-i2s-in.c
@@ -464,7 +464,7 @@ static int img_i2s_in_probe(struct platform_device *pdev)
if (ret)
goto err_pm_disable;
}
- ret = pm_runtime_get_sync(&pdev->dev);
+ ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0)
goto err_suspend;
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index 31f1dd6541aa..7d59846808b5 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
@@ -127,7 +127,7 @@ static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
snd_pcm_uframes_t period_size;
ssize_t periodbytes;
ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
- u32 buffer_addr = virt_to_phys(substream->dma_buffer.area);
+ u32 buffer_addr = virt_to_phys(substream->runtime->dma_area);
channels = substream->runtime->channels;
period_size = substream->runtime->period_size;
@@ -233,7 +233,6 @@ static int sst_platform_alloc_stream(struct snd_pcm_substream *substream,
/* set codec params and inform SST driver the same */
sst_fill_pcm_params(substream, &param);
sst_fill_alloc_params(substream, &alloc_params);
- substream->runtime->dma_area = substream->dma_buffer.area;
str_params.sparams = param;
str_params.aparams = alloc_params;
str_params.codec = SST_CODEC_TYPE_PCM;
@@ -500,14 +499,14 @@ static struct snd_soc_dai_driver sst_platform_dai[] = {
.channels_min = SST_STEREO,
.channels_max = SST_STEREO,
.rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.capture = {
.stream_name = "Headset Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
},
},
{
@@ -518,7 +517,7 @@ static struct snd_soc_dai_driver sst_platform_dai[] = {
.channels_min = SST_STEREO,
.channels_max = SST_STEREO,
.rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
},
},
{
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 6012367f6fe4..7830d014d924 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -284,9 +284,6 @@ static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
{"Headphone", NULL, "Platform Clock"},
{"Headset Mic", NULL, "Platform Clock"},
- {"Internal Mic", NULL, "Platform Clock"},
- {"Speaker", NULL, "Platform Clock"},
-
{"Headset Mic", NULL, "MICBIAS1"},
{"IN2P", NULL, "Headset Mic"},
{"Headphone", NULL, "HPOL"},
@@ -294,19 +291,23 @@ static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
};
static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = {
+ {"Internal Mic", NULL, "Platform Clock"},
{"DMIC1", NULL, "Internal Mic"},
};
static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = {
+ {"Internal Mic", NULL, "Platform Clock"},
{"DMIC2", NULL, "Internal Mic"},
};
static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = {
+ {"Internal Mic", NULL, "Platform Clock"},
{"Internal Mic", NULL, "MICBIAS1"},
{"IN1P", NULL, "Internal Mic"},
};
static const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = {
+ {"Internal Mic", NULL, "Platform Clock"},
{"Internal Mic", NULL, "MICBIAS1"},
{"IN3P", NULL, "Internal Mic"},
};
@@ -348,6 +349,7 @@ static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = {
};
static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = {
+ {"Speaker", NULL, "Platform Clock"},
{"Speaker", NULL, "SPOLP"},
{"Speaker", NULL, "SPOLN"},
{"Speaker", NULL, "SPORP"},
@@ -355,6 +357,7 @@ static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = {
};
static const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = {
+ {"Speaker", NULL, "Platform Clock"},
{"Speaker", NULL, "SPOLP"},
{"Speaker", NULL, "SPOLN"},
};
@@ -400,6 +403,19 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
+ { /* Acer One 10 S1002 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "One S1002"),
+ },
+ .driver_data = (void *)(BYT_RT5640_IN1_MAP |
+ BYT_RT5640_JD_SRC_JD2_IN4N |
+ BYT_RT5640_OVCD_TH_2000UA |
+ BYT_RT5640_OVCD_SF_0P75 |
+ BYT_RT5640_DIFF_MIC |
+ BYT_RT5640_SSP0_AIF2 |
+ BYT_RT5640_MCLK_EN),
+ },
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -424,6 +440,18 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
},
{
.matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 140 CESIUM"),
+ },
+ .driver_data = (void *)(BYT_RT5640_IN1_MAP |
+ BYT_RT5640_JD_SRC_JD2_IN4N |
+ BYT_RT5640_OVCD_TH_2000UA |
+ BYT_RT5640_OVCD_SF_0P75 |
+ BYT_RT5640_SSP0_AIF1 |
+ BYT_RT5640_MCLK_EN),
+ },
+ {
+ .matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
},
@@ -451,6 +479,9 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),
},
.driver_data = (void *)(BYT_RT5640_IN1_MAP |
+ BYT_RT5640_JD_SRC_JD2_IN4N |
+ BYT_RT5640_OVCD_TH_2000UA |
+ BYT_RT5640_OVCD_SF_0P75 |
BYT_RT5640_MONO_SPEAKER |
BYT_RT5640_DIFF_MIC |
BYT_RT5640_SSP0_AIF2 |
@@ -485,6 +516,23 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_MCLK_EN),
},
{
+ /* Chuwi Hi8 (CWI509) */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
+ DMI_MATCH(DMI_BOARD_NAME, "BYT-PA03C"),
+ DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "S806"),
+ },
+ .driver_data = (void *)(BYT_RT5640_IN1_MAP |
+ BYT_RT5640_JD_SRC_JD2_IN4N |
+ BYT_RT5640_OVCD_TH_2000UA |
+ BYT_RT5640_OVCD_SF_0P75 |
+ BYT_RT5640_MONO_SPEAKER |
+ BYT_RT5640_DIFF_MIC |
+ BYT_RT5640_SSP0_AIF1 |
+ BYT_RT5640_MCLK_EN),
+ },
+ {
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
@@ -513,6 +561,27 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_MONO_SPEAKER |
BYT_RT5640_MCLK_EN),
},
+ { /* Estar Beauty HD MID 7316R */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Estar"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"),
+ },
+ .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
+ BYT_RT5640_MONO_SPEAKER |
+ BYT_RT5640_SSP0_AIF1 |
+ BYT_RT5640_MCLK_EN),
+ },
+ { /* Glavey TM800A550L */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+ /* Above strings are too generic, also match on BIOS version */
+ DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),
+ },
+ .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
+ BYT_RT5640_SSP0_AIF1 |
+ BYT_RT5640_MCLK_EN),
+ },
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
@@ -580,6 +649,20 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_MONO_SPEAKER |
BYT_RT5640_MCLK_EN),
},
+ { /* Lenovo Miix 3-830 */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 3-830"),
+ },
+ .driver_data = (void *)(BYT_RT5640_IN1_MAP |
+ BYT_RT5640_JD_SRC_JD2_IN4N |
+ BYT_RT5640_OVCD_TH_2000UA |
+ BYT_RT5640_OVCD_SF_0P75 |
+ BYT_RT5640_MONO_SPEAKER |
+ BYT_RT5640_DIFF_MIC |
+ BYT_RT5640_SSP0_AIF1 |
+ BYT_RT5640_MCLK_EN),
+ },
{ /* Linx Linx7 tablet */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LINX"),
@@ -776,6 +859,20 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF2 |
BYT_RT5640_MCLK_EN),
},
+ { /* Voyo Winpad A15 */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+ /* Above strings are too generic, also match on BIOS date */
+ DMI_MATCH(DMI_BIOS_DATE, "11/20/2014"),
+ },
+ .driver_data = (void *)(BYT_RT5640_IN1_MAP |
+ BYT_RT5640_JD_SRC_JD2_IN4N |
+ BYT_RT5640_OVCD_TH_2000UA |
+ BYT_RT5640_OVCD_SF_0P75 |
+ BYT_RT5640_DIFF_MIC |
+ BYT_RT5640_MCLK_EN),
+ },
{ /* Catch-all for generic Insyde tablets, must be last */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 4606f6f582d6..921c09cdb480 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -436,6 +436,19 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
BYT_RT5651_MONO_SPEAKER),
},
{
+ /* Jumper EZpad 7 */
+ .callback = byt_rt5651_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Jumper"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
+ /* Jumper12x.WJ2012.bsBKRCP05 with the version dropped */
+ DMI_MATCH(DMI_BIOS_VERSION, "Jumper12x.WJ2012.bsBKRCP"),
+ },
+ .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
+ BYT_RT5651_IN2_MAP |
+ BYT_RT5651_JD_NOT_INV),
+ },
+ {
/* KIANO SlimNote 14.2 */
.callback = byt_rt5651_quirk_cb,
.matches = {
diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c
index 3dadf9bff796..cf47fd9cd506 100644
--- a/sound/soc/intel/boards/haswell.c
+++ b/sound/soc/intel/boards/haswell.c
@@ -206,6 +206,7 @@ static struct platform_driver haswell_audio = {
.probe = haswell_audio_probe,
.driver = {
.name = "haswell-audio",
+ .pm = &snd_soc_pm_ops,
},
};
diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c
index 537a88932bb6..69362eae65be 100644
--- a/sound/soc/intel/boards/kbl_da7219_max98357a.c
+++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c
@@ -607,7 +607,7 @@ static int kabylake_audio_probe(struct platform_device *pdev)
static const struct platform_device_id kbl_board_ids[] = {
{
- .name = "kbl_da7219_max98357a",
+ .name = "kbl_da7219_mx98357a",
.driver_data =
(kernel_ulong_t)&kabylake_audio_card_da7219_m98357a,
},
@@ -629,4 +629,4 @@ module_platform_driver(kabylake_audio)
MODULE_DESCRIPTION("Audio Machine driver-DA7219 & MAX98357A in I2S mode");
MODULE_AUTHOR("Naveen Manohar <naveen.m@intel.com>");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:kbl_da7219_max98357a");
+MODULE_ALIAS("platform:kbl_da7219_mx98357a");
diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c
index 829f95fc4179..16996f6aa2dc 100644
--- a/sound/soc/intel/boards/kbl_da7219_max98927.c
+++ b/sound/soc/intel/boards/kbl_da7219_max98927.c
@@ -282,12 +282,34 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
- struct snd_soc_dpcm *dpcm = container_of(
- params, struct snd_soc_dpcm, hw_params);
- struct snd_soc_dai_link *fe_dai_link = dpcm->fe->dai_link;
- struct snd_soc_dai_link *be_dai_link = dpcm->be->dai_link;
+ struct snd_soc_dpcm *dpcm, *rtd_dpcm = NULL;
/*
+ * The following loop will be called only for playback stream
+ * In this platform, there is only one playback device on every SSP
+ */
+ for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) {
+ rtd_dpcm = dpcm;
+ break;
+ }
+
+ /*
+ * This following loop will be called only for capture stream
+ * In this platform, there is only one capture device on every SSP
+ */
+ for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_CAPTURE, dpcm) {
+ rtd_dpcm = dpcm;
+ break;
+ }
+
+ if (!rtd_dpcm)
+ return -EINVAL;
+
+ /*
+ * The above 2 loops are mutually exclusive based on the stream direction,
+ * thus rtd_dpcm variable will never be overwritten
+ */
+ /*
* Topology for kblda7219m98373 & kblmax98373 supports only S24_LE,
* where as kblda7219m98927 & kblmax98927 supports S16_LE by default.
* Skipping the port wise FE and BE configuration for kblda7219m98373 &
@@ -309,9 +331,9 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
/*
* The ADSP will convert the FE rate to 48k, stereo, 24 bit
*/
- if (!strcmp(fe_dai_link->name, "Kbl Audio Port") ||
- !strcmp(fe_dai_link->name, "Kbl Audio Headset Playback") ||
- !strcmp(fe_dai_link->name, "Kbl Audio Capture Port")) {
+ if (!strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Port") ||
+ !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Headset Playback") ||
+ !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Capture Port")) {
rate->min = rate->max = 48000;
channels->min = channels->max = 2;
snd_mask_none(fmt);
@@ -322,7 +344,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
* The speaker on the SSP0 supports S16_LE and not S24_LE.
* thus changing the mask here
*/
- if (!strcmp(be_dai_link->name, "SSP0-Codec"))
+ if (!strcmp(rtd_dpcm->be->dai_link->name, "SSP0-Codec"))
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
return 0;
diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c
index 7cefda341fbf..a540a2dad80c 100644
--- a/sound/soc/intel/boards/kbl_rt5663_max98927.c
+++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c
@@ -401,17 +401,40 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
- struct snd_soc_dpcm *dpcm = container_of(
- params, struct snd_soc_dpcm, hw_params);
- struct snd_soc_dai_link *fe_dai_link = dpcm->fe->dai_link;
- struct snd_soc_dai_link *be_dai_link = dpcm->be->dai_link;
+ struct snd_soc_dpcm *dpcm, *rtd_dpcm = NULL;
+
+ /*
+ * The following loop will be called only for playback stream
+ * In this platform, there is only one playback device on every SSP
+ */
+ for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) {
+ rtd_dpcm = dpcm;
+ break;
+ }
+
+ /*
+ * This following loop will be called only for capture stream
+ * In this platform, there is only one capture device on every SSP
+ */
+ for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_CAPTURE, dpcm) {
+ rtd_dpcm = dpcm;
+ break;
+ }
+
+ if (!rtd_dpcm)
+ return -EINVAL;
+
+ /*
+ * The above 2 loops are mutually exclusive based on the stream direction,
+ * thus rtd_dpcm variable will never be overwritten
+ */
/*
* The ADSP will convert the FE rate to 48k, stereo, 24 bit
*/
- if (!strcmp(fe_dai_link->name, "Kbl Audio Port") ||
- !strcmp(fe_dai_link->name, "Kbl Audio Headset Playback") ||
- !strcmp(fe_dai_link->name, "Kbl Audio Capture Port")) {
+ if (!strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Port") ||
+ !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Headset Playback") ||
+ !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Capture Port")) {
rate->min = rate->max = 48000;
channels->min = channels->max = 2;
snd_mask_none(fmt);
@@ -421,7 +444,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
* The speaker on the SSP0 supports S16_LE and not S24_LE.
* thus changing the mask here
*/
- if (!strcmp(be_dai_link->name, "SSP0-Codec"))
+ if (!strcmp(rtd_dpcm->be->dai_link->name, "SSP0-Codec"))
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
return 0;
diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
index e200baa11011..df7f82e55a5a 100644
--- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
@@ -113,7 +113,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = {
},
{
.id = "DLGS7219",
- .drv_name = "kbl_da7219_max98373",
+ .drv_name = "kbl_da7219_mx98373",
.fw_filename = "intel/dsp_fw_kbl.bin",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &kbl_7219_98373_codecs,
diff --git a/sound/soc/intel/common/soc-intel-quirks.h b/sound/soc/intel/common/soc-intel-quirks.h
index 863a477d3405..645baf0ed3dd 100644
--- a/sound/soc/intel/common/soc-intel-quirks.h
+++ b/sound/soc/intel/common/soc-intel-quirks.h
@@ -11,6 +11,7 @@
#if IS_ENABLED(CONFIG_X86)
+#include <linux/dmi.h>
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
#include <asm/iosf_mbi.h>
@@ -40,12 +41,36 @@ SOC_INTEL_IS_CPU(cml, INTEL_FAM6_KABYLAKE_L);
static inline bool soc_intel_is_byt_cr(struct platform_device *pdev)
{
+ /*
+ * List of systems which:
+ * 1. Use a non CR version of the Bay Trail SoC
+ * 2. Contain at least 6 interrupt resources so that the
+ * platform_get_resource(pdev, IORESOURCE_IRQ, 5) check below
+ * succeeds
+ * 3. Despite 1. and 2. still have their IPC IRQ at index 0 rather then 5
+ *
+ * This needs to be here so that it can be shared between the SST and
+ * SOF drivers. We rely on the compiler to optimize this out in files
+ * where soc_intel_is_byt_cr is not used.
+ */
+ static const struct dmi_system_id force_bytcr_table[] = {
+ { /* Lenovo Yoga Tablet 2 series */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_FAMILY, "YOGATablet2"),
+ },
+ },
+ {}
+ };
struct device *dev = &pdev->dev;
int status = 0;
if (!soc_intel_is_byt())
return false;
+ if (dmi_check_system(force_bytcr_table))
+ return true;
+
if (iosf_mbi_available()) {
u32 bios_status;
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c
index 92a82e6b5fe6..38b9d7494083 100644
--- a/sound/soc/intel/skylake/bxt-sst.c
+++ b/sound/soc/intel/skylake/bxt-sst.c
@@ -17,7 +17,6 @@
#include "skl.h"
#define BXT_BASEFW_TIMEOUT 3000
-#define BXT_INIT_TIMEOUT 300
#define BXT_ROM_INIT_TIMEOUT 70
#define BXT_IPC_PURGE_FW 0x01004000
@@ -38,8 +37,6 @@
/* Delay before scheduling D0i3 entry */
#define BXT_D0I3_DELAY 5000
-#define BXT_FW_ROM_INIT_RETRY 3
-
static unsigned int bxt_get_errorcode(struct sst_dsp *ctx)
{
return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE);
diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c
index 4f64f097e9ae..e808f62960ba 100644
--- a/sound/soc/intel/skylake/cnl-sst.c
+++ b/sound/soc/intel/skylake/cnl-sst.c
@@ -57,18 +57,34 @@ static int cnl_prepare_fw(struct sst_dsp *ctx, const void *fwdata, u32 fwsize)
ctx->dsp_ops.stream_tag = stream_tag;
memcpy(ctx->dmab.area, fwdata, fwsize);
+ ret = skl_dsp_core_power_up(ctx, SKL_DSP_CORE0_MASK);
+ if (ret < 0) {
+ dev_err(ctx->dev, "dsp core0 power up failed\n");
+ ret = -EIO;
+ goto base_fw_load_failed;
+ }
+
/* purge FW request */
sst_dsp_shim_write(ctx, CNL_ADSP_REG_HIPCIDR,
CNL_ADSP_REG_HIPCIDR_BUSY | (CNL_IPC_PURGE |
((stream_tag - 1) << CNL_ROM_CTRL_DMA_ID)));
- ret = cnl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK);
+ ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK);
if (ret < 0) {
- dev_err(ctx->dev, "dsp boot core failed ret: %d\n", ret);
+ dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret);
ret = -EIO;
goto base_fw_load_failed;
}
+ ret = sst_dsp_register_poll(ctx, CNL_ADSP_REG_HIPCIDA,
+ CNL_ADSP_REG_HIPCIDA_DONE,
+ CNL_ADSP_REG_HIPCIDA_DONE,
+ BXT_INIT_TIMEOUT, "HIPCIDA Done");
+ if (ret < 0) {
+ dev_err(ctx->dev, "timeout for purge request: %d\n", ret);
+ goto base_fw_load_failed;
+ }
+
/* enable interrupt */
cnl_ipc_int_enable(ctx);
cnl_ipc_op_int_enable(ctx);
@@ -109,7 +125,7 @@ static int cnl_load_base_firmware(struct sst_dsp *ctx)
{
struct firmware stripped_fw;
struct skl_dev *cnl = ctx->thread_context;
- int ret;
+ int ret, i;
if (!ctx->fw) {
ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev);
@@ -131,12 +147,16 @@ static int cnl_load_base_firmware(struct sst_dsp *ctx)
stripped_fw.size = ctx->fw->size;
skl_dsp_strip_extended_manifest(&stripped_fw);
- ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size);
- if (ret < 0) {
- dev_err(ctx->dev, "prepare firmware failed: %d\n", ret);
- goto cnl_load_base_firmware_failed;
+ for (i = 0; i < BXT_FW_ROM_INIT_RETRY; i++) {
+ ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size);
+ if (!ret)
+ break;
+ dev_dbg(ctx->dev, "prepare firmware failed: %d\n", ret);
}
+ if (ret < 0)
+ goto cnl_load_base_firmware_failed;
+
ret = sst_transfer_fw_host_dma(ctx);
if (ret < 0) {
dev_err(ctx->dev, "transfer firmware failed: %d\n", ret);
@@ -158,6 +178,7 @@ static int cnl_load_base_firmware(struct sst_dsp *ctx)
return 0;
cnl_load_base_firmware_failed:
+ dev_err(ctx->dev, "firmware load failed: %d\n", ret);
release_firmware(ctx->fw);
ctx->fw = NULL;
@@ -203,6 +224,7 @@ static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
"dsp boot timeout, status=%#x error=%#x\n",
sst_dsp_shim_read(ctx, CNL_ADSP_FW_STATUS),
sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE));
+ ret = -ETIMEDOUT;
goto err;
}
} else {
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c
index 476ef1897961..79c6cf2c14bf 100644
--- a/sound/soc/intel/skylake/skl-messages.c
+++ b/sound/soc/intel/skylake/skl-messages.c
@@ -802,9 +802,12 @@ static u16 skl_get_module_param_size(struct skl_dev *skl,
case SKL_MODULE_TYPE_BASE_OUTFMT:
case SKL_MODULE_TYPE_MIC_SELECT:
- case SKL_MODULE_TYPE_KPB:
return sizeof(struct skl_base_outfmt_cfg);
+ case SKL_MODULE_TYPE_MIXER:
+ case SKL_MODULE_TYPE_KPB:
+ return sizeof(struct skl_base_cfg);
+
default:
/*
* return only base cfg when no specific module type is
@@ -857,10 +860,14 @@ static int skl_set_module_format(struct skl_dev *skl,
case SKL_MODULE_TYPE_BASE_OUTFMT:
case SKL_MODULE_TYPE_MIC_SELECT:
- case SKL_MODULE_TYPE_KPB:
skl_set_base_outfmt_format(skl, module_config, *param_data);
break;
+ case SKL_MODULE_TYPE_MIXER:
+ case SKL_MODULE_TYPE_KPB:
+ skl_set_base_module_format(skl, module_config, *param_data);
+ break;
+
default:
skl_set_base_module_format(skl, module_config, *param_data);
break;
diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c
index 19f328d71f24..d9c8f5cb389e 100644
--- a/sound/soc/intel/skylake/skl-nhlt.c
+++ b/sound/soc/intel/skylake/skl-nhlt.c
@@ -182,7 +182,8 @@ void skl_nhlt_remove_sysfs(struct skl_dev *skl)
{
struct device *dev = &skl->pci->dev;
- sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr);
+ if (skl->nhlt)
+ sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr);
}
/*
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c
index 7f287424af9b..439dd4ba690c 100644
--- a/sound/soc/intel/skylake/skl-pcm.c
+++ b/sound/soc/intel/skylake/skl-pcm.c
@@ -1333,21 +1333,6 @@ static int skl_get_module_info(struct skl_dev *skl,
return -EIO;
}
- list_for_each_entry(module, &skl->uuid_list, list) {
- if (guid_equal(uuid_mod, &module->uuid)) {
- mconfig->id.module_id = module->id;
- if (mconfig->module)
- mconfig->module->loadable = module->is_loadable;
- ret = 0;
- break;
- }
- }
-
- if (ret)
- return ret;
-
- uuid_mod = &module->uuid;
- ret = -EIO;
for (i = 0; i < skl->nr_modules; i++) {
skl_module = skl->modules[i];
uuid_tplg = &skl_module->uuid;
@@ -1357,10 +1342,18 @@ static int skl_get_module_info(struct skl_dev *skl,
break;
}
}
+
if (skl->nr_modules && ret)
return ret;
+ ret = -EIO;
list_for_each_entry(module, &skl->uuid_list, list) {
+ if (guid_equal(uuid_mod, &module->uuid)) {
+ mconfig->id.module_id = module->id;
+ mconfig->module->loadable = module->is_loadable;
+ ret = 0;
+ }
+
for (i = 0; i < MAX_IN_QUEUE; i++) {
pin_id = &mconfig->m_in_pin[i].id;
if (guid_equal(&pin_id->mod_uuid, &module->uuid))
@@ -1374,7 +1367,7 @@ static int skl_get_module_info(struct skl_dev *skl,
}
}
- return 0;
+ return ret;
}
static int skl_populate_modules(struct skl_dev *skl)
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h
index cdfec0fca577..1df9ef422f61 100644
--- a/sound/soc/intel/skylake/skl-sst-dsp.h
+++ b/sound/soc/intel/skylake/skl-sst-dsp.h
@@ -67,6 +67,8 @@ struct skl_dev;
#define SKL_FW_INIT 0x1
#define SKL_FW_RFW_START 0xf
+#define BXT_FW_ROM_INIT_RETRY 3
+#define BXT_INIT_TIMEOUT 300
#define SKL_ADSPIC_IPC 1
#define SKL_ADSPIS_IPC 1
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c
index 69cd7a81bf2a..254b796e635d 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -14,6 +14,7 @@
#include <linux/uuid.h>
#include <sound/intel-nhlt.h>
#include <sound/soc.h>
+#include <sound/soc-acpi.h>
#include <sound/soc-topology.h>
#include <uapi/sound/snd_sst_tokens.h>
#include <uapi/sound/skl-tplg-interface.h>
@@ -112,7 +113,7 @@ static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w,
static void skl_dump_mconfig(struct skl_dev *skl, struct skl_module_cfg *mcfg)
{
- struct skl_module_iface *iface = &mcfg->module->formats[0];
+ struct skl_module_iface *iface = &mcfg->module->formats[mcfg->fmt_idx];
dev_dbg(skl->dev, "Dumping config\n");
dev_dbg(skl->dev, "Input Format:\n");
@@ -194,8 +195,8 @@ static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg,
struct skl_module_fmt *in_fmt, *out_fmt;
/* Fixups will be applied to pin 0 only */
- in_fmt = &m_cfg->module->formats[0].inputs[0].fmt;
- out_fmt = &m_cfg->module->formats[0].outputs[0].fmt;
+ in_fmt = &m_cfg->module->formats[m_cfg->fmt_idx].inputs[0].fmt;
+ out_fmt = &m_cfg->module->formats[m_cfg->fmt_idx].outputs[0].fmt;
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (is_fe) {
@@ -238,9 +239,9 @@ static void skl_tplg_update_buffer_size(struct skl_dev *skl,
/* Since fixups is applied to pin 0 only, ibs, obs needs
* change for pin 0 only
*/
- res = &mcfg->module->resources[0];
- in_fmt = &mcfg->module->formats[0].inputs[0].fmt;
- out_fmt = &mcfg->module->formats[0].outputs[0].fmt;
+ res = &mcfg->module->resources[mcfg->res_idx];
+ in_fmt = &mcfg->module->formats[mcfg->fmt_idx].inputs[0].fmt;
+ out_fmt = &mcfg->module->formats[mcfg->fmt_idx].outputs[0].fmt;
if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT)
multiplier = 5;
@@ -578,6 +579,38 @@ static int skl_tplg_unload_pipe_modules(struct skl_dev *skl,
return ret;
}
+static bool skl_tplg_is_multi_fmt(struct skl_dev *skl, struct skl_pipe *pipe)
+{
+ struct skl_pipe_fmt *cur_fmt;
+ struct skl_pipe_fmt *next_fmt;
+ int i;
+
+ if (pipe->nr_cfgs <= 1)
+ return false;
+
+ if (pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
+ return true;
+
+ for (i = 0; i < pipe->nr_cfgs - 1; i++) {
+ if (pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) {
+ cur_fmt = &pipe->configs[i].out_fmt;
+ next_fmt = &pipe->configs[i + 1].out_fmt;
+ } else {
+ cur_fmt = &pipe->configs[i].in_fmt;
+ next_fmt = &pipe->configs[i + 1].in_fmt;
+ }
+
+ if (!CHECK_HW_PARAMS(cur_fmt->channels, cur_fmt->freq,
+ cur_fmt->bps,
+ next_fmt->channels,
+ next_fmt->freq,
+ next_fmt->bps))
+ return true;
+ }
+
+ return false;
+}
+
/*
* Here, we select pipe format based on the pipe type and pipe
* direction to determine the current config index for the pipeline.
@@ -600,6 +633,14 @@ skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig)
return 0;
}
+ if (skl_tplg_is_multi_fmt(skl, pipe)) {
+ pipe->cur_config_idx = pipe->pipe_config_idx;
+ pipe->memory_pages = pconfig->mem_pages;
+ dev_dbg(skl->dev, "found pipe config idx:%d\n",
+ pipe->cur_config_idx);
+ return 0;
+ }
+
if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) {
dev_dbg(skl->dev, "No conn_type detected, take 0th config\n");
pipe->cur_config_idx = 0;
@@ -1314,6 +1355,68 @@ static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w,
return 0;
}
+static int skl_tplg_multi_config_set_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol,
+ bool is_set)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct hdac_bus *bus = snd_soc_component_get_drvdata(component);
+ struct skl_dev *skl = bus_to_skl(bus);
+ struct skl_pipeline *ppl;
+ struct skl_pipe *pipe = NULL;
+ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
+ u32 *pipe_id;
+
+ if (!ec)
+ return -EINVAL;
+
+ if (is_set && ucontrol->value.enumerated.item[0] > ec->items)
+ return -EINVAL;
+
+ pipe_id = ec->dobj.private;
+
+ list_for_each_entry(ppl, &skl->ppl_list, node) {
+ if (ppl->pipe->ppl_id == *pipe_id) {
+ pipe = ppl->pipe;
+ break;
+ }
+ }
+ if (!pipe)
+ return -EIO;
+
+ if (is_set)
+ pipe->pipe_config_idx = ucontrol->value.enumerated.item[0];
+ else
+ ucontrol->value.enumerated.item[0] = pipe->pipe_config_idx;
+
+ return 0;
+}
+
+static int skl_tplg_multi_config_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return skl_tplg_multi_config_set_get(kcontrol, ucontrol, false);
+}
+
+static int skl_tplg_multi_config_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true);
+}
+
+static int skl_tplg_multi_config_get_dmic(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return skl_tplg_multi_config_set_get(kcontrol, ucontrol, false);
+}
+
+static int skl_tplg_multi_config_set_dmic(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true);
+}
+
static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol,
unsigned int __user *data, unsigned int size)
{
@@ -1360,12 +1463,6 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
struct skl_dev *skl = get_skl_ctx(w->dapm->dev);
if (ac->params) {
- /*
- * Widget data is expected to be stripped of T and L
- */
- size -= 2 * sizeof(unsigned int);
- data += 2;
-
if (size > ac->max)
return -EINVAL;
ac->size = size;
@@ -1534,11 +1631,12 @@ int skl_tplg_update_pipe_params(struct device *dev,
struct skl_module_cfg *mconfig,
struct skl_pipe_params *params)
{
- struct skl_module_res *res = &mconfig->module->resources[0];
+ struct skl_module_res *res;
struct skl_dev *skl = get_skl_ctx(dev);
struct skl_module_fmt *format = NULL;
u8 cfg_idx = mconfig->pipe->cur_config_idx;
+ res = &mconfig->module->resources[mconfig->res_idx];
skl_tplg_fill_dma_id(mconfig, params);
mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx;
mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx;
@@ -1547,9 +1645,9 @@ int skl_tplg_update_pipe_params(struct device *dev,
return 0;
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK)
- format = &mconfig->module->formats[0].inputs[0].fmt;
+ format = &mconfig->module->formats[mconfig->fmt_idx].inputs[0].fmt;
else
- format = &mconfig->module->formats[0].outputs[0].fmt;
+ format = &mconfig->module->formats[mconfig->fmt_idx].outputs[0].fmt;
/* set the hw_params */
format->s_freq = params->s_freq;
@@ -1853,6 +1951,16 @@ static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = {
.get = skl_tplg_mic_control_get,
.put = skl_tplg_mic_control_set,
},
+ {
+ .id = SKL_CONTROL_TYPE_MULTI_IO_SELECT,
+ .get = skl_tplg_multi_config_get,
+ .put = skl_tplg_multi_config_set,
+ },
+ {
+ .id = SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC,
+ .get = skl_tplg_multi_config_get_dmic,
+ .put = skl_tplg_multi_config_set_dmic,
+ }
};
static int skl_tplg_fill_pipe_cfg(struct device *dev,
@@ -3013,12 +3121,21 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
case SND_SOC_TPLG_CTL_ENUM:
tplg_ec = container_of(hdr,
struct snd_soc_tplg_enum_control, hdr);
- if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) {
+ if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READ) {
se = (struct soc_enum *)kctl->private_value;
if (tplg_ec->priv.size)
- return skl_init_enum_data(bus->dev, se,
- tplg_ec);
+ skl_init_enum_data(bus->dev, se, tplg_ec);
}
+
+ /*
+ * now that the control initializations are done, remove
+ * write permission for the DMIC configuration enums to
+ * avoid conflicts between NHLT settings and user interaction
+ */
+
+ if (hdr->ops.get == SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC)
+ kctl->access = SNDRV_CTL_ELEM_ACCESS_READ;
+
break;
default:
@@ -3488,6 +3605,38 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt, int index,
return 0;
}
+static void skl_tplg_complete(struct snd_soc_component *component)
+{
+ struct snd_soc_dobj *dobj;
+ struct snd_soc_acpi_mach *mach =
+ dev_get_platdata(component->card->dev);
+ int i;
+
+ list_for_each_entry(dobj, &component->dobj_list, list) {
+ struct snd_kcontrol *kcontrol = dobj->control.kcontrol;
+ struct soc_enum *se;
+ char **texts;
+ char chan_text[4];
+
+ if (dobj->type != SND_SOC_DOBJ_ENUM || !kcontrol ||
+ kcontrol->put != skl_tplg_multi_config_set_dmic)
+ continue;
+
+ se = (struct soc_enum *)kcontrol->private_value;
+ texts = dobj->control.dtexts;
+ sprintf(chan_text, "c%d", mach->mach_params.dmic_num);
+
+ for (i = 0; i < se->items; i++) {
+ struct snd_ctl_elem_value val = {};
+
+ if (strstr(texts[i], chan_text)) {
+ val.value.enumerated.item[0] = i;
+ kcontrol->put(kcontrol, &val);
+ }
+ }
+ }
+}
+
static struct snd_soc_tplg_ops skl_tplg_ops = {
.widget_load = skl_tplg_widget_load,
.control_load = skl_tplg_control_load,
@@ -3497,6 +3646,7 @@ static struct snd_soc_tplg_ops skl_tplg_ops = {
.io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops),
.manifest = skl_manifest_load,
.dai_load = skl_dai_load,
+ .complete = skl_tplg_complete,
};
/*
@@ -3565,8 +3715,20 @@ int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus)
ret = request_firmware(&fw, skl->tplg_name, bus->dev);
if (ret < 0) {
- dev_info(bus->dev, "tplg fw %s load failed with %d, falling back to dfw_sst.bin",
- skl->tplg_name, ret);
+ char alt_tplg_name[64];
+
+ snprintf(alt_tplg_name, sizeof(alt_tplg_name), "%s-tplg.bin",
+ skl->mach->drv_name);
+ dev_info(bus->dev, "tplg fw %s load failed with %d, trying alternative tplg name %s",
+ skl->tplg_name, ret, alt_tplg_name);
+
+ ret = request_firmware(&fw, alt_tplg_name, bus->dev);
+ if (!ret)
+ goto component_load;
+
+ dev_info(bus->dev, "tplg %s failed with %d, falling back to dfw_sst.bin",
+ alt_tplg_name, ret);
+
ret = request_firmware(&fw, "dfw_sst.bin", bus->dev);
if (ret < 0) {
dev_err(bus->dev, "Fallback tplg fw %s load failed with %d\n",
@@ -3575,6 +3737,8 @@ int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus)
}
}
+component_load:
+
/*
* The complete tplg for SKL is loaded as index 0, we don't use
* any other index
diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h
index e967800dbb62..06576147cc29 100644
--- a/sound/soc/intel/skylake/skl-topology.h
+++ b/sound/soc/intel/skylake/skl-topology.h
@@ -306,6 +306,7 @@ struct skl_pipe {
struct skl_path_config configs[SKL_MAX_PATH_CONFIGS];
struct list_head w_list;
bool passthru;
+ u32 pipe_config_idx;
};
enum skl_module_state {
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c
index 141dbbf975ac..2e5fbd220923 100644
--- a/sound/soc/intel/skylake/skl.c
+++ b/sound/soc/intel/skylake/skl.c
@@ -129,6 +129,7 @@ static int skl_init_chip(struct hdac_bus *bus, bool full_reset)
struct hdac_ext_link *hlink;
int ret;
+ snd_hdac_set_codec_wakeup(bus, true);
skl_enable_miscbdcge(bus->dev, false);
ret = snd_hdac_bus_init_chip(bus, full_reset);
@@ -137,6 +138,7 @@ static int skl_init_chip(struct hdac_bus *bus, bool full_reset)
writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV);
skl_enable_miscbdcge(bus->dev, true);
+ snd_hdac_set_codec_wakeup(bus, false);
return ret;
}
@@ -480,13 +482,8 @@ static struct skl_ssp_clk skl_ssp_clks[] = {
static struct snd_soc_acpi_mach *skl_find_hda_machine(struct skl_dev *skl,
struct snd_soc_acpi_mach *machines)
{
- struct hdac_bus *bus = skl_to_bus(skl);
struct snd_soc_acpi_mach *mach;
- /* check if we have any codecs detected on bus */
- if (bus->codec_mask == 0)
- return NULL;
-
/* point to common table */
mach = snd_soc_acpi_intel_hda_machines;
@@ -635,6 +632,9 @@ static int skl_clock_device_register(struct skl_dev *skl)
struct platform_device_info pdevinfo = {NULL};
struct skl_clk_pdata *clk_pdata;
+ if (!skl->nhlt)
+ return 0;
+
clk_pdata = devm_kzalloc(&skl->pci->dev, sizeof(*clk_pdata),
GFP_KERNEL);
if (!clk_pdata)
@@ -807,6 +807,9 @@ static void skl_probe_work(struct work_struct *work)
return;
}
+ skl_init_pci(skl);
+ skl_dum_set(bus);
+
err = skl_init_chip(bus, true);
if (err < 0) {
dev_err(bus->dev, "Init chip failed with err: %d\n", err);
@@ -922,8 +925,6 @@ static int skl_first_init(struct hdac_bus *bus)
return -ENXIO;
}
- snd_hdac_bus_reset_link(bus, true);
-
snd_hdac_bus_parse_capabilities(bus);
/* check if PPCAP exists */
@@ -971,11 +972,7 @@ static int skl_first_init(struct hdac_bus *bus)
if (err < 0)
return err;
- /* initialize chip */
- skl_init_pci(skl);
- skl_dum_set(bus);
-
- return skl_init_chip(bus, true);
+ return 0;
}
static int skl_probe(struct pci_dev *pci,
@@ -1080,8 +1077,6 @@ static int skl_probe(struct pci_dev *pci,
if (bus->mlcap)
snd_hdac_ext_bus_get_ml_capabilities(bus);
- snd_hdac_bus_stop_chip(bus);
-
/* create device for soc dmic */
err = skl_dmic_device_register(skl);
if (err < 0) {
@@ -1098,7 +1093,8 @@ out_dsp_free:
out_clk_free:
skl_clock_device_unregister(skl);
out_nhlt_free:
- intel_nhlt_free(skl->nhlt);
+ if (skl->nhlt)
+ intel_nhlt_free(skl->nhlt);
out_free:
skl_free(bus);
@@ -1147,7 +1143,8 @@ static void skl_remove(struct pci_dev *pci)
skl_dmic_device_unregister(skl);
skl_clock_device_unregister(skl);
skl_nhlt_remove_sysfs(skl);
- intel_nhlt_free(skl->nhlt);
+ if (skl->nhlt)
+ intel_nhlt_free(skl->nhlt);
skl_free(bus);
dev_set_drvdata(&pci->dev, NULL);
}
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index 0bbd86390be5..9bfd2aabbfe6 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -309,10 +309,14 @@ static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
switch (clk_id) {
case JZ4740_I2S_CLKSRC_EXT:
parent = clk_get(NULL, "ext");
+ if (IS_ERR(parent))
+ return PTR_ERR(parent);
clk_set_parent(i2s->clk_i2s, parent);
break;
case JZ4740_I2S_CLKSRC_PLL:
parent = clk_get(NULL, "pll half");
+ if (IS_ERR(parent))
+ return PTR_ERR(parent);
clk_set_parent(i2s->clk_i2s, parent);
ret = clk_set_rate(i2s->clk_i2s, freq);
break;
diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c
index d00608c73c6e..b66f7dee1e14 100644
--- a/sound/soc/mediatek/common/mtk-btcvsd.c
+++ b/sound/soc/mediatek/common/mtk-btcvsd.c
@@ -1302,7 +1302,7 @@ static const struct snd_soc_component_driver mtk_btcvsd_snd_platform = {
static int mtk_btcvsd_snd_probe(struct platform_device *pdev)
{
- int ret = 0;
+ int ret;
int irq_id;
u32 offset[5] = {0, 0, 0, 0, 0};
struct mtk_btcvsd_snd *btcvsd;
@@ -1358,7 +1358,8 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev)
btcvsd->bt_sram_bank2_base = of_iomap(dev->of_node, 1);
if (!btcvsd->bt_sram_bank2_base) {
dev_err(dev, "iomap bt_sram_bank2_base fail\n");
- return -EIO;
+ ret = -EIO;
+ goto unmap_pkv_err;
}
btcvsd->infra = syscon_regmap_lookup_by_phandle(dev->of_node,
@@ -1366,7 +1367,8 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev)
if (IS_ERR(btcvsd->infra)) {
dev_err(dev, "cannot find infra controller: %ld\n",
PTR_ERR(btcvsd->infra));
- return PTR_ERR(btcvsd->infra);
+ ret = PTR_ERR(btcvsd->infra);
+ goto unmap_bank2_err;
}
/* get offset */
@@ -1375,7 +1377,7 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev)
ARRAY_SIZE(offset));
if (ret) {
dev_warn(dev, "%s(), get offset fail, ret %d\n", __func__, ret);
- return ret;
+ goto unmap_bank2_err;
}
btcvsd->infra_misc_offset = offset[0];
btcvsd->conn_bt_cvsd_mask = offset[1];
@@ -1394,8 +1396,18 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev)
mtk_btcvsd_snd_set_state(btcvsd, btcvsd->tx, BT_SCO_STATE_IDLE);
mtk_btcvsd_snd_set_state(btcvsd, btcvsd->rx, BT_SCO_STATE_IDLE);
- return devm_snd_soc_register_component(dev, &mtk_btcvsd_snd_platform,
- NULL, 0);
+ ret = devm_snd_soc_register_component(dev, &mtk_btcvsd_snd_platform,
+ NULL, 0);
+ if (ret)
+ goto unmap_bank2_err;
+
+ return 0;
+
+unmap_bank2_err:
+ iounmap(btcvsd->bt_sram_bank2_base);
+unmap_pkv_err:
+ iounmap(btcvsd->bt_pkv_base);
+ return ret;
}
static int mtk_btcvsd_snd_remove(struct platform_device *pdev)
diff --git a/sound/soc/mediatek/mt2701/mt2701-wm8960.c b/sound/soc/mediatek/mt2701/mt2701-wm8960.c
index 8c4c89e4c616..b9ad42112ea1 100644
--- a/sound/soc/mediatek/mt2701/mt2701-wm8960.c
+++ b/sound/soc/mediatek/mt2701/mt2701-wm8960.c
@@ -129,7 +129,8 @@ static int mt2701_wm8960_machine_probe(struct platform_device *pdev)
if (!codec_node) {
dev_err(&pdev->dev,
"Property 'audio-codec' missing or invalid\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto put_platform_node;
}
for_each_card_prelinks(card, i, dai_link) {
if (dai_link->codecs->name)
@@ -140,7 +141,7 @@ static int mt2701_wm8960_machine_probe(struct platform_device *pdev)
ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
if (ret) {
dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret);
- return ret;
+ goto put_codec_node;
}
ret = devm_snd_soc_register_card(&pdev->dev, card);
@@ -148,6 +149,10 @@ static int mt2701_wm8960_machine_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
__func__, ret);
+put_codec_node:
+ of_node_put(codec_node);
+put_platform_node:
+ of_node_put(platform_node);
return ret;
}
diff --git a/sound/soc/mediatek/mt8173/mt8173-max98090.c b/sound/soc/mediatek/mt8173/mt8173-max98090.c
index 22c00600c999..32df18180114 100644
--- a/sound/soc/mediatek/mt8173/mt8173-max98090.c
+++ b/sound/soc/mediatek/mt8173/mt8173-max98090.c
@@ -167,7 +167,8 @@ static int mt8173_max98090_dev_probe(struct platform_device *pdev)
if (!codec_node) {
dev_err(&pdev->dev,
"Property 'audio-codec' missing or invalid\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto put_platform_node;
}
for_each_card_prelinks(card, i, dai_link) {
if (dai_link->codecs->name)
@@ -180,6 +181,11 @@ static int mt8173_max98090_dev_probe(struct platform_device *pdev)
if (ret)
dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
__func__, ret);
+
+ of_node_put(codec_node);
+
+put_platform_node:
+ of_node_put(platform_node);
return ret;
}
diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c
index 8717e87bfe26..6f8542329bab 100644
--- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c
+++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c
@@ -218,6 +218,8 @@ static int mt8173_rt5650_rt5514_dev_probe(struct platform_device *pdev)
if (ret)
dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
__func__, ret);
+
+ of_node_put(platform_node);
return ret;
}
diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c
index 9d4dd9721154..727ff0f7f20b 100644
--- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c
+++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c
@@ -285,6 +285,8 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev)
if (ret)
dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
__func__, ret);
+
+ of_node_put(platform_node);
return ret;
}
diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c
index ef6f23675286..21e7d4d3ded5 100644
--- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c
+++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c
@@ -309,6 +309,8 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev)
if (ret)
dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
__func__, ret);
+
+ of_node_put(platform_node);
return ret;
}
diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig
index 2e3676147cea..e0d24592ebd7 100644
--- a/sound/soc/meson/Kconfig
+++ b/sound/soc/meson/Kconfig
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
menu "ASoC support for Amlogic platforms"
- depends on ARCH_MESON || COMPILE_TEST
+ depends on ARCH_MESON || (COMPILE_TEST && COMMON_CLK)
config SND_MESON_AXG_FIFO
tristate
diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c
index e25336f73912..f5a431b8de6c 100644
--- a/sound/soc/meson/axg-tdm-interface.c
+++ b/sound/soc/meson/axg-tdm-interface.c
@@ -467,8 +467,20 @@ static int axg_tdm_iface_set_bias_level(struct snd_soc_component *component,
return ret;
}
+static const struct snd_soc_dapm_widget axg_tdm_iface_dapm_widgets[] = {
+ SND_SOC_DAPM_SIGGEN("Playback Signal"),
+};
+
+static const struct snd_soc_dapm_route axg_tdm_iface_dapm_routes[] = {
+ { "Loopback", NULL, "Playback Signal" },
+};
+
static const struct snd_soc_component_driver axg_tdm_iface_component_drv = {
- .set_bias_level = axg_tdm_iface_set_bias_level,
+ .dapm_widgets = axg_tdm_iface_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(axg_tdm_iface_dapm_widgets),
+ .dapm_routes = axg_tdm_iface_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(axg_tdm_iface_dapm_routes),
+ .set_bias_level = axg_tdm_iface_set_bias_level,
};
static const struct of_device_id axg_tdm_iface_of_match[] = {
diff --git a/sound/soc/meson/axg-tdmin.c b/sound/soc/meson/axg-tdmin.c
index 88ed95ae886b..b4faf9d5c1aa 100644
--- a/sound/soc/meson/axg-tdmin.c
+++ b/sound/soc/meson/axg-tdmin.c
@@ -228,15 +228,6 @@ static const struct axg_tdm_formatter_driver axg_tdmin_drv = {
.regmap_cfg = &axg_tdmin_regmap_cfg,
.ops = &axg_tdmin_ops,
.quirks = &(const struct axg_tdm_formatter_hw) {
- .skew_offset = 2,
- },
-};
-
-static const struct axg_tdm_formatter_driver g12a_tdmin_drv = {
- .component_drv = &axg_tdmin_component_drv,
- .regmap_cfg = &axg_tdmin_regmap_cfg,
- .ops = &axg_tdmin_ops,
- .quirks = &(const struct axg_tdm_formatter_hw) {
.skew_offset = 3,
},
};
@@ -247,10 +238,10 @@ static const struct of_device_id axg_tdmin_of_match[] = {
.data = &axg_tdmin_drv,
}, {
.compatible = "amlogic,g12a-tdmin",
- .data = &g12a_tdmin_drv,
+ .data = &axg_tdmin_drv,
}, {
.compatible = "amlogic,sm1-tdmin",
- .data = &g12a_tdmin_drv,
+ .data = &axg_tdmin_drv,
}, {}
};
MODULE_DEVICE_TABLE(of, axg_tdmin_of_match);
diff --git a/sound/soc/meson/g12a-tohdmitx.c b/sound/soc/meson/g12a-tohdmitx.c
index 9cfbd343a00c..cbe47e0cae42 100644
--- a/sound/soc/meson/g12a-tohdmitx.c
+++ b/sound/soc/meson/g12a-tohdmitx.c
@@ -127,7 +127,7 @@ static int g12a_tohdmitx_i2s_mux_put_enum(struct snd_kcontrol *kcontrol,
snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
- return 0;
+ return 1;
}
static const struct snd_kcontrol_new g12a_tohdmitx_i2s_mux =
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index 1e38ce858326..c899a05e896f 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -455,7 +455,10 @@ static int mxs_saif_hw_params(struct snd_pcm_substream *substream,
* basic clock which should be fast enough for the internal
* logic.
*/
- clk_enable(saif->clk);
+ ret = clk_enable(saif->clk);
+ if (ret)
+ return ret;
+
ret = clk_set_rate(saif->clk, 24000000);
clk_disable(saif->clk);
if (ret)
@@ -764,6 +767,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
saif->master_id = saif->id;
} else {
ret = of_alias_get_id(master, "saif");
+ of_node_put(master);
if (ret < 0)
return ret;
else
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
index 9841e1da9782..8282fe6d00dd 100644
--- a/sound/soc/mxs/mxs-sgtl5000.c
+++ b/sound/soc/mxs/mxs-sgtl5000.c
@@ -118,6 +118,9 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev)
codec_np = of_parse_phandle(np, "audio-codec", 0);
if (!saif_np[0] || !saif_np[1] || !codec_np) {
dev_err(&pdev->dev, "phandle missing or invalid\n");
+ of_node_put(codec_np);
+ of_node_put(saif_np[0]);
+ of_node_put(saif_np[1]);
return -EINVAL;
}
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c
index dbce7e92baf3..c5d6952a4a33 100644
--- a/sound/soc/qcom/lpass-cpu.c
+++ b/sound/soc/qcom/lpass-cpu.c
@@ -174,21 +174,6 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int lpass_cpu_daiops_hw_free(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
- int ret;
-
- ret = regmap_write(drvdata->lpaif_map,
- LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id),
- 0);
- if (ret)
- dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret);
-
- return ret;
-}
-
static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -269,7 +254,6 @@ const struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops = {
.startup = lpass_cpu_daiops_startup,
.shutdown = lpass_cpu_daiops_shutdown,
.hw_params = lpass_cpu_daiops_hw_params,
- .hw_free = lpass_cpu_daiops_hw_free,
.prepare = lpass_cpu_daiops_prepare,
.trigger = lpass_cpu_daiops_trigger,
};
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
index 4c745baa39f7..b1981d84ac18 100644
--- a/sound/soc/qcom/lpass-platform.c
+++ b/sound/soc/qcom/lpass-platform.c
@@ -61,7 +61,7 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
int ret, dma_ch, dir = substream->stream;
struct lpass_pcm_data *data;
- data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -73,8 +73,10 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
else
dma_ch = 0;
- if (dma_ch < 0)
+ if (dma_ch < 0) {
+ kfree(data);
return dma_ch;
+ }
drvdata->substream[dma_ch] = substream;
@@ -95,6 +97,7 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
ret = snd_pcm_hw_constraint_integer(runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
if (ret < 0) {
+ kfree(data);
dev_err(soc_runtime->dev, "setting constraints failed: %d\n",
ret);
return -EINVAL;
@@ -119,6 +122,7 @@ static int lpass_platform_pcmops_close(struct snd_pcm_substream *substream)
if (v->free_dma_channel)
v->free_dma_channel(drvdata, data->dma_ch);
+ kfree(data);
return 0;
}
diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c
index 745cc9dd14f3..bc65009be875 100644
--- a/sound/soc/qcom/qdsp6/q6routing.c
+++ b/sound/soc/qcom/qdsp6/q6routing.c
@@ -440,9 +440,15 @@ static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol,
struct session_data *session = &data->sessions[session_id];
if (ucontrol->value.integer.value[0]) {
+ if (session->port_id == be_id)
+ return 0;
+
session->port_id = be_id;
snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, update);
} else {
+ if (session->port_id == -1 || session->port_id != be_id)
+ return 0;
+
session->port_id = -1;
snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, update);
}
diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
index 7e6c41e63d8e..23e1de61e92e 100644
--- a/sound/soc/qcom/sdm845.c
+++ b/sound/soc/qcom/sdm845.c
@@ -16,6 +16,7 @@
#include "qdsp6/q6afe.h"
#include "../codecs/rt5663.h"
+#define DRIVER_NAME "sdm845"
#define DEFAULT_SAMPLE_RATE_48K 48000
#define DEFAULT_MCLK_RATE 24576000
#define TDM_BCLK_RATE 6144000
@@ -407,6 +408,7 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev)
goto data_alloc_fail;
}
+ card->driver_name = DRIVER_NAME;
card->dapm_widgets = sdm845_snd_widgets;
card->num_dapm_widgets = ARRAY_SIZE(sdm845_snd_widgets);
card->dev = dev;
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 61c984f10d8e..086c90e09577 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -186,7 +186,9 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
{
struct rk_i2s_dev *i2s = to_info(cpu_dai);
unsigned int mask = 0, val = 0;
+ int ret = 0;
+ pm_runtime_get_sync(cpu_dai->dev);
mask = I2S_CKR_MSS_MASK;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
@@ -199,7 +201,8 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
i2s->is_master_mode = false;
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_pm_put;
}
regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
@@ -213,7 +216,8 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
val = I2S_CKR_CKP_POS;
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_pm_put;
}
regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
@@ -229,14 +233,15 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
case SND_SOC_DAIFMT_I2S:
val = I2S_TXCR_IBM_NORMAL;
break;
- case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */
- val = I2S_TXCR_TFS_PCM;
- break;
- case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */
+ case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */
val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1);
break;
+ case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */
+ val = I2S_TXCR_TFS_PCM;
+ break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_pm_put;
}
regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val);
@@ -252,19 +257,23 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
case SND_SOC_DAIFMT_I2S:
val = I2S_RXCR_IBM_NORMAL;
break;
- case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */
- val = I2S_RXCR_TFS_PCM;
- break;
- case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */
+ case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */
val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1);
break;
+ case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */
+ val = I2S_RXCR_TFS_PCM;
+ break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_pm_put;
}
regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val);
- return 0;
+err_pm_put:
+ pm_runtime_put(cpu_dai->dev);
+
+ return ret;
}
static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
index 65497cd477a5..47f6f5d70853 100644
--- a/sound/soc/samsung/idma.c
+++ b/sound/soc/samsung/idma.c
@@ -363,6 +363,8 @@ static int preallocate_idma_buffer(struct snd_pcm *pcm, int stream)
buf->addr = idma.lp_tx_addr;
buf->bytes = idma_hardware.buffer_bytes_max;
buf->area = (unsigned char * __force)ioremap(buf->addr, buf->bytes);
+ if (!buf->area)
+ return -ENOMEM;
return 0;
}
diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c
index bb9910d4cbe2..058847071584 100644
--- a/sound/soc/samsung/tm2_wm5110.c
+++ b/sound/soc/samsung/tm2_wm5110.c
@@ -553,7 +553,7 @@ static int tm2_probe(struct platform_device *pdev)
ret = of_parse_phandle_with_args(dev->of_node, "i2s-controller",
cells_name, i, &args);
- if (!args.np) {
+ if (ret) {
dev_err(dev, "i2s-controller property parse error: %d\n", i);
ret = -EINVAL;
goto dai_node_put;
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 3447dbdba1f1..6ac7df30a289 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -816,14 +816,27 @@ static int fsi_clk_enable(struct device *dev,
return ret;
}
- clk_enable(clock->xck);
- clk_enable(clock->ick);
- clk_enable(clock->div);
+ ret = clk_enable(clock->xck);
+ if (ret)
+ goto err;
+ ret = clk_enable(clock->ick);
+ if (ret)
+ goto disable_xck;
+ ret = clk_enable(clock->div);
+ if (ret)
+ goto disable_ick;
clock->count++;
}
return ret;
+
+disable_ick:
+ clk_disable(clock->ick);
+disable_xck:
+ clk_disable(clock->xck);
+err:
+ return ret;
}
static int fsi_clk_disable(struct device *dev,
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index b9aacf3d3b29..7532ab27a48d 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -289,7 +289,6 @@ static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val)
int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)
{
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct clk *clk;
int i;
int sel_table[] = {
[CLKA] = 0x1,
@@ -302,10 +301,9 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)
* find suitable clock from
* AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI.
*/
- for_each_rsnd_clk(clk, adg, i) {
+ for (i = 0; i < CLKMAX; i++)
if (rate == adg->clk_rate[i])
return sel_table[i];
- }
/*
* find divided clock from BRGA/BRGB
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index a6c1cf987e6e..df8d7b53b760 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -1426,8 +1426,75 @@ static int rsnd_hw_params(struct snd_pcm_substream *substream,
}
if (io->converted_chan)
dev_dbg(dev, "convert channels = %d\n", io->converted_chan);
- if (io->converted_rate)
+ if (io->converted_rate) {
+ /*
+ * SRC supports convert rates from params_rate(hw_params)/k_down
+ * to params_rate(hw_params)*k_up, where k_up is always 6, and
+ * k_down depends on number of channels and SRC unit.
+ * So all SRC units can upsample audio up to 6 times regardless
+ * its number of channels. And all SRC units can downsample
+ * 2 channel audio up to 6 times too.
+ */
+ int k_up = 6;
+ int k_down = 6;
+ int channel;
+ struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
+
dev_dbg(dev, "convert rate = %d\n", io->converted_rate);
+
+ channel = io->converted_chan ? io->converted_chan :
+ params_channels(hw_params);
+
+ switch (rsnd_mod_id(src_mod)) {
+ /*
+ * SRC0 can downsample 4, 6 and 8 channel audio up to 4 times.
+ * SRC1, SRC3 and SRC4 can downsample 4 channel audio
+ * up to 4 times.
+ * SRC1, SRC3 and SRC4 can downsample 6 and 8 channel audio
+ * no more than twice.
+ */
+ case 1:
+ case 3:
+ case 4:
+ if (channel > 4) {
+ k_down = 2;
+ break;
+ }
+ fallthrough;
+ case 0:
+ if (channel > 2)
+ k_down = 4;
+ break;
+
+ /* Other SRC units do not support more than 2 channels */
+ default:
+ if (channel > 2)
+ return -EINVAL;
+ }
+
+ if (params_rate(hw_params) > io->converted_rate * k_down) {
+ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min =
+ io->converted_rate * k_down;
+ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max =
+ io->converted_rate * k_down;
+ hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
+ } else if (params_rate(hw_params) * k_up < io->converted_rate) {
+ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min =
+ (io->converted_rate + k_up - 1) / k_up;
+ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max =
+ (io->converted_rate + k_up - 1) / k_up;
+ hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
+ }
+
+ /*
+ * TBD: Max SRC input and output rates also depend on number
+ * of channels and SRC unit:
+ * SRC1, SRC3 and SRC4 do not support more than 128kHz
+ * for 6 channel and 96kHz for 8 channel audio.
+ * Perhaps this function should return EINVAL if the input or
+ * the output rate exceeds the limitation.
+ */
+ }
}
ret = rsnd_dai_call(hw_params, io, substream, hw_params);
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 47d5ddb526f2..09af402ca31f 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -507,10 +507,15 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+ int ret;
if (!rsnd_ssi_is_run_mods(mod, io))
return 0;
+ ret = rsnd_ssi_master_clk_start(mod, io);
+ if (ret < 0)
+ return ret;
+
ssi->usrcnt++;
rsnd_mod_power_on(mod);
@@ -792,7 +797,6 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
SSI_SYS_STATUS(i * 2),
0xf << (id * 4));
stop = true;
- break;
}
}
break;
@@ -810,7 +814,6 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
SSI_SYS_STATUS((i * 2) + 1),
0xf << 4);
stop = true;
- break;
}
}
break;
@@ -1060,13 +1063,6 @@ static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod,
return 0;
}
-static int rsnd_ssi_prepare(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- return rsnd_ssi_master_clk_start(mod, io);
-}
-
static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
.name = SSI_NAME,
.probe = rsnd_ssi_common_probe,
@@ -1079,7 +1075,6 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
.pointer = rsnd_ssi_pio_pointer,
.pcm_new = rsnd_ssi_pcm_new,
.hw_params = rsnd_ssi_hw_params,
- .prepare = rsnd_ssi_prepare,
.get_status = rsnd_ssi_get_status,
};
@@ -1166,7 +1161,6 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
.pcm_new = rsnd_ssi_pcm_new,
.fallback = rsnd_ssi_fallback,
.hw_params = rsnd_ssi_hw_params,
- .prepare = rsnd_ssi_prepare,
.get_status = rsnd_ssi_get_status,
};
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 9e54d8ae6d2c..da6e40aef7b6 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -871,6 +871,11 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
return -EINVAL;
}
+ if (!codec_dai) {
+ dev_err(rtd->card->dev, "Missing codec\n");
+ return -EINVAL;
+ }
+
/* check client and interface hw capabilities */
if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 9df20768a8f2..093ab32ea2c3 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3178,7 +3178,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
if (!routes) {
dev_err(card->dev,
"ASoC: Could not allocate DAPM route table\n");
- return -EINVAL;
+ return -ENOMEM;
}
for (i = 0; i < num_routes; i++) {
@@ -3362,7 +3362,7 @@ int snd_soc_get_dai_name(struct of_phandle_args *args,
for_each_component(pos) {
component_of_node = soc_component_to_node(pos);
- if (component_of_node != args->np)
+ if (component_of_node != args->np || !pos->num_dai)
continue;
ret = snd_soc_component_of_xlate_dai_name(pos, args, dai_name);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 06aa39379749..56c9c4189f26 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1676,8 +1676,7 @@ static void dapm_seq_run(struct snd_soc_card *card,
switch (w->id) {
case snd_soc_dapm_pre:
if (!w->event)
- list_for_each_entry_safe_continue(w, n, list,
- power_list);
+ continue;
if (event == SND_SOC_DAPM_STREAM_START)
ret = w->event(w,
@@ -1689,8 +1688,7 @@ static void dapm_seq_run(struct snd_soc_card *card,
case snd_soc_dapm_post:
if (!w->event)
- list_for_each_entry_safe_continue(w, n, list,
- power_list);
+ continue;
if (event == SND_SOC_DAPM_STREAM_START)
ret = w->event(w,
@@ -2484,6 +2482,7 @@ void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w)
enum snd_soc_dapm_direction dir;
list_del(&w->list);
+ list_del(&w->dirty);
/*
* remove source and sink paths associated to this widget.
* While removing the path, remove reference to it from both
@@ -2541,10 +2540,16 @@ static struct snd_soc_dapm_widget *dapm_find_widget(
return NULL;
}
-static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
- const char *pin, int status)
+/*
+ * set the DAPM pin status:
+ * returns 1 when the value has been updated, 0 when unchanged, or a negative
+ * error code; called from kcontrol put callback
+ */
+static int __snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
+ const char *pin, int status)
{
struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
+ int ret = 0;
dapm_assert_locked(dapm);
@@ -2557,13 +2562,26 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
dapm_mark_dirty(w, "pin configuration");
dapm_widget_invalidate_input_paths(w);
dapm_widget_invalidate_output_paths(w);
+ ret = 1;
}
w->connected = status;
if (status == 0)
w->force = 0;
- return 0;
+ return ret;
+}
+
+/*
+ * similar as __snd_soc_dapm_set_pin(), but returns 0 when successful;
+ * called from several API functions below
+ */
+static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
+ const char *pin, int status)
+{
+ int ret = __snd_soc_dapm_set_pin(dapm, pin, status);
+
+ return ret < 0 ? ret : 0;
}
/**
@@ -3403,7 +3421,6 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
update.val = val;
card->update = &update;
}
- change |= reg_change;
ret = soc_dapm_mixer_update_power(card, kcontrol, connect,
rconnect);
@@ -3509,7 +3526,6 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
update.val = val;
card->update = &update;
}
- change |= reg_change;
ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e);
@@ -3579,14 +3595,15 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
const char *pin = (const char *)kcontrol->private_value;
+ int ret;
- if (ucontrol->value.integer.value[0])
- snd_soc_dapm_enable_pin(&card->dapm, pin);
- else
- snd_soc_dapm_disable_pin(&card->dapm, pin);
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+ ret = __snd_soc_dapm_set_pin(&card->dapm, pin,
+ !!ucontrol->value.integer.value[0]);
+ mutex_unlock(&card->dapm_mutex);
snd_soc_dapm_sync(&card->dapm);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
@@ -4028,7 +4045,7 @@ static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol,
rtd->params_select = ucontrol->value.enumerated.item[0];
- return 0;
+ return 1;
}
static void
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index 95fc24580f85..7a37312c8e0c 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -314,7 +314,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
unsigned int sign_bit = mc->sign_bit;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert;
- int err;
+ int err, ret;
bool type_2r = false;
unsigned int val2 = 0;
unsigned int val, val_mask;
@@ -322,13 +322,27 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
if (sign_bit)
mask = BIT(sign_bit + 1) - 1;
- val = ((ucontrol->value.integer.value[0] + min) & mask);
+ val = ucontrol->value.integer.value[0];
+ if (mc->platform_max && ((int)val + min) > mc->platform_max)
+ return -EINVAL;
+ if (val > max - min)
+ return -EINVAL;
+ if (val < 0)
+ return -EINVAL;
+ val = (val + min) & mask;
if (invert)
val = max - val;
val_mask = mask << shift;
val = val << shift;
if (snd_soc_volsw_is_stereo(mc)) {
- val2 = ((ucontrol->value.integer.value[1] + min) & mask);
+ val2 = ucontrol->value.integer.value[1];
+ if (mc->platform_max && ((int)val2 + min) > mc->platform_max)
+ return -EINVAL;
+ if (val2 > max - min)
+ return -EINVAL;
+ if (val2 < 0)
+ return -EINVAL;
+ val2 = (val2 + min) & mask;
if (invert)
val2 = max - val2;
if (reg == reg2) {
@@ -342,12 +356,18 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
err = snd_soc_component_update_bits(component, reg, val_mask, val);
if (err < 0)
return err;
+ ret = err;
- if (type_2r)
+ if (type_2r) {
err = snd_soc_component_update_bits(component, reg2, val_mask,
- val2);
+ val2);
+ /* Don't discard any error code or drop change flag */
+ if (ret == 0 || err < 0) {
+ ret = err;
+ }
+ }
- return err;
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
@@ -422,8 +442,15 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
int err = 0;
unsigned int val, val_mask, val2 = 0;
+ val = ucontrol->value.integer.value[0];
+ if (mc->platform_max && val > mc->platform_max)
+ return -EINVAL;
+ if (val > max - min)
+ return -EINVAL;
+ if (val < 0)
+ return -EINVAL;
val_mask = mask << shift;
- val = (ucontrol->value.integer.value[0] + min) & mask;
+ val = (val + min) & mask;
val = val << shift;
err = snd_soc_component_update_bits(component, reg, val_mask, val);
@@ -496,7 +523,15 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert;
unsigned int val, val_mask;
- int ret;
+ int err, ret, tmp;
+
+ tmp = ucontrol->value.integer.value[0];
+ if (tmp < 0)
+ return -EINVAL;
+ if (mc->platform_max && tmp > mc->platform_max)
+ return -EINVAL;
+ if (tmp > mc->max - mc->min + 1)
+ return -EINVAL;
if (invert)
val = (max - ucontrol->value.integer.value[0]) & mask;
@@ -505,11 +540,20 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
val_mask = mask << shift;
val = val << shift;
- ret = snd_soc_component_update_bits(component, reg, val_mask, val);
- if (ret < 0)
- return ret;
+ err = snd_soc_component_update_bits(component, reg, val_mask, val);
+ if (err < 0)
+ return err;
+ ret = err;
if (snd_soc_volsw_is_stereo(mc)) {
+ tmp = ucontrol->value.integer.value[1];
+ if (tmp < 0)
+ return -EINVAL;
+ if (mc->platform_max && tmp > mc->platform_max)
+ return -EINVAL;
+ if (tmp > mc->max - mc->min + 1)
+ return -EINVAL;
+
if (invert)
val = (max - ucontrol->value.integer.value[1]) & mask;
else
@@ -517,8 +561,12 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
val_mask = mask << shift;
val = val << shift;
- ret = snd_soc_component_update_bits(component, rreg, val_mask,
+ err = snd_soc_component_update_bits(component, rreg, val_mask,
val);
+ /* Don't discard any error code or drop change flag */
+ if (ret == 0 || err < 0) {
+ ret = err;
+ }
}
return ret;
@@ -889,6 +937,8 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
unsigned int i, regval, regmask;
int err;
+ if (val < mc->min || val > mc->max)
+ return -EINVAL;
if (invert)
val = max - val;
val &= mask;
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index cc4e9aa80fb0..1196167364d4 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2346,6 +2346,7 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_DRAIN:
ret = dpcm_dai_trigger_fe_be(substream, cmd, true);
break;
case SNDRV_PCM_TRIGGER_STOP:
@@ -2363,6 +2364,7 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_DRAIN:
ret = dpcm_dai_trigger_fe_be(substream, cmd, false);
break;
case SNDRV_PCM_TRIGGER_STOP:
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 0100f123484e..870b00229353 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -587,7 +587,8 @@ static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr,
if (le32_to_cpu(hdr->ops.info) == SND_SOC_TPLG_CTL_BYTES
&& k->iface & SNDRV_CTL_ELEM_IFACE_MIXER
- && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE
+ && (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ
+ || k->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
&& k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
struct soc_bytes_ext *sbe;
struct snd_soc_tplg_bytes_control *be;
@@ -982,7 +983,7 @@ static int soc_tplg_denum_create_values(struct soc_enum *se,
return -EINVAL;
se->dobj.control.dvalues = kzalloc(le32_to_cpu(ec->items) *
- sizeof(u32),
+ sizeof(*se->dobj.control.dvalues),
GFP_KERNEL);
if (!se->dobj.control.dvalues)
return -ENOMEM;
@@ -2777,6 +2778,7 @@ EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove_all);
/* remove dynamic controls from the component driver */
int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index)
{
+ struct snd_card *card = comp->card->snd_card;
struct snd_soc_dobj *dobj, *next_dobj;
int pass = SOC_TPLG_PASS_END;
@@ -2784,6 +2786,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index)
while (pass >= SOC_TPLG_PASS_START) {
/* remove mixer controls */
+ down_write(&card->controls_rwsem);
list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list,
list) {
@@ -2827,6 +2830,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index)
break;
}
}
+ up_write(&card->controls_rwsem);
pass--;
}
diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c
index 5529e8eeca46..08726034ff09 100644
--- a/sound/soc/sof/debug.c
+++ b/sound/soc/sof/debug.c
@@ -135,7 +135,7 @@ static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer,
char *string;
int ret;
- string = kzalloc(count, GFP_KERNEL);
+ string = kzalloc(count+1, GFP_KERNEL);
if (!string)
return -ENOMEM;
diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c
index 9e8233c10d86..df38616c431a 100644
--- a/sound/soc/sof/intel/hda-codec.c
+++ b/sound/soc/sof/intel/hda-codec.c
@@ -68,8 +68,7 @@ void hda_codec_jack_check(struct snd_sof_dev *sdev)
* has been recorded in STATESTS
*/
if (codec->jacktbl.used)
- schedule_delayed_work(&codec->jackpoll_work,
- codec->jackpoll_interval);
+ pm_request_resume(&codec->core.dev);
}
#else
void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev) {}
diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c
index 3f645200d3a5..b3cdd10c83ae 100644
--- a/sound/soc/sof/intel/hda-dai.c
+++ b/sound/soc/sof/intel/hda-dai.c
@@ -67,6 +67,7 @@ static struct hdac_ext_stream *
return NULL;
}
+ spin_lock_irq(&bus->reg_lock);
list_for_each_entry(stream, &bus->stream_list, list) {
struct hdac_ext_stream *hstream =
stream_to_hdac_ext_stream(stream);
@@ -106,12 +107,12 @@ static struct hdac_ext_stream *
* is updated in snd_hdac_ext_stream_decouple().
*/
if (!res->decoupled)
- snd_hdac_ext_stream_decouple(bus, res, true);
- spin_lock_irq(&bus->reg_lock);
+ snd_hdac_ext_stream_decouple_locked(bus, res, true);
+
res->link_locked = 1;
res->link_substream = substream;
- spin_unlock_irq(&bus->reg_lock);
}
+ spin_unlock_irq(&bus->reg_lock);
return res;
}
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c
index fb55a3c5afd0..06715b3d8c31 100644
--- a/sound/soc/sof/intel/hda-dsp.c
+++ b/sound/soc/sof/intel/hda-dsp.c
@@ -179,7 +179,7 @@ int hda_dsp_core_power_down(struct snd_sof_dev *sdev, unsigned int core_mask)
return snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
HDA_DSP_REG_ADSPCS, adspcs,
- !(adspcs & HDA_DSP_ADSPCS_SPA_MASK(core_mask)),
+ !(adspcs & HDA_DSP_ADSPCS_CPA_MASK(core_mask)),
HDA_DSP_REG_POLL_INTERVAL_US,
HDA_DSP_PD_TIMEOUT * USEC_PER_MSEC);
}
@@ -192,10 +192,17 @@ bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev,
val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS);
- is_enable = ((val & HDA_DSP_ADSPCS_CPA_MASK(core_mask)) &&
- (val & HDA_DSP_ADSPCS_SPA_MASK(core_mask)) &&
- !(val & HDA_DSP_ADSPCS_CRST_MASK(core_mask)) &&
- !(val & HDA_DSP_ADSPCS_CSTALL_MASK(core_mask)));
+#define MASK_IS_EQUAL(v, m, field) ({ \
+ u32 _m = field(m); \
+ ((v) & _m) == _m; \
+})
+
+ is_enable = MASK_IS_EQUAL(val, core_mask, HDA_DSP_ADSPCS_CPA_MASK) &&
+ MASK_IS_EQUAL(val, core_mask, HDA_DSP_ADSPCS_SPA_MASK) &&
+ !(val & HDA_DSP_ADSPCS_CRST_MASK(core_mask)) &&
+ !(val & HDA_DSP_ADSPCS_CSTALL_MASK(core_mask));
+
+#undef MASK_IS_EQUAL
dev_dbg(sdev->dev, "DSP core(s) enabled? %d : core_mask %x\n",
is_enable, core_mask);
diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c
index 356bb134ae93..7573f3f9f0f2 100644
--- a/sound/soc/sof/intel/hda-loader.c
+++ b/sound/soc/sof/intel/hda-loader.c
@@ -50,7 +50,7 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, &pci->dev, size, dmab);
if (ret < 0) {
dev_err(sdev->dev, "error: memory alloc failed: %x\n", ret);
- goto error;
+ goto out_put;
}
hstream->period_bytes = 0;/* initialize period_bytes */
@@ -60,16 +60,17 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
ret = hda_dsp_stream_hw_params(sdev, dsp_stream, dmab, NULL);
if (ret < 0) {
dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret);
- goto error;
+ goto out_free;
}
hda_dsp_stream_spib_config(sdev, dsp_stream, HDA_DSP_SPIB_ENABLE, size);
return hstream->stream_tag;
-error:
- hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
+out_free:
snd_dma_free_pages(dmab);
+out_put:
+ hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
return ret;
}
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 3c4b604412f0..a10166741865 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -672,6 +672,7 @@ free_streams:
/* dsp_unmap: not currently used */
iounmap(sdev->bar[HDA_DSP_BAR]);
hdac_bus_unmap:
+ platform_device_unregister(hdev->dmic_dev);
iounmap(bus->remap_addr);
err:
return ret;
diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c
index 2ed92c990b97..dd9013c47664 100644
--- a/sound/soc/sti/uniperif_player.c
+++ b/sound/soc/sti/uniperif_player.c
@@ -91,7 +91,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player);
/* Stop the player */
- snd_pcm_stop_xrun(player->substream);
+ snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
}
ret = IRQ_HANDLED;
@@ -105,7 +105,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player);
/* Stop the player */
- snd_pcm_stop_xrun(player->substream);
+ snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
ret = IRQ_HANDLED;
}
@@ -138,7 +138,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
dev_err(player->dev, "Underflow recovery failed\n");
/* Stop the player */
- snd_pcm_stop_xrun(player->substream);
+ snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
ret = IRQ_HANDLED;
}
diff --git a/sound/soc/sti/uniperif_reader.c b/sound/soc/sti/uniperif_reader.c
index 136059331211..065c5f0d1f5f 100644
--- a/sound/soc/sti/uniperif_reader.c
+++ b/sound/soc/sti/uniperif_reader.c
@@ -65,7 +65,7 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) {
dev_err(reader->dev, "FIFO error detected\n");
- snd_pcm_stop_xrun(reader->substream);
+ snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN);
ret = IRQ_HANDLED;
}
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index ee448d5e07a6..c4021d6ac9df 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -1364,6 +1364,7 @@ static struct snd_soc_card *sun4i_codec_create_card(struct device *dev)
return ERR_PTR(-ENOMEM);
card->dev = dev;
+ card->owner = THIS_MODULE;
card->name = "sun4i-codec";
card->dapm_widgets = sun4i_codec_card_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(sun4i_codec_card_dapm_widgets);
@@ -1396,6 +1397,7 @@ static struct snd_soc_card *sun6i_codec_create_card(struct device *dev)
return ERR_PTR(-ENOMEM);
card->dev = dev;
+ card->owner = THIS_MODULE;
card->name = "A31 Audio Codec";
card->dapm_widgets = sun6i_codec_card_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
@@ -1449,6 +1451,7 @@ static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev)
return ERR_PTR(-ENOMEM);
card->dev = dev;
+ card->owner = THIS_MODULE;
card->name = "A23 Audio Codec";
card->dapm_widgets = sun6i_codec_card_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
@@ -1487,6 +1490,7 @@ static struct snd_soc_card *sun8i_h3_codec_create_card(struct device *dev)
return ERR_PTR(-ENOMEM);
card->dev = dev;
+ card->owner = THIS_MODULE;
card->name = "H3 Audio Codec";
card->dapm_widgets = sun6i_codec_card_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
@@ -1525,6 +1529,7 @@ static struct snd_soc_card *sun8i_v3s_codec_create_card(struct device *dev)
return ERR_PTR(-ENOMEM);
card->dev = dev;
+ card->owner = THIS_MODULE;
card->name = "V3s Audio Codec";
card->dapm_widgets = sun6i_codec_card_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index d0a8d5810c0a..9655dec4166b 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -442,11 +442,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
switch (i2s->format & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_DSP_A:
case SND_SOC_DAIFMT_DSP_B:
- case SND_SOC_DAIFMT_LEFT_J:
- case SND_SOC_DAIFMT_RIGHT_J:
lrck_period = params_physical_width(params) * slots;
break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ case SND_SOC_DAIFMT_RIGHT_J:
case SND_SOC_DAIFMT_I2S:
lrck_period = params_physical_width(params);
break;
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index 9e8b1497efd3..a281ceb3c67e 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -139,6 +139,7 @@ static struct snd_soc_dai_link tegra_alc5632_dai = {
static struct snd_soc_card snd_soc_tegra_alc5632 = {
.name = "tegra-alc5632",
+ .driver_name = "tegra",
.owner = THIS_MODULE,
.dai_link = &tegra_alc5632_dai,
.num_links = 1,
diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c
index 4954a33ff46b..30edd70e8183 100644
--- a/sound/soc/tegra/tegra_max98090.c
+++ b/sound/soc/tegra/tegra_max98090.c
@@ -182,6 +182,7 @@ static struct snd_soc_dai_link tegra_max98090_dai = {
static struct snd_soc_card snd_soc_tegra_max98090 = {
.name = "tegra-max98090",
+ .driver_name = "tegra",
.owner = THIS_MODULE,
.dai_link = &tegra_max98090_dai,
.num_links = 1,
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c
index d46915a3ec4c..3d68a41040ed 100644
--- a/sound/soc/tegra/tegra_rt5640.c
+++ b/sound/soc/tegra/tegra_rt5640.c
@@ -132,6 +132,7 @@ static struct snd_soc_dai_link tegra_rt5640_dai = {
static struct snd_soc_card snd_soc_tegra_rt5640 = {
.name = "tegra-rt5640",
+ .driver_name = "tegra",
.owner = THIS_MODULE,
.dai_link = &tegra_rt5640_dai,
.num_links = 1,
diff --git a/sound/soc/tegra/tegra_rt5677.c b/sound/soc/tegra/tegra_rt5677.c
index 81cb6cc6236e..ae150ade9441 100644
--- a/sound/soc/tegra/tegra_rt5677.c
+++ b/sound/soc/tegra/tegra_rt5677.c
@@ -175,6 +175,7 @@ static struct snd_soc_dai_link tegra_rt5677_dai = {
static struct snd_soc_card snd_soc_tegra_rt5677 = {
.name = "tegra-rt5677",
+ .driver_name = "tegra",
.owner = THIS_MODULE,
.dai_link = &tegra_rt5677_dai,
.num_links = 1,
diff --git a/sound/soc/tegra/tegra_sgtl5000.c b/sound/soc/tegra/tegra_sgtl5000.c
index e13b81d29cf3..fe21d9eff8c0 100644
--- a/sound/soc/tegra/tegra_sgtl5000.c
+++ b/sound/soc/tegra/tegra_sgtl5000.c
@@ -97,6 +97,7 @@ static struct snd_soc_dai_link tegra_sgtl5000_dai = {
static struct snd_soc_card snd_soc_tegra_sgtl5000 = {
.name = "tegra-sgtl5000",
+ .driver_name = "tegra",
.owner = THIS_MODULE,
.dai_link = &tegra_sgtl5000_dai,
.num_links = 1,
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index f6dd790dad71..a2362a2189dc 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -101,6 +101,7 @@ static struct snd_soc_dai_link tegra_wm8753_dai = {
static struct snd_soc_card snd_soc_tegra_wm8753 = {
.name = "tegra-wm8753",
+ .driver_name = "tegra",
.owner = THIS_MODULE,
.dai_link = &tegra_wm8753_dai,
.num_links = 1,
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index 0fa01cacfec9..08bcc94dcff8 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -217,6 +217,7 @@ static struct snd_soc_dai_link tegra_wm8903_dai = {
static struct snd_soc_card snd_soc_tegra_wm8903 = {
.name = "tegra-wm8903",
+ .driver_name = "tegra",
.owner = THIS_MODULE,
.dai_link = &tegra_wm8903_dai,
.num_links = 1,
diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c
index b85bd9f89073..232eac58373a 100644
--- a/sound/soc/tegra/tegra_wm9712.c
+++ b/sound/soc/tegra/tegra_wm9712.c
@@ -54,6 +54,7 @@ static struct snd_soc_dai_link tegra_wm9712_dai = {
static struct snd_soc_card snd_soc_tegra_wm9712 = {
.name = "tegra-wm9712",
+ .driver_name = "tegra",
.owner = THIS_MODULE,
.dai_link = &tegra_wm9712_dai,
.num_links = 1,
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
index 3f67ddd13674..5086bc2446d2 100644
--- a/sound/soc/tegra/trimslice.c
+++ b/sound/soc/tegra/trimslice.c
@@ -94,6 +94,7 @@ static struct snd_soc_dai_link trimslice_tlv320aic23_dai = {
static struct snd_soc_card snd_soc_trimslice = {
.name = "tegra-trimslice",
+ .driver_name = "tegra",
.owner = THIS_MODULE,
.dai_link = &trimslice_tlv320aic23_dai,
.num_links = 1,
diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c
index d89b5c928c4d..b2b2dcdb05d4 100644
--- a/sound/soc/ti/davinci-i2s.c
+++ b/sound/soc/ti/davinci-i2s.c
@@ -708,7 +708,9 @@ static int davinci_i2s_probe(struct platform_device *pdev)
dev->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(dev->clk))
return -ENODEV;
- clk_enable(dev->clk);
+ ret = clk_enable(dev->clk);
+ if (ret)
+ goto err_put_clk;
dev->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, dev);
@@ -730,6 +732,7 @@ err_unregister_component:
snd_soc_unregister_component(&pdev->dev);
err_release_clk:
clk_disable(dev->clk);
+err_put_clk:
clk_put(dev->clk);
return ret;
}
diff --git a/sound/soc/uniphier/Kconfig b/sound/soc/uniphier/Kconfig
index aa3592ee1358..ddfa6424c656 100644
--- a/sound/soc/uniphier/Kconfig
+++ b/sound/soc/uniphier/Kconfig
@@ -23,7 +23,6 @@ config SND_SOC_UNIPHIER_LD11
tristate "UniPhier LD11/LD20 Device Driver"
depends on SND_SOC_UNIPHIER
select SND_SOC_UNIPHIER_AIO
- select SND_SOC_UNIPHIER_AIO_DMA
help
This adds ASoC driver for Socionext UniPhier LD11/LD20
input and output that can be used with other codecs.
@@ -34,7 +33,6 @@ config SND_SOC_UNIPHIER_PXS2
tristate "UniPhier PXs2 Device Driver"
depends on SND_SOC_UNIPHIER
select SND_SOC_UNIPHIER_AIO
- select SND_SOC_UNIPHIER_AIO_DMA
help
This adds ASoC driver for Socionext UniPhier PXs2
input and output that can be used with other codecs.
diff --git a/sound/soc/xilinx/xlnx_formatter_pcm.c b/sound/soc/xilinx/xlnx_formatter_pcm.c
index 48970efe7838..4caee57114b8 100644
--- a/sound/soc/xilinx/xlnx_formatter_pcm.c
+++ b/sound/soc/xilinx/xlnx_formatter_pcm.c
@@ -37,6 +37,7 @@
#define XLNX_AUD_XFER_COUNT 0x28
#define XLNX_AUD_CH_STS_START 0x2C
#define XLNX_BYTES_PER_CH 0x44
+#define XLNX_AUD_ALIGN_BYTES 64
#define AUD_STS_IOC_IRQ_MASK BIT(31)
#define AUD_STS_CH_STS_MASK BIT(29)
@@ -370,12 +371,32 @@ static int xlnx_formatter_pcm_open(struct snd_pcm_substream *substream)
snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware);
runtime->private_data = stream_data;
- /* Resize the period size divisible by 64 */
+ /* Resize the period bytes as divisible by 64 */
err = snd_pcm_hw_constraint_step(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64);
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+ XLNX_AUD_ALIGN_BYTES);
if (err) {
dev_err(component->dev,
- "unable to set constraint on period bytes\n");
+ "Unable to set constraint on period bytes\n");
+ return err;
+ }
+
+ /* Resize the buffer bytes as divisible by 64 */
+ err = snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+ XLNX_AUD_ALIGN_BYTES);
+ if (err) {
+ dev_err(component->dev,
+ "Unable to set constraint on buffer bytes\n");
+ return err;
+ }
+
+ /* Set periods as integer multiple */
+ err = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (err < 0) {
+ dev_err(component->dev,
+ "Unable to set constraint on periods to be integer\n");
return err;
}
@@ -461,8 +482,8 @@ static int xlnx_formatter_pcm_hw_params(struct snd_pcm_substream *substream,
stream_data->buffer_size = size;
- low = lower_32_bits(substream->dma_buffer.addr);
- high = upper_32_bits(substream->dma_buffer.addr);
+ low = lower_32_bits(runtime->dma_addr);
+ high = upper_32_bits(runtime->dma_addr);
writel(low, stream_data->mmio + XLNX_AUD_BUFF_ADDR_LSB);
writel(high, stream_data->mmio + XLNX_AUD_BUFF_ADDR_MSB);
diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index 4de1ba9a418d..6e5d315bab59 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -218,7 +218,9 @@ static int snd_at73c213_pcm_open(struct snd_pcm_substream *substream)
runtime->hw = snd_at73c213_playback_hw;
chip->substream = substream;
- clk_enable(chip->ssc->clk);
+ err = clk_enable(chip->ssc->clk);
+ if (err)
+ return err;
return 0;
}
@@ -784,7 +786,9 @@ static int snd_at73c213_chip_init(struct snd_at73c213 *chip)
goto out;
/* Enable DAC master clock. */
- clk_enable(chip->board->dac_clk);
+ retval = clk_enable(chip->board->dac_clk);
+ if (retval)
+ goto out;
/* Initialize at73c213 on SPI bus. */
retval = snd_at73c213_write_reg(chip, DAC_RST, 0x04);
@@ -897,7 +901,9 @@ static int snd_at73c213_dev_init(struct snd_card *card,
chip->card = card;
chip->irq = -1;
- clk_enable(chip->ssc->clk);
+ retval = clk_enable(chip->ssc->clk);
+ if (retval)
+ return retval;
retval = request_irq(irq, snd_at73c213_interrupt, 0, "at73c213", chip);
if (retval) {
@@ -1016,7 +1022,9 @@ static int snd_at73c213_remove(struct spi_device *spi)
int retval;
/* Stop playback. */
- clk_enable(chip->ssc->clk);
+ retval = clk_enable(chip->ssc->clk);
+ if (retval)
+ goto out;
ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS));
clk_disable(chip->ssc->clk);
@@ -1096,9 +1104,16 @@ static int snd_at73c213_resume(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
struct snd_at73c213 *chip = card->private_data;
+ int retval;
- clk_enable(chip->board->dac_clk);
- clk_enable(chip->ssc->clk);
+ retval = clk_enable(chip->board->dac_clk);
+ if (retval)
+ return retval;
+ retval = clk_enable(chip->ssc->clk);
+ if (retval) {
+ clk_disable(chip->board->dac_clk);
+ return retval;
+ }
ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXEN));
return 0;
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index f65e6c7b139f..6695530bba9b 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -88,7 +88,7 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch
emu->name = kstrdup(name, GFP_KERNEL);
emu->voices = kcalloc(emu->max_voices, sizeof(struct snd_emux_voice),
GFP_KERNEL);
- if (emu->voices == NULL)
+ if (emu->name == NULL || emu->voices == NULL)
return -ENOMEM;
/* create soundfont list */
diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c
index 43a2a62d66f7..49629d4bb327 100644
--- a/sound/usb/6fire/comm.c
+++ b/sound/usb/6fire/comm.c
@@ -95,7 +95,7 @@ static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev)
int actual_len;
ret = usb_interrupt_msg(dev, usb_sndintpipe(dev, COMM_EP),
- buffer, buffer[1] + 2, &actual_len, HZ);
+ buffer, buffer[1] + 2, &actual_len, 1000);
if (ret < 0)
return ret;
else if (actual_len != buffer[1] + 2)
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c
index 69137c14d0dc..2333e8ff3411 100644
--- a/sound/usb/6fire/firmware.c
+++ b/sound/usb/6fire/firmware.c
@@ -162,7 +162,7 @@ static int usb6fire_fw_ezusb_write(struct usb_device *device,
ret = usb_control_msg(device, usb_sndctrlpipe(device, 0), type,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value, 0, data, len, HZ);
+ value, 0, data, len, 1000);
if (ret < 0)
return ret;
else if (ret != len)
@@ -175,7 +175,7 @@ static int usb6fire_fw_ezusb_read(struct usb_device *device,
{
int ret = usb_control_msg(device, usb_rcvctrlpipe(device, 0), type,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value,
- 0, data, len, HZ);
+ 0, data, len, 1000);
if (ret < 0)
return ret;
else if (ret != len)
@@ -190,7 +190,7 @@ static int usb6fire_fw_fpga_write(struct usb_device *device,
int ret;
ret = usb_bulk_msg(device, usb_sndbulkpipe(device, FPGA_EP), data, len,
- &actual_len, HZ);
+ &actual_len, 1000);
if (ret < 0)
return ret;
else if (actual_len != len)
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 230d862cfa3a..c2dd18c5cadb 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -176,9 +176,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
ctrlif, interface);
return -EINVAL;
}
- usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L);
-
- return 0;
+ return usb_driver_claim_interface(&usb_audio_driver, iface,
+ USB_AUDIO_IFACE_UNUSED);
}
if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
@@ -198,7 +197,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
if (! snd_usb_parse_audio_interface(chip, interface)) {
usb_set_interface(dev, interface, 0); /* reset the current interface */
- usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L);
+ return usb_driver_claim_interface(&usb_audio_driver, iface,
+ USB_AUDIO_IFACE_UNUSED);
}
return 0;
@@ -703,7 +703,7 @@ static void usb_audio_disconnect(struct usb_interface *intf)
struct snd_card *card;
struct list_head *p;
- if (chip == (void *)-1L)
+ if (chip == USB_AUDIO_IFACE_UNUSED)
return;
card = chip->card;
@@ -811,7 +811,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
struct usb_mixer_interface *mixer;
struct list_head *p;
- if (chip == (void *)-1L)
+ if (chip == USB_AUDIO_IFACE_UNUSED)
return 0;
if (!chip->num_suspended_intf++) {
@@ -842,7 +842,7 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
struct list_head *p;
int err = 0;
- if (chip == (void *)-1L)
+ if (chip == USB_AUDIO_IFACE_UNUSED)
return 0;
atomic_inc(&chip->active); /* avoid autopm */
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index b118cf97607f..3d1c0ec11753 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -296,7 +296,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id);
if (selector) {
- int ret, i, cur;
+ int ret, i, cur, err;
/* the entity ID we are looking for is a selector.
* find out what it currently selects */
@@ -318,13 +318,23 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
ret = __uac_clock_find_source(chip, fmt,
selector->baCSourceID[ret - 1],
visited, validate);
+ if (ret > 0) {
+ /*
+ * For Samsung USBC Headset (AKG), setting clock selector again
+ * will result in incorrect default clock setting problems
+ */
+ if (chip->usb_id == USB_ID(0x04e8, 0xa051))
+ return ret;
+ err = uac_clock_selector_set_val(chip, entity_id, cur);
+ if (err < 0)
+ return err;
+ }
+
if (!validate || ret > 0 || !chip->autoclock)
return ret;
/* The current clock source is invalid, try others. */
for (i = 1; i <= selector->bNrInPins; i++) {
- int err;
-
if (i == cur)
continue;
@@ -390,7 +400,7 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip,
selector = snd_usb_find_clock_selector_v3(chip->ctrl_intf, entity_id);
if (selector) {
- int ret, i, cur;
+ int ret, i, cur, err;
/* the entity ID we are looking for is a selector.
* find out what it currently selects */
@@ -412,6 +422,12 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip,
ret = __uac3_clock_find_source(chip, fmt,
selector->baCSourceID[ret - 1],
visited, validate);
+ if (ret > 0) {
+ err = uac_clock_selector_set_val(chip, entity_id, cur);
+ if (err < 0)
+ return err;
+ }
+
if (!validate || ret > 0 || !chip->autoclock)
return ret;
@@ -531,6 +547,12 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
}
crate = data[0] | (data[1] << 8) | (data[2] << 16);
+ if (!crate) {
+ dev_info(&dev->dev, "failed to read current rate; disabling the check\n");
+ chip->sample_rate_read_error = 3; /* three strikes, see above */
+ return 0;
+ }
+
if (crate != rate) {
dev_warn(&dev->dev, "current rate %d is different from the runtime rate %d\n", crate, rate);
// runtime->rate = crate;
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 1f9ea513230a..84b66f7c627c 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -40,6 +40,8 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
case UAC_VERSION_1:
default: {
struct uac_format_type_i_discrete_descriptor *fmt = _fmt;
+ if (format >= 64)
+ return 0; /* invalid format */
sample_width = fmt->bBitResolution;
sample_bytes = fmt->bSubframeSize;
format = 1ULL << format;
@@ -193,9 +195,11 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
continue;
/* C-Media CM6501 mislabels its 96 kHz altsetting */
/* Terratec Aureon 7.1 USB C-Media 6206, too */
+ /* Ozone Z90 USB C-Media, too */
if (rate == 48000 && nr_rates == 1 &&
(chip->usb_id == USB_ID(0x0d8c, 0x0201) ||
chip->usb_id == USB_ID(0x0d8c, 0x0102) ||
+ chip->usb_id == USB_ID(0x0d8c, 0x0078) ||
chip->usb_id == USB_ID(0x0ccd, 0x00b1)) &&
fp->altsetting == 5 && fp->maxpacksize == 392)
rate = 96000;
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index 0caf53f5764c..8ca56ba600cf 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -113,12 +113,12 @@ static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,
retval = usb_interrupt_msg(line6->usbdev,
usb_sndintpipe(line6->usbdev, properties->ep_ctrl_w),
(char *)frag_buf, frag_size,
- &partial, LINE6_TIMEOUT * HZ);
+ &partial, LINE6_TIMEOUT);
} else {
retval = usb_bulk_msg(line6->usbdev,
usb_sndbulkpipe(line6->usbdev, properties->ep_ctrl_w),
(char *)frag_buf, frag_size,
- &partial, LINE6_TIMEOUT * HZ);
+ &partial, LINE6_TIMEOUT);
}
if (retval) {
@@ -350,7 +350,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data,
ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
(datalen << 8) | 0x21, address,
- NULL, 0, LINE6_TIMEOUT * HZ);
+ NULL, 0, LINE6_TIMEOUT);
if (ret < 0) {
dev_err(line6->ifcdev, "read request failed (error %d)\n", ret);
@@ -365,7 +365,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data,
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_DIR_IN,
0x0012, 0x0000, len, 1,
- LINE6_TIMEOUT * HZ);
+ LINE6_TIMEOUT);
if (ret < 0) {
dev_err(line6->ifcdev,
"receive length failed (error %d)\n", ret);
@@ -393,7 +393,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data,
ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x0013, 0x0000, data, datalen,
- LINE6_TIMEOUT * HZ);
+ LINE6_TIMEOUT);
if (ret < 0)
dev_err(line6->ifcdev, "read failed (error %d)\n", ret);
@@ -425,7 +425,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data,
ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
0x0022, address, data, datalen,
- LINE6_TIMEOUT * HZ);
+ LINE6_TIMEOUT);
if (ret < 0) {
dev_err(line6->ifcdev,
@@ -441,7 +441,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data,
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_DIR_IN,
0x0012, 0x0000,
- status, 1, LINE6_TIMEOUT * HZ);
+ status, 1, LINE6_TIMEOUT);
if (ret < 0) {
dev_err(line6->ifcdev,
@@ -690,6 +690,10 @@ static int line6_init_cap_control(struct usb_line6 *line6)
line6->buffer_message = kmalloc(LINE6_MIDI_MESSAGE_MAXLEN, GFP_KERNEL);
if (!line6->buffer_message)
return -ENOMEM;
+
+ ret = line6_init_midi(line6);
+ if (ret < 0)
+ return ret;
} else {
ret = line6_hwdep_init(line6);
if (ret < 0)
diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h
index e5e572ed5f30..890c239e3fc0 100644
--- a/sound/usb/line6/driver.h
+++ b/sound/usb/line6/driver.h
@@ -27,7 +27,7 @@
#define LINE6_FALLBACK_INTERVAL 10
#define LINE6_FALLBACK_MAXPACKETSIZE 16
-#define LINE6_TIMEOUT 1
+#define LINE6_TIMEOUT 1000
#define LINE6_BUFSIZE_LISTEN 64
#define LINE6_MIDI_MESSAGE_MAXLEN 256
diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c
index ee4c9d220fdf..b667bb8ad938 100644
--- a/sound/usb/line6/pod.c
+++ b/sound/usb/line6/pod.c
@@ -376,11 +376,6 @@ static int pod_init(struct usb_line6 *line6,
if (err < 0)
return err;
- /* initialize MIDI subsystem: */
- err = line6_init_midi(line6);
- if (err < 0)
- return err;
-
/* initialize PCM subsystem: */
err = line6_init_pcm(line6, &pod_pcm_properties);
if (err < 0)
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c
index 5d9954a2d05e..8b1610bdb8d5 100644
--- a/sound/usb/line6/podhd.c
+++ b/sound/usb/line6/podhd.c
@@ -190,7 +190,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod)
ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
0x11, 0,
- NULL, 0, LINE6_TIMEOUT * HZ);
+ NULL, 0, LINE6_TIMEOUT);
if (ret < 0) {
dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret);
goto exit;
@@ -200,7 +200,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod)
ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x11, 0x0,
- init_bytes, 3, LINE6_TIMEOUT * HZ);
+ init_bytes, 3, LINE6_TIMEOUT);
if (ret < 0) {
dev_err(pod->line6.ifcdev,
"receive length failed (error %d)\n", ret);
@@ -220,7 +220,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod)
USB_REQ_SET_FEATURE,
USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT,
1, 0,
- NULL, 0, LINE6_TIMEOUT * HZ);
+ NULL, 0, LINE6_TIMEOUT);
exit:
kfree(init_bytes);
return ret;
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
index d0a555dbe324..21f86c71dad7 100644
--- a/sound/usb/line6/toneport.c
+++ b/sound/usb/line6/toneport.c
@@ -128,7 +128,7 @@ static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
- cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ);
+ cmd1, cmd2, NULL, 0, LINE6_TIMEOUT);
if (ret < 0) {
dev_err(&usbdev->dev, "send failed (error %d)\n", ret);
diff --git a/sound/usb/line6/variax.c b/sound/usb/line6/variax.c
index ed158f04de80..c2245aa93b08 100644
--- a/sound/usb/line6/variax.c
+++ b/sound/usb/line6/variax.c
@@ -159,7 +159,6 @@ static int variax_init(struct usb_line6 *line6,
const struct usb_device_id *id)
{
struct usb_line6_variax *variax = line6_to_variax(line6);
- int err;
line6->process_message = line6_variax_process_message;
line6->disconnect = line6_variax_disconnect;
@@ -172,11 +171,6 @@ static int variax_init(struct usb_line6 *line6,
if (variax->buffer_activate == NULL)
return -ENOMEM;
- /* initialize MIDI subsystem: */
- err = line6_init_midi(&variax->line6);
- if (err < 0)
- return err;
-
/* initiate startup procedure: */
schedule_delayed_work(&line6->startup_work,
msecs_to_jiffies(VARIAX_STARTUP_DELAY1));
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index bc9068b616bb..ce501200e592 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -1210,6 +1210,7 @@ static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream)
} while (drain_urbs && timeout);
finish_wait(&ep->drain_wait, &wait);
}
+ port->active = 0;
spin_unlock_irq(&ep->buffer_lock);
}
@@ -1332,7 +1333,7 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
error:
snd_usbmidi_in_endpoint_delete(ep);
- return -ENOMEM;
+ return err;
}
/*
@@ -1889,6 +1890,12 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi,
ms_ep = find_usb_ms_endpoint_descriptor(hostep);
if (!ms_ep)
continue;
+ if (ms_ep->bLength <= sizeof(*ms_ep))
+ continue;
+ if (ms_ep->bNumEmbMIDIJack > 0x10)
+ continue;
+ if (ms_ep->bLength < sizeof(*ms_ep) + ms_ep->bNumEmbMIDIJack)
+ continue;
if (usb_endpoint_dir_out(ep)) {
if (endpoints[epidx].out_ep) {
if (++epidx >= MIDI_MAX_ENDPOINTS) {
@@ -2141,6 +2148,8 @@ static int snd_usbmidi_detect_roland(struct snd_usb_midi *umidi,
cs_desc[1] == USB_DT_CS_INTERFACE &&
cs_desc[2] == 0xf1 &&
cs_desc[3] == 0x02) {
+ if (cs_desc[4] > 0x10 || cs_desc[5] > 0x10)
+ continue;
endpoint->in_cables = (1 << cs_desc[4]) - 1;
endpoint->out_cables = (1 << cs_desc[5]) - 1;
return snd_usbmidi_detect_endpoints(umidi, endpoint, 1);
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c
index 307b72d5fffa..77304a29a61d 100644
--- a/sound/usb/misc/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -1020,7 +1020,7 @@ static int detect_usb_format(struct ua101 *ua)
fmt_playback->bSubframeSize * ua->playback.channels;
epd = &ua->intf[INTF_CAPTURE]->altsetting[1].endpoint[0].desc;
- if (!usb_endpoint_is_isoc_in(epd)) {
+ if (!usb_endpoint_is_isoc_in(epd) || usb_endpoint_maxp(epd) == 0) {
dev_err(&ua->dev->dev, "invalid capture endpoint\n");
return -ENXIO;
}
@@ -1028,7 +1028,7 @@ static int detect_usb_format(struct ua101 *ua)
ua->capture.max_packet_bytes = usb_endpoint_maxp(epd);
epd = &ua->intf[INTF_PLAYBACK]->altsetting[1].endpoint[0].desc;
- if (!usb_endpoint_is_isoc_out(epd)) {
+ if (!usb_endpoint_is_isoc_out(epd) || usb_endpoint_maxp(epd) == 0) {
dev_err(&ua->dev->dev, "invalid playback endpoint\n");
return -ENXIO;
}
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 8aa96ed0b1b5..67eb1293fa15 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1030,7 +1030,7 @@ struct usb_feature_control_info {
int type_uac2; /* data type for uac2 if different from uac1, else -1 */
};
-static struct usb_feature_control_info audio_feature_info[] = {
+static const struct usb_feature_control_info audio_feature_info[] = {
{ UAC_FU_MUTE, "Mute", USB_MIXER_INV_BOOLEAN, -1 },
{ UAC_FU_VOLUME, "Volume", USB_MIXER_S16, -1 },
{ UAC_FU_BASS, "Tone Control - Bass", USB_MIXER_S8, -1 },
@@ -1544,7 +1544,7 @@ static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
strlcpy(kctl->id.name, "Headphone", sizeof(kctl->id.name));
}
-static struct usb_feature_control_info *get_feature_control_info(int control)
+static const struct usb_feature_control_info *get_feature_control_info(int control)
{
int i;
@@ -1562,7 +1562,7 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer,
struct usb_audio_term *oterm,
int unitid, int nameid, int readonly_mask)
{
- struct usb_feature_control_info *ctl_info;
+ const struct usb_feature_control_info *ctl_info;
unsigned int len = 0;
int mapped_name = 0;
struct snd_kcontrol *kctl;
@@ -2237,7 +2237,7 @@ static const struct snd_kcontrol_new mixer_procunit_ctl = {
*/
struct procunit_value_info {
int control;
- char *suffix;
+ const char *suffix;
int val_type;
int min_value;
};
@@ -2245,44 +2245,44 @@ struct procunit_value_info {
struct procunit_info {
int type;
char *name;
- struct procunit_value_info *values;
+ const struct procunit_value_info *values;
};
-static struct procunit_value_info undefined_proc_info[] = {
+static const struct procunit_value_info undefined_proc_info[] = {
{ 0x00, "Control Undefined", 0 },
{ 0 }
};
-static struct procunit_value_info updown_proc_info[] = {
+static const struct procunit_value_info updown_proc_info[] = {
{ UAC_UD_ENABLE, "Switch", USB_MIXER_BOOLEAN },
{ UAC_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
{ 0 }
};
-static struct procunit_value_info prologic_proc_info[] = {
+static const struct procunit_value_info prologic_proc_info[] = {
{ UAC_DP_ENABLE, "Switch", USB_MIXER_BOOLEAN },
{ UAC_DP_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
{ 0 }
};
-static struct procunit_value_info threed_enh_proc_info[] = {
+static const struct procunit_value_info threed_enh_proc_info[] = {
{ UAC_3D_ENABLE, "Switch", USB_MIXER_BOOLEAN },
{ UAC_3D_SPACE, "Spaciousness", USB_MIXER_U8 },
{ 0 }
};
-static struct procunit_value_info reverb_proc_info[] = {
+static const struct procunit_value_info reverb_proc_info[] = {
{ UAC_REVERB_ENABLE, "Switch", USB_MIXER_BOOLEAN },
{ UAC_REVERB_LEVEL, "Level", USB_MIXER_U8 },
{ UAC_REVERB_TIME, "Time", USB_MIXER_U16 },
{ UAC_REVERB_FEEDBACK, "Feedback", USB_MIXER_U8 },
{ 0 }
};
-static struct procunit_value_info chorus_proc_info[] = {
+static const struct procunit_value_info chorus_proc_info[] = {
{ UAC_CHORUS_ENABLE, "Switch", USB_MIXER_BOOLEAN },
{ UAC_CHORUS_LEVEL, "Level", USB_MIXER_U8 },
{ UAC_CHORUS_RATE, "Rate", USB_MIXER_U16 },
{ UAC_CHORUS_DEPTH, "Depth", USB_MIXER_U16 },
{ 0 }
};
-static struct procunit_value_info dcr_proc_info[] = {
+static const struct procunit_value_info dcr_proc_info[] = {
{ UAC_DCR_ENABLE, "Switch", USB_MIXER_BOOLEAN },
{ UAC_DCR_RATE, "Ratio", USB_MIXER_U16 },
{ UAC_DCR_MAXAMPL, "Max Amp", USB_MIXER_S16 },
@@ -2292,7 +2292,7 @@ static struct procunit_value_info dcr_proc_info[] = {
{ 0 }
};
-static struct procunit_info procunits[] = {
+static const struct procunit_info procunits[] = {
{ UAC_PROCESS_UP_DOWNMIX, "Up Down", updown_proc_info },
{ UAC_PROCESS_DOLBY_PROLOGIC, "Dolby Prologic", prologic_proc_info },
{ UAC_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", threed_enh_proc_info },
@@ -2302,16 +2302,16 @@ static struct procunit_info procunits[] = {
{ 0 },
};
-static struct procunit_value_info uac3_updown_proc_info[] = {
+static const struct procunit_value_info uac3_updown_proc_info[] = {
{ UAC3_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
{ 0 }
};
-static struct procunit_value_info uac3_stereo_ext_proc_info[] = {
+static const struct procunit_value_info uac3_stereo_ext_proc_info[] = {
{ UAC3_EXT_WIDTH_CONTROL, "Width Control", USB_MIXER_U8 },
{ 0 }
};
-static struct procunit_info uac3_procunits[] = {
+static const struct procunit_info uac3_procunits[] = {
{ UAC3_PROCESS_UP_DOWNMIX, "Up Down", uac3_updown_proc_info },
{ UAC3_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", uac3_stereo_ext_proc_info },
{ UAC3_PROCESS_MULTI_FUNCTION, "Multi-Function", undefined_proc_info },
@@ -2321,23 +2321,23 @@ static struct procunit_info uac3_procunits[] = {
/*
* predefined data for extension units
*/
-static struct procunit_value_info clock_rate_xu_info[] = {
+static const struct procunit_value_info clock_rate_xu_info[] = {
{ USB_XU_CLOCK_RATE_SELECTOR, "Selector", USB_MIXER_U8, 0 },
{ 0 }
};
-static struct procunit_value_info clock_source_xu_info[] = {
+static const struct procunit_value_info clock_source_xu_info[] = {
{ USB_XU_CLOCK_SOURCE_SELECTOR, "External", USB_MIXER_BOOLEAN },
{ 0 }
};
-static struct procunit_value_info spdif_format_xu_info[] = {
+static const struct procunit_value_info spdif_format_xu_info[] = {
{ USB_XU_DIGITAL_FORMAT_SELECTOR, "SPDIF/AC3", USB_MIXER_BOOLEAN },
{ 0 }
};
-static struct procunit_value_info soft_limit_xu_info[] = {
+static const struct procunit_value_info soft_limit_xu_info[] = {
{ USB_XU_SOFT_LIMIT_SELECTOR, " ", USB_MIXER_BOOLEAN },
{ 0 }
};
-static struct procunit_info extunits[] = {
+static const struct procunit_info extunits[] = {
{ USB_XU_CLOCK_RATE, "Clock rate", clock_rate_xu_info },
{ USB_XU_CLOCK_SOURCE, "DigitalIn CLK source", clock_source_xu_info },
{ USB_XU_DIGITAL_IO_STATUS, "DigitalOut format:", spdif_format_xu_info },
@@ -2349,7 +2349,7 @@ static struct procunit_info extunits[] = {
* build a processing/extension unit
*/
static int build_audio_procunit(struct mixer_build *state, int unitid,
- void *raw_desc, struct procunit_info *list,
+ void *raw_desc, const struct procunit_info *list,
bool extension_unit)
{
struct uac_processing_unit_descriptor *desc = raw_desc;
@@ -2357,14 +2357,14 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
struct usb_mixer_elem_info *cval;
struct snd_kcontrol *kctl;
int i, err, nameid, type, len;
- struct procunit_info *info;
- struct procunit_value_info *valinfo;
+ const struct procunit_info *info;
+ const struct procunit_value_info *valinfo;
const struct usbmix_name_map *map;
- static struct procunit_value_info default_value_info[] = {
+ static const struct procunit_value_info default_value_info[] = {
{ 0x01, "Switch", USB_MIXER_BOOLEAN },
{ 0 }
};
- static struct procunit_info default_info = {
+ static const struct procunit_info default_info = {
0, NULL, default_value_info
};
const char *name = extension_unit ?
@@ -2842,7 +2842,7 @@ struct uac3_badd_profile {
int st_chmask; /* side tone mixing channel mask */
};
-static struct uac3_badd_profile uac3_badd_profiles[] = {
+static const struct uac3_badd_profile uac3_badd_profiles[] = {
{
/*
* BAIF, BAOF or combination of both
@@ -2903,7 +2903,7 @@ static struct uac3_badd_profile uac3_badd_profiles[] = {
};
static bool uac3_badd_func_has_valid_channels(struct usb_mixer_interface *mixer,
- struct uac3_badd_profile *f,
+ const struct uac3_badd_profile *f,
int c_chmask, int p_chmask)
{
/*
@@ -2947,7 +2947,7 @@ static int snd_usb_mixer_controls_badd(struct usb_mixer_interface *mixer,
struct usb_device *dev = mixer->chip->dev;
struct usb_interface_assoc_descriptor *assoc;
int badd_profile = mixer->chip->badd_profile;
- struct uac3_badd_profile *f;
+ const struct uac3_badd_profile *f;
const struct usbmix_ctl_map *map;
int p_chmask = 0, c_chmask = 0, st_chmask = 0;
int i;
@@ -3241,8 +3241,17 @@ static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer,
struct usb_mixer_elem_list *list)
{
struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
- static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN",
- "S8", "U8", "S16", "U16"};
+ static const char * const val_types[] = {
+ [USB_MIXER_BOOLEAN] = "BOOLEAN",
+ [USB_MIXER_INV_BOOLEAN] = "INV_BOOLEAN",
+ [USB_MIXER_S8] = "S8",
+ [USB_MIXER_U8] = "U8",
+ [USB_MIXER_S16] = "S16",
+ [USB_MIXER_U16] = "U16",
+ [USB_MIXER_S32] = "S32",
+ [USB_MIXER_U32] = "U32",
+ [USB_MIXER_BESPOKEN] = "BESPOKEN",
+ };
snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, "
"channels=%i, type=\"%s\"\n", cval->head.id,
cval->control, cval->cmask, cval->channels,
@@ -3598,6 +3607,9 @@ static int restore_mixer_value(struct usb_mixer_elem_list *list)
struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
int c, err, idx;
+ if (cval->val_type == USB_MIXER_BESPOKEN)
+ return 0;
+
if (cval->cmask) {
idx = 0;
for (c = 0; c < MAX_CHANNELS; c++) {
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index 01b5e5cc2221..0e813cd85bee 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -55,6 +55,7 @@ enum {
USB_MIXER_U16,
USB_MIXER_S32,
USB_MIXER_U32,
+ USB_MIXER_BESPOKEN, /* non-standard type */
};
typedef void (*usb_mixer_elem_dump_func_t)(struct snd_info_buffer *buffer,
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index ac84f0b2b0bc..dda13624a28c 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -14,7 +14,7 @@ struct usbmix_name_map {
int id;
const char *name;
int control;
- struct usbmix_dB_map *dB;
+ const struct usbmix_dB_map *dB;
};
struct usbmix_selector_map {
@@ -53,7 +53,7 @@ Mic-IN[9] --+->FU[10]----------------------------+ |
++--+->SU[11]-->FU[12] --------------------------------------------------------------------------------------> USB_OUT[13]
*/
-static struct usbmix_name_map extigy_map[] = {
+static const struct usbmix_name_map extigy_map[] = {
/* 1: IT pcm */
{ 2, "PCM Playback" }, /* FU */
/* 3: IT pcm */
@@ -94,12 +94,12 @@ static struct usbmix_name_map extigy_map[] = {
* e.g. no Master and fake PCM volume
* Pavel Mihaylov <bin@bash.info>
*/
-static struct usbmix_dB_map mp3plus_dB_1 = {.min = -4781, .max = 0};
+static const struct usbmix_dB_map mp3plus_dB_1 = {.min = -4781, .max = 0};
/* just guess */
-static struct usbmix_dB_map mp3plus_dB_2 = {.min = -1781, .max = 618};
+static const struct usbmix_dB_map mp3plus_dB_2 = {.min = -1781, .max = 618};
/* just guess */
-static struct usbmix_name_map mp3plus_map[] = {
+static const struct usbmix_name_map mp3plus_map[] = {
/* 1: IT pcm */
/* 2: IT mic */
/* 3: IT line */
@@ -140,7 +140,7 @@ Lin_IN[7]-+--->FU[8]---+ +->EU[23]->FU[28]------------->Spk_OUT[19]
| ^
+->FU[13]--------------------------------------+
*/
-static struct usbmix_name_map audigy2nx_map[] = {
+static const struct usbmix_name_map audigy2nx_map[] = {
/* 1: IT pcm playback */
/* 4: IT digital in */
{ 6, "Digital In Playback" }, /* FU */
@@ -168,12 +168,12 @@ static struct usbmix_name_map audigy2nx_map[] = {
{ 0 } /* terminator */
};
-static struct usbmix_name_map mbox1_map[] = {
+static const struct usbmix_name_map mbox1_map[] = {
{ 1, "Clock" },
{ 0 } /* terminator */
};
-static struct usbmix_selector_map c400_selectors[] = {
+static const struct usbmix_selector_map c400_selectors[] = {
{
.id = 0x80,
.count = 2,
@@ -182,7 +182,7 @@ static struct usbmix_selector_map c400_selectors[] = {
{ 0 } /* terminator */
};
-static struct usbmix_selector_map audigy2nx_selectors[] = {
+static const struct usbmix_selector_map audigy2nx_selectors[] = {
{
.id = 14, /* Capture Source */
.count = 3,
@@ -202,21 +202,21 @@ static struct usbmix_selector_map audigy2nx_selectors[] = {
};
/* Creative SoundBlaster Live! 24-bit External */
-static struct usbmix_name_map live24ext_map[] = {
+static const struct usbmix_name_map live24ext_map[] = {
/* 2: PCM Playback Volume */
{ 5, "Mic Capture" }, /* FU, default PCM Capture Volume */
{ 0 } /* terminator */
};
/* LineX FM Transmitter entry - needed to bypass controls bug */
-static struct usbmix_name_map linex_map[] = {
+static const struct usbmix_name_map linex_map[] = {
/* 1: IT pcm */
/* 2: OT Speaker */
{ 3, "Master" }, /* FU: master volume - left / right / mute */
{ 0 } /* terminator */
};
-static struct usbmix_name_map maya44_map[] = {
+static const struct usbmix_name_map maya44_map[] = {
/* 1: IT line */
{ 2, "Line Playback" }, /* FU */
/* 3: IT line */
@@ -239,7 +239,7 @@ static struct usbmix_name_map maya44_map[] = {
* so this map removes all unwanted sliders from alsamixer
*/
-static struct usbmix_name_map justlink_map[] = {
+static const struct usbmix_name_map justlink_map[] = {
/* 1: IT pcm playback */
/* 2: Not present */
{ 3, NULL}, /* IT mic (No mic input on device) */
@@ -256,7 +256,7 @@ static struct usbmix_name_map justlink_map[] = {
};
/* TerraTec Aureon 5.1 MkII USB */
-static struct usbmix_name_map aureon_51_2_map[] = {
+static const struct usbmix_name_map aureon_51_2_map[] = {
/* 1: IT USB */
/* 2: IT Mic */
/* 3: IT Line */
@@ -275,7 +275,7 @@ static struct usbmix_name_map aureon_51_2_map[] = {
{} /* terminator */
};
-static struct usbmix_name_map scratch_live_map[] = {
+static const struct usbmix_name_map scratch_live_map[] = {
/* 1: IT Line 1 (USB streaming) */
/* 2: OT Line 1 (Speaker) */
/* 3: IT Line 1 (Line connector) */
@@ -291,7 +291,7 @@ static struct usbmix_name_map scratch_live_map[] = {
{ 0 } /* terminator */
};
-static struct usbmix_name_map ebox44_map[] = {
+static const struct usbmix_name_map ebox44_map[] = {
{ 4, NULL }, /* FU */
{ 6, NULL }, /* MU */
{ 7, NULL }, /* FU */
@@ -306,7 +306,7 @@ static struct usbmix_name_map ebox44_map[] = {
* FIXME: or mp3plus_map should use "Capture Source" too,
* so this maps can be merget
*/
-static struct usbmix_name_map hercules_usb51_map[] = {
+static const struct usbmix_name_map hercules_usb51_map[] = {
{ 8, "Capture Source" }, /* SU, default "PCM Capture Source" */
{ 9, "Master Playback" }, /* FU, default "Speaker Playback" */
{ 10, "Mic Boost", 7 }, /* FU, default "Auto Gain Input" */
@@ -317,7 +317,7 @@ static struct usbmix_name_map hercules_usb51_map[] = {
};
/* Plantronics Gamecom 780 has a broken volume control, better to disable it */
-static struct usbmix_name_map gamecom780_map[] = {
+static const struct usbmix_name_map gamecom780_map[] = {
{ 9, NULL }, /* FU, speaker out */
{}
};
@@ -331,12 +331,19 @@ static const struct usbmix_name_map scms_usb3318_map[] = {
};
/* Bose companion 5, the dB conversion factor is 16 instead of 256 */
-static struct usbmix_dB_map bose_companion5_dB = {-5006, -6};
-static struct usbmix_name_map bose_companion5_map[] = {
+static const struct usbmix_dB_map bose_companion5_dB = {-5006, -6};
+static const struct usbmix_name_map bose_companion5_map[] = {
{ 3, NULL, .dB = &bose_companion5_dB },
{ 0 } /* terminator */
};
+/* Sennheiser Communications Headset [PC 8], the dB value is reported as -6 negative maximum */
+static const struct usbmix_dB_map sennheiser_pc8_dB = {-9500, 0};
+static const struct usbmix_name_map sennheiser_pc8_map[] = {
+ { 9, NULL, .dB = &sennheiser_pc8_dB },
+ { 0 } /* terminator */
+};
+
/*
* Dell usb dock with ALC4020 codec had a firmware problem where it got
* screwed up when zero volume is passed; just skip it as a workaround
@@ -406,7 +413,7 @@ static const struct usbmix_name_map aorus_master_alc1220vb_map[] = {
* Control map entries
*/
-static struct usbmix_ctl_map usbmix_ctl_maps[] = {
+static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
{
.id = USB_ID(0x041e, 0x3000),
.map = extigy_map,
@@ -560,37 +567,37 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
* Control map entries for UAC3 BADD profiles
*/
-static struct usbmix_name_map uac3_badd_generic_io_map[] = {
+static const struct usbmix_name_map uac3_badd_generic_io_map[] = {
{ UAC3_BADD_FU_ID2, "Generic Out Playback" },
{ UAC3_BADD_FU_ID5, "Generic In Capture" },
{ 0 } /* terminator */
};
-static struct usbmix_name_map uac3_badd_headphone_map[] = {
+static const struct usbmix_name_map uac3_badd_headphone_map[] = {
{ UAC3_BADD_FU_ID2, "Headphone Playback" },
{ 0 } /* terminator */
};
-static struct usbmix_name_map uac3_badd_speaker_map[] = {
+static const struct usbmix_name_map uac3_badd_speaker_map[] = {
{ UAC3_BADD_FU_ID2, "Speaker Playback" },
{ 0 } /* terminator */
};
-static struct usbmix_name_map uac3_badd_microphone_map[] = {
+static const struct usbmix_name_map uac3_badd_microphone_map[] = {
{ UAC3_BADD_FU_ID5, "Mic Capture" },
{ 0 } /* terminator */
};
/* Covers also 'headset adapter' profile */
-static struct usbmix_name_map uac3_badd_headset_map[] = {
+static const struct usbmix_name_map uac3_badd_headset_map[] = {
{ UAC3_BADD_FU_ID2, "Headset Playback" },
{ UAC3_BADD_FU_ID5, "Headset Capture" },
{ UAC3_BADD_FU_ID7, "Sidetone Mixing" },
{ 0 } /* terminator */
};
-static struct usbmix_name_map uac3_badd_speakerphone_map[] = {
+static const struct usbmix_name_map uac3_badd_speakerphone_map[] = {
{ UAC3_BADD_FU_ID2, "Speaker Playback" },
{ UAC3_BADD_FU_ID5, "Mic Capture" },
{ 0 } /* terminator */
};
-static struct usbmix_ctl_map uac3_badd_usbmix_ctl_maps[] = {
+static const struct usbmix_ctl_map uac3_badd_usbmix_ctl_maps[] = {
{
.id = UAC3_FUNCTION_SUBCLASS_GENERIC_IO,
.map = uac3_badd_generic_io_map,
@@ -619,5 +626,10 @@ static struct usbmix_ctl_map uac3_badd_usbmix_ctl_maps[] = {
.id = UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE,
.map = uac3_badd_speakerphone_map,
},
+ {
+ /* Sennheiser Communications Headset [PC 8] */
+ .id = USB_ID(0x1395, 0x0025),
+ .map = sennheiser_pc8_map,
+ },
{ 0 } /* terminator */
};
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 49f0dc0e3e4d..1f7c80541d03 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -119,7 +119,7 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
* Create a set of standard UAC controls from a table
*/
static int snd_create_std_mono_table(struct usb_mixer_interface *mixer,
- struct std_mono_table *t)
+ const struct std_mono_table *t)
{
int err;
@@ -1388,7 +1388,7 @@ static int snd_c400_create_mixer(struct usb_mixer_interface *mixer)
* are valid they presents mono controls as L and R channels of
* stereo. So we provide a good mixer here.
*/
-static struct std_mono_table ebox44_table[] = {
+static const struct std_mono_table ebox44_table[] = {
{
.unitid = 4,
.control = 1,
@@ -1697,7 +1697,7 @@ static struct snd_kcontrol_new snd_microii_mixer_spdif[] = {
static int snd_microii_controls_create(struct usb_mixer_interface *mixer)
{
int err, i;
- static usb_mixer_elem_resume_func_t resume_funcs[] = {
+ static const usb_mixer_elem_resume_func_t resume_funcs[] = {
snd_microii_spdif_default_update,
NULL,
snd_microii_spdif_switch_update
@@ -2268,7 +2268,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
case USB_ID(0x1235, 0x8203): /* Focusrite Scarlett 6i6 2nd Gen */
case USB_ID(0x1235, 0x8204): /* Focusrite Scarlett 18i8 2nd Gen */
case USB_ID(0x1235, 0x8201): /* Focusrite Scarlett 18i20 2nd Gen */
- err = snd_scarlett_gen2_controls_create(mixer);
+ err = snd_scarlett_gen2_init(mixer);
break;
case USB_ID(0x041e, 0x323b): /* Creative Sound Blaster E1 */
@@ -2370,9 +2370,10 @@ void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
if (unitid == 7 && cval->control == UAC_FU_VOLUME)
snd_dragonfly_quirk_db_scale(mixer, cval, kctl);
break;
- /* lowest playback value is muted on C-Media devices */
- case USB_ID(0x0d8c, 0x000c):
- case USB_ID(0x0d8c, 0x0014):
+ /* lowest playback value is muted on some devices */
+ case USB_ID(0x0d8c, 0x000c): /* C-Media */
+ case USB_ID(0x0d8c, 0x0014): /* C-Media */
+ case USB_ID(0x19f7, 0x0003): /* RODE NT-USB */
if (strstr(kctl->id.name, "Playback"))
cval->min_mute = 1;
break;
diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c
index 83715fd8dfd6..6217424e973f 100644
--- a/sound/usb/mixer_scarlett.c
+++ b/sound/usb/mixer_scarlett.c
@@ -623,7 +623,7 @@ static int add_output_ctls(struct usb_mixer_interface *mixer,
/********************** device-specific config *************************/
/* untested... */
-static struct scarlett_device_info s6i6_info = {
+static const struct scarlett_device_info s6i6_info = {
.matrix_in = 18,
.matrix_out = 8,
.input_len = 6,
@@ -665,7 +665,7 @@ static struct scarlett_device_info s6i6_info = {
};
/* untested... */
-static struct scarlett_device_info s8i6_info = {
+static const struct scarlett_device_info s8i6_info = {
.matrix_in = 18,
.matrix_out = 6,
.input_len = 8,
@@ -704,7 +704,7 @@ static struct scarlett_device_info s8i6_info = {
}
};
-static struct scarlett_device_info s18i6_info = {
+static const struct scarlett_device_info s18i6_info = {
.matrix_in = 18,
.matrix_out = 6,
.input_len = 18,
@@ -741,7 +741,7 @@ static struct scarlett_device_info s18i6_info = {
}
};
-static struct scarlett_device_info s18i8_info = {
+static const struct scarlett_device_info s18i8_info = {
.matrix_in = 18,
.matrix_out = 8,
.input_len = 18,
@@ -783,7 +783,7 @@ static struct scarlett_device_info s18i8_info = {
}
};
-static struct scarlett_device_info s18i20_info = {
+static const struct scarlett_device_info s18i20_info = {
.matrix_in = 18,
.matrix_out = 8,
.input_len = 18,
@@ -833,7 +833,7 @@ static struct scarlett_device_info s18i20_info = {
static int scarlett_controls_create_generic(struct usb_mixer_interface *mixer,
- struct scarlett_device_info *info)
+ const struct scarlett_device_info *info)
{
int i, err;
char mx[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
@@ -896,7 +896,7 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer)
{
int err, i, o;
char mx[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- struct scarlett_device_info *info;
+ const struct scarlett_device_info *info;
struct usb_mixer_elem_info *elem;
static char sample_rate_buffer[4] = { '\x80', '\xbb', '\x00', '\x00' };
diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
index 74c00c905d24..ab7abe360fcf 100644
--- a/sound/usb/mixer_scarlett_gen2.c
+++ b/sound/usb/mixer_scarlett_gen2.c
@@ -254,10 +254,10 @@ static const struct scarlett2_device_info s6i6_gen2_info = {
.pad_input_count = 2,
.line_out_descrs = {
- "Monitor L",
- "Monitor R",
- "Headphones L",
- "Headphones R",
+ "Headphones 1 L",
+ "Headphones 1 R",
+ "Headphones 2 L",
+ "Headphones 2 R",
},
.ports = {
@@ -356,7 +356,7 @@ static const struct scarlett2_device_info s18i8_gen2_info = {
},
[SCARLETT2_PORT_TYPE_PCM] = {
.id = 0x600,
- .num = { 20, 18, 18, 14, 10 },
+ .num = { 8, 18, 18, 14, 10 },
.src_descr = "PCM %d",
.src_num_offset = 1,
.dst_descr = "PCM %02d Capture"
@@ -635,7 +635,7 @@ static int scarlett2_usb(
/* send a second message to get the response */
err = snd_usb_ctl_msg(mixer->chip->dev,
- usb_sndctrlpipe(mixer->chip->dev, 0),
+ usb_rcvctrlpipe(mixer->chip->dev, 0),
SCARLETT2_USB_VENDOR_SPECIFIC_CMD_RESP,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
0,
@@ -949,10 +949,15 @@ static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer,
if (!elem)
return -ENOMEM;
+ /* We set USB_MIXER_BESPOKEN type, so that the core USB mixer code
+ * ignores them for resume and other operations.
+ * Also, the head.id field is set to 0, as we don't use this field.
+ */
elem->head.mixer = mixer;
elem->control = index;
- elem->head.id = index;
+ elem->head.id = 0;
elem->channels = channels;
+ elem->val_type = USB_MIXER_BESPOKEN;
kctl = snd_ctl_new1(ncontrol, elem);
if (!kctl) {
@@ -1028,11 +1033,10 @@ static int scarlett2_master_volume_ctl_get(struct snd_kcontrol *kctl,
struct usb_mixer_interface *mixer = elem->head.mixer;
struct scarlett2_mixer_data *private = mixer->private_data;
- if (private->vol_updated) {
- mutex_lock(&private->data_mutex);
+ mutex_lock(&private->data_mutex);
+ if (private->vol_updated)
scarlett2_update_volumes(mixer);
- mutex_unlock(&private->data_mutex);
- }
+ mutex_unlock(&private->data_mutex);
ucontrol->value.integer.value[0] = private->master_vol;
return 0;
@@ -1046,11 +1050,10 @@ static int scarlett2_volume_ctl_get(struct snd_kcontrol *kctl,
struct scarlett2_mixer_data *private = mixer->private_data;
int index = elem->control;
- if (private->vol_updated) {
- mutex_lock(&private->data_mutex);
+ mutex_lock(&private->data_mutex);
+ if (private->vol_updated)
scarlett2_update_volumes(mixer);
- mutex_unlock(&private->data_mutex);
- }
+ mutex_unlock(&private->data_mutex);
ucontrol->value.integer.value[0] = private->vol[index];
return 0;
@@ -1181,6 +1184,8 @@ static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl,
/* Send SW/HW switch change to the device */
err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SW_HW_SWITCH,
index, val);
+ if (err == 0)
+ err = 1;
unlock:
mutex_unlock(&private->data_mutex);
@@ -1241,6 +1246,8 @@ static int scarlett2_level_enum_ctl_put(struct snd_kcontrol *kctl,
/* Send switch change to the device */
err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_LEVEL_SWITCH,
index, val);
+ if (err == 0)
+ err = 1;
unlock:
mutex_unlock(&private->data_mutex);
@@ -1291,6 +1298,8 @@ static int scarlett2_pad_ctl_put(struct snd_kcontrol *kctl,
/* Send switch change to the device */
err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_PAD_SWITCH,
index, val);
+ if (err == 0)
+ err = 1;
unlock:
mutex_unlock(&private->data_mutex);
@@ -1314,11 +1323,10 @@ static int scarlett2_button_ctl_get(struct snd_kcontrol *kctl,
struct usb_mixer_interface *mixer = elem->head.mixer;
struct scarlett2_mixer_data *private = mixer->private_data;
- if (private->vol_updated) {
- mutex_lock(&private->data_mutex);
+ mutex_lock(&private->data_mutex);
+ if (private->vol_updated)
scarlett2_update_volumes(mixer);
- mutex_unlock(&private->data_mutex);
- }
+ mutex_unlock(&private->data_mutex);
ucontrol->value.enumerated.item[0] = private->buttons[elem->control];
return 0;
@@ -1347,6 +1355,8 @@ static int scarlett2_button_ctl_put(struct snd_kcontrol *kctl,
/* Send switch change to the device */
err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_BUTTONS,
index, val);
+ if (err == 0)
+ err = 1;
unlock:
mutex_unlock(&private->data_mutex);
@@ -1997,38 +2007,11 @@ static int scarlett2_mixer_status_create(struct usb_mixer_interface *mixer)
return usb_submit_urb(mixer->urb, GFP_KERNEL);
}
-/* Entry point */
-int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer)
+static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer,
+ const struct scarlett2_device_info *info)
{
- const struct scarlett2_device_info *info;
int err;
- /* only use UAC_VERSION_2 */
- if (!mixer->protocol)
- return 0;
-
- switch (mixer->chip->usb_id) {
- case USB_ID(0x1235, 0x8203):
- info = &s6i6_gen2_info;
- break;
- case USB_ID(0x1235, 0x8204):
- info = &s18i8_gen2_info;
- break;
- case USB_ID(0x1235, 0x8201):
- info = &s18i20_gen2_info;
- break;
- default: /* device not (yet) supported */
- return -EINVAL;
- }
-
- if (!(mixer->chip->setup & SCARLETT2_ENABLE)) {
- usb_audio_err(mixer->chip,
- "Focusrite Scarlett Gen 2 Mixer Driver disabled; "
- "use options snd_usb_audio device_setup=1 "
- "to enable and report any issues to g@b4.vu");
- return 0;
- }
-
/* Initialise private data, routing, sequence number */
err = scarlett2_init_private(mixer, info);
if (err < 0)
@@ -2073,3 +2056,51 @@ int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer)
return 0;
}
+
+int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer)
+{
+ struct snd_usb_audio *chip = mixer->chip;
+ const struct scarlett2_device_info *info;
+ int err;
+
+ /* only use UAC_VERSION_2 */
+ if (!mixer->protocol)
+ return 0;
+
+ switch (chip->usb_id) {
+ case USB_ID(0x1235, 0x8203):
+ info = &s6i6_gen2_info;
+ break;
+ case USB_ID(0x1235, 0x8204):
+ info = &s18i8_gen2_info;
+ break;
+ case USB_ID(0x1235, 0x8201):
+ info = &s18i20_gen2_info;
+ break;
+ default: /* device not (yet) supported */
+ return -EINVAL;
+ }
+
+ if (!(chip->setup & SCARLETT2_ENABLE)) {
+ usb_audio_info(chip,
+ "Focusrite Scarlett Gen 2 Mixer Driver disabled; "
+ "use options snd_usb_audio vid=0x%04x pid=0x%04x "
+ "device_setup=1 to enable and report any issues "
+ "to g@b4.vu",
+ USB_ID_VENDOR(chip->usb_id),
+ USB_ID_PRODUCT(chip->usb_id));
+ return 0;
+ }
+
+ usb_audio_info(chip,
+ "Focusrite Scarlett Gen 2 Mixer Driver enabled pid=0x%04x",
+ USB_ID_PRODUCT(chip->usb_id));
+
+ err = snd_scarlett_gen2_controls_create(mixer, info);
+ if (err < 0)
+ usb_audio_err(mixer->chip,
+ "Error initialising Scarlett Mixer Driver: %d",
+ err);
+
+ return err;
+}
diff --git a/sound/usb/mixer_scarlett_gen2.h b/sound/usb/mixer_scarlett_gen2.h
index 52e1dad77afd..668c6b0cb50a 100644
--- a/sound/usb/mixer_scarlett_gen2.h
+++ b/sound/usb/mixer_scarlett_gen2.h
@@ -2,6 +2,6 @@
#ifndef __USB_MIXER_SCARLETT_GEN2_H
#define __USB_MIXER_SCARLETT_GEN2_H
-int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer);
+int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer);
#endif /* __USB_MIXER_SCARLETT_GEN2_H */
diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c
index f0e8e1539450..c6c834ac83ac 100644
--- a/sound/usb/mixer_us16x08.c
+++ b/sound/usb/mixer_us16x08.c
@@ -607,7 +607,7 @@ static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol,
static int snd_us16x08_meter_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- uinfo->count = 1;
+ uinfo->count = 34;
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->value.integer.max = 0x7FFF;
uinfo->value.integer.min = 0;
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 878f1201aad6..75218539fb10 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -323,6 +323,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
switch (subs->stream->chip->usb_id) {
case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
+ case USB_ID(0x22f0, 0x0006): /* Allen&Heath Qu-16 */
ep = 0x81;
ifnum = 3;
goto add_sync_ep_from_ifnum;
@@ -332,6 +333,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
ifnum = 2;
goto add_sync_ep_from_ifnum;
case USB_ID(0x2466, 0x8003): /* Fractal Audio Axe-Fx II */
+ case USB_ID(0x0499, 0x172a): /* Yamaha MODX */
ep = 0x86;
ifnum = 2;
goto add_sync_ep_from_ifnum;
@@ -339,6 +341,10 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
ep = 0x81;
ifnum = 2;
goto add_sync_ep_from_ifnum;
+ case USB_ID(0x1686, 0xf029): /* Zoom UAC-2 */
+ ep = 0x82;
+ ifnum = 2;
+ goto add_sync_ep_from_ifnum;
case USB_ID(0x1397, 0x0001): /* Behringer UFX1604 */
case USB_ID(0x1397, 0x0002): /* Behringer UFX1204 */
ep = 0x81;
@@ -1879,7 +1885,7 @@ void snd_usb_preallocate_buffer(struct snd_usb_substream *subs)
{
struct snd_pcm *pcm = subs->stream->pcm;
struct snd_pcm_substream *s = pcm->streams[subs->direction].substream;
- struct device *dev = subs->dev->bus->controller;
+ struct device *dev = subs->dev->bus->sysdev;
if (!snd_usb_use_vmalloc)
snd_pcm_lib_preallocate_pages(s, SNDRV_DMA_TYPE_DEV_SG,
diff --git a/sound/usb/proc.c b/sound/usb/proc.c
index 49e3f176aaf5..ffbf4bd9208c 100644
--- a/sound/usb/proc.c
+++ b/sound/usb/proc.c
@@ -60,7 +60,7 @@ void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct snd_info_buffer *buffer)
{
struct audioformat *fp;
- static char *sync_types[4] = {
+ static const char * const sync_types[4] = {
"NONE", "ASYNC", "ADAPTIVE", "SYNC"
};
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 8c3b3a291ddb..c29ccdf9e8bc 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -25,6 +25,16 @@
.idProduct = prod, \
.bInterfaceClass = USB_CLASS_VENDOR_SPEC
+/* A standard entry matching with vid/pid and the audio class/subclass */
+#define USB_AUDIO_DEVICE(vend, prod) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+ USB_DEVICE_ID_MATCH_INT_CLASS | \
+ USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
+ .idVendor = vend, \
+ .idProduct = prod, \
+ .bInterfaceClass = USB_CLASS_AUDIO, \
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL
+
/* HP Thunderbolt Dock Audio Headset */
{
USB_DEVICE(0x03f0, 0x0269),
@@ -126,6 +136,48 @@
},
/*
+ * Creative Technology, Ltd Live! Cam Sync HD [VF0770]
+ * The device advertises 8 formats, but only a rate of 48kHz is honored by the
+ * hardware and 24 bits give chopped audio, so only report the one working
+ * combination.
+ */
+{
+ USB_DEVICE(0x041e, 0x4095),
+ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = &(const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 2,
+ .type = QUIRK_AUDIO_STANDARD_MIXER,
+ },
+ {
+ .ifnum = 3,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels = 2,
+ .fmt_bits = 16,
+ .iface = 3,
+ .altsetting = 4,
+ .altset_idx = 4,
+ .endpoint = 0x82,
+ .ep_attr = 0x05,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .nr_rates = 1,
+ .rate_table = (unsigned int[]) { 48000 },
+ },
+ },
+ {
+ .ifnum = -1
+ },
+ },
+ },
+},
+
+/*
* HP Wireless Audio
* When not ignored, causes instability issues for some users, forcing them to
* blacklist the entire module.
@@ -2485,6 +2537,16 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
+{
+ USB_DEVICE_VENDOR_SPEC(0x0944, 0x0204),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "KORG, Inc.",
+ /* .product_name = "ToneLab EX", */
+ .ifnum = 3,
+ .type = QUIRK_MIDI_STANDARD_INTERFACE,
+ }
+},
+
/* AKAI devices */
{
USB_DEVICE(0x09e8, 0x0062),
@@ -3754,5 +3816,37 @@ ALC1220_VB_DESKTOP(0x26ce, 0x0a01), /* Asrock TRX40 Creator */
}
}
},
+{
+ /*
+ * Sennheiser GSP670
+ * Change order of interfaces loaded
+ */
+ USB_DEVICE(0x1395, 0x0300),
+ .bInterfaceClass = USB_CLASS_PER_INTERFACE,
+ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = &(const struct snd_usb_audio_quirk[]) {
+ // Communication
+ {
+ .ifnum = 3,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ // Recording
+ {
+ .ifnum = 4,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ // Main
+ {
+ .ifnum = 1,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
#undef USB_DEVICE_VENDOR_SPEC
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index cc75d9749e9f..72223545abfd 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -55,8 +55,12 @@ static int create_composite_quirk(struct snd_usb_audio *chip,
if (!iface)
continue;
if (quirk->ifnum != probed_ifnum &&
- !usb_interface_claimed(iface))
- usb_driver_claim_interface(driver, iface, (void *)-1L);
+ !usb_interface_claimed(iface)) {
+ err = usb_driver_claim_interface(driver, iface,
+ USB_AUDIO_IFACE_UNUSED);
+ if (err < 0)
+ return err;
+ }
}
return 0;
@@ -390,8 +394,12 @@ static int create_autodetect_quirks(struct snd_usb_audio *chip,
continue;
err = create_autodetect_quirk(chip, iface, driver);
- if (err >= 0)
- usb_driver_claim_interface(driver, iface, (void *)-1L);
+ if (err >= 0) {
+ err = usb_driver_claim_interface(driver, iface,
+ USB_AUDIO_IFACE_UNUSED);
+ if (err < 0)
+ return err;
+ }
}
return 0;
@@ -1452,6 +1460,8 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */
case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */
case USB_ID(0x2912, 0x30c8): /* Audioengine D1 */
+ case USB_ID(0x413c, 0xa506): /* Dell AE515 sound bar */
+ case USB_ID(0x046d, 0x084c): /* Logitech ConferenceCam Connect */
return true;
}
@@ -1604,13 +1614,21 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
&& (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
msleep(20);
- /* Zoom R16/24, Logitech H650e/H570e, Jabra 550a, Kingston HyperX
- * needs a tiny delay here, otherwise requests like get/set
- * frequency return as failed despite actually succeeding.
+ /*
+ * Plantronics headsets (C320, C320-M, etc) need a delay to avoid
+ * random microhpone failures.
+ */
+ if (USB_ID_VENDOR(chip->usb_id) == 0x047f &&
+ (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+ msleep(20);
+
+ /* Zoom R16/24, many Logitech(at least H650e/H570e/BCC950),
+ * Jabra 550a, Kingston HyperX needs a tiny delay here,
+ * otherwise requests like get/set frequency return
+ * as failed despite actually succeeding.
*/
if ((chip->usb_id == USB_ID(0x1686, 0x00dd) ||
- chip->usb_id == USB_ID(0x046d, 0x0a46) ||
- chip->usb_id == USB_ID(0x046d, 0x0a56) ||
+ USB_ID_VENDOR(chip->usb_id) == 0x046d || /* Logitech */
chip->usb_id == USB_ID(0x0b0e, 0x0349) ||
chip->usb_id == USB_ID(0x0951, 0x16ad)) &&
(requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
@@ -1731,7 +1749,9 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
case 0x25ce: /* Mytek devices */
case 0x278b: /* Rotel? */
case 0x292b: /* Gustard/Ess based devices */
+ case 0x2972: /* FiiO devices */
case 0x2ab6: /* T+A devices */
+ case 0x3353: /* Khadas devices */
case 0x3842: /* EVGA */
case 0xc502: /* HiBy devices */
if (fp->dsd_raw)
@@ -1820,6 +1840,12 @@ static const struct registration_quirk registration_quirks[] = {
REG_QUIRK_ENTRY(0x0951, 0x16d8, 2), /* Kingston HyperX AMP */
REG_QUIRK_ENTRY(0x0951, 0x16ed, 2), /* Kingston HyperX Cloud Alpha S */
REG_QUIRK_ENTRY(0x0951, 0x16ea, 2), /* Kingston HyperX Cloud Flight S */
+ REG_QUIRK_ENTRY(0x0ecb, 0x1f46, 2), /* JBL Quantum 600 */
+ REG_QUIRK_ENTRY(0x0ecb, 0x1f47, 2), /* JBL Quantum 800 */
+ REG_QUIRK_ENTRY(0x0ecb, 0x1f4c, 2), /* JBL Quantum 400 */
+ REG_QUIRK_ENTRY(0x0ecb, 0x2039, 2), /* JBL Quantum 400 */
+ REG_QUIRK_ENTRY(0x0ecb, 0x203c, 2), /* JBL Quantum 600 */
+ REG_QUIRK_ENTRY(0x0ecb, 0x203e, 2), /* JBL Quantum 800 */
{ 0 } /* terminator */
};
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index d01edd5da6cf..eff1ac1dc9ba 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -193,16 +193,16 @@ static int usb_chmap_ctl_get(struct snd_kcontrol *kcontrol,
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
struct snd_usb_substream *subs = info->private_data;
struct snd_pcm_chmap_elem *chmap = NULL;
- int i;
+ int i = 0;
- memset(ucontrol->value.integer.value, 0,
- sizeof(ucontrol->value.integer.value));
if (subs->cur_audiofmt)
chmap = subs->cur_audiofmt->chmap;
if (chmap) {
for (i = 0; i < chmap->channels; i++)
ucontrol->value.integer.value[i] = chmap->map[i];
}
+ for (; i < subs->channels_max; i++)
+ ucontrol->value.integer.value[i] = 0;
return 0;
}
@@ -240,7 +240,7 @@ static int add_chmap(struct snd_pcm *pcm, int stream,
static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
int protocol)
{
- static unsigned int uac1_maps[] = {
+ static const unsigned int uac1_maps[] = {
SNDRV_CHMAP_FL, /* left front */
SNDRV_CHMAP_FR, /* right front */
SNDRV_CHMAP_FC, /* center front */
@@ -255,7 +255,7 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
SNDRV_CHMAP_TC, /* top */
0 /* terminator */
};
- static unsigned int uac2_maps[] = {
+ static const unsigned int uac2_maps[] = {
SNDRV_CHMAP_FL, /* front left */
SNDRV_CHMAP_FR, /* front right */
SNDRV_CHMAP_FC, /* front center */
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 55a2119c2411..b1959e04cbb1 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -8,7 +8,7 @@
*/
/* handling of USB vendor/product ID pairs as 32-bit numbers */
-#define USB_ID(vendor, product) (((vendor) << 16) | (product))
+#define USB_ID(vendor, product) (((unsigned int)(vendor) << 16) | (product))
#define USB_ID_VENDOR(id) ((id) >> 16)
#define USB_ID_PRODUCT(id) ((u16)(id))
@@ -59,6 +59,8 @@ struct snd_usb_audio {
struct media_intf_devnode *ctl_intf_media_devnode;
};
+#define USB_AUDIO_IFACE_UNUSED ((void *)-1L)
+
#define usb_audio_err(chip, fmt, args...) \
dev_err(&(chip)->dev->dev, fmt, ##args)
#define usb_audio_warn(chip, fmt, args...) \
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c
index 091c071b270a..cff684942c4f 100644
--- a/sound/usb/usx2y/usb_stream.c
+++ b/sound/usb/usx2y/usb_stream.c
@@ -142,8 +142,11 @@ void usb_stream_free(struct usb_stream_kernel *sk)
if (!s)
return;
- free_pages_exact(sk->write_page, s->write_size);
- sk->write_page = NULL;
+ if (sk->write_page) {
+ free_pages_exact(sk->write_page, s->write_size);
+ sk->write_page = NULL;
+ }
+
free_pages_exact(s, s->read_size);
sk->s = NULL;
}
diff --git a/sound/usb/validate.c b/sound/usb/validate.c
index 5a3c4f7882b0..89a48d731719 100644
--- a/sound/usb/validate.c
+++ b/sound/usb/validate.c
@@ -233,7 +233,7 @@ static bool validate_midi_out_jack(const void *p,
#define FIXED(p, t, s) { .protocol = (p), .type = (t), .size = sizeof(s) }
#define FUNC(p, t, f) { .protocol = (p), .type = (t), .func = (f) }
-static struct usb_desc_validator audio_validators[] = {
+static const struct usb_desc_validator audio_validators[] = {
/* UAC1 */
FUNC(UAC_VERSION_1, UAC_HEADER, validate_uac1_header),
FIXED(UAC_VERSION_1, UAC_INPUT_TERMINAL,
@@ -288,7 +288,7 @@ static struct usb_desc_validator audio_validators[] = {
{ } /* terminator */
};
-static struct usb_desc_validator midi_validators[] = {
+static const struct usb_desc_validator midi_validators[] = {
FIXED(UAC_VERSION_ALL, USB_MS_HEADER,
struct usb_ms_header_descriptor),
FIXED(UAC_VERSION_ALL, USB_MS_MIDI_IN_JACK,
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c
index 5fd4e32247a6..a314f13e3292 100644
--- a/sound/x86/intel_hdmi_audio.c
+++ b/sound/x86/intel_hdmi_audio.c
@@ -1279,7 +1279,7 @@ static int had_pcm_mmap(struct snd_pcm_substream *substream,
{
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
return remap_pfn_range(vma, vma->vm_start,
- substream->dma_buffer.addr >> PAGE_SHIFT,
+ substream->runtime->dma_addr >> PAGE_SHIFT,
vma->vm_end - vma->vm_start, vma->vm_page_prot);
}