summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2019-03-18 11:14:51 +0000
committerMark Brown <broonie@kernel.org>2019-03-18 11:14:51 +0000
commit22d91ed32b653481f47e81719858678e8c92089e (patch)
treea10d240e35ba7fa5d6bb1c9aad1a5db622e5dddd /sound
parent2b13bee3884926cba22061efa75bd315e871de24 (diff)
parent9e98c678c2d6ae3a17cb2de55d17f69dddaa231b (diff)
downloadlinux-22d91ed32b653481f47e81719858678e8c92089e.tar.bz2
Merge tag 'v5.1-rc1' into asoc-5.1
Linux 5.1-rc1
Diffstat (limited to 'sound')
-rw-r--r--sound/ac97/bus.c2
-rw-r--r--sound/aoa/core/gpio-feature.c1
-rw-r--r--sound/aoa/soundbus/i2sbus/core.c4
-rw-r--r--sound/arm/aaci.c4
-rw-r--r--sound/arm/pxa2xx-ac97.c1
-rw-r--r--sound/atmel/ac97c.c4
-rw-r--r--sound/core/compress_offload.c11
-rw-r--r--sound/core/info.c131
-rw-r--r--sound/core/init.c31
-rw-r--r--sound/core/memalloc.c2
-rw-r--r--sound/core/oss/pcm_oss.c1
-rw-r--r--sound/core/pcm.c163
-rw-r--r--sound/core/pcm_lib.c22
-rw-r--r--sound/core/pcm_local.h1
-rw-r--r--sound/core/pcm_memory.c62
-rw-r--r--sound/core/pcm_native.c315
-rw-r--r--sound/drivers/aloop.c14
-rw-r--r--sound/drivers/dummy.c12
-rw-r--r--sound/drivers/opl4/opl4_proc.c4
-rw-r--r--sound/drivers/pcsp/pcsp.c1
-rw-r--r--sound/drivers/vx/vx_core.c9
-rw-r--r--sound/firewire/Kconfig1
-rw-r--r--sound/firewire/bebob/bebob.c14
-rw-r--r--sound/firewire/bebob/bebob_proc.c12
-rw-r--r--sound/firewire/dice/dice-proc.c12
-rw-r--r--sound/firewire/dice/dice.c12
-rw-r--r--sound/firewire/digi00x/digi00x-proc.c16
-rw-r--r--sound/firewire/fireface/Makefile4
-rw-r--r--sound/firewire/fireface/ff-midi.c2
-rw-r--r--sound/firewire/fireface/ff-pcm.c2
-rw-r--r--sound/firewire/fireface/ff-proc.c229
-rw-r--r--sound/firewire/fireface/ff-protocol-ff400.c161
-rw-r--r--sound/firewire/fireface/ff-protocol-ff800.c143
-rw-r--r--sound/firewire/fireface/ff-protocol-former.c597
-rw-r--r--sound/firewire/fireface/ff-protocol-latter.c430
-rw-r--r--sound/firewire/fireface/ff-stream.c40
-rw-r--r--sound/firewire/fireface/ff-transaction.c143
-rw-r--r--sound/firewire/fireface/ff.c28
-rw-r--r--sound/firewire/fireface/ff.h23
-rw-r--r--sound/firewire/fireworks/fireworks_proc.c12
-rw-r--r--sound/firewire/motu/amdtp-motu.c4
-rw-r--r--sound/firewire/motu/motu-proc.c12
-rw-r--r--sound/firewire/oxfw/oxfw-proc.c12
-rw-r--r--sound/firewire/tascam/tascam-proc.c12
-rw-r--r--sound/hda/hdac_component.c4
-rw-r--r--sound/hda/hdac_controller.c8
-rw-r--r--sound/hda/hdac_i915.c10
-rw-r--r--sound/hda/hdac_stream.c47
-rw-r--r--sound/i2c/other/ak4113.c5
-rw-r--r--sound/i2c/other/ak4114.c5
-rw-r--r--sound/i2c/other/ak4xxx-adda.c8
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c3
-rw-r--r--sound/isa/als100.c1
-rw-r--r--sound/isa/cmi8328.c1
-rw-r--r--sound/isa/cmi8330.c3
-rw-r--r--sound/isa/es1688/es1688.c2
-rw-r--r--sound/isa/es1688/es1688_lib.c6
-rw-r--r--sound/isa/es18xx.c4
-rw-r--r--sound/isa/gus/gus_irq.c5
-rw-r--r--sound/isa/gus/gus_main.c13
-rw-r--r--sound/isa/gus/gus_mem.c6
-rw-r--r--sound/isa/gus/gus_pcm.c4
-rw-r--r--sound/isa/opti9xx/miro.c5
-rw-r--r--sound/isa/sb/jazz16.c1
-rw-r--r--sound/isa/sb/sb16.c1
-rw-r--r--sound/isa/sb/sb16_csp.c5
-rw-r--r--sound/isa/sb/sb16_main.c12
-rw-r--r--sound/isa/sb/sb8.c1
-rw-r--r--sound/isa/sb/sb8_main.c2
-rw-r--r--sound/isa/sscape.c7
-rw-r--r--sound/isa/wss/wss_lib.c3
-rw-r--r--sound/mips/hal2.c31
-rw-r--r--sound/mips/sgio2audio.c7
-rw-r--r--sound/parisc/harmony.c10
-rw-r--r--sound/pci/ac97/ac97_proc.c26
-rw-r--r--sound/pci/ad1889.c13
-rw-r--r--sound/pci/ak4531_codec.c5
-rw-r--r--sound/pci/ali5451/ali5451.c8
-rw-r--r--sound/pci/als300.c1
-rw-r--r--sound/pci/als4000.c1
-rw-r--r--sound/pci/asihpi/asihpi.c6
-rw-r--r--sound/pci/atiixp.c24
-rw-r--r--sound/pci/atiixp_modem.c8
-rw-r--r--sound/pci/aw2/aw2-alsa.c40
-rw-r--r--sound/pci/azt3328.c4
-rw-r--r--sound/pci/bt87x.c10
-rw-r--r--sound/pci/ca0106/ca0106_main.c19
-rw-r--r--sound/pci/ca0106/ca0106_proc.c40
-rw-r--r--sound/pci/cmipci.c9
-rw-r--r--sound/pci/cs4281.c5
-rw-r--r--sound/pci/cs46xx/cs46xx_dsp_spos.h6
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c6
-rw-r--r--sound/pci/cs46xx/dsp_spos.c133
-rw-r--r--sound/pci/cs46xx/dsp_spos_scb_lib.c19
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pm.c1
-rw-r--r--sound/pci/ctxfi/ctatc.c8
-rw-r--r--sound/pci/echoaudio/echoaudio.c19
-rw-r--r--sound/pci/emu10k1/emu10k1.c6
-rw-r--r--sound/pci/emu10k1/emu10k1x.c12
-rw-r--r--sound/pci/emu10k1/emupcm.c22
-rw-r--r--sound/pci/emu10k1/emuproc.c81
-rw-r--r--sound/pci/emu10k1/p16v.c17
-rw-r--r--sound/pci/ens1370.c9
-rw-r--r--sound/pci/es1938.c1
-rw-r--r--sound/pci/es1968.c1
-rw-r--r--sound/pci/fm801.c1
-rw-r--r--sound/pci/hda/hda_beep.c151
-rw-r--r--sound/pci/hda/hda_beep.h5
-rw-r--r--sound/pci/hda/hda_bind.c3
-rw-r--r--sound/pci/hda/hda_codec.c56
-rw-r--r--sound/pci/hda/hda_intel.c2
-rw-r--r--sound/pci/hda/hda_proc.c9
-rw-r--r--sound/pci/hda/hda_tegra.c132
-rw-r--r--sound/pci/hda/patch_ca0132.c4
-rw-r--r--sound/pci/hda/patch_conexant.c4
-rw-r--r--sound/pci/hda/patch_hdmi.c77
-rw-r--r--sound/pci/hda/patch_realtek.c305
-rw-r--r--sound/pci/ice1712/ews.c7
-rw-r--r--sound/pci/ice1712/ice1712.c8
-rw-r--r--sound/pci/ice1712/ice1724.c8
-rw-r--r--sound/pci/ice1712/pontis.c12
-rw-r--r--sound/pci/ice1712/prodigy192.c5
-rw-r--r--sound/pci/ice1712/prodigy_hifi.c8
-rw-r--r--sound/pci/ice1712/quartet.c4
-rw-r--r--sound/pci/intel8x0.c8
-rw-r--r--sound/pci/intel8x0m.c9
-rw-r--r--sound/pci/korg1212/korg1212.c6
-rw-r--r--sound/pci/lola/lola_proc.c16
-rw-r--r--sound/pci/lx6464es/lx6464es.c16
-rw-r--r--sound/pci/maestro3.c1
-rw-r--r--sound/pci/mixart/mixart.c6
-rw-r--r--sound/pci/nm256/nm256.c1
-rw-r--r--sound/pci/oxygen/oxygen_lib.c12
-rw-r--r--sound/pci/oxygen/pcm1796.h1
-rw-r--r--sound/pci/oxygen/xonar_pcm179x.c71
-rw-r--r--sound/pci/pcxhr/pcxhr.c21
-rw-r--r--sound/pci/riptide/riptide.c7
-rw-r--r--sound/pci/rme32.c5
-rw-r--r--sound/pci/rme96.c7
-rw-r--r--sound/pci/rme9652/hdsp.c5
-rw-r--r--sound/pci/rme9652/hdspm.c75
-rw-r--r--sound/pci/rme9652/rme9652.c6
-rw-r--r--sound/pci/sis7019.c1
-rw-r--r--sound/pci/sonicvibes.c6
-rw-r--r--sound/pci/trident/trident_main.c8
-rw-r--r--sound/pci/via82xx.c8
-rw-r--r--sound/pci/via82xx_modem.c16
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c10
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_core.c6
-rw-r--r--sound/ppc/pmac.c1
-rw-r--r--sound/ppc/snd_ps3.c6
-rw-r--r--sound/ppc/tumbler.c1
-rw-r--r--sound/sh/aica.c14
-rw-r--r--sound/soc/amd/acp-pcm-dma.c26
-rw-r--r--sound/soc/amd/raven/acp3x-pcm-dma.c8
-rw-r--r--sound/soc/dwc/dwc-pcm.c3
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-pcm.c9
-rw-r--r--sound/soc/intel/baytrail/sst-baytrail-pcm.c15
-rw-r--r--sound/soc/intel/haswell/sst-haswell-pcm.c10
-rw-r--r--sound/soc/intel/skylake/skl-pcm.c9
-rw-r--r--sound/soc/mediatek/common/mtk-afe-platform-driver.c6
-rw-r--r--sound/soc/meson/axg-fifo.c7
-rw-r--r--sound/soc/sh/fsi.c3
-rw-r--r--sound/soc/sh/rcar/core.c5
-rw-r--r--sound/soc/sh/siu_pcm.c15
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c5
-rw-r--r--sound/soc/soc-pcm.c1
-rw-r--r--sound/soc/stm/stm32_adfsdm.c5
-rw-r--r--sound/soc/txx9/txx9aclc.c4
-rw-r--r--sound/soc/uniphier/aio-dma.c3
-rw-r--r--sound/soc/xilinx/xlnx_formatter_pcm.c3
-rw-r--r--sound/soc/xtensa/xtfpga-i2s.c6
-rw-r--r--sound/sparc/dbri.c19
-rw-r--r--sound/spi/at73c213.c2
-rw-r--r--sound/synth/emux/emux_proc.c4
-rw-r--r--sound/usb/card.c1
-rw-r--r--sound/usb/card.h1
-rw-r--r--sound/usb/format.c2
-rw-r--r--sound/usb/line6/driver.c4
-rw-r--r--sound/usb/line6/pod.c3
-rw-r--r--sound/usb/mixer.c13
-rw-r--r--sound/usb/mixer_quirks.c6
-rw-r--r--sound/usb/pcm.c13
-rw-r--r--sound/usb/proc.c14
-rw-r--r--sound/usb/quirks-table.h65
-rw-r--r--sound/usb/quirks.c119
-rw-r--r--sound/usb/usx2y/usb_stream.c5
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c21
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c19
-rw-r--r--sound/x86/intel_hdmi_audio.c15
190 files changed, 2768 insertions, 2348 deletions
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c
index 9f0c480489ef..9cbf6927abe9 100644
--- a/sound/ac97/bus.c
+++ b/sound/ac97/bus.c
@@ -84,7 +84,7 @@ ac97_of_get_child_device(struct ac97_controller *ac97_ctrl, int idx,
if ((idx != of_property_read_u32(node, "reg", &reg)) ||
!of_device_is_compatible(node, compat))
continue;
- return of_node_get(node);
+ return node;
}
return NULL;
diff --git a/sound/aoa/core/gpio-feature.c b/sound/aoa/core/gpio-feature.c
index 65557421fe0b..c3ff721e4660 100644
--- a/sound/aoa/core/gpio-feature.c
+++ b/sound/aoa/core/gpio-feature.c
@@ -82,6 +82,7 @@ static struct device_node *get_gpio(char *name,
if (altname && (strcmp(audio_gpio, altname) == 0))
break;
}
+ of_node_put(gpio);
/* still not found, assume not there */
if (!np)
return NULL;
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c
index 40ebde2e1ab1..904659d14988 100644
--- a/sound/aoa/soundbus/i2sbus/core.c
+++ b/sound/aoa/soundbus/i2sbus/core.c
@@ -380,10 +380,6 @@ static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state)
int err, ret = 0;
list_for_each_entry(i2sdev, &control->list, item) {
- /* Notify Alsa */
- /* Suspend PCM streams */
- snd_pcm_suspend_all(i2sdev->sound.pcm);
-
/* Notify codecs */
list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
err = 0;
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 0114ffed56dd..a2d4b41096e0 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -757,7 +757,6 @@ static int aaci_do_suspend(struct snd_card *card)
{
struct aaci *aaci = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
- snd_pcm_suspend_all(aaci->pcm);
return 0;
}
@@ -942,7 +941,8 @@ static int aaci_init_pcm(struct aaci *aaci)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- NULL, 0, 64 * 1024);
+ aaci->card->dev,
+ 0, 64 * 1024);
}
return ret;
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 1f72672262d0..68fe5bb11eea 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -124,7 +124,6 @@ static int pxa2xx_ac97_do_suspend(struct snd_card *card)
pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
- snd_pcm_suspend_all(pxa2xx_ac97_pcm);
snd_ac97_suspend(pxa2xx_ac97_ac97);
if (platform_ops && platform_ops->suspend)
platform_ops->suspend(platform_ops->priv);
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index 380025887aef..33c87a0547a9 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -603,11 +603,9 @@ static int atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &atmel_ac97_capture_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_ac97_playback_ops);
- retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
&chip->pdev->dev, hw.periods_min * hw.period_bytes_min,
hw.buffer_bytes_max);
- if (retval)
- return retval;
pcm->private_data = chip;
pcm->info_flags = 0;
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index f7d2b373da0a..a1a6fd75cfe5 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -1015,22 +1015,13 @@ static int snd_compress_proc_init(struct snd_compr *compr)
if (!entry)
return -ENOMEM;
entry->mode = S_IFDIR | 0555;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- return -ENOMEM;
- }
compr->proc_root = entry;
entry = snd_info_create_card_entry(compr->card, "info",
compr->proc_root);
- if (entry) {
+ if (entry)
snd_info_set_text_ops(entry, compr,
snd_compress_proc_info_read);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
compr->proc_info_entry = entry;
return 0;
diff --git a/sound/core/info.c b/sound/core/info.c
index fe502bc5e6d2..96a074019c33 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -463,11 +463,12 @@ static struct snd_info_entry *create_subdir(struct module *mod,
}
static struct snd_info_entry *
-snd_info_create_entry(const char *name, struct snd_info_entry *parent);
+snd_info_create_entry(const char *name, struct snd_info_entry *parent,
+ struct module *module);
int __init snd_info_init(void)
{
- snd_proc_root = snd_info_create_entry("asound", NULL);
+ snd_proc_root = snd_info_create_entry("asound", NULL, THIS_MODULE);
if (!snd_proc_root)
return -ENOMEM;
snd_proc_root->mode = S_IFDIR | 0555;
@@ -503,6 +504,14 @@ int __exit snd_info_done(void)
return 0;
}
+static void snd_card_id_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct snd_card *card = entry->private_data;
+
+ snd_iprintf(buffer, "%s\n", card->id);
+}
+
/*
* create a card proc file
* called from init.c
@@ -520,28 +529,8 @@ int snd_info_card_create(struct snd_card *card)
if (!entry)
return -ENOMEM;
card->proc_root = entry;
- return 0;
-}
-
-/* register all pending info entries */
-static int snd_info_register_recursive(struct snd_info_entry *entry)
-{
- struct snd_info_entry *p;
- int err;
- if (!entry->p) {
- err = snd_info_register(entry);
- if (err < 0)
- return err;
- }
-
- list_for_each_entry(p, &entry->children, list) {
- err = snd_info_register_recursive(p);
- if (err < 0)
- return err;
- }
-
- return 0;
+ return snd_card_ro_proc_new(card, "id", card, snd_card_id_read);
}
/*
@@ -557,7 +546,7 @@ int snd_info_card_register(struct snd_card *card)
if (snd_BUG_ON(!card))
return -ENXIO;
- err = snd_info_register_recursive(card->proc_root);
+ err = snd_info_register(card->proc_root);
if (err < 0)
return err;
@@ -705,7 +694,8 @@ EXPORT_SYMBOL(snd_info_get_str);
* Return: The pointer of the new instance, or %NULL on failure.
*/
static struct snd_info_entry *
-snd_info_create_entry(const char *name, struct snd_info_entry *parent)
+snd_info_create_entry(const char *name, struct snd_info_entry *parent,
+ struct module *module)
{
struct snd_info_entry *entry;
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
@@ -722,6 +712,7 @@ snd_info_create_entry(const char *name, struct snd_info_entry *parent)
INIT_LIST_HEAD(&entry->children);
INIT_LIST_HEAD(&entry->list);
entry->parent = parent;
+ entry->module = module;
if (parent)
list_add_tail(&entry->list, &parent->children);
return entry;
@@ -741,10 +732,9 @@ struct snd_info_entry *snd_info_create_module_entry(struct module * module,
const char *name,
struct snd_info_entry *parent)
{
- struct snd_info_entry *entry = snd_info_create_entry(name, parent);
- if (entry)
- entry->module = module;
- return entry;
+ if (!parent)
+ parent = snd_proc_root;
+ return snd_info_create_entry(name, parent, module);
}
EXPORT_SYMBOL(snd_info_create_module_entry);
@@ -762,12 +752,9 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
const char *name,
struct snd_info_entry * parent)
{
- struct snd_info_entry *entry = snd_info_create_entry(name, parent);
- if (entry) {
- entry->module = card->module;
- entry->card = card;
- }
- return entry;
+ if (!parent)
+ parent = card->proc_root;
+ return snd_info_create_entry(name, parent, card->module);
}
EXPORT_SYMBOL(snd_info_create_card_entry);
@@ -813,15 +800,7 @@ void snd_info_free_entry(struct snd_info_entry * entry)
}
EXPORT_SYMBOL(snd_info_free_entry);
-/**
- * snd_info_register - register the info entry
- * @entry: the info entry
- *
- * Registers the proc info entry.
- *
- * Return: Zero if successful, or a negative error code on failure.
- */
-int snd_info_register(struct snd_info_entry * entry)
+static int __snd_info_register(struct snd_info_entry *entry)
{
struct proc_dir_entry *root, *p = NULL;
@@ -829,6 +808,8 @@ int snd_info_register(struct snd_info_entry * entry)
return -ENXIO;
root = entry->parent == NULL ? snd_proc_root->p : entry->parent->p;
mutex_lock(&info_mutex);
+ if (entry->p || !root)
+ goto unlock;
if (S_ISDIR(entry->mode)) {
p = proc_mkdir_mode(entry->name, entry->mode, root);
if (!p) {
@@ -850,11 +831,73 @@ int snd_info_register(struct snd_info_entry * entry)
proc_set_size(p, entry->size);
}
entry->p = p;
+ unlock:
mutex_unlock(&info_mutex);
return 0;
}
+
+/**
+ * snd_info_register - register the info entry
+ * @entry: the info entry
+ *
+ * Registers the proc info entry.
+ * The all children entries are registered recursively.
+ *
+ * Return: Zero if successful, or a negative error code on failure.
+ */
+int snd_info_register(struct snd_info_entry *entry)
+{
+ struct snd_info_entry *p;
+ int err;
+
+ if (!entry->p) {
+ err = __snd_info_register(entry);
+ if (err < 0)
+ return err;
+ }
+
+ list_for_each_entry(p, &entry->children, list) {
+ err = snd_info_register(p);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
EXPORT_SYMBOL(snd_info_register);
+/**
+ * snd_card_rw_proc_new - Create a read/write text proc file entry for the card
+ * @card: the card instance
+ * @name: the file name
+ * @private_data: the arbitrary private data
+ * @read: the read callback
+ * @write: the write callback, NULL for read-only
+ *
+ * This proc file entry will be registered via snd_card_register() call, and
+ * it will be removed automatically at the card removal, too.
+ */
+int snd_card_rw_proc_new(struct snd_card *card, const char *name,
+ void *private_data,
+ void (*read)(struct snd_info_entry *,
+ struct snd_info_buffer *),
+ void (*write)(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer))
+{
+ struct snd_info_entry *entry;
+
+ entry = snd_info_create_card_entry(card, name, card->proc_root);
+ if (!entry)
+ return -ENOMEM;
+ snd_info_set_text_ops(entry, private_data, read);
+ if (write) {
+ entry->mode |= 0200;
+ entry->c.text.write = write;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_card_rw_proc_new);
+
/*
*/
diff --git a/sound/core/init.c b/sound/core/init.c
index 4849c611c0fe..0c4dc40376a7 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -100,31 +100,6 @@ int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag);
EXPORT_SYMBOL(snd_mixer_oss_notify_callback);
#endif
-#ifdef CONFIG_SND_PROC_FS
-static void snd_card_id_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- snd_iprintf(buffer, "%s\n", entry->card->id);
-}
-
-static int init_info_for_card(struct snd_card *card)
-{
- struct snd_info_entry *entry;
-
- entry = snd_info_create_card_entry(card, "id", card->proc_root);
- if (!entry) {
- dev_dbg(card->dev, "unable to create card entry\n");
- return -ENOMEM;
- }
- entry->c.text.read = snd_card_id_read;
- card->proc_id = entry;
-
- return snd_info_card_register(card);
-}
-#else /* !CONFIG_SND_PROC_FS */
-#define init_info_for_card(card)
-#endif
-
static int check_empty_slot(struct module *module, int slot)
{
return !slots[slot] || !*slots[slot];
@@ -491,7 +466,6 @@ static int snd_card_do_free(struct snd_card *card)
snd_device_free_all(card);
if (card->private_free)
card->private_free(card);
- snd_info_free_entry(card->proc_id);
if (snd_info_card_free(card) < 0) {
dev_warn(card->dev, "unable to free card info\n");
/* Not fatal error */
@@ -795,7 +769,10 @@ int snd_card_register(struct snd_card *card)
}
snd_cards[card->number] = card;
mutex_unlock(&snd_card_mutex);
- init_info_for_card(card);
+ err = snd_info_card_register(card);
+ if (err < 0)
+ return err;
+
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 59a4adc286ed..eb974235c92b 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -182,6 +182,8 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
return -ENXIO;
if (WARN_ON(!dmab))
return -ENXIO;
+ if (WARN_ON(!device))
+ return -EINVAL;
dmab->dev.type = type;
dmab->dev.dev = device;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 467039b342b5..d5b0d7ba83c4 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2427,7 +2427,6 @@ static int snd_pcm_oss_open_file(struct file *file,
}
pcm_oss_file->streams[idx] = substream;
- substream->file = pcm_oss_file;
snd_pcm_oss_init_substream(substream, &setup[idx], minor);
}
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 01b9d62eef14..7b63aee124af 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -528,52 +528,44 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
if (!entry)
return -ENOMEM;
entry->mode = S_IFDIR | 0555;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- return -ENOMEM;
- }
pstr->proc_root = entry;
entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root);
- if (entry) {
+ if (entry)
snd_info_set_text_ops(entry, pstr, snd_pcm_stream_proc_info_read);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- pstr->proc_info_entry = entry;
-
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
entry = snd_info_create_card_entry(pcm->card, "xrun_debug",
pstr->proc_root);
if (entry) {
- entry->c.text.read = snd_pcm_xrun_debug_read;
+ snd_info_set_text_ops(entry, pstr, snd_pcm_xrun_debug_read);
entry->c.text.write = snd_pcm_xrun_debug_write;
entry->mode |= 0200;
- entry->private_data = pstr;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
}
- pstr->proc_xrun_debug_entry = entry;
#endif
return 0;
}
static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr)
{
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
- snd_info_free_entry(pstr->proc_xrun_debug_entry);
- pstr->proc_xrun_debug_entry = NULL;
-#endif
- snd_info_free_entry(pstr->proc_info_entry);
- pstr->proc_info_entry = NULL;
snd_info_free_entry(pstr->proc_root);
pstr->proc_root = NULL;
return 0;
}
+static struct snd_info_entry *
+create_substream_info_entry(struct snd_pcm_substream *substream,
+ const char *name,
+ void (*read)(struct snd_info_entry *,
+ struct snd_info_buffer *))
+{
+ struct snd_info_entry *entry;
+
+ entry = snd_info_create_card_entry(substream->pcm->card, name,
+ substream->proc_root);
+ if (entry)
+ snd_info_set_text_ops(entry, substream, read);
+ return entry;
+}
+
static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
{
struct snd_info_entry *entry;
@@ -588,101 +580,61 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
if (!entry)
return -ENOMEM;
entry->mode = S_IFDIR | 0555;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- return -ENOMEM;
- }
substream->proc_root = entry;
- entry = snd_info_create_card_entry(card, "info", substream->proc_root);
- if (entry) {
- snd_info_set_text_ops(entry, substream,
- snd_pcm_substream_proc_info_read);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- substream->proc_info_entry = entry;
- entry = snd_info_create_card_entry(card, "hw_params",
- substream->proc_root);
- if (entry) {
- snd_info_set_text_ops(entry, substream,
- snd_pcm_substream_proc_hw_params_read);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- substream->proc_hw_params_entry = entry;
- entry = snd_info_create_card_entry(card, "sw_params",
- substream->proc_root);
- if (entry) {
- snd_info_set_text_ops(entry, substream,
- snd_pcm_substream_proc_sw_params_read);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- substream->proc_sw_params_entry = entry;
- entry = snd_info_create_card_entry(card, "status",
- substream->proc_root);
- if (entry) {
- snd_info_set_text_ops(entry, substream,
- snd_pcm_substream_proc_status_read);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- substream->proc_status_entry = entry;
+
+ create_substream_info_entry(substream, "info",
+ snd_pcm_substream_proc_info_read);
+ create_substream_info_entry(substream, "hw_params",
+ snd_pcm_substream_proc_hw_params_read);
+ create_substream_info_entry(substream, "sw_params",
+ snd_pcm_substream_proc_sw_params_read);
+ create_substream_info_entry(substream, "status",
+ snd_pcm_substream_proc_status_read);
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
- entry = snd_info_create_card_entry(card, "xrun_injection",
- substream->proc_root);
+ entry = create_substream_info_entry(substream, "xrun_injection", NULL);
if (entry) {
- entry->private_data = substream;
- entry->c.text.read = NULL;
entry->c.text.write = snd_pcm_xrun_injection_write;
entry->mode = S_IFREG | 0200;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
}
- substream->proc_xrun_injection_entry = entry;
#endif /* CONFIG_SND_PCM_XRUN_DEBUG */
return 0;
}
-static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream)
-{
- snd_info_free_entry(substream->proc_info_entry);
- substream->proc_info_entry = NULL;
- snd_info_free_entry(substream->proc_hw_params_entry);
- substream->proc_hw_params_entry = NULL;
- snd_info_free_entry(substream->proc_sw_params_entry);
- substream->proc_sw_params_entry = NULL;
- snd_info_free_entry(substream->proc_status_entry);
- substream->proc_status_entry = NULL;
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
- snd_info_free_entry(substream->proc_xrun_injection_entry);
- substream->proc_xrun_injection_entry = NULL;
-#endif
- snd_info_free_entry(substream->proc_root);
- substream->proc_root = NULL;
- return 0;
-}
#else /* !CONFIG_SND_VERBOSE_PROCFS */
static inline int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) { return 0; }
static inline int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { return 0; }
static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) { return 0; }
-static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; }
#endif /* CONFIG_SND_VERBOSE_PROCFS */
static const struct attribute_group *pcm_dev_attr_groups[];
+/*
+ * PM callbacks: we need to deal only with suspend here, as the resume is
+ * triggered either from user-space or the driver's resume callback
+ */
+#ifdef CONFIG_PM_SLEEP
+static int do_pcm_suspend(struct device *dev)
+{
+ struct snd_pcm_str *pstr = container_of(dev, struct snd_pcm_str, dev);
+
+ if (!pstr->pcm->no_device_suspend)
+ snd_pcm_suspend_all(pstr->pcm);
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops pcm_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(do_pcm_suspend, NULL)
+};
+
+/* device type for PCM -- basically only for passing PM callbacks */
+static const struct device_type pcm_dev_type = {
+ .name = "pcm",
+ .pm = &pcm_dev_pm_ops,
+};
+
/**
* snd_pcm_new_stream - create a new PCM stream
* @pcm: the pcm instance
@@ -713,6 +665,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
snd_device_initialize(&pstr->dev, pcm->card);
pstr->dev.groups = pcm_dev_attr_groups;
+ pstr->dev.type = &pcm_dev_type;
dev_set_name(&pstr->dev, "pcmC%iD%i%c", pcm->card->number, pcm->device,
stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c');
@@ -753,9 +706,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
}
}
substream->group = &substream->self_group;
- spin_lock_init(&substream->self_group.lock);
- mutex_init(&substream->self_group.mutex);
- INIT_LIST_HEAD(&substream->self_group.substreams);
+ snd_pcm_group_init(&substream->self_group);
list_add_tail(&substream->link_list, &substream->self_group.substreams);
atomic_set(&substream->mmap_count, 0);
prev = substream;
@@ -885,15 +836,17 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
struct snd_pcm_oss_setup *setup, *setupn;
#endif
+
+ /* free all proc files under the stream */
+ snd_pcm_stream_proc_done(pstr);
+
substream = pstr->substream;
while (substream) {
substream_next = substream->next;
snd_pcm_timer_done(substream);
- snd_pcm_substream_proc_done(substream);
kfree(substream);
substream = substream_next;
}
- snd_pcm_stream_proc_done(pstr);
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
for (setup = pstr->oss.setup_list; setup; setup = setupn) {
setupn = setup->next;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 40013b26f671..345ab1ab2cac 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2176,17 +2176,16 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
+ /*
+ * If size < start_threshold, wait indefinitely. Another
+ * thread may start capture
+ */
if (!is_playback &&
- runtime->status->state == SNDRV_PCM_STATE_PREPARED) {
- if (size >= runtime->start_threshold) {
- err = snd_pcm_start(substream);
- if (err < 0)
- goto _end_unlock;
- } else {
- /* nothing to do */
- err = 0;
+ runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
+ size >= runtime->start_threshold) {
+ err = snd_pcm_start(substream);
+ if (err < 0)
goto _end_unlock;
- }
}
avail = snd_pcm_avail(substream);
@@ -2219,9 +2218,8 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
if (frames > cont)
frames = cont;
if (snd_BUG_ON(!frames)) {
- runtime->twake = 0;
- snd_pcm_stream_unlock_irq(substream);
- return -EINVAL;
+ err = -EINVAL;
+ goto _end_unlock;
}
snd_pcm_stream_unlock_irq(substream);
err = writer(substream, appl_ofs, data, offset, frames,
diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h
index c515612969a4..0b4b5dfaec18 100644
--- a/sound/core/pcm_local.h
+++ b/sound/core/pcm_local.h
@@ -66,5 +66,6 @@ static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {}
#endif
void __snd_pcm_xrun(struct snd_pcm_substream *substream);
+void snd_pcm_group_init(struct snd_pcm_group *group);
#endif /* __SOUND_CORE_PCM_LOCAL_H */
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 4b5356a10315..ed73be80bd29 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -87,19 +87,10 @@ static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream
* @substream: the pcm substream instance
*
* Releases the pre-allocated buffer of the given substream.
- *
- * Return: Zero if successful, or a negative error code on failure.
*/
-int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
+void snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
{
snd_pcm_lib_preallocate_dma_free(substream);
-#ifdef CONFIG_SND_VERBOSE_PROCFS
- snd_info_free_entry(substream->proc_prealloc_max_entry);
- substream->proc_prealloc_max_entry = NULL;
- snd_info_free_entry(substream->proc_prealloc_entry);
- substream->proc_prealloc_entry = NULL;
-#endif
- return 0;
}
/**
@@ -107,10 +98,8 @@ int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
* @pcm: the pcm instance
*
* Releases all the pre-allocated buffers on the given pcm.
- *
- * Return: Zero if successful, or a negative error code on failure.
*/
-int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
+void snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
int stream;
@@ -118,7 +107,6 @@ int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
for (stream = 0; stream < 2; stream++)
for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
snd_pcm_lib_preallocate_free(substream);
- return 0;
}
EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
@@ -198,26 +186,19 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
{
struct snd_info_entry *entry;
- if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) {
- entry->c.text.read = snd_pcm_lib_preallocate_proc_read;
+ entry = snd_info_create_card_entry(substream->pcm->card, "prealloc",
+ substream->proc_root);
+ if (entry) {
+ snd_info_set_text_ops(entry, substream,
+ snd_pcm_lib_preallocate_proc_read);
entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
entry->mode |= 0200;
- entry->private_data = substream;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
}
- substream->proc_prealloc_entry = entry;
- if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc_max", substream->proc_root)) != NULL) {
- entry->c.text.read = snd_pcm_lib_preallocate_max_proc_read;
- entry->private_data = substream;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- substream->proc_prealloc_max_entry = entry;
+ entry = snd_info_create_card_entry(substream->pcm->card, "prealloc_max",
+ substream->proc_root);
+ if (entry)
+ snd_info_set_text_ops(entry, substream,
+ snd_pcm_lib_preallocate_max_proc_read);
}
#else /* !CONFIG_SND_VERBOSE_PROCFS */
@@ -227,7 +208,7 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
/*
* pre-allocate the buffer and create a proc file for the substream
*/
-static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
+static void snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
size_t size, size_t max)
{
@@ -238,7 +219,6 @@ static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
substream->buffer_bytes_max = substream->dma_buffer.bytes;
substream->dma_max = max;
preallocate_info_init(substream);
- return 0;
}
@@ -251,16 +231,14 @@ static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
* @max: the max. allowed pre-allocation size
*
* Do pre-allocation for the given DMA buffer type.
- *
- * Return: Zero if successful, or a negative error code on failure.
*/
-int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
+void snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
int type, struct device *data,
size_t size, size_t max)
{
substream->dma_buffer.dev.type = type;
substream->dma_buffer.dev.dev = data;
- return snd_pcm_lib_preallocate_pages1(substream, size, max);
+ snd_pcm_lib_preallocate_pages1(substream, size, max);
}
EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
@@ -274,21 +252,17 @@ EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
*
* Do pre-allocation to all substreams of the given pcm for the
* specified DMA type.
- *
- * Return: Zero if successful, or a negative error code on failure.
*/
-int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
+void snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
int type, void *data,
size_t size, size_t max)
{
struct snd_pcm_substream *substream;
- int stream, err;
+ int stream;
for (stream = 0; stream < 2; stream++)
for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
- if ((err = snd_pcm_lib_preallocate_pages(substream, type, data, size, max)) < 0)
- return err;
- return 0;
+ snd_pcm_lib_preallocate_pages(substream, type, data, size, max);
}
EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 818dff1de545..f731f904e8cc 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -85,71 +85,30 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
*
*/
-static DEFINE_RWLOCK(snd_pcm_link_rwlock);
static DECLARE_RWSEM(snd_pcm_link_rwsem);
-/* Writer in rwsem may block readers even during its waiting in queue,
- * and this may lead to a deadlock when the code path takes read sem
- * twice (e.g. one in snd_pcm_action_nonatomic() and another in
- * snd_pcm_stream_lock()). As a (suboptimal) workaround, let writer to
- * sleep until all the readers are completed without blocking by writer.
- */
-static inline void down_write_nonfifo(struct rw_semaphore *lock)
+void snd_pcm_group_init(struct snd_pcm_group *group)
{
- while (!down_write_trylock(lock))
- msleep(1);
+ spin_lock_init(&group->lock);
+ mutex_init(&group->mutex);
+ INIT_LIST_HEAD(&group->substreams);
+ refcount_set(&group->refs, 0);
}
-#define PCM_LOCK_DEFAULT 0
-#define PCM_LOCK_IRQ 1
-#define PCM_LOCK_IRQSAVE 2
-
-static unsigned long __snd_pcm_stream_lock_mode(struct snd_pcm_substream *substream,
- unsigned int mode)
-{
- unsigned long flags = 0;
- if (substream->pcm->nonatomic) {
- down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
- mutex_lock(&substream->self_group.mutex);
- } else {
- switch (mode) {
- case PCM_LOCK_DEFAULT:
- read_lock(&snd_pcm_link_rwlock);
- break;
- case PCM_LOCK_IRQ:
- read_lock_irq(&snd_pcm_link_rwlock);
- break;
- case PCM_LOCK_IRQSAVE:
- read_lock_irqsave(&snd_pcm_link_rwlock, flags);
- break;
- }
- spin_lock(&substream->self_group.lock);
- }
- return flags;
+/* define group lock helpers */
+#define DEFINE_PCM_GROUP_LOCK(action, mutex_action) \
+static void snd_pcm_group_ ## action(struct snd_pcm_group *group, bool nonatomic) \
+{ \
+ if (nonatomic) \
+ mutex_ ## mutex_action(&group->mutex); \
+ else \
+ spin_ ## action(&group->lock); \
}
-static void __snd_pcm_stream_unlock_mode(struct snd_pcm_substream *substream,
- unsigned int mode, unsigned long flags)
-{
- if (substream->pcm->nonatomic) {
- mutex_unlock(&substream->self_group.mutex);
- up_read(&snd_pcm_link_rwsem);
- } else {
- spin_unlock(&substream->self_group.lock);
-
- switch (mode) {
- case PCM_LOCK_DEFAULT:
- read_unlock(&snd_pcm_link_rwlock);
- break;
- case PCM_LOCK_IRQ:
- read_unlock_irq(&snd_pcm_link_rwlock);
- break;
- case PCM_LOCK_IRQSAVE:
- read_unlock_irqrestore(&snd_pcm_link_rwlock, flags);
- break;
- }
- }
-}
+DEFINE_PCM_GROUP_LOCK(lock, lock);
+DEFINE_PCM_GROUP_LOCK(unlock, unlock);
+DEFINE_PCM_GROUP_LOCK(lock_irq, lock);
+DEFINE_PCM_GROUP_LOCK(unlock_irq, unlock);
/**
* snd_pcm_stream_lock - Lock the PCM stream
@@ -161,7 +120,7 @@ static void __snd_pcm_stream_unlock_mode(struct snd_pcm_substream *substream,
*/
void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
{
- __snd_pcm_stream_lock_mode(substream, PCM_LOCK_DEFAULT);
+ snd_pcm_group_lock(&substream->self_group, substream->pcm->nonatomic);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
@@ -173,7 +132,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
*/
void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)
{
- __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_DEFAULT, 0);
+ snd_pcm_group_unlock(&substream->self_group, substream->pcm->nonatomic);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
@@ -187,7 +146,8 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
*/
void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
{
- __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQ);
+ snd_pcm_group_lock_irq(&substream->self_group,
+ substream->pcm->nonatomic);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
@@ -199,13 +159,19 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
*/
void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)
{
- __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQ, 0);
+ snd_pcm_group_unlock_irq(&substream->self_group,
+ substream->pcm->nonatomic);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq);
unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream)
{
- return __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQSAVE);
+ unsigned long flags = 0;
+ if (substream->pcm->nonatomic)
+ mutex_lock(&substream->self_group.mutex);
+ else
+ spin_lock_irqsave(&substream->self_group.lock, flags);
+ return flags;
}
EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
@@ -219,7 +185,10 @@ EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
unsigned long flags)
{
- __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQSAVE, flags);
+ if (substream->pcm->nonatomic)
+ mutex_unlock(&substream->self_group.mutex);
+ else
+ spin_unlock_irqrestore(&substream->self_group.lock, flags);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
@@ -1124,6 +1093,68 @@ static int snd_pcm_action_single(const struct action_ops *ops,
return res;
}
+static void snd_pcm_group_assign(struct snd_pcm_substream *substream,
+ struct snd_pcm_group *new_group)
+{
+ substream->group = new_group;
+ list_move(&substream->link_list, &new_group->substreams);
+}
+
+/*
+ * Unref and unlock the group, but keep the stream lock;
+ * when the group becomes empty and no longer referred, destroy itself
+ */
+static void snd_pcm_group_unref(struct snd_pcm_group *group,
+ struct snd_pcm_substream *substream)
+{
+ bool do_free;
+
+ if (!group)
+ return;
+ do_free = refcount_dec_and_test(&group->refs) &&
+ list_empty(&group->substreams);
+ snd_pcm_group_unlock(group, substream->pcm->nonatomic);
+ if (do_free)
+ kfree(group);
+}
+
+/*
+ * Lock the group inside a stream lock and reference it;
+ * return the locked group object, or NULL if not linked
+ */
+static struct snd_pcm_group *
+snd_pcm_stream_group_ref(struct snd_pcm_substream *substream)
+{
+ bool nonatomic = substream->pcm->nonatomic;
+ struct snd_pcm_group *group;
+ bool trylock;
+
+ for (;;) {
+ if (!snd_pcm_stream_linked(substream))
+ return NULL;
+ group = substream->group;
+ /* block freeing the group object */
+ refcount_inc(&group->refs);
+
+ trylock = nonatomic ? mutex_trylock(&group->mutex) :
+ spin_trylock(&group->lock);
+ if (trylock)
+ break; /* OK */
+
+ /* re-lock for avoiding ABBA deadlock */
+ snd_pcm_stream_unlock(substream);
+ snd_pcm_group_lock(group, nonatomic);
+ snd_pcm_stream_lock(substream);
+
+ /* check the group again; the above opens a small race window */
+ if (substream->group == group)
+ break; /* OK */
+ /* group changed, try again */
+ snd_pcm_group_unref(group, substream);
+ }
+ return group;
+}
+
/*
* Note: call with stream lock
*/
@@ -1131,28 +1162,15 @@ static int snd_pcm_action(const struct action_ops *ops,
struct snd_pcm_substream *substream,
int state)
{
+ struct snd_pcm_group *group;
int res;
- if (!snd_pcm_stream_linked(substream))
- return snd_pcm_action_single(ops, substream, state);
-
- if (substream->pcm->nonatomic) {
- if (!mutex_trylock(&substream->group->mutex)) {
- mutex_unlock(&substream->self_group.mutex);
- mutex_lock(&substream->group->mutex);
- mutex_lock(&substream->self_group.mutex);
- }
+ group = snd_pcm_stream_group_ref(substream);
+ if (group)
res = snd_pcm_action_group(ops, substream, state, 1);
- mutex_unlock(&substream->group->mutex);
- } else {
- if (!spin_trylock(&substream->group->lock)) {
- spin_unlock(&substream->self_group.lock);
- spin_lock(&substream->group->lock);
- spin_lock(&substream->self_group.lock);
- }
- res = snd_pcm_action_group(ops, substream, state, 1);
- spin_unlock(&substream->group->lock);
- }
+ else
+ res = snd_pcm_action_single(ops, substream, state);
+ snd_pcm_group_unref(group, substream);
return res;
}
@@ -1179,6 +1197,7 @@ static int snd_pcm_action_nonatomic(const struct action_ops *ops,
{
int res;
+ /* Guarantee the group members won't change during non-atomic action */
down_read(&snd_pcm_link_rwsem);
if (snd_pcm_stream_linked(substream))
res = snd_pcm_action_group(ops, substream, state, 0);
@@ -1460,29 +1479,24 @@ static const struct action_ops snd_pcm_action_suspend = {
.post_action = snd_pcm_post_suspend
};
-/**
+/*
* snd_pcm_suspend - trigger SUSPEND to all linked streams
* @substream: the PCM substream
*
* After this call, all streams are changed to SUSPENDED state.
*
- * Return: Zero if successful (or @substream is %NULL), or a negative error
- * code.
+ * Return: Zero if successful, or a negative error code.
*/
-int snd_pcm_suspend(struct snd_pcm_substream *substream)
+static int snd_pcm_suspend(struct snd_pcm_substream *substream)
{
int err;
unsigned long flags;
- if (! substream)
- return 0;
-
snd_pcm_stream_lock_irqsave(substream, flags);
err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0);
snd_pcm_stream_unlock_irqrestore(substream, flags);
return err;
}
-EXPORT_SYMBOL(snd_pcm_suspend);
/**
* snd_pcm_suspend_all - trigger SUSPEND to all substreams in the given pcm
@@ -1506,6 +1520,14 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm)
/* FIXME: the open/close code should lock this as well */
if (substream->runtime == NULL)
continue;
+
+ /*
+ * Skip BE dai link PCM's that are internal and may
+ * not have their substream ops set.
+ */
+ if (!substream->ops)
+ continue;
+
err = snd_pcm_suspend(substream);
if (err < 0 && err != -EBUSY)
return err;
@@ -1792,8 +1814,6 @@ static const struct action_ops snd_pcm_action_drain_init = {
.post_action = snd_pcm_post_drain_init
};
-static int snd_pcm_drop(struct snd_pcm_substream *substream);
-
/*
* Drain the stream(s).
* When the substream is linked, sync until the draining of all playback streams
@@ -1807,6 +1827,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
struct snd_card *card;
struct snd_pcm_runtime *runtime;
struct snd_pcm_substream *s;
+ struct snd_pcm_group *group;
wait_queue_entry_t wait;
int result = 0;
int nonblock = 0;
@@ -1823,7 +1844,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
} else if (substream->f_flags & O_NONBLOCK)
nonblock = 1;
- down_read(&snd_pcm_link_rwsem);
snd_pcm_stream_lock_irq(substream);
/* resume pause */
if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
@@ -1848,6 +1868,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
}
/* find a substream to drain */
to_check = NULL;
+ group = snd_pcm_stream_group_ref(substream);
snd_pcm_group_for_each_entry(s, substream) {
if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
continue;
@@ -1857,12 +1878,12 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
break;
}
}
+ snd_pcm_group_unref(group, substream);
if (!to_check)
break; /* all drained */
init_waitqueue_entry(&wait, current);
add_wait_queue(&to_check->sleep, &wait);
snd_pcm_stream_unlock_irq(substream);
- up_read(&snd_pcm_link_rwsem);
if (runtime->no_period_wakeup)
tout = MAX_SCHEDULE_TIMEOUT;
else {
@@ -1874,9 +1895,17 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
tout = msecs_to_jiffies(tout * 1000);
}
tout = schedule_timeout_interruptible(tout);
- down_read(&snd_pcm_link_rwsem);
+
snd_pcm_stream_lock_irq(substream);
- remove_wait_queue(&to_check->sleep, &wait);
+ group = snd_pcm_stream_group_ref(substream);
+ snd_pcm_group_for_each_entry(s, substream) {
+ if (s->runtime == to_check) {
+ remove_wait_queue(&to_check->sleep, &wait);
+ break;
+ }
+ }
+ snd_pcm_group_unref(group, substream);
+
if (card->shutdown) {
result = -ENODEV;
break;
@@ -1896,7 +1925,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
unlock:
snd_pcm_stream_unlock_irq(substream);
- up_read(&snd_pcm_link_rwsem);
return result;
}
@@ -1935,13 +1963,19 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
static bool is_pcm_file(struct file *file)
{
struct inode *inode = file_inode(file);
+ struct snd_pcm *pcm;
unsigned int minor;
if (!S_ISCHR(inode->i_mode) || imajor(inode) != snd_major)
return false;
minor = iminor(inode);
- return snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) ||
- snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE);
+ pcm = snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
+ if (!pcm)
+ pcm = snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE);
+ if (!pcm)
+ return false;
+ snd_card_unref(pcm->card);
+ return true;
}
/*
@@ -1952,7 +1986,8 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
int res = 0;
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream1;
- struct snd_pcm_group *group;
+ struct snd_pcm_group *group, *target_group;
+ bool nonatomic = substream->pcm->nonatomic;
struct fd f = fdget(fd);
if (!f.file)
@@ -1963,13 +1998,14 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
}
pcm_file = f.file->private_data;
substream1 = pcm_file->substream;
- group = kmalloc(sizeof(*group), GFP_KERNEL);
+ group = kzalloc(sizeof(*group), GFP_KERNEL);
if (!group) {
res = -ENOMEM;
goto _nolock;
}
- down_write_nonfifo(&snd_pcm_link_rwsem);
- write_lock_irq(&snd_pcm_link_rwlock);
+ snd_pcm_group_init(group);
+
+ down_write(&snd_pcm_link_rwsem);
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
substream->runtime->status->state != substream1->runtime->status->state ||
substream->pcm->nonatomic != substream1->pcm->nonatomic) {
@@ -1980,23 +2016,23 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
res = -EALREADY;
goto _end;
}
+
+ snd_pcm_stream_lock_irq(substream);
if (!snd_pcm_stream_linked(substream)) {
- substream->group = group;
- group = NULL;
- spin_lock_init(&substream->group->lock);
- mutex_init(&substream->group->mutex);
- INIT_LIST_HEAD(&substream->group->substreams);
- list_add_tail(&substream->link_list, &substream->group->substreams);
- substream->group->count = 1;
- }
- list_add_tail(&substream1->link_list, &substream->group->substreams);
- substream->group->count++;
- substream1->group = substream->group;
+ snd_pcm_group_assign(substream, group);
+ group = NULL; /* assigned, don't free this one below */
+ }
+ target_group = substream->group;
+ snd_pcm_stream_unlock_irq(substream);
+
+ snd_pcm_group_lock_irq(target_group, nonatomic);
+ snd_pcm_stream_lock(substream1);
+ snd_pcm_group_assign(substream1, target_group);
+ snd_pcm_stream_unlock(substream1);
+ snd_pcm_group_unlock_irq(target_group, nonatomic);
_end:
- write_unlock_irq(&snd_pcm_link_rwlock);
up_write(&snd_pcm_link_rwsem);
_nolock:
- snd_card_unref(substream1->pcm->card);
kfree(group);
_badf:
fdput(f);
@@ -2005,34 +2041,43 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
static void relink_to_local(struct snd_pcm_substream *substream)
{
- substream->group = &substream->self_group;
- INIT_LIST_HEAD(&substream->self_group.substreams);
- list_add_tail(&substream->link_list, &substream->self_group.substreams);
+ snd_pcm_stream_lock(substream);
+ snd_pcm_group_assign(substream, &substream->self_group);
+ snd_pcm_stream_unlock(substream);
}
static int snd_pcm_unlink(struct snd_pcm_substream *substream)
{
- struct snd_pcm_substream *s;
+ struct snd_pcm_group *group;
+ bool nonatomic = substream->pcm->nonatomic;
+ bool do_free = false;
int res = 0;
- down_write_nonfifo(&snd_pcm_link_rwsem);
- write_lock_irq(&snd_pcm_link_rwlock);
+ down_write(&snd_pcm_link_rwsem);
+
if (!snd_pcm_stream_linked(substream)) {
res = -EALREADY;
goto _end;
}
- list_del(&substream->link_list);
- substream->group->count--;
- if (substream->group->count == 1) { /* detach the last stream, too */
- snd_pcm_group_for_each_entry(s, substream) {
- relink_to_local(s);
- break;
- }
- kfree(substream->group);
- }
+
+ group = substream->group;
+ snd_pcm_group_lock_irq(group, nonatomic);
+
relink_to_local(substream);
+
+ /* detach the last stream, too */
+ if (list_is_singular(&group->substreams)) {
+ relink_to_local(list_first_entry(&group->substreams,
+ struct snd_pcm_substream,
+ link_list));
+ do_free = !refcount_read(&group->refs);
+ }
+
+ snd_pcm_group_unlock_irq(group, nonatomic);
+ if (do_free)
+ kfree(group);
+
_end:
- write_unlock_irq(&snd_pcm_link_rwlock);
up_write(&snd_pcm_link_rwsem);
return res;
}
@@ -2457,10 +2502,8 @@ static int snd_pcm_open_file(struct file *file,
return -ENOMEM;
}
pcm_file->substream = substream;
- if (substream->ref_count == 1) {
- substream->file = pcm_file;
+ if (substream->ref_count == 1)
substream->pcm_release = pcm_release_private;
- }
file->private_data = pcm_file;
return 0;
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 1e34e6381baa..8c3fbe1276be 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -1133,16 +1133,10 @@ static void print_cable_info(struct snd_info_entry *entry,
static int loopback_proc_new(struct loopback *loopback, int cidx)
{
char name[32];
- struct snd_info_entry *entry;
- int err;
snprintf(name, sizeof(name), "cable#%d", cidx);
- err = snd_card_proc_new(loopback->card, name, &entry);
- if (err < 0)
- return err;
-
- snd_info_set_text_ops(entry, loopback, print_cable_info);
- return 0;
+ return snd_card_ro_proc_new(loopback->card, name, loopback,
+ print_cable_info);
}
static int loopback_probe(struct platform_device *devptr)
@@ -1200,12 +1194,8 @@ static int loopback_remove(struct platform_device *devptr)
static int loopback_suspend(struct device *pdev)
{
struct snd_card *card = dev_get_drvdata(pdev);
- struct loopback *loopback = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-
- snd_pcm_suspend_all(loopback->pcm[0]);
- snd_pcm_suspend_all(loopback->pcm[1]);
return 0;
}
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 9af154db530a..2672c2e13334 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -1037,14 +1037,8 @@ static void dummy_proc_write(struct snd_info_entry *entry,
static void dummy_proc_init(struct snd_dummy *chip)
{
- struct snd_info_entry *entry;
-
- if (!snd_card_proc_new(chip->card, "dummy_pcm", &entry)) {
- snd_info_set_text_ops(entry, chip, dummy_proc_read);
- entry->c.text.write = dummy_proc_write;
- entry->mode |= 0200;
- entry->private_data = chip;
- }
+ snd_card_rw_proc_new(chip->card, "dummy_pcm", chip,
+ dummy_proc_read, dummy_proc_write);
}
#else
#define dummy_proc_init(x)
@@ -1138,10 +1132,8 @@ static int snd_dummy_remove(struct platform_device *devptr)
static int snd_dummy_suspend(struct device *pdev)
{
struct snd_card *card = dev_get_drvdata(pdev);
- struct snd_dummy *dummy = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(dummy->pcm);
return 0;
}
diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c
index 16b24091d799..f1b839a0e7b7 100644
--- a/sound/drivers/opl4/opl4_proc.c
+++ b/sound/drivers/opl4/opl4_proc.c
@@ -114,10 +114,6 @@ int snd_opl4_create_proc(struct snd_opl4 *opl4)
entry->c.ops = &snd_opl4_mem_proc_ops;
entry->module = THIS_MODULE;
entry->private_data = opl4;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
}
opl4->proc_entry = entry;
return 0;
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index 0dd3f46eb03e..d83ad3820f02 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -197,7 +197,6 @@ static int pcsp_suspend(struct device *dev)
{
struct snd_pcsp *chip = dev_get_drvdata(dev);
pcsp_stop_beep(chip);
- snd_pcm_suspend_all(chip->pcm);
return 0;
}
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index 04368dd59a4c..543945643a76 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -643,10 +643,7 @@ static void vx_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *b
static void vx_proc_init(struct vx_core *chip)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(chip->card, "vx-status", &entry))
- snd_info_set_text_ops(entry, chip, vx_proc_read);
+ snd_card_ro_proc_new(chip->card, "vx-status", chip, vx_proc_read);
}
@@ -732,12 +729,8 @@ EXPORT_SYMBOL(snd_vx_dsp_load);
*/
int snd_vx_suspend(struct vx_core *chip)
{
- unsigned int i;
-
snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
chip->chip_status |= VX_STAT_IN_SUSPEND;
- for (i = 0; i < chip->hw->num_codecs; i++)
- snd_pcm_suspend_all(chip->pcm[i]);
return 0;
}
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig
index 052e00590259..b9e96d0b3a0a 100644
--- a/sound/firewire/Kconfig
+++ b/sound/firewire/Kconfig
@@ -163,5 +163,6 @@ config SND_FIREFACE
Say Y here to include support for RME fireface series.
* Fireface 400
* Fireface 800
+ * Fireface UCX
endif # SND_FIREWIRE
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c
index d91874275d2c..5b46e8dcc2dd 100644
--- a/sound/firewire/bebob/bebob.c
+++ b/sound/firewire/bebob/bebob.c
@@ -448,7 +448,19 @@ static const struct ieee1394_device_id bebob_id_table[] = {
/* Focusrite, SaffirePro 26 I/O */
SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x00000003, &saffirepro_26_spec),
/* Focusrite, SaffirePro 10 I/O */
- SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x00000006, &saffirepro_10_spec),
+ {
+ // The combination of vendor_id and model_id is the same as the
+ // same as the one of Liquid Saffire 56.
+ .match_flags = IEEE1394_MATCH_VENDOR_ID |
+ IEEE1394_MATCH_MODEL_ID |
+ IEEE1394_MATCH_SPECIFIER_ID |
+ IEEE1394_MATCH_VERSION,
+ .vendor_id = VEN_FOCUSRITE,
+ .model_id = 0x000006,
+ .specifier_id = 0x00a02d,
+ .version = 0x010001,
+ .driver_data = (kernel_ulong_t)&saffirepro_10_spec,
+ },
/* Focusrite, Saffire(no label and LE) */
SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, MODEL_FOCUSRITE_SAFFIRE_BOTH,
&saffire_spec),
diff --git a/sound/firewire/bebob/bebob_proc.c b/sound/firewire/bebob/bebob_proc.c
index 8096891af913..05e2a1c6326c 100644
--- a/sound/firewire/bebob/bebob_proc.c
+++ b/sound/firewire/bebob/bebob_proc.c
@@ -163,12 +163,8 @@ add_node(struct snd_bebob *bebob, struct snd_info_entry *root, const char *name,
struct snd_info_entry *entry;
entry = snd_info_create_card_entry(bebob->card, name, root);
- if (entry == NULL)
- return;
-
- snd_info_set_text_ops(entry, bebob, op);
- if (snd_info_register(entry) < 0)
- snd_info_free_entry(entry);
+ if (entry)
+ snd_info_set_text_ops(entry, bebob, op);
}
void snd_bebob_proc_init(struct snd_bebob *bebob)
@@ -184,10 +180,6 @@ void snd_bebob_proc_init(struct snd_bebob *bebob)
if (root == NULL)
return;
root->mode = S_IFDIR | 0555;
- if (snd_info_register(root) < 0) {
- snd_info_free_entry(root);
- return;
- }
add_node(bebob, root, "clock", proc_read_clock);
add_node(bebob, root, "firmware", proc_read_hw_info);
diff --git a/sound/firewire/dice/dice-proc.c b/sound/firewire/dice/dice-proc.c
index bb870fc73f99..9b1d509c6320 100644
--- a/sound/firewire/dice/dice-proc.c
+++ b/sound/firewire/dice/dice-proc.c
@@ -285,12 +285,8 @@ static void add_node(struct snd_dice *dice, struct snd_info_entry *root,
struct snd_info_entry *entry;
entry = snd_info_create_card_entry(dice->card, name, root);
- if (!entry)
- return;
-
- snd_info_set_text_ops(entry, dice, op);
- if (snd_info_register(entry) < 0)
- snd_info_free_entry(entry);
+ if (entry)
+ snd_info_set_text_ops(entry, dice, op);
}
void snd_dice_create_proc(struct snd_dice *dice)
@@ -306,10 +302,6 @@ void snd_dice_create_proc(struct snd_dice *dice)
if (!root)
return;
root->mode = S_IFDIR | 0555;
- if (snd_info_register(root) < 0) {
- snd_info_free_entry(root);
- return;
- }
add_node(dice, root, "dice", dice_proc_read);
add_node(dice, root, "formation", dice_proc_read_formation);
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c
index ed50b222d36e..eee184b05d93 100644
--- a/sound/firewire/dice/dice.c
+++ b/sound/firewire/dice/dice.c
@@ -18,6 +18,7 @@ MODULE_LICENSE("GPL v2");
#define OUI_ALESIS 0x000595
#define OUI_MAUDIO 0x000d6c
#define OUI_MYTEK 0x001ee8
+#define OUI_SSL 0x0050c2 // Actually ID reserved by IEEE.
#define DICE_CATEGORY_ID 0x04
#define WEISS_CATEGORY_ID 0x00
@@ -196,7 +197,7 @@ static int dice_probe(struct fw_unit *unit,
struct snd_dice *dice;
int err;
- if (!entry->driver_data) {
+ if (!entry->driver_data && entry->vendor_id != OUI_SSL) {
err = check_dice_category(unit);
if (err < 0)
return -ENODEV;
@@ -361,6 +362,15 @@ static const struct ieee1394_device_id dice_id_table[] = {
.model_id = 0x000002,
.driver_data = (kernel_ulong_t)snd_dice_detect_mytek_formats,
},
+ // Solid State Logic, Duende Classic and Mini.
+ // NOTE: each field of GUID in config ROM is not compliant to standard
+ // DICE scheme.
+ {
+ .match_flags = IEEE1394_MATCH_VENDOR_ID |
+ IEEE1394_MATCH_MODEL_ID,
+ .vendor_id = OUI_SSL,
+ .model_id = 0x000070,
+ },
{
.match_flags = IEEE1394_MATCH_VERSION,
.version = DICE_INTERFACE,
diff --git a/sound/firewire/digi00x/digi00x-proc.c b/sound/firewire/digi00x/digi00x-proc.c
index 6996d5a6ff5f..d22e8675b10f 100644
--- a/sound/firewire/digi00x/digi00x-proc.c
+++ b/sound/firewire/digi00x/digi00x-proc.c
@@ -80,20 +80,8 @@ void snd_dg00x_proc_init(struct snd_dg00x *dg00x)
return;
root->mode = S_IFDIR | 0555;
- if (snd_info_register(root) < 0) {
- snd_info_free_entry(root);
- return;
- }
entry = snd_info_create_card_entry(dg00x->card, "clock", root);
- if (entry == NULL) {
- snd_info_free_entry(root);
- return;
- }
-
- snd_info_set_text_ops(entry, dg00x, proc_read_clock);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- snd_info_free_entry(root);
- }
+ if (entry)
+ snd_info_set_text_ops(entry, dg00x, proc_read_clock);
}
diff --git a/sound/firewire/fireface/Makefile b/sound/firewire/fireface/Makefile
index 79a7d6d99d72..d64f4e2a1096 100644
--- a/sound/firewire/fireface/Makefile
+++ b/sound/firewire/fireface/Makefile
@@ -1,4 +1,4 @@
snd-fireface-objs := ff.o ff-transaction.o ff-midi.o ff-proc.o amdtp-ff.o \
- ff-stream.o ff-pcm.o ff-hwdep.o ff-protocol-ff400.o \
- ff-protocol-ff800.o
+ ff-stream.o ff-pcm.o ff-hwdep.o ff-protocol-former.o \
+ ff-protocol-latter.o
obj-$(CONFIG_SND_FIREFACE) += snd-fireface.o
diff --git a/sound/firewire/fireface/ff-midi.c b/sound/firewire/fireface/ff-midi.c
index 6a49611ee462..5b44e1c4569a 100644
--- a/sound/firewire/fireface/ff-midi.c
+++ b/sound/firewire/fireface/ff-midi.c
@@ -19,7 +19,7 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream)
struct snd_ff *ff = substream->rmidi->private_data;
/* Initialize internal status. */
- ff->running_status[substream->number] = 0;
+ ff->on_sysex[substream->number] = 0;
ff->rx_midi_error[substream->number] = false;
WRITE_ONCE(ff->rx_midi_substreams[substream->number], substream);
diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c
index d0bc96b20a65..5adf04b95c04 100644
--- a/sound/firewire/fireface/ff-pcm.c
+++ b/sound/firewire/fireface/ff-pcm.c
@@ -152,7 +152,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
if (err < 0)
goto release_lock;
- err = snd_ff_transaction_get_clock(ff, &rate, &src);
+ err = ff->spec->protocol->get_clock(ff, &rate, &src);
if (err < 0)
goto release_lock;
diff --git a/sound/firewire/fireface/ff-proc.c b/sound/firewire/fireface/ff-proc.c
index a0c550dabe9a..b886b541c94b 100644
--- a/sound/firewire/fireface/ff-proc.c
+++ b/sound/firewire/fireface/ff-proc.c
@@ -8,209 +8,29 @@
#include "./ff.h"
-static void proc_dump_clock_config(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
+const char *snd_ff_proc_get_clk_label(enum snd_ff_clock_src src)
{
- struct snd_ff *ff = entry->private_data;
- __le32 reg;
- u32 data;
- unsigned int rate;
- const char *src;
- int err;
-
- err = snd_fw_transaction(ff->unit, TCODE_READ_BLOCK_REQUEST,
- SND_FF_REG_CLOCK_CONFIG, &reg, sizeof(reg), 0);
- if (err < 0)
- return;
-
- data = le32_to_cpu(reg);
-
- snd_iprintf(buffer, "Output S/PDIF format: %s (Emphasis: %s)\n",
- (data & 0x20) ? "Professional" : "Consumer",
- (data & 0x40) ? "on" : "off");
-
- snd_iprintf(buffer, "Optical output interface format: %s\n",
- ((data >> 8) & 0x01) ? "S/PDIF" : "ADAT");
-
- snd_iprintf(buffer, "Word output single speed: %s\n",
- ((data >> 8) & 0x20) ? "on" : "off");
-
- snd_iprintf(buffer, "S/PDIF input interface: %s\n",
- ((data >> 8) & 0x02) ? "Optical" : "Coaxial");
-
- switch ((data >> 1) & 0x03) {
- case 0x01:
- rate = 32000;
- break;
- case 0x00:
- rate = 44100;
- break;
- case 0x03:
- rate = 48000;
- break;
- case 0x02:
- default:
- return;
- }
-
- if (data & 0x08)
- rate *= 2;
- else if (data & 0x10)
- rate *= 4;
-
- snd_iprintf(buffer, "Sampling rate: %d\n", rate);
-
- if (data & 0x01) {
- src = "Internal";
- } else {
- switch ((data >> 10) & 0x07) {
- case 0x00:
- src = "ADAT1";
- break;
- case 0x01:
- src = "ADAT2";
- break;
- case 0x03:
- src = "S/PDIF";
- break;
- case 0x04:
- src = "Word";
- break;
- case 0x05:
- src = "LTC";
- break;
- default:
- return;
- }
- }
-
- snd_iprintf(buffer, "Sync to clock source: %s\n", src);
+ static const char *const labels[] = {
+ "Internal",
+ "S/PDIF",
+ "ADAT1",
+ "ADAT2",
+ "Word",
+ "LTC",
+ };
+
+ if (src >= ARRAY_SIZE(labels))
+ return NULL;
+
+ return labels[src];
}
-static void proc_dump_sync_status(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
+static void proc_dump_status(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
struct snd_ff *ff = entry->private_data;
- __le32 reg;
- u32 data;
- int err;
- err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
- SND_FF_REG_SYNC_STATUS, &reg, sizeof(reg), 0);
- if (err < 0)
- return;
-
- data = le32_to_cpu(reg);
-
- snd_iprintf(buffer, "External source detection:\n");
-
- snd_iprintf(buffer, "Word Clock:");
- if ((data >> 24) & 0x20) {
- if ((data >> 24) & 0x40)
- snd_iprintf(buffer, "sync\n");
- else
- snd_iprintf(buffer, "lock\n");
- } else {
- snd_iprintf(buffer, "none\n");
- }
-
- snd_iprintf(buffer, "S/PDIF:");
- if ((data >> 16) & 0x10) {
- if ((data >> 16) & 0x04)
- snd_iprintf(buffer, "sync\n");
- else
- snd_iprintf(buffer, "lock\n");
- } else {
- snd_iprintf(buffer, "none\n");
- }
-
- snd_iprintf(buffer, "ADAT1:");
- if ((data >> 8) & 0x04) {
- if ((data >> 8) & 0x10)
- snd_iprintf(buffer, "sync\n");
- else
- snd_iprintf(buffer, "lock\n");
- } else {
- snd_iprintf(buffer, "none\n");
- }
-
- snd_iprintf(buffer, "ADAT2:");
- if ((data >> 8) & 0x08) {
- if ((data >> 8) & 0x20)
- snd_iprintf(buffer, "sync\n");
- else
- snd_iprintf(buffer, "lock\n");
- } else {
- snd_iprintf(buffer, "none\n");
- }
-
- snd_iprintf(buffer, "\nUsed external source:\n");
-
- if (((data >> 22) & 0x07) == 0x07) {
- snd_iprintf(buffer, "None\n");
- } else {
- switch ((data >> 22) & 0x07) {
- case 0x00:
- snd_iprintf(buffer, "ADAT1:");
- break;
- case 0x01:
- snd_iprintf(buffer, "ADAT2:");
- break;
- case 0x03:
- snd_iprintf(buffer, "S/PDIF:");
- break;
- case 0x04:
- snd_iprintf(buffer, "Word:");
- break;
- case 0x07:
- snd_iprintf(buffer, "Nothing:");
- break;
- case 0x02:
- case 0x05:
- case 0x06:
- default:
- snd_iprintf(buffer, "unknown:");
- break;
- }
-
- if ((data >> 25) & 0x07) {
- switch ((data >> 25) & 0x07) {
- case 0x01:
- snd_iprintf(buffer, "32000\n");
- break;
- case 0x02:
- snd_iprintf(buffer, "44100\n");
- break;
- case 0x03:
- snd_iprintf(buffer, "48000\n");
- break;
- case 0x04:
- snd_iprintf(buffer, "64000\n");
- break;
- case 0x05:
- snd_iprintf(buffer, "88200\n");
- break;
- case 0x06:
- snd_iprintf(buffer, "96000\n");
- break;
- case 0x07:
- snd_iprintf(buffer, "128000\n");
- break;
- case 0x08:
- snd_iprintf(buffer, "176400\n");
- break;
- case 0x09:
- snd_iprintf(buffer, "192000\n");
- break;
- case 0x00:
- snd_iprintf(buffer, "unknown\n");
- break;
- }
- }
- }
-
- snd_iprintf(buffer, "Multiplied:");
- snd_iprintf(buffer, "%d\n", (data & 0x3ff) * 250);
+ ff->spec->protocol->dump_status(ff, buffer);
}
static void add_node(struct snd_ff *ff, struct snd_info_entry *root,
@@ -221,12 +41,8 @@ static void add_node(struct snd_ff *ff, struct snd_info_entry *root,
struct snd_info_entry *entry;
entry = snd_info_create_card_entry(ff->card, name, root);
- if (entry == NULL)
- return;
-
- snd_info_set_text_ops(entry, ff, op);
- if (snd_info_register(entry) < 0)
- snd_info_free_entry(entry);
+ if (entry)
+ snd_info_set_text_ops(entry, ff, op);
}
void snd_ff_proc_init(struct snd_ff *ff)
@@ -242,11 +58,6 @@ void snd_ff_proc_init(struct snd_ff *ff)
if (root == NULL)
return;
root->mode = S_IFDIR | 0555;
- if (snd_info_register(root) < 0) {
- snd_info_free_entry(root);
- return;
- }
- add_node(ff, root, "clock-config", proc_dump_clock_config);
- add_node(ff, root, "sync-status", proc_dump_sync_status);
+ add_node(ff, root, "status", proc_dump_status);
}
diff --git a/sound/firewire/fireface/ff-protocol-ff400.c b/sound/firewire/fireface/ff-protocol-ff400.c
deleted file mode 100644
index 2280fab9b3c7..000000000000
--- a/sound/firewire/fireface/ff-protocol-ff400.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * ff-protocol-ff400.c - a part of driver for RME Fireface series
- *
- * Copyright (c) 2015-2017 Takashi Sakamoto
- *
- * Licensed under the terms of the GNU General Public License, version 2.
- */
-
-#include <linux/delay.h>
-#include "ff.h"
-
-#define FF400_STF 0x000080100500ull
-#define FF400_RX_PACKET_FORMAT 0x000080100504ull
-#define FF400_ISOC_COMM_START 0x000080100508ull
-#define FF400_TX_PACKET_FORMAT 0x00008010050cull
-#define FF400_ISOC_COMM_STOP 0x000080100510ull
-
-/*
- * Fireface 400 manages isochronous channel number in 3 bit field. Therefore,
- * we can allocate between 0 and 7 channel.
- */
-static int keep_resources(struct snd_ff *ff, unsigned int rate)
-{
- enum snd_ff_stream_mode mode;
- int i;
- int err;
-
- // Check whether the given value is supported or not.
- for (i = 0; i < CIP_SFC_COUNT; i++) {
- if (amdtp_rate_table[i] == rate)
- break;
- }
- if (i >= CIP_SFC_COUNT)
- return -EINVAL;
-
- err = snd_ff_stream_get_multiplier_mode(i, &mode);
- if (err < 0)
- return err;
-
- /* Keep resources for in-stream. */
- ff->tx_resources.channels_mask = 0x00000000000000ffuLL;
- err = fw_iso_resources_allocate(&ff->tx_resources,
- amdtp_stream_get_max_payload(&ff->tx_stream),
- fw_parent_device(ff->unit)->max_speed);
- if (err < 0)
- return err;
-
- /* Keep resources for out-stream. */
- err = amdtp_ff_set_parameters(&ff->rx_stream, rate,
- ff->spec->pcm_playback_channels[mode]);
- if (err < 0)
- return err;
- ff->rx_resources.channels_mask = 0x00000000000000ffuLL;
- err = fw_iso_resources_allocate(&ff->rx_resources,
- amdtp_stream_get_max_payload(&ff->rx_stream),
- fw_parent_device(ff->unit)->max_speed);
- if (err < 0)
- fw_iso_resources_free(&ff->tx_resources);
-
- return err;
-}
-
-static int ff400_begin_session(struct snd_ff *ff, unsigned int rate)
-{
- __le32 reg;
- int err;
-
- err = keep_resources(ff, rate);
- if (err < 0)
- return err;
-
- /* Set the number of data blocks transferred in a second. */
- reg = cpu_to_le32(rate);
- err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
- FF400_STF, &reg, sizeof(reg), 0);
- if (err < 0)
- return err;
-
- msleep(100);
-
- /*
- * Set isochronous channel and the number of quadlets of received
- * packets.
- */
- reg = cpu_to_le32(((ff->rx_stream.data_block_quadlets << 3) << 8) |
- ff->rx_resources.channel);
- err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
- FF400_RX_PACKET_FORMAT, &reg, sizeof(reg), 0);
- if (err < 0)
- return err;
-
- /*
- * Set isochronous channel and the number of quadlets of transmitted
- * packet.
- */
- /* TODO: investigate the purpose of this 0x80. */
- reg = cpu_to_le32((0x80 << 24) |
- (ff->tx_resources.channel << 5) |
- (ff->tx_stream.data_block_quadlets));
- err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
- FF400_TX_PACKET_FORMAT, &reg, sizeof(reg), 0);
- if (err < 0)
- return err;
-
- /* Allow to transmit packets. */
- reg = cpu_to_le32(0x00000001);
- return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
- FF400_ISOC_COMM_START, &reg, sizeof(reg), 0);
-}
-
-static void ff400_finish_session(struct snd_ff *ff)
-{
- __le32 reg;
-
- reg = cpu_to_le32(0x80000000);
- snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
- FF400_ISOC_COMM_STOP, &reg, sizeof(reg), 0);
-}
-
-static void ff400_handle_midi_msg(struct snd_ff *ff, __le32 *buf, size_t length)
-{
- int i;
-
- for (i = 0; i < length / 4; i++) {
- u32 quad = le32_to_cpu(buf[i]);
- u8 byte;
- unsigned int index;
- struct snd_rawmidi_substream *substream;
-
- /* Message in first port. */
- /*
- * This value may represent the index of this unit when the same
- * units are on the same IEEE 1394 bus. This driver doesn't use
- * it.
- */
- index = (quad >> 8) & 0xff;
- if (index > 0) {
- substream = READ_ONCE(ff->tx_midi_substreams[0]);
- if (substream != NULL) {
- byte = quad & 0xff;
- snd_rawmidi_receive(substream, &byte, 1);
- }
- }
-
- /* Message in second port. */
- index = (quad >> 24) & 0xff;
- if (index > 0) {
- substream = READ_ONCE(ff->tx_midi_substreams[1]);
- if (substream != NULL) {
- byte = (quad >> 16) & 0xff;
- snd_rawmidi_receive(substream, &byte, 1);
- }
- }
- }
-}
-
-const struct snd_ff_protocol snd_ff_protocol_ff400 = {
- .handle_midi_msg = ff400_handle_midi_msg,
- .begin_session = ff400_begin_session,
- .finish_session = ff400_finish_session,
-};
diff --git a/sound/firewire/fireface/ff-protocol-ff800.c b/sound/firewire/fireface/ff-protocol-ff800.c
deleted file mode 100644
index 2acbf6039770..000000000000
--- a/sound/firewire/fireface/ff-protocol-ff800.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * ff-protocol-ff800.c - a part of driver for RME Fireface series
- *
- * Copyright (c) 2018 Takashi Sakamoto
- *
- * Licensed under the terms of the GNU General Public License, version 2.
- */
-
-#include <linux/delay.h>
-
-#include "ff.h"
-
-#define FF800_STF 0x0000fc88f000
-#define FF800_RX_PACKET_FORMAT 0x0000fc88f004
-#define FF800_ALLOC_TX_STREAM 0x0000fc88f008
-#define FF800_ISOC_COMM_START 0x0000fc88f00c
-#define FF800_TX_S800_FLAG 0x00000800
-#define FF800_ISOC_COMM_STOP 0x0000fc88f010
-
-#define FF800_TX_PACKET_ISOC_CH 0x0000801c0008
-
-static int allocate_rx_resources(struct snd_ff *ff)
-{
- u32 data;
- __le32 reg;
- int err;
-
- // Controllers should allocate isochronous resources for rx stream.
- err = fw_iso_resources_allocate(&ff->rx_resources,
- amdtp_stream_get_max_payload(&ff->rx_stream),
- fw_parent_device(ff->unit)->max_speed);
- if (err < 0)
- return err;
-
- // Set isochronous channel and the number of quadlets of rx packets.
- data = ff->rx_stream.data_block_quadlets << 3;
- data = (data << 8) | ff->rx_resources.channel;
- reg = cpu_to_le32(data);
- return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
- FF800_RX_PACKET_FORMAT, &reg, sizeof(reg), 0);
-}
-
-static int allocate_tx_resources(struct snd_ff *ff)
-{
- __le32 reg;
- unsigned int count;
- unsigned int tx_isoc_channel;
- int err;
-
- reg = cpu_to_le32(ff->tx_stream.data_block_quadlets);
- err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
- FF800_ALLOC_TX_STREAM, &reg, sizeof(reg), 0);
- if (err < 0)
- return err;
-
- // Wait till the format of tx packet is available.
- count = 0;
- while (count++ < 10) {
- u32 data;
- err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
- FF800_TX_PACKET_ISOC_CH, &reg, sizeof(reg), 0);
- if (err < 0)
- return err;
-
- data = le32_to_cpu(reg);
- if (data != 0xffffffff) {
- tx_isoc_channel = data;
- break;
- }
-
- msleep(50);
- }
- if (count >= 10)
- return -ETIMEDOUT;
-
- // NOTE: this is a makeshift to start OHCI 1394 IR context in the
- // channel. On the other hand, 'struct fw_iso_resources.allocated' is
- // not true and it's not deallocated at stop.
- ff->tx_resources.channel = tx_isoc_channel;
-
- return 0;
-}
-
-static int ff800_begin_session(struct snd_ff *ff, unsigned int rate)
-{
- __le32 reg;
- int err;
-
- reg = cpu_to_le32(rate);
- err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
- FF800_STF, &reg, sizeof(reg), 0);
- if (err < 0)
- return err;
-
- // If starting isochronous communication immediately, change of STF has
- // no effect. In this case, the communication runs based on former STF.
- // Let's sleep for a bit.
- msleep(100);
-
- err = allocate_rx_resources(ff);
- if (err < 0)
- return err;
-
- err = allocate_tx_resources(ff);
- if (err < 0)
- return err;
-
- reg = cpu_to_le32(0x80000000);
- reg |= cpu_to_le32(ff->tx_stream.data_block_quadlets);
- if (fw_parent_device(ff->unit)->max_speed == SCODE_800)
- reg |= cpu_to_le32(FF800_TX_S800_FLAG);
- return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
- FF800_ISOC_COMM_START, &reg, sizeof(reg), 0);
-}
-
-static void ff800_finish_session(struct snd_ff *ff)
-{
- __le32 reg;
-
- reg = cpu_to_le32(0x80000000);
- snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
- FF800_ISOC_COMM_STOP, &reg, sizeof(reg), 0);
-}
-
-static void ff800_handle_midi_msg(struct snd_ff *ff, __le32 *buf, size_t length)
-{
- int i;
-
- for (i = 0; i < length / 4; i++) {
- u8 byte = le32_to_cpu(buf[i]) & 0xff;
- struct snd_rawmidi_substream *substream;
-
- substream = READ_ONCE(ff->tx_midi_substreams[0]);
- if (substream)
- snd_rawmidi_receive(substream, &byte, 1);
- }
-}
-
-const struct snd_ff_protocol snd_ff_protocol_ff800 = {
- .handle_midi_msg = ff800_handle_midi_msg,
- .begin_session = ff800_begin_session,
- .finish_session = ff800_finish_session,
-};
diff --git a/sound/firewire/fireface/ff-protocol-former.c b/sound/firewire/fireface/ff-protocol-former.c
new file mode 100644
index 000000000000..8d1c2c6e907b
--- /dev/null
+++ b/sound/firewire/fireface/ff-protocol-former.c
@@ -0,0 +1,597 @@
+// SPDX-License-Identifier: GPL-2.0
+// ff-protocol-former.c - a part of driver for RME Fireface series
+//
+// Copyright (c) 2019 Takashi Sakamoto
+//
+// Licensed under the terms of the GNU General Public License, version 2.
+
+#include <linux/delay.h>
+
+#include "ff.h"
+
+#define FORMER_REG_SYNC_STATUS 0x0000801c0000ull
+/* For block write request. */
+#define FORMER_REG_FETCH_PCM_FRAMES 0x0000801c0000ull
+#define FORMER_REG_CLOCK_CONFIG 0x0000801c0004ull
+
+static int parse_clock_bits(u32 data, unsigned int *rate,
+ enum snd_ff_clock_src *src)
+{
+ static const struct {
+ unsigned int rate;
+ u32 mask;
+ } *rate_entry, rate_entries[] = {
+ { 32000, 0x00000002, },
+ { 44100, 0x00000000, },
+ { 48000, 0x00000006, },
+ { 64000, 0x0000000a, },
+ { 88200, 0x00000008, },
+ { 96000, 0x0000000e, },
+ { 128000, 0x00000012, },
+ { 176400, 0x00000010, },
+ { 192000, 0x00000016, },
+ };
+ static const struct {
+ enum snd_ff_clock_src src;
+ u32 mask;
+ } *clk_entry, clk_entries[] = {
+ { SND_FF_CLOCK_SRC_ADAT1, 0x00000000, },
+ { SND_FF_CLOCK_SRC_ADAT2, 0x00000400, },
+ { SND_FF_CLOCK_SRC_SPDIF, 0x00000c00, },
+ { SND_FF_CLOCK_SRC_WORD, 0x00001000, },
+ { SND_FF_CLOCK_SRC_LTC, 0x00001800, },
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) {
+ rate_entry = rate_entries + i;
+ if ((data & 0x0000001e) == rate_entry->mask) {
+ *rate = rate_entry->rate;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(rate_entries))
+ return -EIO;
+
+ if (data & 0x00000001) {
+ *src = SND_FF_CLOCK_SRC_INTERNAL;
+ } else {
+ for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
+ clk_entry = clk_entries + i;
+ if ((data & 0x00001c00) == clk_entry->mask) {
+ *src = clk_entry->src;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(clk_entries))
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int former_get_clock(struct snd_ff *ff, unsigned int *rate,
+ enum snd_ff_clock_src *src)
+{
+ __le32 reg;
+ u32 data;
+ int err;
+
+ err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
+ FORMER_REG_CLOCK_CONFIG, &reg, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+ data = le32_to_cpu(reg);
+
+ return parse_clock_bits(data, rate, src);
+}
+
+static int former_switch_fetching_mode(struct snd_ff *ff, bool enable)
+{
+ unsigned int count;
+ __le32 *reg;
+ int i;
+ int err;
+
+ count = 0;
+ for (i = 0; i < SND_FF_STREAM_MODE_COUNT; ++i)
+ count = max(count, ff->spec->pcm_playback_channels[i]);
+
+ reg = kcalloc(count, sizeof(__le32), GFP_KERNEL);
+ if (!reg)
+ return -ENOMEM;
+
+ if (!enable) {
+ /*
+ * Each quadlet is corresponding to data channels in a data
+ * blocks in reverse order. Precisely, quadlets for available
+ * data channels should be enabled. Here, I take second best
+ * to fetch PCM frames from all of data channels regardless of
+ * stf.
+ */
+ for (i = 0; i < count; ++i)
+ reg[i] = cpu_to_le32(0x00000001);
+ }
+
+ err = snd_fw_transaction(ff->unit, TCODE_WRITE_BLOCK_REQUEST,
+ FORMER_REG_FETCH_PCM_FRAMES, reg,
+ sizeof(__le32) * count, 0);
+ kfree(reg);
+ return err;
+}
+
+static void dump_clock_config(struct snd_ff *ff, struct snd_info_buffer *buffer)
+{
+ __le32 reg;
+ u32 data;
+ unsigned int rate;
+ enum snd_ff_clock_src src;
+ const char *label;
+ int err;
+
+ err = snd_fw_transaction(ff->unit, TCODE_READ_BLOCK_REQUEST,
+ FORMER_REG_CLOCK_CONFIG, &reg, sizeof(reg), 0);
+ if (err < 0)
+ return;
+ data = le32_to_cpu(reg);
+
+ snd_iprintf(buffer, "Output S/PDIF format: %s (Emphasis: %s)\n",
+ (data & 0x00000020) ? "Professional" : "Consumer",
+ (data & 0x00000040) ? "on" : "off");
+
+ snd_iprintf(buffer, "Optical output interface format: %s\n",
+ (data & 0x00000100) ? "S/PDIF" : "ADAT");
+
+ snd_iprintf(buffer, "Word output single speed: %s\n",
+ (data & 0x00002000) ? "on" : "off");
+
+ snd_iprintf(buffer, "S/PDIF input interface: %s\n",
+ (data & 0x00000200) ? "Optical" : "Coaxial");
+
+ err = parse_clock_bits(data, &rate, &src);
+ if (err < 0)
+ return;
+ label = snd_ff_proc_get_clk_label(src);
+ if (!label)
+ return;
+
+ snd_iprintf(buffer, "Clock configuration: %d %s\n", rate, label);
+}
+
+static void dump_sync_status(struct snd_ff *ff, struct snd_info_buffer *buffer)
+{
+ static const struct {
+ char *const label;
+ u32 locked_mask;
+ u32 synced_mask;
+ } *clk_entry, clk_entries[] = {
+ { "WDClk", 0x40000000, 0x20000000, },
+ { "S/PDIF", 0x00080000, 0x00040000, },
+ { "ADAT1", 0x00000400, 0x00001000, },
+ { "ADAT2", 0x00000800, 0x00002000, },
+ };
+ static const struct {
+ char *const label;
+ u32 mask;
+ } *referred_entry, referred_entries[] = {
+ { "ADAT1", 0x00000000, },
+ { "ADAT2", 0x00400000, },
+ { "S/PDIF", 0x00c00000, },
+ { "WDclk", 0x01000000, },
+ { "TCO", 0x01400000, },
+ };
+ static const struct {
+ unsigned int rate;
+ u32 mask;
+ } *rate_entry, rate_entries[] = {
+ { 32000, 0x02000000, },
+ { 44100, 0x04000000, },
+ { 48000, 0x06000000, },
+ { 64000, 0x08000000, },
+ { 88200, 0x0a000000, },
+ { 96000, 0x0c000000, },
+ { 128000, 0x0e000000, },
+ { 176400, 0x10000000, },
+ { 192000, 0x12000000, },
+ };
+ __le32 reg[2];
+ u32 data[2];
+ int i;
+ int err;
+
+ err = snd_fw_transaction(ff->unit, TCODE_READ_BLOCK_REQUEST,
+ FORMER_REG_SYNC_STATUS, reg, sizeof(reg), 0);
+ if (err < 0)
+ return;
+ data[0] = le32_to_cpu(reg[0]);
+ data[1] = le32_to_cpu(reg[1]);
+
+ snd_iprintf(buffer, "External source detection:\n");
+
+ for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
+ const char *state;
+
+ clk_entry = clk_entries + i;
+ if (data[0] & clk_entry->locked_mask) {
+ if (data[0] & clk_entry->synced_mask)
+ state = "sync";
+ else
+ state = "lock";
+ } else {
+ state = "none";
+ }
+
+ snd_iprintf(buffer, "%s: %s\n", clk_entry->label, state);
+ }
+
+ snd_iprintf(buffer, "Referred clock:\n");
+
+ if (data[1] & 0x00000001) {
+ snd_iprintf(buffer, "Internal\n");
+ } else {
+ unsigned int rate;
+ const char *label;
+
+ for (i = 0; i < ARRAY_SIZE(referred_entries); ++i) {
+ referred_entry = referred_entries + i;
+ if ((data[0] & 0x1e0000) == referred_entry->mask) {
+ label = referred_entry->label;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(referred_entries))
+ label = "none";
+
+ for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) {
+ rate_entry = rate_entries + i;
+ if ((data[0] & 0x1e000000) == rate_entry->mask) {
+ rate = rate_entry->rate;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(rate_entries))
+ rate = 0;
+
+ snd_iprintf(buffer, "%s %d\n", label, rate);
+ }
+}
+
+static void former_dump_status(struct snd_ff *ff,
+ struct snd_info_buffer *buffer)
+{
+ dump_clock_config(ff, buffer);
+ dump_sync_status(ff, buffer);
+}
+
+static int former_fill_midi_msg(struct snd_ff *ff,
+ struct snd_rawmidi_substream *substream,
+ unsigned int port)
+{
+ u8 *buf = (u8 *)ff->msg_buf[port];
+ int len;
+ int i;
+
+ len = snd_rawmidi_transmit_peek(substream, buf,
+ SND_FF_MAXIMIM_MIDI_QUADS);
+ if (len <= 0)
+ return len;
+
+ // One quadlet includes one byte.
+ for (i = len - 1; i >= 0; --i)
+ ff->msg_buf[port][i] = cpu_to_le32(buf[i]);
+ ff->rx_bytes[port] = len;
+
+ return len;
+}
+
+#define FF800_STF 0x0000fc88f000
+#define FF800_RX_PACKET_FORMAT 0x0000fc88f004
+#define FF800_ALLOC_TX_STREAM 0x0000fc88f008
+#define FF800_ISOC_COMM_START 0x0000fc88f00c
+#define FF800_TX_S800_FLAG 0x00000800
+#define FF800_ISOC_COMM_STOP 0x0000fc88f010
+
+#define FF800_TX_PACKET_ISOC_CH 0x0000801c0008
+
+static int allocate_rx_resources(struct snd_ff *ff)
+{
+ u32 data;
+ __le32 reg;
+ int err;
+
+ // Controllers should allocate isochronous resources for rx stream.
+ err = fw_iso_resources_allocate(&ff->rx_resources,
+ amdtp_stream_get_max_payload(&ff->rx_stream),
+ fw_parent_device(ff->unit)->max_speed);
+ if (err < 0)
+ return err;
+
+ // Set isochronous channel and the number of quadlets of rx packets.
+ data = ff->rx_stream.data_block_quadlets << 3;
+ data = (data << 8) | ff->rx_resources.channel;
+ reg = cpu_to_le32(data);
+ return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ FF800_RX_PACKET_FORMAT, &reg, sizeof(reg), 0);
+}
+
+static int allocate_tx_resources(struct snd_ff *ff)
+{
+ __le32 reg;
+ unsigned int count;
+ unsigned int tx_isoc_channel;
+ int err;
+
+ reg = cpu_to_le32(ff->tx_stream.data_block_quadlets);
+ err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ FF800_ALLOC_TX_STREAM, &reg, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+
+ // Wait till the format of tx packet is available.
+ count = 0;
+ while (count++ < 10) {
+ u32 data;
+ err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
+ FF800_TX_PACKET_ISOC_CH, &reg, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+
+ data = le32_to_cpu(reg);
+ if (data != 0xffffffff) {
+ tx_isoc_channel = data;
+ break;
+ }
+
+ msleep(50);
+ }
+ if (count >= 10)
+ return -ETIMEDOUT;
+
+ // NOTE: this is a makeshift to start OHCI 1394 IR context in the
+ // channel. On the other hand, 'struct fw_iso_resources.allocated' is
+ // not true and it's not deallocated at stop.
+ ff->tx_resources.channel = tx_isoc_channel;
+
+ return 0;
+}
+
+static int ff800_begin_session(struct snd_ff *ff, unsigned int rate)
+{
+ __le32 reg;
+ int err;
+
+ reg = cpu_to_le32(rate);
+ err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ FF800_STF, &reg, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+
+ // If starting isochronous communication immediately, change of STF has
+ // no effect. In this case, the communication runs based on former STF.
+ // Let's sleep for a bit.
+ msleep(100);
+
+ err = allocate_rx_resources(ff);
+ if (err < 0)
+ return err;
+
+ err = allocate_tx_resources(ff);
+ if (err < 0)
+ return err;
+
+ reg = cpu_to_le32(0x80000000);
+ reg |= cpu_to_le32(ff->tx_stream.data_block_quadlets);
+ if (fw_parent_device(ff->unit)->max_speed == SCODE_800)
+ reg |= cpu_to_le32(FF800_TX_S800_FLAG);
+ return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ FF800_ISOC_COMM_START, &reg, sizeof(reg), 0);
+}
+
+static void ff800_finish_session(struct snd_ff *ff)
+{
+ __le32 reg;
+
+ reg = cpu_to_le32(0x80000000);
+ snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ FF800_ISOC_COMM_STOP, &reg, sizeof(reg), 0);
+}
+
+// Fireface 800 doesn't allow drivers to register lower 4 bytes of destination
+// address.
+// A write transaction to clear registered higher 4 bytes of destination address
+// has an effect to suppress asynchronous transaction from device.
+static void ff800_handle_midi_msg(struct snd_ff *ff, unsigned int offset,
+ __le32 *buf, size_t length)
+{
+ int i;
+
+ for (i = 0; i < length / 4; i++) {
+ u8 byte = le32_to_cpu(buf[i]) & 0xff;
+ struct snd_rawmidi_substream *substream;
+
+ substream = READ_ONCE(ff->tx_midi_substreams[0]);
+ if (substream)
+ snd_rawmidi_receive(substream, &byte, 1);
+ }
+}
+
+const struct snd_ff_protocol snd_ff_protocol_ff800 = {
+ .handle_midi_msg = ff800_handle_midi_msg,
+ .fill_midi_msg = former_fill_midi_msg,
+ .get_clock = former_get_clock,
+ .switch_fetching_mode = former_switch_fetching_mode,
+ .begin_session = ff800_begin_session,
+ .finish_session = ff800_finish_session,
+ .dump_status = former_dump_status,
+};
+
+#define FF400_STF 0x000080100500ull
+#define FF400_RX_PACKET_FORMAT 0x000080100504ull
+#define FF400_ISOC_COMM_START 0x000080100508ull
+#define FF400_TX_PACKET_FORMAT 0x00008010050cull
+#define FF400_ISOC_COMM_STOP 0x000080100510ull
+
+/*
+ * Fireface 400 manages isochronous channel number in 3 bit field. Therefore,
+ * we can allocate between 0 and 7 channel.
+ */
+static int keep_resources(struct snd_ff *ff, unsigned int rate)
+{
+ enum snd_ff_stream_mode mode;
+ int i;
+ int err;
+
+ // Check whether the given value is supported or not.
+ for (i = 0; i < CIP_SFC_COUNT; i++) {
+ if (amdtp_rate_table[i] == rate)
+ break;
+ }
+ if (i >= CIP_SFC_COUNT)
+ return -EINVAL;
+
+ err = snd_ff_stream_get_multiplier_mode(i, &mode);
+ if (err < 0)
+ return err;
+
+ /* Keep resources for in-stream. */
+ ff->tx_resources.channels_mask = 0x00000000000000ffuLL;
+ err = fw_iso_resources_allocate(&ff->tx_resources,
+ amdtp_stream_get_max_payload(&ff->tx_stream),
+ fw_parent_device(ff->unit)->max_speed);
+ if (err < 0)
+ return err;
+
+ /* Keep resources for out-stream. */
+ ff->rx_resources.channels_mask = 0x00000000000000ffuLL;
+ err = fw_iso_resources_allocate(&ff->rx_resources,
+ amdtp_stream_get_max_payload(&ff->rx_stream),
+ fw_parent_device(ff->unit)->max_speed);
+ if (err < 0)
+ fw_iso_resources_free(&ff->tx_resources);
+
+ return err;
+}
+
+static int ff400_begin_session(struct snd_ff *ff, unsigned int rate)
+{
+ __le32 reg;
+ int err;
+
+ err = keep_resources(ff, rate);
+ if (err < 0)
+ return err;
+
+ /* Set the number of data blocks transferred in a second. */
+ reg = cpu_to_le32(rate);
+ err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ FF400_STF, &reg, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+
+ msleep(100);
+
+ /*
+ * Set isochronous channel and the number of quadlets of received
+ * packets.
+ */
+ reg = cpu_to_le32(((ff->rx_stream.data_block_quadlets << 3) << 8) |
+ ff->rx_resources.channel);
+ err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ FF400_RX_PACKET_FORMAT, &reg, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+
+ /*
+ * Set isochronous channel and the number of quadlets of transmitted
+ * packet.
+ */
+ /* TODO: investigate the purpose of this 0x80. */
+ reg = cpu_to_le32((0x80 << 24) |
+ (ff->tx_resources.channel << 5) |
+ (ff->tx_stream.data_block_quadlets));
+ err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ FF400_TX_PACKET_FORMAT, &reg, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+
+ /* Allow to transmit packets. */
+ reg = cpu_to_le32(0x00000001);
+ return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ FF400_ISOC_COMM_START, &reg, sizeof(reg), 0);
+}
+
+static void ff400_finish_session(struct snd_ff *ff)
+{
+ __le32 reg;
+
+ reg = cpu_to_le32(0x80000000);
+ snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ FF400_ISOC_COMM_STOP, &reg, sizeof(reg), 0);
+}
+
+// For Fireface 400, lower 4 bytes of destination address is configured by bit
+// flag in quadlet register (little endian) at 0x'0000'801'0051c. Drivers can
+// select one of 4 options:
+//
+// bit flags: offset of destination address
+// - 0x04000000: 0x'....'....'0000'0000
+// - 0x08000000: 0x'....'....'0000'0080
+// - 0x10000000: 0x'....'....'0000'0100
+// - 0x20000000: 0x'....'....'0000'0180
+//
+// Drivers can suppress the device to transfer asynchronous transactions by
+// using below 2 bits.
+// - 0x01000000: suppress transmission
+// - 0x02000000: suppress transmission
+//
+// Actually, the register is write-only and includes the other options such as
+// input attenuation. This driver allocates destination address with '0000'0000
+// in its lower offset and expects userspace application to configure the
+// register for it.
+static void ff400_handle_midi_msg(struct snd_ff *ff, unsigned int offset,
+ __le32 *buf, size_t length)
+{
+ int i;
+
+ for (i = 0; i < length / 4; i++) {
+ u32 quad = le32_to_cpu(buf[i]);
+ u8 byte;
+ unsigned int index;
+ struct snd_rawmidi_substream *substream;
+
+ /* Message in first port. */
+ /*
+ * This value may represent the index of this unit when the same
+ * units are on the same IEEE 1394 bus. This driver doesn't use
+ * it.
+ */
+ index = (quad >> 8) & 0xff;
+ if (index > 0) {
+ substream = READ_ONCE(ff->tx_midi_substreams[0]);
+ if (substream != NULL) {
+ byte = quad & 0xff;
+ snd_rawmidi_receive(substream, &byte, 1);
+ }
+ }
+
+ /* Message in second port. */
+ index = (quad >> 24) & 0xff;
+ if (index > 0) {
+ substream = READ_ONCE(ff->tx_midi_substreams[1]);
+ if (substream != NULL) {
+ byte = (quad >> 16) & 0xff;
+ snd_rawmidi_receive(substream, &byte, 1);
+ }
+ }
+ }
+}
+
+const struct snd_ff_protocol snd_ff_protocol_ff400 = {
+ .handle_midi_msg = ff400_handle_midi_msg,
+ .fill_midi_msg = former_fill_midi_msg,
+ .get_clock = former_get_clock,
+ .switch_fetching_mode = former_switch_fetching_mode,
+ .begin_session = ff400_begin_session,
+ .finish_session = ff400_finish_session,
+ .dump_status = former_dump_status,
+};
diff --git a/sound/firewire/fireface/ff-protocol-latter.c b/sound/firewire/fireface/ff-protocol-latter.c
new file mode 100644
index 000000000000..c8236ff89b7f
--- /dev/null
+++ b/sound/firewire/fireface/ff-protocol-latter.c
@@ -0,0 +1,430 @@
+// SPDX-License-Identifier: GPL-2.0
+// ff-protocol-latter - a part of driver for RME Fireface series
+//
+// Copyright (c) 2019 Takashi Sakamoto
+//
+// Licensed under the terms of the GNU General Public License, version 2.
+
+#include <linux/delay.h>
+
+#include "ff.h"
+
+#define LATTER_STF 0xffff00000004
+#define LATTER_ISOC_CHANNELS 0xffff00000008
+#define LATTER_ISOC_START 0xffff0000000c
+#define LATTER_FETCH_MODE 0xffff00000010
+#define LATTER_SYNC_STATUS 0x0000801c0000
+
+static int parse_clock_bits(u32 data, unsigned int *rate,
+ enum snd_ff_clock_src *src)
+{
+ static const struct {
+ unsigned int rate;
+ u32 flag;
+ } *rate_entry, rate_entries[] = {
+ { 32000, 0x00000000, },
+ { 44100, 0x01000000, },
+ { 48000, 0x02000000, },
+ { 64000, 0x04000000, },
+ { 88200, 0x05000000, },
+ { 96000, 0x06000000, },
+ { 128000, 0x08000000, },
+ { 176400, 0x09000000, },
+ { 192000, 0x0a000000, },
+ };
+ static const struct {
+ enum snd_ff_clock_src src;
+ u32 flag;
+ } *clk_entry, clk_entries[] = {
+ { SND_FF_CLOCK_SRC_SPDIF, 0x00000200, },
+ { SND_FF_CLOCK_SRC_ADAT1, 0x00000400, },
+ { SND_FF_CLOCK_SRC_WORD, 0x00000600, },
+ { SND_FF_CLOCK_SRC_INTERNAL, 0x00000e00, },
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) {
+ rate_entry = rate_entries + i;
+ if ((data & 0x0f000000) == rate_entry->flag) {
+ *rate = rate_entry->rate;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(rate_entries))
+ return -EIO;
+
+ for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
+ clk_entry = clk_entries + i;
+ if ((data & 0x000e00) == clk_entry->flag) {
+ *src = clk_entry->src;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(clk_entries))
+ return -EIO;
+
+ return 0;
+}
+
+static int latter_get_clock(struct snd_ff *ff, unsigned int *rate,
+ enum snd_ff_clock_src *src)
+{
+ __le32 reg;
+ u32 data;
+ int err;
+
+ err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
+ LATTER_SYNC_STATUS, &reg, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+ data = le32_to_cpu(reg);
+
+ return parse_clock_bits(data, rate, src);
+}
+
+static int latter_switch_fetching_mode(struct snd_ff *ff, bool enable)
+{
+ u32 data;
+ __le32 reg;
+
+ if (enable)
+ data = 0x00000000;
+ else
+ data = 0xffffffff;
+ reg = cpu_to_le32(data);
+
+ return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ LATTER_FETCH_MODE, &reg, sizeof(reg), 0);
+}
+
+static int keep_resources(struct snd_ff *ff, unsigned int rate)
+{
+ enum snd_ff_stream_mode mode;
+ int i;
+ int err;
+
+ // Check whether the given value is supported or not.
+ for (i = 0; i < CIP_SFC_COUNT; i++) {
+ if (amdtp_rate_table[i] == rate)
+ break;
+ }
+ if (i >= CIP_SFC_COUNT)
+ return -EINVAL;
+
+ err = snd_ff_stream_get_multiplier_mode(i, &mode);
+ if (err < 0)
+ return err;
+
+ /* Keep resources for in-stream. */
+ ff->tx_resources.channels_mask = 0x00000000000000ffuLL;
+ err = fw_iso_resources_allocate(&ff->tx_resources,
+ amdtp_stream_get_max_payload(&ff->tx_stream),
+ fw_parent_device(ff->unit)->max_speed);
+ if (err < 0)
+ return err;
+
+ /* Keep resources for out-stream. */
+ ff->rx_resources.channels_mask = 0x00000000000000ffuLL;
+ err = fw_iso_resources_allocate(&ff->rx_resources,
+ amdtp_stream_get_max_payload(&ff->rx_stream),
+ fw_parent_device(ff->unit)->max_speed);
+ if (err < 0)
+ fw_iso_resources_free(&ff->tx_resources);
+
+ return err;
+}
+
+static int latter_begin_session(struct snd_ff *ff, unsigned int rate)
+{
+ static const struct {
+ unsigned int stf;
+ unsigned int code;
+ unsigned int flag;
+ } *entry, rate_table[] = {
+ { 32000, 0x00, 0x92, },
+ { 44100, 0x02, 0x92, },
+ { 48000, 0x04, 0x92, },
+ { 64000, 0x08, 0x8e, },
+ { 88200, 0x0a, 0x8e, },
+ { 96000, 0x0c, 0x8e, },
+ { 128000, 0x10, 0x8c, },
+ { 176400, 0x12, 0x8c, },
+ { 192000, 0x14, 0x8c, },
+ };
+ u32 data;
+ __le32 reg;
+ unsigned int count;
+ int i;
+ int err;
+
+ for (i = 0; i < ARRAY_SIZE(rate_table); ++i) {
+ entry = rate_table + i;
+ if (entry->stf == rate)
+ break;
+ }
+ if (i == ARRAY_SIZE(rate_table))
+ return -EINVAL;
+
+ reg = cpu_to_le32(entry->code);
+ err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ LATTER_STF, &reg, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+
+ // Confirm to shift transmission clock.
+ count = 0;
+ while (count++ < 10) {
+ unsigned int curr_rate;
+ enum snd_ff_clock_src src;
+
+ err = latter_get_clock(ff, &curr_rate, &src);
+ if (err < 0)
+ return err;
+
+ if (curr_rate == rate)
+ break;
+ }
+ if (count == 10)
+ return -ETIMEDOUT;
+
+ err = keep_resources(ff, rate);
+ if (err < 0)
+ return err;
+
+ data = (ff->tx_resources.channel << 8) | ff->rx_resources.channel;
+ reg = cpu_to_le32(data);
+ err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ LATTER_ISOC_CHANNELS, &reg, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+
+ // Always use the maximum number of data channels in data block of
+ // packet.
+ reg = cpu_to_le32(entry->flag);
+ return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ LATTER_ISOC_START, &reg, sizeof(reg), 0);
+}
+
+static void latter_finish_session(struct snd_ff *ff)
+{
+ __le32 reg;
+
+ reg = cpu_to_le32(0x00000000);
+ snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ LATTER_ISOC_START, &reg, sizeof(reg), 0);
+}
+
+static void latter_dump_status(struct snd_ff *ff, struct snd_info_buffer *buffer)
+{
+ static const struct {
+ char *const label;
+ u32 locked_mask;
+ u32 synced_mask;
+ } *clk_entry, clk_entries[] = {
+ { "S/PDIF", 0x00000001, 0x00000010, },
+ { "ADAT", 0x00000002, 0x00000020, },
+ { "WDClk", 0x00000004, 0x00000040, },
+ };
+ __le32 reg;
+ u32 data;
+ unsigned int rate;
+ enum snd_ff_clock_src src;
+ const char *label;
+ int i;
+ int err;
+
+ err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
+ LATTER_SYNC_STATUS, &reg, sizeof(reg), 0);
+ if (err < 0)
+ return;
+ data = le32_to_cpu(reg);
+
+ snd_iprintf(buffer, "External source detection:\n");
+
+ for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
+ clk_entry = clk_entries + i;
+ snd_iprintf(buffer, "%s: ", clk_entry->label);
+ if (data & clk_entry->locked_mask) {
+ if (data & clk_entry->synced_mask)
+ snd_iprintf(buffer, "sync\n");
+ else
+ snd_iprintf(buffer, "lock\n");
+ } else {
+ snd_iprintf(buffer, "none\n");
+ }
+ }
+
+ err = parse_clock_bits(data, &rate, &src);
+ if (err < 0)
+ return;
+ label = snd_ff_proc_get_clk_label(src);
+ if (!label)
+ return;
+
+ snd_iprintf(buffer, "Referred clock: %s %d\n", label, rate);
+}
+
+// NOTE: transactions are transferred within 0x00-0x7f in allocated range of
+// address. This seems to be for check of discontinuity in receiver side.
+//
+// Like Fireface 400, drivers can select one of 4 options for lower 4 bytes of
+// destination address by bit flags in quadlet register (little endian) at
+// 0x'ffff'0000'0014:
+//
+// bit flags: offset of destination address
+// - 0x00002000: 0x'....'....'0000'0000
+// - 0x00004000: 0x'....'....'0000'0080
+// - 0x00008000: 0x'....'....'0000'0100
+// - 0x00010000: 0x'....'....'0000'0180
+//
+// Drivers can suppress the device to transfer asynchronous transactions by
+// clear these bit flags.
+//
+// Actually, the register is write-only and includes the other settings such as
+// input attenuation. This driver allocates for the first option
+// (0x'....'....'0000'0000) and expects userspace application to configure the
+// register for it.
+static void latter_handle_midi_msg(struct snd_ff *ff, unsigned int offset,
+ __le32 *buf, size_t length)
+{
+ u32 data = le32_to_cpu(*buf);
+ unsigned int index = (data & 0x000000f0) >> 4;
+ u8 byte[3];
+ struct snd_rawmidi_substream *substream;
+ unsigned int len;
+
+ if (index >= ff->spec->midi_in_ports)
+ return;
+
+ switch (data & 0x0000000f) {
+ case 0x00000008:
+ case 0x00000009:
+ case 0x0000000a:
+ case 0x0000000b:
+ case 0x0000000e:
+ len = 3;
+ break;
+ case 0x0000000c:
+ case 0x0000000d:
+ len = 2;
+ break;
+ default:
+ len = data & 0x00000003;
+ if (len == 0)
+ len = 3;
+ break;
+ }
+
+ byte[0] = (data & 0x0000ff00) >> 8;
+ byte[1] = (data & 0x00ff0000) >> 16;
+ byte[2] = (data & 0xff000000) >> 24;
+
+ substream = READ_ONCE(ff->tx_midi_substreams[index]);
+ if (substream)
+ snd_rawmidi_receive(substream, byte, len);
+}
+
+/*
+ * When return minus value, given argument is not MIDI status.
+ * When return 0, given argument is a beginning of system exclusive.
+ * When return the others, given argument is MIDI data.
+ */
+static inline int calculate_message_bytes(u8 status)
+{
+ switch (status) {
+ case 0xf6: /* Tune request. */
+ case 0xf8: /* Timing clock. */
+ case 0xfa: /* Start. */
+ case 0xfb: /* Continue. */
+ case 0xfc: /* Stop. */
+ case 0xfe: /* Active sensing. */
+ case 0xff: /* System reset. */
+ return 1;
+ case 0xf1: /* MIDI time code quarter frame. */
+ case 0xf3: /* Song select. */
+ return 2;
+ case 0xf2: /* Song position pointer. */
+ return 3;
+ case 0xf0: /* Exclusive. */
+ return 0;
+ case 0xf7: /* End of exclusive. */
+ break;
+ case 0xf4: /* Undefined. */
+ case 0xf5: /* Undefined. */
+ case 0xf9: /* Undefined. */
+ case 0xfd: /* Undefined. */
+ break;
+ default:
+ switch (status & 0xf0) {
+ case 0x80: /* Note on. */
+ case 0x90: /* Note off. */
+ case 0xa0: /* Polyphonic key pressure. */
+ case 0xb0: /* Control change and Mode change. */
+ case 0xe0: /* Pitch bend change. */
+ return 3;
+ case 0xc0: /* Program change. */
+ case 0xd0: /* Channel pressure. */
+ return 2;
+ default:
+ break;
+ }
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int latter_fill_midi_msg(struct snd_ff *ff,
+ struct snd_rawmidi_substream *substream,
+ unsigned int port)
+{
+ u32 data = {0};
+ u8 *buf = (u8 *)&data;
+ int consumed;
+
+ buf[0] = port << 4;
+ consumed = snd_rawmidi_transmit_peek(substream, buf + 1, 3);
+ if (consumed <= 0)
+ return consumed;
+
+ if (!ff->on_sysex[port]) {
+ if (buf[1] != 0xf0) {
+ if (consumed < calculate_message_bytes(buf[1]))
+ return 0;
+ } else {
+ // The beginning of exclusives.
+ ff->on_sysex[port] = true;
+ }
+
+ buf[0] |= consumed;
+ } else {
+ if (buf[1] != 0xf7) {
+ if (buf[2] == 0xf7 || buf[3] == 0xf7) {
+ // Transfer end code at next time.
+ consumed -= 1;
+ }
+
+ buf[0] |= consumed;
+ } else {
+ // The end of exclusives.
+ ff->on_sysex[port] = false;
+ consumed = 1;
+ buf[0] |= 0x0f;
+ }
+ }
+
+ ff->msg_buf[port][0] = cpu_to_le32(data);
+ ff->rx_bytes[port] = consumed;
+
+ return 1;
+}
+
+const struct snd_ff_protocol snd_ff_protocol_latter = {
+ .handle_midi_msg = latter_handle_midi_msg,
+ .fill_midi_msg = latter_fill_midi_msg,
+ .get_clock = latter_get_clock,
+ .switch_fetching_mode = latter_switch_fetching_mode,
+ .begin_session = latter_begin_session,
+ .finish_session = latter_finish_session,
+ .dump_status = latter_dump_status,
+};
diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c
index a490e4553721..a8a90f1ae09e 100644
--- a/sound/firewire/fireface/ff-stream.c
+++ b/sound/firewire/fireface/ff-stream.c
@@ -37,44 +37,10 @@ static void release_resources(struct snd_ff *ff)
fw_iso_resources_free(&ff->rx_resources);
}
-static int switch_fetching_mode(struct snd_ff *ff, bool enable)
-{
- unsigned int count;
- __le32 *reg;
- int i;
- int err;
-
- count = 0;
- for (i = 0; i < SND_FF_STREAM_MODE_COUNT; ++i)
- count = max(count, ff->spec->pcm_playback_channels[i]);
-
- reg = kcalloc(count, sizeof(__le32), GFP_KERNEL);
- if (!reg)
- return -ENOMEM;
-
- if (!enable) {
- /*
- * Each quadlet is corresponding to data channels in a data
- * blocks in reverse order. Precisely, quadlets for available
- * data channels should be enabled. Here, I take second best
- * to fetch PCM frames from all of data channels regardless of
- * stf.
- */
- for (i = 0; i < count; ++i)
- reg[i] = cpu_to_le32(0x00000001);
- }
-
- err = snd_fw_transaction(ff->unit, TCODE_WRITE_BLOCK_REQUEST,
- SND_FF_REG_FETCH_PCM_FRAMES, reg,
- sizeof(__le32) * count, 0);
- kfree(reg);
- return err;
-}
-
static inline void finish_session(struct snd_ff *ff)
{
ff->spec->protocol->finish_session(ff);
- switch_fetching_mode(ff, false);
+ ff->spec->protocol->switch_fetching_mode(ff, false);
}
static int init_stream(struct snd_ff *ff, enum amdtp_stream_direction dir)
@@ -147,7 +113,7 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
if (ff->substreams_counter == 0)
return 0;
- err = snd_ff_transaction_get_clock(ff, &curr_rate, &src);
+ err = ff->spec->protocol->get_clock(ff, &curr_rate, &src);
if (err < 0)
return err;
if (curr_rate != rate ||
@@ -206,7 +172,7 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
goto error;
}
- err = switch_fetching_mode(ff, true);
+ err = ff->spec->protocol->switch_fetching_mode(ff, true);
if (err < 0)
goto error;
}
diff --git a/sound/firewire/fireface/ff-transaction.c b/sound/firewire/fireface/ff-transaction.c
index 5f4ddfd55403..0d6ad19363b8 100644
--- a/sound/firewire/fireface/ff-transaction.c
+++ b/sound/firewire/fireface/ff-transaction.c
@@ -8,72 +8,6 @@
#include "ff.h"
-#define SND_FF_REG_MIDI_RX_PORT_0 0x000080180000ull
-#define SND_FF_REG_MIDI_RX_PORT_1 0x000080190000ull
-
-int snd_ff_transaction_get_clock(struct snd_ff *ff, unsigned int *rate,
- enum snd_ff_clock_src *src)
-{
- __le32 reg;
- u32 data;
- int err;
-
- err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
- SND_FF_REG_CLOCK_CONFIG, &reg, sizeof(reg), 0);
- if (err < 0)
- return err;
- data = le32_to_cpu(reg);
-
- /* Calculate sampling rate. */
- switch ((data >> 1) & 0x03) {
- case 0x01:
- *rate = 32000;
- break;
- case 0x00:
- *rate = 44100;
- break;
- case 0x03:
- *rate = 48000;
- break;
- case 0x02:
- default:
- return -EIO;
- }
-
- if (data & 0x08)
- *rate *= 2;
- else if (data & 0x10)
- *rate *= 4;
-
- /* Calculate source of clock. */
- if (data & 0x01) {
- *src = SND_FF_CLOCK_SRC_INTERNAL;
- } else {
- /* TODO: 0x02, 0x06, 0x07? */
- switch ((data >> 10) & 0x07) {
- case 0x00:
- *src = SND_FF_CLOCK_SRC_ADAT1;
- break;
- case 0x01:
- *src = SND_FF_CLOCK_SRC_ADAT2;
- break;
- case 0x03:
- *src = SND_FF_CLOCK_SRC_SPDIF;
- break;
- case 0x04:
- *src = SND_FF_CLOCK_SRC_WORD;
- break;
- case 0x05:
- *src = SND_FF_CLOCK_SRC_LTC;
- break;
- default:
- return -EIO;
- }
- }
-
- return 0;
-}
-
static void finish_transmit_midi_msg(struct snd_ff *ff, unsigned int port,
int rcode)
{
@@ -117,23 +51,17 @@ static void finish_transmit_midi1_msg(struct fw_card *card, int rcode,
finish_transmit_midi_msg(ff, 1, rcode);
}
-static inline void fill_midi_buf(struct snd_ff *ff, unsigned int port,
- unsigned int index, u8 byte)
-{
- ff->msg_buf[port][index] = cpu_to_le32(byte);
-}
-
static void transmit_midi_msg(struct snd_ff *ff, unsigned int port)
{
struct snd_rawmidi_substream *substream =
READ_ONCE(ff->rx_midi_substreams[port]);
- u8 *buf = (u8 *)ff->msg_buf[port];
- int i, len;
+ int quad_count;
struct fw_device *fw_dev = fw_parent_device(ff->unit);
unsigned long long addr;
int generation;
fw_transaction_callback_t callback;
+ int tcode;
if (substream == NULL || snd_rawmidi_transmit_empty(substream))
return;
@@ -147,26 +75,26 @@ static void transmit_midi_msg(struct snd_ff *ff, unsigned int port)
return;
}
- len = snd_rawmidi_transmit_peek(substream, buf,
- SND_FF_MAXIMIM_MIDI_QUADS);
- if (len <= 0)
+ quad_count = ff->spec->protocol->fill_midi_msg(ff, substream, port);
+ if (quad_count <= 0)
return;
- for (i = len - 1; i >= 0; i--)
- fill_midi_buf(ff, port, i, buf[i]);
-
if (port == 0) {
- addr = SND_FF_REG_MIDI_RX_PORT_0;
+ addr = ff->spec->midi_rx_addrs[0];
callback = finish_transmit_midi0_msg;
} else {
- addr = SND_FF_REG_MIDI_RX_PORT_1;
+ addr = ff->spec->midi_rx_addrs[1];
callback = finish_transmit_midi1_msg;
}
/* Set interval to next transaction. */
ff->next_ktime[port] = ktime_add_ns(ktime_get(),
- len * 8 * NSEC_PER_SEC / 31250);
- ff->rx_bytes[port] = len;
+ ff->rx_bytes[port] * 8 * NSEC_PER_SEC / 31250);
+
+ if (quad_count == 1)
+ tcode = TCODE_WRITE_QUADLET_REQUEST;
+ else
+ tcode = TCODE_WRITE_BLOCK_REQUEST;
/*
* In Linux FireWire core, when generation is updated with memory
@@ -178,10 +106,9 @@ static void transmit_midi_msg(struct snd_ff *ff, unsigned int port)
*/
generation = fw_dev->generation;
smp_rmb();
- fw_send_request(fw_dev->card, &ff->transactions[port],
- TCODE_WRITE_BLOCK_REQUEST,
+ fw_send_request(fw_dev->card, &ff->transactions[port], tcode,
fw_dev->node_id, generation, fw_dev->max_speed,
- addr, &ff->msg_buf[port], len * 4,
+ addr, &ff->msg_buf[port], quad_count * 4,
callback, &ff->transactions[port]);
}
@@ -209,7 +136,9 @@ static void handle_midi_msg(struct fw_card *card, struct fw_request *request,
fw_send_response(card, request, RCODE_COMPLETE);
- ff->spec->protocol->handle_midi_msg(ff, buf, length);
+ offset -= ff->async_handler.offset;
+ ff->spec->protocol->handle_midi_msg(ff, (unsigned int)offset, buf,
+ length);
}
static int allocate_own_address(struct snd_ff *ff, int i)
@@ -217,7 +146,7 @@ static int allocate_own_address(struct snd_ff *ff, int i)
struct fw_address_region midi_msg_region;
int err;
- ff->async_handler.length = SND_FF_MAXIMIM_MIDI_QUADS * 4;
+ ff->async_handler.length = ff->spec->midi_addr_range;
ff->async_handler.address_callback = handle_midi_msg;
ff->async_handler.callback_data = ff;
@@ -236,35 +165,13 @@ static int allocate_own_address(struct snd_ff *ff, int i)
return err;
}
-/*
- * Controllers are allowed to register higher 4 bytes of address to receive
- * the transactions. Different models have different registers for this purpose;
- * e.g. 0x'0000'8010'03f4 for Fireface 400.
- * The controllers are not allowed to register lower 4 bytes of the address.
- * They are forced to select one of 4 options for the part of address by writing
- * corresponding bits to 0x'0000'8010'051f.
- *
- * The 3rd-6th bits of this register are flags to indicate lower 4 bytes of
- * address to which the device transferrs the transactions. In short:
- * - 0x20: 0x'....'....'0000'0180
- * - 0x10: 0x'....'....'0000'0100
- * - 0x08: 0x'....'....'0000'0080
- * - 0x04: 0x'....'....'0000'0000
- *
- * This driver configure 0x'....'....'0000'0000 to receive MIDI messages from
- * units. The 3rd bit of the register should be configured, however this driver
- * deligates this task to userspace applications due to a restriction that this
- * register is write-only and the other bits have own effects.
- *
- * Unlike Fireface 800, Fireface 400 cancels transferring asynchronous
- * transactions when the 1st and 2nd of the register stand. These two bits have
- * the same effect.
- * - 0x02, 0x01: cancel transferring
- *
- * On the other hand, the bits have no effect on Fireface 800. This model
- * cancels asynchronous transactions when the higher 4 bytes of address is
- * overwritten with zero.
- */
+// Controllers are allowed to register higher 4 bytes of destination address to
+// receive asynchronous transactions for MIDI messages, while the way to
+// register lower 4 bytes of address is different depending on protocols. For
+// details, please refer to comments in protocol implementations.
+//
+// This driver expects userspace applications to configure registers for the
+// lower address because in most cases such registers has the other settings.
int snd_ff_transaction_reregister(struct snd_ff *ff)
{
struct fw_card *fw_card = fw_parent_device(ff->unit)->card;
diff --git a/sound/firewire/fireface/ff.c b/sound/firewire/fireface/ff.c
index 36575f4159d1..a9611157f4c8 100644
--- a/sound/firewire/fireface/ff.c
+++ b/sound/firewire/fireface/ff.c
@@ -153,6 +153,8 @@ static const struct snd_ff_spec spec_ff800 = {
.midi_out_ports = 1,
.protocol = &snd_ff_protocol_ff800,
.midi_high_addr = 0x000200000320ull,
+ .midi_addr_range = 12,
+ .midi_rx_addrs = {0x000080180000ull, 0},
};
static const struct snd_ff_spec spec_ff400 = {
@@ -163,6 +165,20 @@ static const struct snd_ff_spec spec_ff400 = {
.midi_out_ports = 2,
.protocol = &snd_ff_protocol_ff400,
.midi_high_addr = 0x0000801003f4ull,
+ .midi_addr_range = SND_FF_MAXIMIM_MIDI_QUADS * 4,
+ .midi_rx_addrs = {0x000080180000ull, 0x000080190000ull},
+};
+
+static const struct snd_ff_spec spec_ucx = {
+ .name = "FirefaceUCX",
+ .pcm_capture_channels = {18, 14, 12},
+ .pcm_playback_channels = {18, 14, 12},
+ .midi_in_ports = 2,
+ .midi_out_ports = 2,
+ .protocol = &snd_ff_protocol_latter,
+ .midi_high_addr = 0xffff00000034ull,
+ .midi_addr_range = 0x80,
+ .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull},
};
static const struct ieee1394_device_id snd_ff_id_table[] = {
@@ -190,6 +206,18 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
.model_id = 0x101800,
.driver_data = (kernel_ulong_t)&spec_ff400,
},
+ // Fireface UCX.
+ {
+ .match_flags = IEEE1394_MATCH_VENDOR_ID |
+ IEEE1394_MATCH_SPECIFIER_ID |
+ IEEE1394_MATCH_VERSION |
+ IEEE1394_MATCH_MODEL_ID,
+ .vendor_id = OUI_RME,
+ .specifier_id = OUI_RME,
+ .version = 0x000004,
+ .model_id = 0x101800,
+ .driver_data = (kernel_ulong_t)&spec_ucx,
+ },
{}
};
MODULE_DEVICE_TABLE(ieee1394, snd_ff_id_table);
diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h
index 7dfc7745a914..ed8fea0ff5e1 100644
--- a/sound/firewire/fireface/ff.h
+++ b/sound/firewire/fireface/ff.h
@@ -35,11 +35,6 @@
#define SND_FF_IN_MIDI_PORTS 2
#define SND_FF_OUT_MIDI_PORTS 2
-#define SND_FF_REG_SYNC_STATUS 0x0000801c0000ull
-/* For block write request. */
-#define SND_FF_REG_FETCH_PCM_FRAMES 0x0000801c0000ull
-#define SND_FF_REG_CLOCK_CONFIG 0x0000801c0004ull
-
enum snd_ff_stream_mode {
SND_FF_STREAM_MODE_LOW = 0,
SND_FF_STREAM_MODE_MID,
@@ -59,6 +54,8 @@ struct snd_ff_spec {
const struct snd_ff_protocol *protocol;
u64 midi_high_addr;
+ u8 midi_addr_range;
+ u64 midi_rx_addrs[SND_FF_OUT_MIDI_PORTS];
};
struct snd_ff {
@@ -78,7 +75,7 @@ struct snd_ff {
/* TO handle MIDI rx. */
struct snd_rawmidi_substream *rx_midi_substreams[SND_FF_OUT_MIDI_PORTS];
- u8 running_status[SND_FF_OUT_MIDI_PORTS];
+ bool on_sysex[SND_FF_OUT_MIDI_PORTS];
__le32 msg_buf[SND_FF_OUT_MIDI_PORTS][SND_FF_MAXIMIM_MIDI_QUADS];
struct work_struct rx_midi_work[SND_FF_OUT_MIDI_PORTS];
struct fw_transaction transactions[SND_FF_OUT_MIDI_PORTS];
@@ -108,16 +105,23 @@ enum snd_ff_clock_src {
};
struct snd_ff_protocol {
- void (*handle_midi_msg)(struct snd_ff *ff, __le32 *buf, size_t length);
+ void (*handle_midi_msg)(struct snd_ff *ff, unsigned int offset,
+ __le32 *buf, size_t length);
+ int (*fill_midi_msg)(struct snd_ff *ff,
+ struct snd_rawmidi_substream *substream,
+ unsigned int port);
+ int (*get_clock)(struct snd_ff *ff, unsigned int *rate,
+ enum snd_ff_clock_src *src);
+ int (*switch_fetching_mode)(struct snd_ff *ff, bool enable);
int (*begin_session)(struct snd_ff *ff, unsigned int rate);
void (*finish_session)(struct snd_ff *ff);
+ void (*dump_status)(struct snd_ff *ff, struct snd_info_buffer *buffer);
};
extern const struct snd_ff_protocol snd_ff_protocol_ff800;
extern const struct snd_ff_protocol snd_ff_protocol_ff400;
+extern const struct snd_ff_protocol snd_ff_protocol_latter;
-int snd_ff_transaction_get_clock(struct snd_ff *ff, unsigned int *rate,
- enum snd_ff_clock_src *src);
int snd_ff_transaction_register(struct snd_ff *ff);
int snd_ff_transaction_reregister(struct snd_ff *ff);
void snd_ff_transaction_unregister(struct snd_ff *ff);
@@ -142,6 +146,7 @@ int snd_ff_stream_lock_try(struct snd_ff *ff);
void snd_ff_stream_lock_release(struct snd_ff *ff);
void snd_ff_proc_init(struct snd_ff *ff);
+const char *snd_ff_proc_get_clk_label(enum snd_ff_clock_src src);
int snd_ff_create_midi_devices(struct snd_ff *ff);
diff --git a/sound/firewire/fireworks/fireworks_proc.c b/sound/firewire/fireworks/fireworks_proc.c
index 779ecec5af62..9fa5c34a9572 100644
--- a/sound/firewire/fireworks/fireworks_proc.c
+++ b/sound/firewire/fireworks/fireworks_proc.c
@@ -199,12 +199,8 @@ add_node(struct snd_efw *efw, struct snd_info_entry *root, const char *name,
struct snd_info_entry *entry;
entry = snd_info_create_card_entry(efw->card, name, root);
- if (entry == NULL)
- return;
-
- snd_info_set_text_ops(entry, efw, op);
- if (snd_info_register(entry) < 0)
- snd_info_free_entry(entry);
+ if (entry)
+ snd_info_set_text_ops(entry, efw, op);
}
void snd_efw_proc_init(struct snd_efw *efw)
@@ -220,10 +216,6 @@ void snd_efw_proc_init(struct snd_efw *efw)
if (root == NULL)
return;
root->mode = S_IFDIR | 0555;
- if (snd_info_register(root) < 0) {
- snd_info_free_entry(root);
- return;
- }
add_node(efw, root, "clock", proc_read_clock);
add_node(efw, root, "firmware", proc_read_hwinfo);
diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c
index f0555a24d90e..6c9b743ea74b 100644
--- a/sound/firewire/motu/amdtp-motu.c
+++ b/sound/firewire/motu/amdtp-motu.c
@@ -136,7 +136,9 @@ static void read_pcm_s32(struct amdtp_stream *s,
byte = (u8 *)buffer + p->pcm_byte_offset;
for (c = 0; c < channels; ++c) {
- *dst = (byte[0] << 24) | (byte[1] << 16) | byte[2];
+ *dst = (byte[0] << 24) |
+ (byte[1] << 16) |
+ (byte[2] << 8);
byte += 3;
dst++;
}
diff --git a/sound/firewire/motu/motu-proc.c b/sound/firewire/motu/motu-proc.c
index ab6830a6d242..94327853620a 100644
--- a/sound/firewire/motu/motu-proc.c
+++ b/sound/firewire/motu/motu-proc.c
@@ -87,12 +87,8 @@ static void add_node(struct snd_motu *motu, struct snd_info_entry *root,
struct snd_info_entry *entry;
entry = snd_info_create_card_entry(motu->card, name, root);
- if (entry == NULL)
- return;
-
- snd_info_set_text_ops(entry, motu, op);
- if (snd_info_register(entry) < 0)
- snd_info_free_entry(entry);
+ if (entry)
+ snd_info_set_text_ops(entry, motu, op);
}
void snd_motu_proc_init(struct snd_motu *motu)
@@ -108,10 +104,6 @@ void snd_motu_proc_init(struct snd_motu *motu)
if (root == NULL)
return;
root->mode = S_IFDIR | 0555;
- if (snd_info_register(root) < 0) {
- snd_info_free_entry(root);
- return;
- }
add_node(motu, root, "clock", proc_read_clock);
add_node(motu, root, "format", proc_read_format);
diff --git a/sound/firewire/oxfw/oxfw-proc.c b/sound/firewire/oxfw/oxfw-proc.c
index 27dac071bc73..644107e3782e 100644
--- a/sound/firewire/oxfw/oxfw-proc.c
+++ b/sound/firewire/oxfw/oxfw-proc.c
@@ -83,12 +83,8 @@ static void add_node(struct snd_oxfw *oxfw, struct snd_info_entry *root,
struct snd_info_entry *entry;
entry = snd_info_create_card_entry(oxfw->card, name, root);
- if (entry == NULL)
- return;
-
- snd_info_set_text_ops(entry, oxfw, op);
- if (snd_info_register(entry) < 0)
- snd_info_free_entry(entry);
+ if (entry)
+ snd_info_set_text_ops(entry, oxfw, op);
}
void snd_oxfw_proc_init(struct snd_oxfw *oxfw)
@@ -104,10 +100,6 @@ void snd_oxfw_proc_init(struct snd_oxfw *oxfw)
if (root == NULL)
return;
root->mode = S_IFDIR | 0555;
- if (snd_info_register(root) < 0) {
- snd_info_free_entry(root);
- return;
- }
add_node(oxfw, root, "formation", proc_read_formation);
}
diff --git a/sound/firewire/tascam/tascam-proc.c b/sound/firewire/tascam/tascam-proc.c
index fee3bf32a0da..8bc8d277394a 100644
--- a/sound/firewire/tascam/tascam-proc.c
+++ b/sound/firewire/tascam/tascam-proc.c
@@ -58,12 +58,8 @@ static void add_node(struct snd_tscm *tscm, struct snd_info_entry *root,
struct snd_info_entry *entry;
entry = snd_info_create_card_entry(tscm->card, name, root);
- if (entry == NULL)
- return;
-
- snd_info_set_text_ops(entry, tscm, op);
- if (snd_info_register(entry) < 0)
- snd_info_free_entry(entry);
+ if (entry)
+ snd_info_set_text_ops(entry, tscm, op);
}
void snd_tscm_proc_init(struct snd_tscm *tscm)
@@ -79,10 +75,6 @@ void snd_tscm_proc_init(struct snd_tscm *tscm)
if (root == NULL)
return;
root->mode = S_IFDIR | 0555;
- if (snd_info_register(root) < 0) {
- snd_info_free_entry(root);
- return;
- }
add_node(tscm, root, "firmware", proc_read_firmware);
}
diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c
index a6d37b9d6413..5c95933e739a 100644
--- a/sound/hda/hdac_component.c
+++ b/sound/hda/hdac_component.c
@@ -269,7 +269,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier);
*/
int snd_hdac_acomp_init(struct hdac_bus *bus,
const struct drm_audio_component_audio_ops *aops,
- int (*match_master)(struct device *, void *),
+ int (*match_master)(struct device *, int, void *),
size_t extra_size)
{
struct component_match *match = NULL;
@@ -288,7 +288,7 @@ int snd_hdac_acomp_init(struct hdac_bus *bus,
bus->audio_component = acomp;
devres_add(dev, acomp);
- component_match_add(dev, &match, match_master, bus);
+ component_match_add_typed(dev, &match, match_master, bus);
ret = component_master_add_with_match(dev, &hdac_component_master_ops,
match);
if (ret < 0)
diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c
index 74244d8e2909..b2e9454f5816 100644
--- a/sound/hda/hdac_controller.c
+++ b/sound/hda/hdac_controller.c
@@ -376,7 +376,7 @@ void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus)
{
unsigned long timeout;
- snd_hdac_chip_updateb(bus, GCTL, 0, AZX_GCTL_RESET);
+ snd_hdac_chip_updateb(bus, GCTL, AZX_GCTL_RESET, AZX_GCTL_RESET);
timeout = jiffies + msecs_to_jiffies(100);
while (!snd_hdac_chip_readb(bus, GCTL) && time_before(jiffies, timeout))
@@ -415,7 +415,7 @@ int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset)
}
/* Accept unsolicited responses */
- snd_hdac_chip_updatel(bus, GCTL, 0, AZX_GCTL_UNSOL);
+ snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL);
/* detect codecs */
if (!bus->codec_mask) {
@@ -431,7 +431,9 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_reset_link);
static void azx_int_enable(struct hdac_bus *bus)
{
/* enable controller CIE and GIE */
- snd_hdac_chip_updatel(bus, INTCTL, 0, AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN);
+ snd_hdac_chip_updatel(bus, INTCTL,
+ AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN,
+ AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN);
}
/* disable interrupts */
diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c
index 617ff1aa818f..575198bd3cd0 100644
--- a/sound/hda/hdac_i915.c
+++ b/sound/hda/hdac_i915.c
@@ -82,9 +82,11 @@ void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
}
EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk);
-static int i915_component_master_match(struct device *dev, void *data)
+static int i915_component_master_match(struct device *dev, int subcomponent,
+ void *data)
{
- return !strcmp(dev->driver->name, "i915");
+ return !strcmp(dev->driver->name, "i915") &&
+ subcomponent == I915_COMPONENT_AUDIO;
}
/* check whether intel graphics is present */
@@ -144,9 +146,9 @@ int snd_hdac_i915_init(struct hdac_bus *bus)
return -ENODEV;
if (!acomp->ops) {
request_module("i915");
- /* 10s timeout */
+ /* 60s timeout */
wait_for_completion_timeout(&bind_complete,
- msecs_to_jiffies(10 * 1000));
+ msecs_to_jiffies(60 * 1000));
}
if (!acomp->ops) {
dev_info(bus->dev, "couldn't bind with audio component\n");
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c
index eee422390d8e..76e9b41fcea2 100644
--- a/sound/hda/hdac_stream.c
+++ b/sound/hda/hdac_stream.c
@@ -13,6 +13,40 @@
#include "trace.h"
/**
+ * snd_hdac_get_stream_stripe_ctl - get stripe control value
+ * @bus: HD-audio core bus
+ * @substream: PCM substream
+ */
+int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned int channels = runtime->channels,
+ rate = runtime->rate,
+ bits_per_sample = runtime->sample_bits,
+ max_sdo_lines, value, sdo_line;
+
+ /* T_AZA_GCAP_NSDO is 1:2 bitfields in GCAP */
+ max_sdo_lines = snd_hdac_chip_readl(bus, GCAP) & AZX_GCAP_NSDO;
+
+ /* following is from HD audio spec */
+ for (sdo_line = max_sdo_lines; sdo_line > 0; sdo_line >>= 1) {
+ if (rate > 48000)
+ value = (channels * bits_per_sample *
+ (rate / 48000)) / sdo_line;
+ else
+ value = (channels * bits_per_sample) / sdo_line;
+
+ if (value >= 8)
+ break;
+ }
+
+ /* stripe value: 0 for 1SDO, 1 for 2SDO, 2 for 4SDO lines */
+ return sdo_line >> 1;
+}
+EXPORT_SYMBOL_GPL(snd_hdac_get_stream_stripe_ctl);
+
+/**
* snd_hdac_stream_init - initialize each stream (aka device)
* @bus: HD-audio core bus
* @azx_dev: HD-audio core stream object to initialize
@@ -48,6 +82,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_stream_init);
void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start)
{
struct hdac_bus *bus = azx_dev->bus;
+ int stripe_ctl;
trace_snd_hdac_stream_start(bus, azx_dev);
@@ -56,7 +91,16 @@ void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start)
azx_dev->start_wallclk -= azx_dev->period_wallclk;
/* enable SIE */
- snd_hdac_chip_updatel(bus, INTCTL, 0, 1 << azx_dev->index);
+ snd_hdac_chip_updatel(bus, INTCTL,
+ 1 << azx_dev->index,
+ 1 << azx_dev->index);
+ /* set stripe control */
+ if (azx_dev->substream)
+ stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream);
+ else
+ stripe_ctl = 0;
+ snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK,
+ stripe_ctl);
/* set DMA start and interrupt mask */
snd_hdac_stream_updateb(azx_dev, SD_CTL,
0, SD_CTL_DMA_START | SD_INT_MASK);
@@ -73,6 +117,7 @@ void snd_hdac_stream_clear(struct hdac_stream *azx_dev)
snd_hdac_stream_updateb(azx_dev, SD_CTL,
SD_CTL_DMA_START | SD_INT_MASK, 0);
snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
+ snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
azx_dev->running = false;
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_clear);
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c
index 4099e6062d3c..573599d0378d 100644
--- a/sound/i2c/other/ak4113.c
+++ b/sound/i2c/other/ak4113.c
@@ -492,9 +492,8 @@ static void snd_ak4113_proc_regs_read(struct snd_info_entry *entry,
static void snd_ak4113_proc_init(struct ak4113 *ak4113)
{
- struct snd_info_entry *entry;
- if (!snd_card_proc_new(ak4113->card, "ak4113", &entry))
- snd_info_set_text_ops(entry, ak4113, snd_ak4113_proc_regs_read);
+ snd_card_ro_proc_new(ak4113->card, "ak4113", ak4113,
+ snd_ak4113_proc_regs_read);
}
int snd_ak4113_build(struct ak4113 *ak4113,
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index 7fb1aeb46915..76afb975782d 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -465,9 +465,8 @@ static void snd_ak4114_proc_regs_read(struct snd_info_entry *entry,
static void snd_ak4114_proc_init(struct ak4114 *ak4114)
{
- struct snd_info_entry *entry;
- if (!snd_card_proc_new(ak4114->card, "ak4114", &entry))
- snd_info_set_text_ops(entry, ak4114, snd_ak4114_proc_regs_read);
+ snd_card_ro_proc_new(ak4114->card, "ak4114", ak4114,
+ snd_ak4114_proc_regs_read);
}
int snd_ak4114_build(struct ak4114 *ak4114,
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 7f2761a2e7c8..62a6c5fa96b5 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -875,13 +875,7 @@ static void proc_regs_read(struct snd_info_entry *entry,
static int proc_init(struct snd_akm4xxx *ak)
{
- struct snd_info_entry *entry;
- int err;
- err = snd_card_proc_new(ak->card, ak->name, &entry);
- if (err < 0)
- return err;
- snd_info_set_text_ops(entry, ak, proc_regs_read);
- return 0;
+ return snd_card_ro_proc_new(ak->card, ak->name, ak, proc_regs_read);
}
int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index fba6d22f7f4b..94b381a78e9e 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -518,7 +518,6 @@ void snd_ad1816a_suspend(struct snd_ad1816a *chip)
int reg;
unsigned long flags;
- snd_pcm_suspend_all(chip->pcm);
spin_lock_irqsave(&chip->lock, flags);
for (reg = 0; reg < 48; reg++)
chip->image[reg] = snd_ad1816a_read(chip, reg);
@@ -694,7 +693,7 @@ int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device)
snd_ad1816a_init(chip);
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_isa_data(),
+ chip->card->dev,
64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
chip->pcm = pcm;
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index f63142ec287e..571108021e9d 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -322,7 +322,6 @@ static int snd_als100_pnp_suspend(struct pnp_card_link *pcard, pm_message_t stat
struct snd_sb *chip = acard->chip;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
snd_sbmixer_suspend(chip);
return 0;
}
diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c
index de6ef1b1cf0e..617977516201 100644
--- a/sound/isa/cmi8328.c
+++ b/sound/isa/cmi8328.c
@@ -434,7 +434,6 @@ static int snd_cmi8328_suspend(struct device *pdev, unsigned int n,
cmi = card->private_data;
snd_cmi8328_cfg_save(cmi->port, cmi->cfg);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(cmi->wss->pcm);
cmi->wss->suspend(cmi->wss);
return 0;
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 6b8c46942efb..1868b73aa49c 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -470,7 +470,7 @@ static int snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &chip->streams[SNDRV_PCM_STREAM_CAPTURE].ops);
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_isa_data(),
+ card->dev,
64*1024, 128*1024);
chip->pcm = pcm;
@@ -484,7 +484,6 @@ static int snd_cmi8330_suspend(struct snd_card *card)
struct snd_cmi8330 *acard = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(acard->pcm);
acard->wss->suspend(acard->wss);
snd_sbmixer_suspend(acard->sb);
return 0;
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 3dfe7e592c25..87527627e059 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -301,10 +301,8 @@ static int snd_es968_pnp_suspend(struct pnp_card_link *pcard,
pm_message_t state)
{
struct snd_card *card = pnp_get_card_drvdata(pcard);
- struct snd_es1688 *chip = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
return 0;
}
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index 50cdce0e8946..1d9556c045e9 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -121,7 +121,7 @@ EXPORT_SYMBOL(snd_es1688_reset);
static int snd_es1688_probe(struct snd_es1688 *chip)
{
unsigned long flags;
- unsigned short major, minor, hw;
+ unsigned short major, minor;
int i;
/*
@@ -166,14 +166,12 @@ static int snd_es1688_probe(struct snd_es1688 *chip)
if (!chip->version)
return -ENODEV; /* probably SB */
- hw = ES1688_HW_AUTO;
switch (chip->version & 0xfff0) {
case 0x4880:
snd_printk(KERN_ERR "[0x%lx] ESS: AudioDrive ES488 detected, "
"but driver is in another place\n", chip->port);
return -ENODEV;
case 0x6880:
- hw = (chip->version & 0x0f) >= 8 ? ES1688_HW_1688 : ES1688_HW_688;
break;
default:
snd_printk(KERN_ERR "[0x%lx] ESS: unknown AudioDrive chip "
@@ -746,7 +744,7 @@ int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, int device)
chip->pcm = pcm;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_isa_data(),
+ card->dev,
64*1024, 64*1024);
return 0;
}
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 0d103d6f805e..07abc7f7840c 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -1717,7 +1717,7 @@ static int snd_es18xx_pcm(struct snd_card *card, int device)
chip->pcm = pcm;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_isa_data(),
+ card->dev,
64*1024,
chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
return 0;
@@ -1731,8 +1731,6 @@ static int snd_es18xx_suspend(struct snd_card *card, pm_message_t state)
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
-
/* power down */
chip->pm_reg = (unsigned char)snd_es18xx_read(chip, ES18XX_PM);
chip->pm_reg |= (ES18XX_PM_FM | ES18XX_PM_SUS);
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c
index 2055aff71b50..0ca6c38e2ed9 100644
--- a/sound/isa/gus/gus_irq.c
+++ b/sound/isa/gus/gus_irq.c
@@ -140,10 +140,7 @@ static void snd_gus_irq_info_read(struct snd_info_entry *entry,
void snd_gus_irq_profile_init(struct snd_gus_card *gus)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(gus->card, "gusirq", &entry))
- snd_info_set_text_ops(entry, gus, snd_gus_irq_info_read);
+ snd_card_ro_proc_new(gus->card, "gusirq", gus, snd_gus_irq_info_read);
}
#endif
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index 3b8a0c880db5..33c8b66d5c8a 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -92,8 +92,17 @@ static const struct snd_kcontrol_new snd_gus_joystick_control = {
static void snd_gus_init_control(struct snd_gus_card *gus)
{
- if (!gus->ace_flag)
- snd_ctl_add(gus->card, snd_ctl_new1(&snd_gus_joystick_control, 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);
+ }
}
/*
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c
index af888a022fc0..4ac76f46dd76 100644
--- a/sound/isa/gus/gus_mem.c
+++ b/sound/isa/gus/gus_mem.c
@@ -238,9 +238,6 @@ int snd_gf1_mem_init(struct snd_gus_card * gus)
{
struct snd_gf1_mem *alloc;
struct snd_gf1_mem_block block;
-#ifdef CONFIG_SND_DEBUG
- struct snd_info_entry *entry;
-#endif
alloc = &gus->gf1.mem_alloc;
mutex_init(&alloc->memory_mutex);
@@ -263,8 +260,7 @@ int snd_gf1_mem_init(struct snd_gus_card * gus)
if (snd_gf1_mem_xalloc(alloc, &block) == NULL)
return -ENOMEM;
#ifdef CONFIG_SND_DEBUG
- if (! snd_card_proc_new(gus->card, "gusmem", &entry))
- snd_info_set_text_ops(entry, gus, snd_gf1_mem_info_read);
+ snd_card_ro_proc_new(gus->card, "gusmem", gus, snd_gf1_mem_info_read);
#endif
return 0;
}
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index 131b28997e1d..b9efc6dff45d 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -891,7 +891,7 @@ int snd_gf1_pcm_new(struct snd_gus_card *gus, int pcm_dev, int control_index)
for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV,
- snd_dma_isa_data(),
+ card->dev,
64*1024, gus->gf1.dma1 > 3 ? 128*1024 : 64*1024);
pcm->info_flags = 0;
@@ -901,7 +901,7 @@ int snd_gf1_pcm_new(struct snd_gus_card *gus, int pcm_dev, int control_index)
if (gus->gf1.dma2 == gus->gf1.dma1)
pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
- SNDRV_DMA_TYPE_DEV, snd_dma_isa_data(),
+ SNDRV_DMA_TYPE_DEV, card->dev,
64*1024, gus->gf1.dma2 > 3 ? 128*1024 : 64*1024);
}
strcpy(pcm->name, pcm->id);
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index c6136c6b0214..997cdfd7b1ea 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -997,10 +997,7 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
static void snd_miro_proc_init(struct snd_card *card,
struct snd_miro *miro)
{
- struct snd_info_entry *entry;
-
- if (!snd_card_proc_new(card, "miro", &entry))
- snd_info_set_text_ops(entry, miro, snd_miro_proc_read);
+ snd_card_ro_proc_new(card, "miro", miro, snd_miro_proc_read);
}
/*
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
index bfa0055e1fd6..7a313ff589c7 100644
--- a/sound/isa/sb/jazz16.c
+++ b/sound/isa/sb/jazz16.c
@@ -356,7 +356,6 @@ static int snd_jazz16_suspend(struct device *pdev, unsigned int n,
struct snd_sb *chip = acard->chip;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
snd_sbmixer_suspend(chip);
return 0;
}
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 8f9ebeb998f6..3844d4c02f49 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -471,7 +471,6 @@ static int snd_sb16_suspend(struct snd_card *card, pm_message_t state)
struct snd_sb *chip = acard->chip;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
snd_sbmixer_suspend(chip);
return 0;
}
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index bf3db0d2ea12..a09ad57b8313 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -1126,10 +1126,9 @@ static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p)
static int init_proc_entry(struct snd_sb_csp * p, int device)
{
char name[16];
- struct snd_info_entry *entry;
+
sprintf(name, "cspD%d", device);
- if (! snd_card_proc_new(p->chip->card, name, &entry))
- snd_info_set_text_ops(entry, p, info_read);
+ snd_card_ro_proc_new(p->chip->card, name, p, info_read);
return 0;
}
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
index 37e6ce7b0b13..473ec74ae48c 100644
--- a/sound/isa/sb/sb16_main.c
+++ b/sound/isa/sb/sb16_main.c
@@ -879,13 +879,17 @@ 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)
- snd_ctl_add(card, snd_ctl_new1(&snd_sb16_dma_control, chip));
- else
+ 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 {
pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
+ }
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_isa_data(),
+ card->dev,
64*1024, 128*1024);
return 0;
}
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index d77dcba276b5..aa2a83eb81a9 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -218,7 +218,6 @@ static int snd_sb8_suspend(struct device *dev, unsigned int n,
struct snd_sb *chip = acard->chip;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
snd_sbmixer_suspend(chip);
return 0;
}
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c
index 8288fae90085..97645a732a71 100644
--- a/sound/isa/sb/sb8_main.c
+++ b/sound/isa/sb/sb8_main.c
@@ -610,7 +610,7 @@ int snd_sb8dsp_pcm(struct snd_sb *chip, int device)
if (chip->dma8 > 3 || chip->dma16 >= 0)
max_prealloc = 128 * 1024;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_isa_data(),
+ card->dev,
64*1024, max_prealloc);
return 0;
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 733adee5afbf..8181db4db019 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -167,12 +167,13 @@ static inline struct soundscape *get_card_soundscape(struct snd_card *c)
* I think this means that the memory has to map to
* contiguous pages of physical memory.
*/
-static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf,
+static struct snd_dma_buffer *get_dmabuf(struct soundscape *s,
+ struct snd_dma_buffer *buf,
unsigned long size)
{
if (buf) {
if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV,
- snd_dma_isa_data(),
+ s->chip->card->dev,
size, buf) < 0) {
snd_printk(KERN_ERR "sscape: Failed to allocate "
"%lu bytes for DMA\n",
@@ -443,7 +444,7 @@ static int upload_dma_data(struct soundscape *s, const unsigned char *data,
int ret;
unsigned char val;
- if (!get_dmabuf(&dma, PAGE_ALIGN(32 * 1024)))
+ if (!get_dmabuf(s, &dma, PAGE_ALIGN(32 * 1024)))
return -ENOMEM;
spin_lock_irqsave(&s->lock, flags);
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 3a5008837576..0dfb8065b403 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -1625,7 +1625,6 @@ static void snd_wss_suspend(struct snd_wss *chip)
int reg;
unsigned long flags;
- snd_pcm_suspend_all(chip->pcm);
spin_lock_irqsave(&chip->reg_lock, flags);
for (reg = 0; reg < 32; reg++)
chip->image[reg] = snd_wss_in(chip, reg);
@@ -1943,7 +1942,7 @@ int snd_wss_pcm(struct snd_wss *chip, int device)
strcpy(pcm->name, snd_wss_chip_id(chip));
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_isa_data(),
+ chip->card->dev,
64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
chip->pcm = pcm;
diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c
index a4ed54aeaf1d..d63e1565b62b 100644
--- a/sound/mips/hal2.c
+++ b/sound/mips/hal2.c
@@ -454,21 +454,22 @@ static inline void hal2_stop_adc(struct snd_hal2 *hal2)
hal2->adc.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD;
}
-static int hal2_alloc_dmabuf(struct hal2_codec *codec)
+static int hal2_alloc_dmabuf(struct snd_hal2 *hal2, struct hal2_codec *codec)
{
+ struct device *dev = hal2->card->dev;
struct hal2_desc *desc;
dma_addr_t desc_dma, buffer_dma;
int count = H2_BUF_SIZE / H2_BLOCK_SIZE;
int i;
- codec->buffer = dma_alloc_attrs(NULL, H2_BUF_SIZE, &buffer_dma,
+ codec->buffer = dma_alloc_attrs(dev, H2_BUF_SIZE, &buffer_dma,
GFP_KERNEL, DMA_ATTR_NON_CONSISTENT);
if (!codec->buffer)
return -ENOMEM;
- desc = dma_alloc_attrs(NULL, count * sizeof(struct hal2_desc),
+ desc = dma_alloc_attrs(dev, count * sizeof(struct hal2_desc),
&desc_dma, GFP_KERNEL, DMA_ATTR_NON_CONSISTENT);
if (!desc) {
- dma_free_attrs(NULL, H2_BUF_SIZE, codec->buffer, buffer_dma,
+ dma_free_attrs(dev, H2_BUF_SIZE, codec->buffer, buffer_dma,
DMA_ATTR_NON_CONSISTENT);
return -ENOMEM;
}
@@ -482,17 +483,19 @@ static int hal2_alloc_dmabuf(struct hal2_codec *codec)
desc_dma : desc_dma + (i + 1) * sizeof(struct hal2_desc);
desc++;
}
- dma_cache_sync(NULL, codec->desc, count * sizeof(struct hal2_desc),
+ dma_cache_sync(dev, codec->desc, count * sizeof(struct hal2_desc),
DMA_TO_DEVICE);
codec->desc_count = count;
return 0;
}
-static void hal2_free_dmabuf(struct hal2_codec *codec)
+static void hal2_free_dmabuf(struct snd_hal2 *hal2, struct hal2_codec *codec)
{
- dma_free_attrs(NULL, codec->desc_count * sizeof(struct hal2_desc),
+ struct device *dev = hal2->card->dev;
+
+ dma_free_attrs(dev, codec->desc_count * sizeof(struct hal2_desc),
codec->desc, codec->desc_dma, DMA_ATTR_NON_CONSISTENT);
- dma_free_attrs(NULL, H2_BUF_SIZE, codec->buffer, codec->buffer_dma,
+ dma_free_attrs(dev, H2_BUF_SIZE, codec->buffer, codec->buffer_dma,
DMA_ATTR_NON_CONSISTENT);
}
@@ -540,7 +543,7 @@ static int hal2_playback_open(struct snd_pcm_substream *substream)
runtime->hw = hal2_pcm_hw;
- err = hal2_alloc_dmabuf(&hal2->dac);
+ err = hal2_alloc_dmabuf(hal2, &hal2->dac);
if (err)
return err;
return 0;
@@ -550,7 +553,7 @@ static int hal2_playback_close(struct snd_pcm_substream *substream)
{
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
- hal2_free_dmabuf(&hal2->dac);
+ hal2_free_dmabuf(hal2, &hal2->dac);
return 0;
}
@@ -606,7 +609,7 @@ static void hal2_playback_transfer(struct snd_pcm_substream *substream,
unsigned char *buf = hal2->dac.buffer + rec->hw_data;
memcpy(buf, substream->runtime->dma_area + rec->sw_data, bytes);
- dma_cache_sync(NULL, buf, bytes, DMA_TO_DEVICE);
+ dma_cache_sync(hal2->card->dev, buf, bytes, DMA_TO_DEVICE);
}
@@ -629,7 +632,7 @@ static int hal2_capture_open(struct snd_pcm_substream *substream)
runtime->hw = hal2_pcm_hw;
- err = hal2_alloc_dmabuf(adc);
+ err = hal2_alloc_dmabuf(hal2, adc);
if (err)
return err;
return 0;
@@ -639,7 +642,7 @@ static int hal2_capture_close(struct snd_pcm_substream *substream)
{
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
- hal2_free_dmabuf(&hal2->adc);
+ hal2_free_dmabuf(hal2, &hal2->adc);
return 0;
}
@@ -694,7 +697,7 @@ static void hal2_capture_transfer(struct snd_pcm_substream *substream,
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
unsigned char *buf = hal2->adc.buffer + rec->hw_data;
- dma_cache_sync(NULL, buf, bytes, DMA_FROM_DEVICE);
+ dma_cache_sync(hal2->card->dev, buf, bytes, DMA_FROM_DEVICE);
memcpy(substream->runtime->dma_area + rec->sw_data, buf, bytes);
}
diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c
index 3ec9391a4736..53a4ee01c522 100644
--- a/sound/mips/sgio2audio.c
+++ b/sound/mips/sgio2audio.c
@@ -805,7 +805,7 @@ static int snd_sgio2audio_free(struct snd_sgio2audio *chip)
free_irq(snd_sgio2_isr_table[i].irq,
&chip->channel[snd_sgio2_isr_table[i].idx]);
- dma_free_coherent(NULL, MACEISA_RINGBUFFERS_SIZE,
+ dma_free_coherent(chip->card->dev, MACEISA_RINGBUFFERS_SIZE,
chip->ring_base, chip->ring_base_dma);
/* release card data */
@@ -843,8 +843,9 @@ static int snd_sgio2audio_create(struct snd_card *card,
chip->card = card;
- chip->ring_base = dma_alloc_coherent(NULL, MACEISA_RINGBUFFERS_SIZE,
- &chip->ring_base_dma, GFP_USER);
+ chip->ring_base = dma_alloc_coherent(card->dev,
+ MACEISA_RINGBUFFERS_SIZE,
+ &chip->ring_base_dma, GFP_KERNEL);
if (chip->ring_base == NULL) {
printk(KERN_ERR
"sgio2audio: could not allocate ring buffers\n");
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index f36e7006e00c..a4264b8943f0 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -669,14 +669,8 @@ snd_harmony_pcm_init(struct snd_harmony *h)
}
/* pre-allocate space for DMA */
- err = snd_pcm_lib_preallocate_pages_for_all(pcm, h->dma.type,
- h->dma.dev,
- MAX_BUF_SIZE,
- MAX_BUF_SIZE);
- if (err < 0) {
- printk(KERN_ERR PFX "buffer allocation error: %d\n", err);
- return err;
- }
+ snd_pcm_lib_preallocate_pages_for_all(pcm, h->dma.type, h->dma.dev,
+ MAX_BUF_SIZE, MAX_BUF_SIZE);
h->st.format = snd_harmony_set_data_format(h,
SNDRV_PCM_FORMAT_S16_BE, 1);
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c
index e120a11c69e8..20516b6907b5 100644
--- a/sound/pci/ac97/ac97_proc.c
+++ b/sound/pci/ac97/ac97_proc.c
@@ -436,25 +436,20 @@ void snd_ac97_proc_init(struct snd_ac97 * ac97)
return;
prefix = ac97_is_audio(ac97) ? "ac97" : "mc97";
sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num);
- if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) {
+ entry = snd_info_create_card_entry(ac97->bus->card, name,
+ ac97->bus->proc);
+ if (entry)
snd_info_set_text_ops(entry, ac97, snd_ac97_proc_read);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
ac97->proc = entry;
sprintf(name, "%s#%d-%d+regs", prefix, ac97->addr, ac97->num);
- if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) {
+ entry = snd_info_create_card_entry(ac97->bus->card, name,
+ ac97->bus->proc);
+ if (entry) {
snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read);
#ifdef CONFIG_SND_DEBUG
entry->mode |= 0200;
entry->c.text.write = snd_ac97_proc_regs_write;
#endif
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
}
ac97->proc_regs = entry;
}
@@ -473,13 +468,10 @@ void snd_ac97_bus_proc_init(struct snd_ac97_bus * bus)
char name[32];
sprintf(name, "codec97#%d", bus->num);
- if ((entry = snd_info_create_card_entry(bus->card, name, bus->card->proc_root)) != NULL) {
+ entry = snd_info_create_card_entry(bus->card, name,
+ bus->card->proc_root);
+ if (entry)
entry->mode = S_IFDIR | 0555;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
bus->proc = entry;
}
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index d9c54c08e2db..fef07ae648e6 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -644,16 +644,11 @@ snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device)
chip->psubs = NULL;
chip->csubs = NULL;
- err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(chip->pci),
BUFFER_BYTES_MAX / 2,
BUFFER_BYTES_MAX);
- if (err < 0) {
- dev_err(chip->card->dev, "buffer allocation error: %d\n", err);
- return err;
- }
-
return 0;
}
@@ -741,10 +736,8 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
static void
snd_ad1889_proc_init(struct snd_ad1889 *chip)
{
- struct snd_info_entry *entry;
-
- if (!snd_card_proc_new(chip->card, chip->card->driver, &entry))
- snd_info_set_text_ops(entry, chip, snd_ad1889_proc_read);
+ snd_card_ro_proc_new(chip->card, chip->card->driver,
+ chip, snd_ad1889_proc_read);
}
static const struct ac97_quirk ac97_quirks[] = {
diff --git a/sound/pci/ak4531_codec.c b/sound/pci/ak4531_codec.c
index 2fb1fbba3e5e..11e902cac71b 100644
--- a/sound/pci/ak4531_codec.c
+++ b/sound/pci/ak4531_codec.c
@@ -481,8 +481,5 @@ static void snd_ak4531_proc_read(struct snd_info_entry *entry,
static void
snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(card, "ak4531", &entry))
- snd_info_set_text_ops(entry, ak4531, snd_ak4531_proc_read);
+ snd_card_ro_proc_new(card, "ak4531", ak4531, snd_ak4531_proc_read);
}
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 9f569379b77e..f7fbe05836b3 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -1882,10 +1882,8 @@ static int ali_suspend(struct device *dev)
return 0;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- for (i = 0; i < chip->num_of_codecs; i++) {
- snd_pcm_suspend_all(chip->pcm[i]);
+ for (i = 0; i < chip->num_of_codecs; i++)
snd_ac97_suspend(chip->ac97[i]);
- }
spin_lock_irq(&chip->reg_lock);
@@ -2051,9 +2049,7 @@ static void snd_ali_proc_read(struct snd_info_entry *entry,
static void snd_ali_proc_init(struct snd_ali *codec)
{
- struct snd_info_entry *entry;
- if (!snd_card_proc_new(codec->card, "ali5451", &entry))
- snd_info_set_text_ops(entry, codec, snd_ali_proc_read);
+ snd_card_ro_proc_new(codec->card, "ali5451", codec, snd_ali_proc_read);
}
static int snd_ali_resources(struct snd_ali *codec)
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index eaa2d853d922..516b3d9cbfdf 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -731,7 +731,6 @@ static int snd_als300_suspend(struct device *dev)
struct snd_als300 *chip = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
snd_ac97_suspend(chip->ac97);
return 0;
}
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 26b097edec8c..45fa38382e79 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -994,7 +994,6 @@ static int snd_als4000_suspend(struct device *dev)
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
snd_sbmixer_suspend(chip);
return 0;
}
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index aad74e809797..32b2f9802479 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -2782,10 +2782,8 @@ snd_asihpi_proc_read(struct snd_info_entry *entry,
static void snd_asihpi_proc_init(struct snd_card_asihpi *asihpi)
{
- struct snd_info_entry *entry;
-
- if (!snd_card_proc_new(asihpi->card, "info", &entry))
- snd_info_set_text_ops(entry, asihpi, snd_asihpi_proc_read);
+ snd_card_ro_proc_new(asihpi->card, "info", asihpi,
+ snd_asihpi_proc_read);
}
/*------------------------------------------------------------
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 1a41f8c80243..169763c88f5e 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -733,6 +733,10 @@ static int snd_atiixp_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
+ if (dma->running && dma->suspended &&
+ cmd == SNDRV_PCM_TRIGGER_RESUME)
+ writel(dma->saved_curptr, chip->remap_addr +
+ dma->ops->dt_cur);
dma->ops->enable_transfer(chip, 1);
dma->running = 1;
dma->suspended = 0;
@@ -740,9 +744,12 @@ static int snd_atiixp_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
+ dma->suspended = cmd == SNDRV_PCM_TRIGGER_SUSPEND;
+ if (dma->running && dma->suspended)
+ dma->saved_curptr = readl(chip->remap_addr +
+ dma->ops->dt_cur);
dma->ops->enable_transfer(chip, 0);
dma->running = 0;
- dma->suspended = cmd == SNDRV_PCM_TRIGGER_SUSPEND;
break;
default:
err = -EINVAL;
@@ -1479,14 +1486,6 @@ static int snd_atiixp_suspend(struct device *dev)
int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- for (i = 0; i < NUM_ATI_PCMDEVS; i++)
- if (chip->pcmdevs[i]) {
- struct atiixp_dma *dma = &chip->dmas[i];
- if (dma->substream && dma->running)
- dma->saved_curptr = readl(chip->remap_addr +
- dma->ops->dt_cur);
- snd_pcm_suspend_all(chip->pcmdevs[i]);
- }
for (i = 0; i < NUM_ATI_CODECS; i++)
snd_ac97_suspend(chip->ac97[i]);
snd_atiixp_aclink_down(chip);
@@ -1514,8 +1513,6 @@ static int snd_atiixp_resume(struct device *dev)
dma->substream->ops->prepare(dma->substream);
writel((u32)dma->desc_buf.addr | ATI_REG_LINKPTR_EN,
chip->remap_addr + dma->ops->llp_offset);
- writel(dma->saved_curptr, chip->remap_addr +
- dma->ops->dt_cur);
}
}
@@ -1546,10 +1543,7 @@ static void snd_atiixp_proc_read(struct snd_info_entry *entry,
static void snd_atiixp_proc_init(struct atiixp *chip)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(chip->card, "atiixp", &entry))
- snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read);
+ snd_card_ro_proc_new(chip->card, "atiixp", chip, snd_atiixp_proc_read);
}
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index dc1de860cedf..cece66bb3644 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1125,8 +1125,6 @@ static int snd_atiixp_suspend(struct device *dev)
int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- for (i = 0; i < NUM_ATI_PCMDEVS; i++)
- snd_pcm_suspend_all(chip->pcmdevs[i]);
for (i = 0; i < NUM_ATI_CODECS; i++)
snd_ac97_suspend(chip->ac97[i]);
snd_atiixp_aclink_down(chip);
@@ -1172,10 +1170,8 @@ static void snd_atiixp_proc_read(struct snd_info_entry *entry,
static void snd_atiixp_proc_init(struct atiixp_modem *chip)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry))
- snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read);
+ snd_card_ro_proc_new(chip->card, "atiixp-modem", chip,
+ snd_atiixp_proc_read);
}
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index 9a49e4243a9c..b07c5fc1da56 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -624,15 +624,10 @@ static int snd_aw2_new_pcm(struct aw2 *chip)
/* pre-allocation of buffers */
/* Preallocate continuous pages. */
- err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_ana,
- SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data
- (chip->pci),
- 64 * 1024, 64 * 1024);
- if (err)
- dev_err(chip->card->dev,
- "snd_pcm_lib_preallocate_pages_for_all error (0x%X)\n",
- err);
+ snd_pcm_lib_preallocate_pages_for_all(pcm_playback_ana,
+ SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ 64 * 1024, 64 * 1024);
err = snd_pcm_new(chip->card, "Audiowerk2 digital playback", 1, 1, 0,
&pcm_playback_num);
@@ -661,15 +656,10 @@ static int snd_aw2_new_pcm(struct aw2 *chip)
/* pre-allocation of buffers */
/* Preallocate continuous pages. */
- err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_num,
- SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data
- (chip->pci),
- 64 * 1024, 64 * 1024);
- if (err)
- dev_err(chip->card->dev,
- "snd_pcm_lib_preallocate_pages_for_all error (0x%X)\n",
- err);
+ snd_pcm_lib_preallocate_pages_for_all(pcm_playback_num,
+ SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ 64 * 1024, 64 * 1024);
err = snd_pcm_new(chip->card, "Audiowerk2 capture", 2, 0, 1,
&pcm_capture);
@@ -699,16 +689,10 @@ static int snd_aw2_new_pcm(struct aw2 *chip)
/* pre-allocation of buffers */
/* Preallocate continuous pages. */
- err = snd_pcm_lib_preallocate_pages_for_all(pcm_capture,
- SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data
- (chip->pci),
- 64 * 1024, 64 * 1024);
- if (err)
- dev_err(chip->card->dev,
- "snd_pcm_lib_preallocate_pages_for_all error (0x%X)\n",
- err);
-
+ snd_pcm_lib_preallocate_pages_for_all(pcm_capture,
+ SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ 64 * 1024, 64 * 1024);
/* Create control */
err = snd_ctl_add(chip->card, snd_ctl_new1(&aw2_control, chip));
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index fc18c29a8173..90348817f096 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -2699,10 +2699,6 @@ snd_azf3328_suspend(struct device *dev)
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- /* same pcm object for playback/capture */
- snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]);
- snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]);
-
snd_azf3328_suspend_ac97(chip);
snd_azf3328_suspend_regs(chip, chip->ctrl_io,
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index ba971042f871..0adcba10c067 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -714,11 +714,11 @@ static int snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
pcm->private_data = chip;
strcpy(pcm->name, name);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_bt87x_pcm_ops);
- return snd_pcm_lib_preallocate_pages_for_all(pcm,
- SNDRV_DMA_TYPE_DEV_SG,
- snd_dma_pci_data(chip->pci),
- 128 * 1024,
- ALIGN(255 * 4092, 1024));
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+ snd_dma_pci_data(chip->pci),
+ 128 * 1024,
+ ALIGN(255 * 4092, 1024));
+ return 0;
}
static int snd_bt87x_create(struct snd_card *card,
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index cd27b5536654..11ef0d636405 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1402,21 +1402,17 @@ static int snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
substream;
substream = substream->next) {
- if ((err = snd_pcm_lib_preallocate_pages(substream,
- SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(emu->pci),
- 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
- return err;
+ snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(emu->pci),
+ 64*1024, 64*1024);
}
for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
substream;
substream = substream->next) {
- if ((err = snd_pcm_lib_preallocate_pages(substream,
- SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(emu->pci),
- 64*1024, 64*1024)) < 0)
- return err;
+ snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(emu->pci),
+ 64*1024, 64*1024);
}
err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, 2,
@@ -1910,11 +1906,8 @@ static int snd_ca0106_suspend(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
struct snd_ca0106 *chip = card->private_data;
- int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- for (i = 0; i < 4; i++)
- snd_pcm_suspend_all(chip->pcm[i]);
if (chip->details->ac97)
snd_ac97_suspend(chip->ac97);
snd_ca0106_mixer_suspend(chip);
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c
index a2c85cc37972..f5b8934db735 100644
--- a/sound/pci/ca0106/ca0106_proc.c
+++ b/sound/pci/ca0106/ca0106_proc.c
@@ -424,30 +424,20 @@ static void snd_ca0106_proc_i2c_write(struct snd_info_entry *entry,
int snd_ca0106_proc_init(struct snd_ca0106 *emu)
{
- struct snd_info_entry *entry;
-
- if(! snd_card_proc_new(emu->card, "iec958", &entry))
- snd_info_set_text_ops(entry, emu, snd_ca0106_proc_iec958);
- if(! snd_card_proc_new(emu->card, "ca0106_reg32", &entry)) {
- snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read32);
- entry->c.text.write = snd_ca0106_proc_reg_write32;
- entry->mode |= 0200;
- }
- if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry))
- snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read16);
- if(! snd_card_proc_new(emu->card, "ca0106_reg8", &entry))
- snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read8);
- if(! snd_card_proc_new(emu->card, "ca0106_regs1", &entry)) {
- snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read1);
- entry->c.text.write = snd_ca0106_proc_reg_write;
- entry->mode |= 0200;
- }
- if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) {
- entry->c.text.write = snd_ca0106_proc_i2c_write;
- entry->private_data = emu;
- entry->mode |= 0200;
- }
- if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry))
- snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read2);
+ snd_card_ro_proc_new(emu->card, "iec958", emu, snd_ca0106_proc_iec958);
+ snd_card_rw_proc_new(emu->card, "ca0106_reg32", emu,
+ snd_ca0106_proc_reg_read32,
+ snd_ca0106_proc_reg_write32);
+ snd_card_ro_proc_new(emu->card, "ca0106_reg16", emu,
+ snd_ca0106_proc_reg_read16);
+ snd_card_ro_proc_new(emu->card, "ca0106_reg8", emu,
+ snd_ca0106_proc_reg_read8);
+ snd_card_rw_proc_new(emu->card, "ca0106_regs1", emu,
+ snd_ca0106_proc_reg_read1,
+ snd_ca0106_proc_reg_write);
+ snd_card_rw_proc_new(emu->card, "ca0106_i2c", emu, NULL,
+ snd_ca0106_proc_i2c_write);
+ snd_card_ro_proc_new(emu->card, "ca0106_regs2", emu,
+ snd_ca0106_proc_reg_read2);
return 0;
}
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 452cc79b44af..701be04aed53 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2792,10 +2792,7 @@ static void snd_cmipci_proc_read(struct snd_info_entry *entry,
static void snd_cmipci_proc_init(struct cmipci *cm)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(cm->card, "cmipci", &entry))
- snd_info_set_text_ops(entry, cm, snd_cmipci_proc_read);
+ snd_card_ro_proc_new(cm->card, "cmipci", cm, snd_cmipci_proc_read);
}
static const struct pci_device_id snd_cmipci_ids[] = {
@@ -3351,10 +3348,6 @@ static int snd_cmipci_suspend(struct device *dev)
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(cm->pcm);
- snd_pcm_suspend_all(cm->pcm2);
- snd_pcm_suspend_all(cm->pcm_spdif);
-
/* save registers */
for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
cm->saved_regs[i] = snd_cmipci_read(cm, saved_regs[i]);
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index ec4247638fa1..15bbf9564c82 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1174,8 +1174,7 @@ static void snd_cs4281_proc_init(struct cs4281 *chip)
{
struct snd_info_entry *entry;
- if (! snd_card_proc_new(chip->card, "cs4281", &entry))
- snd_info_set_text_ops(entry, chip, snd_cs4281_proc_read);
+ snd_card_ro_proc_new(chip->card, "cs4281", chip, snd_cs4281_proc_read);
if (! snd_card_proc_new(chip->card, "cs4281_BA0", &entry)) {
entry->content = SNDRV_INFO_CONTENT_DATA;
entry->private_data = chip;
@@ -2002,8 +2001,6 @@ static int cs4281_suspend(struct device *dev)
unsigned int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
-
snd_ac97_suspend(chip->ac97);
snd_ac97_suspend(chip->ac97_secondary);
diff --git a/sound/pci/cs46xx/cs46xx_dsp_spos.h b/sound/pci/cs46xx/cs46xx_dsp_spos.h
index 8008c59288a6..a02e1e19c021 100644
--- a/sound/pci/cs46xx/cs46xx_dsp_spos.h
+++ b/sound/pci/cs46xx/cs46xx_dsp_spos.h
@@ -177,22 +177,16 @@ struct dsp_spos_instance {
/* proc fs */
struct snd_card *snd_card;
struct snd_info_entry * proc_dsp_dir;
- struct snd_info_entry * proc_sym_info_entry;
- struct snd_info_entry * proc_modules_info_entry;
- struct snd_info_entry * proc_parameter_dump_info_entry;
- struct snd_info_entry * proc_sample_dump_info_entry;
/* SCB's descriptors */
int nscb;
int scb_highest_frag_index;
struct dsp_scb_descriptor scbs[DSP_MAX_SCB_DESC];
- struct snd_info_entry * proc_scb_info_entry;
struct dsp_scb_descriptor * the_null_scb;
/* Task's descriptors */
int ntask;
struct dsp_task_descriptor tasks[DSP_MAX_TASK_DESC];
- struct snd_info_entry * proc_task_info_entry;
/* SPDIF status */
int spdif_status_out;
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 750eec437a79..a77d4cc44028 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -3781,12 +3781,6 @@ static int snd_cs46xx_suspend(struct device *dev)
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
chip->in_suspend = 1;
- snd_pcm_suspend_all(chip->pcm);
-#ifdef CONFIG_SND_CS46XX_NEW_DSP
- snd_pcm_suspend_all(chip->pcm_rear);
- snd_pcm_suspend_all(chip->pcm_center_lfe);
- snd_pcm_suspend_all(chip->pcm_iec958);
-#endif
// chip->ac97_powerdown = snd_cs46xx_codec_read(chip, AC97_POWER_CONTROL);
// chip->ac97_general_purpose = snd_cs46xx_codec_read(chip, BA0_AC97_GENERAL_PURPOSE);
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index 5fc497c6d738..c28e58602679 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -799,92 +799,49 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
ins->snd_card = card;
- if ((entry = snd_info_create_card_entry(card, "dsp", card->proc_root)) != NULL) {
- entry->content = SNDRV_INFO_CONTENT_TEXT;
+ entry = snd_info_create_card_entry(card, "dsp", card->proc_root);
+ if (entry)
entry->mode = S_IFDIR | 0555;
-
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
-
ins->proc_dsp_dir = entry;
if (!ins->proc_dsp_dir)
return -ENOMEM;
- if ((entry = snd_info_create_card_entry(card, "spos_symbols", ins->proc_dsp_dir)) != NULL) {
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->private_data = chip;
- entry->mode = S_IFREG | 0644;
- entry->c.text.read = cs46xx_dsp_proc_symbol_table_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- ins->proc_sym_info_entry = entry;
+ entry = snd_info_create_card_entry(card, "spos_symbols",
+ ins->proc_dsp_dir);
+ if (entry)
+ snd_info_set_text_ops(entry, chip,
+ cs46xx_dsp_proc_symbol_table_read);
- if ((entry = snd_info_create_card_entry(card, "spos_modules", ins->proc_dsp_dir)) != NULL) {
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->private_data = chip;
- entry->mode = S_IFREG | 0644;
- entry->c.text.read = cs46xx_dsp_proc_modules_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- ins->proc_modules_info_entry = entry;
-
- if ((entry = snd_info_create_card_entry(card, "parameter", ins->proc_dsp_dir)) != NULL) {
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->private_data = chip;
- entry->mode = S_IFREG | 0644;
- entry->c.text.read = cs46xx_dsp_proc_parameter_dump_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- ins->proc_parameter_dump_info_entry = entry;
-
- if ((entry = snd_info_create_card_entry(card, "sample", ins->proc_dsp_dir)) != NULL) {
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->private_data = chip;
- entry->mode = S_IFREG | 0644;
- entry->c.text.read = cs46xx_dsp_proc_sample_dump_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- ins->proc_sample_dump_info_entry = entry;
-
- if ((entry = snd_info_create_card_entry(card, "task_tree", ins->proc_dsp_dir)) != NULL) {
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->private_data = chip;
- entry->mode = S_IFREG | 0644;
- entry->c.text.read = cs46xx_dsp_proc_task_tree_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- ins->proc_task_info_entry = entry;
-
- if ((entry = snd_info_create_card_entry(card, "scb_info", ins->proc_dsp_dir)) != NULL) {
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->private_data = chip;
- entry->mode = S_IFREG | 0644;
- entry->c.text.read = cs46xx_dsp_proc_scb_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- ins->proc_scb_info_entry = entry;
+ entry = snd_info_create_card_entry(card, "spos_modules",
+ ins->proc_dsp_dir);
+ if (entry)
+ snd_info_set_text_ops(entry, chip,
+ cs46xx_dsp_proc_modules_read);
+
+ entry = snd_info_create_card_entry(card, "parameter",
+ ins->proc_dsp_dir);
+ if (entry)
+ snd_info_set_text_ops(entry, chip,
+ cs46xx_dsp_proc_parameter_dump_read);
+
+ entry = snd_info_create_card_entry(card, "sample",
+ ins->proc_dsp_dir);
+ if (entry)
+ snd_info_set_text_ops(entry, chip,
+ cs46xx_dsp_proc_sample_dump_read);
+
+ entry = snd_info_create_card_entry(card, "task_tree",
+ ins->proc_dsp_dir);
+ if (entry)
+ snd_info_set_text_ops(entry, chip,
+ cs46xx_dsp_proc_task_tree_read);
+
+ entry = snd_info_create_card_entry(card, "scb_info",
+ ins->proc_dsp_dir);
+ if (entry)
+ snd_info_set_text_ops(entry, chip,
+ cs46xx_dsp_proc_scb_read);
mutex_lock(&chip->spos_mutex);
/* register/update SCB's entries on proc */
@@ -906,24 +863,6 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip)
if (!ins)
return 0;
- snd_info_free_entry(ins->proc_sym_info_entry);
- ins->proc_sym_info_entry = NULL;
-
- snd_info_free_entry(ins->proc_modules_info_entry);
- ins->proc_modules_info_entry = NULL;
-
- snd_info_free_entry(ins->proc_parameter_dump_info_entry);
- ins->proc_parameter_dump_info_entry = NULL;
-
- snd_info_free_entry(ins->proc_sample_dump_info_entry);
- ins->proc_sample_dump_info_entry = NULL;
-
- snd_info_free_entry(ins->proc_scb_info_entry);
- ins->proc_scb_info_entry = NULL;
-
- snd_info_free_entry(ins->proc_task_info_entry);
- ins->proc_task_info_entry = NULL;
-
mutex_lock(&chip->spos_mutex);
for (i = 0; i < ins->nscb; ++i) {
if (ins->scbs[i].deleted) continue;
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
index 8d0a3d357345..1d9d610262de 100644
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c
@@ -254,8 +254,9 @@ void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip,
if (ins->snd_card != NULL && ins->proc_dsp_dir != NULL &&
scb->proc_info == NULL) {
- if ((entry = snd_info_create_card_entry(ins->snd_card, scb->scb_name,
- ins->proc_dsp_dir)) != NULL) {
+ entry = snd_info_create_card_entry(ins->snd_card, scb->scb_name,
+ ins->proc_dsp_dir);
+ if (entry) {
scb_info = kmalloc(sizeof(struct proc_scb_info), GFP_KERNEL);
if (!scb_info) {
snd_info_free_entry(entry);
@@ -265,18 +266,8 @@ void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip,
scb_info->chip = chip;
scb_info->scb_desc = scb;
-
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->private_data = scb_info;
- entry->mode = S_IFREG | 0644;
-
- entry->c.text.read = cs46xx_dsp_proc_scb_info_read;
-
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- kfree (scb_info);
- entry = NULL;
- }
+ snd_info_set_text_ops(entry, scb_info,
+ cs46xx_dsp_proc_scb_info_read);
}
out:
scb->proc_info = entry;
diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c
index 82bd10b68a77..446ef1f1b45a 100644
--- a/sound/pci/cs5535audio/cs5535audio_pm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pm.c
@@ -62,7 +62,6 @@ static int __maybe_unused snd_cs5535audio_suspend(struct device *dev)
int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(cs5535au->pcm);
snd_ac97_suspend(cs5535au->ac97);
for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
struct cs5535audio_dma *dma = &cs5535au->dmas[i];
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
index 2ada8444abd9..e622613ea947 100644
--- a/sound/pci/ctxfi/ctatc.c
+++ b/sound/pci/ctxfi/ctatc.c
@@ -1548,18 +1548,10 @@ static void atc_connect_resources(struct ct_atc *atc)
#ifdef CONFIG_PM_SLEEP
static int atc_suspend(struct ct_atc *atc)
{
- int i;
struct hw *hw = atc->hw;
snd_power_change_state(atc->card, SNDRV_CTL_POWER_D3hot);
- for (i = FRONT; i < NUM_PCMS; i++) {
- if (!atc->pcms[i])
- continue;
-
- snd_pcm_suspend_all(atc->pcms[i]);
- }
-
atc_release_resources(atc);
hw->suspend(hw);
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 907cf1a46712..ea876b0b02b9 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -884,17 +884,15 @@ static const struct snd_pcm_ops digital_capture_ops = {
static int snd_echo_preallocate_pages(struct snd_pcm *pcm, struct device *dev)
{
struct snd_pcm_substream *ss;
- int stream, err;
+ int stream;
for (stream = 0; stream < 2; stream++)
- for (ss = pcm->streams[stream].substream; ss; ss = ss->next) {
- err = snd_pcm_lib_preallocate_pages(ss, SNDRV_DMA_TYPE_DEV_SG,
- dev,
- ss->number ? 0 : 128<<10,
- 256<<10);
- if (err < 0)
- return err;
- }
+ for (ss = pcm->streams[stream].substream; ss; ss = ss->next)
+ snd_pcm_lib_preallocate_pages(ss, SNDRV_DMA_TYPE_DEV_SG,
+ dev,
+ ss->number ? 0 : 128<<10,
+ 256<<10);
+
return 0;
}
@@ -2165,9 +2163,6 @@ static int snd_echo_suspend(struct device *dev)
{
struct echoaudio *chip = dev_get_drvdata(dev);
- snd_pcm_suspend_all(chip->analog_pcm);
- snd_pcm_suspend_all(chip->digital_pcm);
-
#ifdef ECHOCARD_HAS_MIDI
/* This call can sleep */
if (chip->midi_out)
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index d3203df50a1a..3c41a0edcfb0 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -224,12 +224,6 @@ static int snd_emu10k1_suspend(struct device *dev)
cancel_delayed_work_sync(&emu->emu1010.firmware_work);
- snd_pcm_suspend_all(emu->pcm);
- snd_pcm_suspend_all(emu->pcm_mic);
- snd_pcm_suspend_all(emu->pcm_efx);
- snd_pcm_suspend_all(emu->pcm_multi);
- snd_pcm_suspend_all(emu->pcm_p16v);
-
snd_ac97_suspend(emu->ac97);
snd_emu10k1_efx_suspend(emu);
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 611589cbdad6..576c7bd03a1a 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -1065,15 +1065,9 @@ static void snd_emu10k1x_proc_reg_write(struct snd_info_entry *entry,
static int snd_emu10k1x_proc_init(struct emu10k1x *emu)
{
- struct snd_info_entry *entry;
-
- if(! snd_card_proc_new(emu->card, "emu10k1x_regs", &entry)) {
- snd_info_set_text_ops(entry, emu, snd_emu10k1x_proc_reg_read);
- entry->c.text.write = snd_emu10k1x_proc_reg_write;
- entry->mode |= 0200;
- entry->private_data = emu;
- }
-
+ snd_card_rw_proc_new(emu->card, "emu10k1x_regs", emu,
+ snd_emu10k1x_proc_reg_read,
+ snd_emu10k1x_proc_reg_write);
return 0;
}
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 30b3472d0b75..f6b4cb9ac75c 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -1427,11 +1427,14 @@ int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device)
emu->pcm = pcm;
for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
- if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0)
- return err;
+ snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG,
+ snd_dma_pci_data(emu->pci),
+ 64*1024, 64*1024);
for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next)
- snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
+ snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(emu->pci),
+ 64*1024, 64*1024);
return 0;
}
@@ -1455,8 +1458,9 @@ int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device)
emu->pcm_multi = pcm;
for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
- if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0)
- return err;
+ snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG,
+ snd_dma_pci_data(emu->pci),
+ 64*1024, 64*1024);
return 0;
}
@@ -1489,7 +1493,9 @@ int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device)
strcpy(pcm->name, "Mic Capture");
emu->pcm_mic = pcm;
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(emu->pci),
+ 64*1024, 64*1024);
return 0;
}
@@ -1862,7 +1868,9 @@ int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device)
if (err < 0)
return err;
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(emu->pci),
+ 64*1024, 64*1024);
return 0;
}
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index b57008031792..a3d9f06e8e6a 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -568,55 +568,40 @@ int snd_emu10k1_proc_init(struct snd_emu10k1 *emu)
struct snd_info_entry *entry;
#ifdef CONFIG_SND_DEBUG
if (emu->card_capabilities->emu_model) {
- if (! snd_card_proc_new(emu->card, "emu1010_regs", &entry))
- snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read);
- }
- if (! snd_card_proc_new(emu->card, "io_regs", &entry)) {
- snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read);
- entry->c.text.write = snd_emu_proc_io_reg_write;
- entry->mode |= 0200;
- }
- if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) {
- snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00a);
- entry->c.text.write = snd_emu_proc_ptr_reg_write00;
- entry->mode |= 0200;
- }
- if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) {
- snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00b);
- entry->c.text.write = snd_emu_proc_ptr_reg_write00;
- entry->mode |= 0200;
- }
- if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) {
- snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20a);
- entry->c.text.write = snd_emu_proc_ptr_reg_write20;
- entry->mode |= 0200;
- }
- if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) {
- snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20b);
- entry->c.text.write = snd_emu_proc_ptr_reg_write20;
- entry->mode |= 0200;
- }
- if (! snd_card_proc_new(emu->card, "ptr_regs20c", &entry)) {
- snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20c);
- entry->c.text.write = snd_emu_proc_ptr_reg_write20;
- entry->mode |= 0200;
+ snd_card_ro_proc_new(emu->card, "emu1010_regs",
+ emu, snd_emu_proc_emu1010_reg_read);
}
+ snd_card_rw_proc_new(emu->card, "io_regs", emu,
+ snd_emu_proc_io_reg_read,
+ snd_emu_proc_io_reg_write);
+ snd_card_rw_proc_new(emu->card, "ptr_regs00a", emu,
+ snd_emu_proc_ptr_reg_read00a,
+ snd_emu_proc_ptr_reg_write00);
+ snd_card_rw_proc_new(emu->card, "ptr_regs00b", emu,
+ snd_emu_proc_ptr_reg_read00b,
+ snd_emu_proc_ptr_reg_write00);
+ snd_card_rw_proc_new(emu->card, "ptr_regs20a", emu,
+ snd_emu_proc_ptr_reg_read20a,
+ snd_emu_proc_ptr_reg_write20);
+ snd_card_rw_proc_new(emu->card, "ptr_regs20b", emu,
+ snd_emu_proc_ptr_reg_read20b,
+ snd_emu_proc_ptr_reg_write20);
+ snd_card_rw_proc_new(emu->card, "ptr_regs20c", emu,
+ snd_emu_proc_ptr_reg_read20c,
+ snd_emu_proc_ptr_reg_write20);
#endif
- if (! snd_card_proc_new(emu->card, "emu10k1", &entry))
- snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_read);
+ snd_card_ro_proc_new(emu->card, "emu10k1", emu, snd_emu10k1_proc_read);
- if (emu->card_capabilities->emu10k2_chip) {
- if (! snd_card_proc_new(emu->card, "spdif-in", &entry))
- snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_spdif_read);
- }
- if (emu->card_capabilities->ca0151_chip) {
- if (! snd_card_proc_new(emu->card, "capture-rates", &entry))
- snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_rates_read);
- }
+ if (emu->card_capabilities->emu10k2_chip)
+ snd_card_ro_proc_new(emu->card, "spdif-in", emu,
+ snd_emu10k1_proc_spdif_read);
+ if (emu->card_capabilities->ca0151_chip)
+ snd_card_ro_proc_new(emu->card, "capture-rates", emu,
+ snd_emu10k1_proc_rates_read);
- if (! snd_card_proc_new(emu->card, "voices", &entry))
- snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_voices_read);
+ snd_card_ro_proc_new(emu->card, "voices", emu,
+ snd_emu10k1_proc_voices_read);
if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) {
entry->content = SNDRV_INFO_CONTENT_DATA;
@@ -646,11 +631,7 @@ int snd_emu10k1_proc_init(struct snd_emu10k1 *emu)
entry->size = emu->audigy ? A_TOTAL_SIZE_CODE : TOTAL_SIZE_CODE;
entry->c.ops = &snd_emu10k1_proc_ops_fx8010;
}
- if (! snd_card_proc_new(emu->card, "fx8010_acode", &entry)) {
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->private_data = emu;
- entry->mode = S_IFREG | 0444 /*| S_IWUSR*/;
- entry->c.text.read = snd_emu10k1_proc_acode_read;
- }
+ snd_card_ro_proc_new(emu->card, "fx8010_acode", emu,
+ snd_emu10k1_proc_acode_read);
return 0;
}
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index 4948b95f6665..672017cac4c7 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -656,11 +656,10 @@ int snd_p16v_pcm(struct snd_emu10k1 *emu, int device)
for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
substream;
substream = substream->next) {
- if ((err = snd_pcm_lib_preallocate_pages(substream,
- SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(emu->pci),
- ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0)
- return err;
+ snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(emu->pci),
+ (65536 - 64) * 8,
+ (65536 - 64) * 8);
/*
dev_dbg(emu->card->dev,
"preallocate playback substream: err=%d\n", err);
@@ -670,11 +669,9 @@ int snd_p16v_pcm(struct snd_emu10k1 *emu, int device)
for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
substream;
substream = substream->next) {
- if ((err = snd_pcm_lib_preallocate_pages(substream,
- SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(emu->pci),
- 65536 - 64, 65536 - 64)) < 0)
- return err;
+ snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(emu->pci),
+ 65536 - 64, 65536 - 64);
/*
dev_dbg(emu->card->dev,
"preallocate capture substream: err=%d\n", err);
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 727eb3da1fda..1cfff35e370e 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -1902,10 +1902,8 @@ static void snd_ensoniq_proc_read(struct snd_info_entry *entry,
static void snd_ensoniq_proc_init(struct ensoniq *ensoniq)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(ensoniq->card, "audiopci", &entry))
- snd_info_set_text_ops(entry, ensoniq, snd_ensoniq_proc_read);
+ snd_card_ro_proc_new(ensoniq->card, "audiopci", ensoniq,
+ snd_ensoniq_proc_read);
}
/*
@@ -2037,9 +2035,6 @@ static int snd_ensoniq_suspend(struct device *dev)
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(ensoniq->pcm1);
- snd_pcm_suspend_all(ensoniq->pcm2);
-
#ifdef CHIP1371
snd_ac97_suspend(ensoniq->u.es1371.ac97);
#else
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 9d248eb2e26c..84d07bce581c 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1475,7 +1475,6 @@ static int es1938_suspend(struct device *dev)
unsigned char *s, *d;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
/* save mixer-related registers */
for (s = saved_regs, d = chip->saved_regs; *s; s++, d++)
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 0b1845ca6005..9dcb698fc8c7 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -2392,7 +2392,6 @@ static int es1968_suspend(struct device *dev)
chip->in_suspend = 1;
cancel_work_sync(&chip->hwvol_work);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
snd_ac97_suspend(chip->ac97);
snd_es1968_bob_stop(chip);
return 0;
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index e3fb9c61017c..1317f3183eb1 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1408,7 +1408,6 @@ static int snd_fm801_suspend(struct device *dev)
if (chip->tea575x_tuner & TUNER_ONLY) {
/* FIXME: tea575x suspend */
} else {
- snd_pcm_suspend_all(chip->pcm);
snd_ac97_suspend(chip->ac97);
snd_ac97_suspend(chip->ac97_sec);
}
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index 066b5b59c4d7..b7d9160ed868 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -127,44 +127,6 @@ static void turn_off_beep(struct hda_beep *beep)
}
}
-static void snd_hda_do_detach(struct hda_beep *beep)
-{
- if (beep->registered)
- input_unregister_device(beep->dev);
- else
- input_free_device(beep->dev);
- beep->dev = NULL;
- turn_off_beep(beep);
-}
-
-static int snd_hda_do_attach(struct hda_beep *beep)
-{
- struct input_dev *input_dev;
- struct hda_codec *codec = beep->codec;
-
- input_dev = input_allocate_device();
- if (!input_dev)
- return -ENOMEM;
-
- /* setup digital beep device */
- input_dev->name = "HDA Digital PCBeep";
- input_dev->phys = beep->phys;
- input_dev->id.bustype = BUS_PCI;
- input_dev->dev.parent = &codec->card->card_dev;
-
- input_dev->id.vendor = codec->core.vendor_id >> 16;
- input_dev->id.product = codec->core.vendor_id & 0xffff;
- input_dev->id.version = 0x01;
-
- input_dev->evbit[0] = BIT_MASK(EV_SND);
- input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
- input_dev->event = snd_hda_beep_event;
- input_set_drvdata(input_dev, beep);
-
- beep->dev = input_dev;
- return 0;
-}
-
/**
* snd_hda_enable_beep_device - Turn on/off beep sound
* @codec: the HDA codec
@@ -186,6 +148,38 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
}
EXPORT_SYMBOL_GPL(snd_hda_enable_beep_device);
+static int beep_dev_register(struct snd_device *device)
+{
+ struct hda_beep *beep = device->device_data;
+ int err;
+
+ err = input_register_device(beep->dev);
+ if (!err)
+ beep->registered = true;
+ return err;
+}
+
+static int beep_dev_disconnect(struct snd_device *device)
+{
+ struct hda_beep *beep = device->device_data;
+
+ if (beep->registered)
+ input_unregister_device(beep->dev);
+ else
+ input_free_device(beep->dev);
+ turn_off_beep(beep);
+ return 0;
+}
+
+static int beep_dev_free(struct snd_device *device)
+{
+ struct hda_beep *beep = device->device_data;
+
+ beep->codec->beep = NULL;
+ kfree(beep);
+ return 0;
+}
+
/**
* snd_hda_attach_beep_device - Attach a beep input device
* @codec: the HDA codec
@@ -194,14 +188,16 @@ EXPORT_SYMBOL_GPL(snd_hda_enable_beep_device);
* Attach a beep object to the given widget. If beep hint is turned off
* explicitly or beep_mode of the codec is turned off, this doesn't nothing.
*
- * The attached beep device has to be registered via
- * snd_hda_register_beep_device() and released via snd_hda_detach_beep_device()
- * appropriately.
- *
* Currently, only one beep device is allowed to each codec.
*/
int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
{
+ static struct snd_device_ops ops = {
+ .dev_register = beep_dev_register,
+ .dev_disconnect = beep_dev_disconnect,
+ .dev_free = beep_dev_free,
+ };
+ struct input_dev *input_dev;
struct hda_beep *beep;
int err;
@@ -226,14 +222,41 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
mutex_init(&beep->mutex);
- err = snd_hda_do_attach(beep);
- if (err < 0) {
- kfree(beep);
- codec->beep = NULL;
- return err;
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ err = -ENOMEM;
+ goto err_free;
}
+ /* setup digital beep device */
+ input_dev->name = "HDA Digital PCBeep";
+ input_dev->phys = beep->phys;
+ input_dev->id.bustype = BUS_PCI;
+ input_dev->dev.parent = &codec->card->card_dev;
+
+ input_dev->id.vendor = codec->core.vendor_id >> 16;
+ input_dev->id.product = codec->core.vendor_id & 0xffff;
+ input_dev->id.version = 0x01;
+
+ input_dev->evbit[0] = BIT_MASK(EV_SND);
+ input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
+ input_dev->event = snd_hda_beep_event;
+ input_set_drvdata(input_dev, beep);
+
+ beep->dev = input_dev;
+
+ err = snd_device_new(codec->card, SNDRV_DEV_JACK, beep, &ops);
+ if (err < 0)
+ goto err_input;
+
return 0;
+
+ err_input:
+ input_free_device(beep->dev);
+ err_free:
+ kfree(beep);
+ codec->beep = NULL;
+ return err;
}
EXPORT_SYMBOL_GPL(snd_hda_attach_beep_device);
@@ -243,41 +266,11 @@ EXPORT_SYMBOL_GPL(snd_hda_attach_beep_device);
*/
void snd_hda_detach_beep_device(struct hda_codec *codec)
{
- struct hda_beep *beep = codec->beep;
- if (beep) {
- if (beep->dev)
- snd_hda_do_detach(beep);
- codec->beep = NULL;
- kfree(beep);
- }
+ if (!codec->bus->shutdown && codec->beep)
+ snd_device_free(codec->card, codec->beep);
}
EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device);
-/**
- * snd_hda_register_beep_device - Register the beep device
- * @codec: the HDA codec
- */
-int snd_hda_register_beep_device(struct hda_codec *codec)
-{
- struct hda_beep *beep = codec->beep;
- int err;
-
- if (!beep || !beep->dev)
- return 0;
-
- err = input_register_device(beep->dev);
- if (err < 0) {
- codec_err(codec, "hda_beep: unable to register input device\n");
- input_free_device(beep->dev);
- codec->beep = NULL;
- kfree(beep);
- return err;
- }
- beep->registered = true;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_register_beep_device);
-
static bool ctl_has_mute(struct snd_kcontrol *kcontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h
index f1457c6b3969..a25358a4807a 100644
--- a/sound/pci/hda/hda_beep.h
+++ b/sound/pci/hda/hda_beep.h
@@ -34,7 +34,6 @@ struct hda_beep {
int snd_hda_enable_beep_device(struct hda_codec *codec, int enable);
int snd_hda_attach_beep_device(struct hda_codec *codec, int nid);
void snd_hda_detach_beep_device(struct hda_codec *codec);
-int snd_hda_register_beep_device(struct hda_codec *codec);
#else
static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
{
@@ -43,9 +42,5 @@ static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
static inline void snd_hda_detach_beep_device(struct hda_codec *codec)
{
}
-static inline int snd_hda_register_beep_device(struct hda_codec *codec)
-{
- return 0;
-}
#endif
#endif
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c
index 9174f1b3a987..1ec706ced75c 100644
--- a/sound/pci/hda/hda_bind.c
+++ b/sound/pci/hda/hda_bind.c
@@ -115,7 +115,8 @@ static int hda_codec_driver_probe(struct device *dev)
err = snd_hda_codec_build_controls(codec);
if (err < 0)
goto error_module;
- if (codec->card->registered) {
+ /* only register after the bus probe finished; otherwise it's racy */
+ if (!codec->bus->bus_probing && codec->card->registered) {
err = snd_card_register(codec->card);
if (err < 0)
goto error_module;
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 9f8d59e7e89f..5f2005098a60 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -813,7 +813,6 @@ void snd_hda_codec_register(struct hda_codec *codec)
if (codec->registered)
return;
if (device_is_registered(hda_codec_dev(codec))) {
- snd_hda_register_beep_device(codec);
codec_display_power(codec, true);
pm_runtime_enable(hda_codec_dev(codec));
/* it was powered up in snd_hda_codec_new(), now all done */
@@ -828,14 +827,6 @@ static int snd_hda_codec_dev_register(struct snd_device *device)
return 0;
}
-static int snd_hda_codec_dev_disconnect(struct snd_device *device)
-{
- struct hda_codec *codec = device->device_data;
-
- snd_hda_detach_beep_device(codec);
- return 0;
-}
-
static int snd_hda_codec_dev_free(struct snd_device *device)
{
struct hda_codec *codec = device->device_data;
@@ -921,7 +912,6 @@ int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card,
int err;
static struct snd_device_ops dev_ops = {
.dev_register = snd_hda_codec_dev_register,
- .dev_disconnect = snd_hda_codec_dev_disconnect,
.dev_free = snd_hda_codec_dev_free,
};
@@ -2917,18 +2907,16 @@ static void hda_call_codec_resume(struct hda_codec *codec)
hda_jackpoll_work(&codec->jackpoll_work.work);
else
snd_hda_jack_report_sync(codec);
+ codec->core.dev.power.power_state = PMSG_ON;
snd_hdac_leave_pm(&codec->core);
}
static int hda_codec_runtime_suspend(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);
- struct hda_pcm *pcm;
unsigned int state;
cancel_delayed_work_sync(&codec->jackpoll_work);
- list_for_each_entry(pcm, &codec->pcm_list_head, list)
- snd_pcm_suspend_all(pcm->pcm);
state = hda_call_codec_suspend(codec);
if (codec->link_down_at_suspend ||
(codec_has_clkstop(codec) && codec_has_epss(codec) &&
@@ -2950,10 +2938,48 @@ static int hda_codec_runtime_resume(struct device *dev)
}
#endif /* CONFIG_PM */
+#ifdef CONFIG_PM_SLEEP
+static int hda_codec_pm_suspend(struct device *dev)
+{
+ dev->power.power_state = PMSG_SUSPEND;
+ return pm_runtime_force_suspend(dev);
+}
+
+static int hda_codec_pm_resume(struct device *dev)
+{
+ dev->power.power_state = PMSG_RESUME;
+ return pm_runtime_force_resume(dev);
+}
+
+static int hda_codec_pm_freeze(struct device *dev)
+{
+ dev->power.power_state = PMSG_FREEZE;
+ return pm_runtime_force_suspend(dev);
+}
+
+static int hda_codec_pm_thaw(struct device *dev)
+{
+ dev->power.power_state = PMSG_THAW;
+ return pm_runtime_force_resume(dev);
+}
+
+static int hda_codec_pm_restore(struct device *dev)
+{
+ dev->power.power_state = PMSG_RESTORE;
+ return pm_runtime_force_resume(dev);
+}
+#endif /* CONFIG_PM_SLEEP */
+
/* referred in hda_bind.c */
const struct dev_pm_ops hda_codec_driver_pm = {
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+#ifdef CONFIG_PM_SLEEP
+ .suspend = hda_codec_pm_suspend,
+ .resume = hda_codec_pm_resume,
+ .freeze = hda_codec_pm_freeze,
+ .thaw = hda_codec_pm_thaw,
+ .poweroff = hda_codec_pm_suspend,
+ .restore = hda_codec_pm_restore,
+#endif /* CONFIG_PM_SLEEP */
SET_RUNTIME_PM_OPS(hda_codec_runtime_suspend, hda_codec_runtime_resume,
NULL)
};
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index e784130ea4e0..e5c49003e75f 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2185,6 +2185,7 @@ static int azx_probe_continue(struct azx *chip)
int dev = chip->dev_index;
int err;
+ to_hda_bus(bus)->bus_probing = 1;
hda->probe_continued = 1;
/* bind with i915 if needed */
@@ -2269,6 +2270,7 @@ out_free:
if (err < 0)
hda->init_failed = 1;
complete_all(&hda->probe_wait);
+ to_hda_bus(bus)->bus_probing = 0;
return err;
}
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index a65740419650..853842987fa1 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -919,15 +919,8 @@ static void print_codec_info(struct snd_info_entry *entry,
int snd_hda_codec_proc_new(struct hda_codec *codec)
{
char name[32];
- struct snd_info_entry *entry;
- int err;
snprintf(name, sizeof(name), "codec#%d", codec->core.addr);
- err = snd_card_proc_new(codec->card, name, &entry);
- if (err < 0)
- return err;
-
- snd_info_set_text_ops(entry, codec, print_codec_info);
- return 0;
+ return snd_card_ro_proc_new(codec->card, name, codec, print_codec_info);
}
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
index 97a176d817a0..3d68f9ef7694 100644
--- a/sound/pci/hda/hda_tegra.c
+++ b/sound/pci/hda/hda_tegra.c
@@ -32,6 +32,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/string.h>
+#include <linux/pm_runtime.h>
#include <sound/core.h>
#include <sound/initval.h>
@@ -218,7 +219,6 @@ disable_hda:
return rc;
}
-#ifdef CONFIG_PM_SLEEP
static void hda_tegra_disable_clocks(struct hda_tegra *data)
{
clk_disable_unprepare(data->hda2hdmi_clk);
@@ -229,43 +229,72 @@ static void hda_tegra_disable_clocks(struct hda_tegra *data)
/*
* power management
*/
-static int hda_tegra_suspend(struct device *dev)
+static int __maybe_unused hda_tegra_suspend(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip = card->private_data;
- struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
- struct hdac_bus *bus = azx_bus(chip);
+ int rc;
+ rc = pm_runtime_force_suspend(dev);
+ if (rc < 0)
+ return rc;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- azx_stop_chip(chip);
- synchronize_irq(bus->irq);
- azx_enter_link_reset(chip);
- hda_tegra_disable_clocks(hda);
+ return 0;
+}
+
+static int __maybe_unused hda_tegra_resume(struct device *dev)
+{
+ struct snd_card *card = dev_get_drvdata(dev);
+ int rc;
+
+ rc = pm_runtime_force_resume(dev);
+ if (rc < 0)
+ return rc;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
-static int hda_tegra_resume(struct device *dev)
+static int __maybe_unused hda_tegra_runtime_suspend(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
struct azx *chip = card->private_data;
struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
+ struct hdac_bus *bus = azx_bus(chip);
- hda_tegra_enable_clocks(hda);
+ if (chip && chip->running) {
+ azx_stop_chip(chip);
+ synchronize_irq(bus->irq);
+ azx_enter_link_reset(chip);
+ }
+ hda_tegra_disable_clocks(hda);
- hda_tegra_init(hda);
+ return 0;
+}
- azx_init_chip(chip, 1);
+static int __maybe_unused hda_tegra_runtime_resume(struct device *dev)
+{
+ struct snd_card *card = dev_get_drvdata(dev);
+ struct azx *chip = card->private_data;
+ struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
+ int rc;
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ rc = hda_tegra_enable_clocks(hda);
+ if (rc != 0)
+ return rc;
+ if (chip && chip->running) {
+ hda_tegra_init(hda);
+ azx_init_chip(chip, 1);
+ }
return 0;
}
-#endif /* CONFIG_PM_SLEEP */
static const struct dev_pm_ops hda_tegra_pm = {
SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
+ SET_RUNTIME_PM_OPS(hda_tegra_runtime_suspend,
+ hda_tegra_runtime_resume,
+ NULL)
};
static int hda_tegra_dev_disconnect(struct snd_device *device)
@@ -303,7 +332,23 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev)
struct hdac_bus *bus = azx_bus(chip);
struct device *dev = hda->dev;
struct resource *res;
- int err;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ hda->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(hda->regs))
+ return PTR_ERR(hda->regs);
+
+ bus->remap_addr = hda->regs + HDA_BAR0;
+ bus->addr = res->start + HDA_BAR0;
+
+ hda_tegra_init(hda);
+
+ return 0;
+}
+
+static int hda_tegra_init_clk(struct hda_tegra *hda)
+{
+ struct device *dev = hda->dev;
hda->hda_clk = devm_clk_get(dev, "hda");
if (IS_ERR(hda->hda_clk)) {
@@ -321,22 +366,6 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev)
return PTR_ERR(hda->hda2hdmi_clk);
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hda->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(hda->regs))
- return PTR_ERR(hda->regs);
-
- bus->remap_addr = hda->regs + HDA_BAR0;
- bus->addr = res->start + HDA_BAR0;
-
- err = hda_tegra_enable_clocks(hda);
- if (err) {
- dev_err(dev, "failed to get enable clocks\n");
- return err;
- }
-
- hda_tegra_init(hda);
-
return 0;
}
@@ -347,8 +376,8 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
int err;
unsigned short gcap;
int irq_id = platform_get_irq(pdev, 0);
- const char *sname;
- struct device_node *root;
+ const char *sname, *drv_name = "tegra-hda";
+ struct device_node *np = pdev->dev.of_node;
err = hda_tegra_init_chip(chip, pdev);
if (err)
@@ -407,17 +436,11 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
}
/* driver name */
- strcpy(card->driver, "tegra-hda");
-
- root = of_find_node_by_path("/");
- sname = of_get_property(root, "compatible", NULL);
- of_node_put(root);
- if (!sname) {
- dev_err(card->dev,
- "failed to get compatible property from root node\n");
- return -ENODEV;
- }
+ strncpy(card->driver, drv_name, sizeof(card->driver));
/* shortname for card */
+ sname = of_get_property(np, "nvidia,model", NULL);
+ if (!sname)
+ sname = drv_name;
if (strlen(sname) > sizeof(card->shortname))
dev_info(card->dev, "truncating shortname for card\n");
strncpy(card->shortname, sname, sizeof(card->shortname));
@@ -487,7 +510,8 @@ MODULE_DEVICE_TABLE(of, hda_tegra_match);
static int hda_tegra_probe(struct platform_device *pdev)
{
- const unsigned int driver_flags = AZX_DCAPS_CORBRP_SELF_CLEAR;
+ const unsigned int driver_flags = AZX_DCAPS_CORBRP_SELF_CLEAR |
+ AZX_DCAPS_PM_RUNTIME;
struct snd_card *card;
struct azx *chip;
struct hda_tegra *hda;
@@ -506,12 +530,21 @@ static int hda_tegra_probe(struct platform_device *pdev)
return err;
}
+ err = hda_tegra_init_clk(hda);
+ if (err < 0)
+ goto out_free;
+
err = hda_tegra_create(card, driver_flags, hda);
if (err < 0)
goto out_free;
card->private_data = chip;
dev_set_drvdata(&pdev->dev, card);
+
+ pm_runtime_enable(hda->dev);
+ if (!azx_has_pm_runtime(chip))
+ pm_runtime_forbid(hda->dev);
+
schedule_work(&hda->probe_work);
return 0;
@@ -528,6 +561,7 @@ static void hda_tegra_probe_work(struct work_struct *work)
struct platform_device *pdev = to_platform_device(hda->dev);
int err;
+ pm_runtime_get_sync(hda->dev);
err = hda_tegra_first_init(chip, pdev);
if (err < 0)
goto out_free;
@@ -549,12 +583,18 @@ static void hda_tegra_probe_work(struct work_struct *work)
snd_hda_set_power_save(&chip->bus, power_save * 1000);
out_free:
+ pm_runtime_put(hda->dev);
return; /* no error return from async probe */
}
static int hda_tegra_remove(struct platform_device *pdev)
{
- return snd_card_free(dev_get_drvdata(&pdev->dev));
+ int ret;
+
+ ret = snd_card_free(dev_get_drvdata(&pdev->dev));
+ pm_runtime_disable(&pdev->dev);
+
+ return ret;
}
static void hda_tegra_shutdown(struct platform_device *pdev)
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index e5bdbc245682..29882bda7632 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -8451,8 +8451,10 @@ static void ca0132_free(struct hda_codec *codec)
ca0132_exit_chip(codec);
snd_hda_power_down(codec);
- if (IS_ENABLED(CONFIG_PCI) && spec->mem_base)
+#ifdef CONFIG_PCI
+ if (spec->mem_base)
pci_iounmap(codec->bus->pci, spec->mem_base);
+#endif
kfree(spec->spec_init_verbs);
kfree(codec->spec);
}
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 152f54137082..fb65ad31e86c 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -924,6 +924,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
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),
@@ -935,6 +936,9 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
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, 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),
+ SND_PCI_QUIRK(0x103c, 0x8457, "HP Z2 G4 mini", CXT_FIXUP_HP_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x103c, 0x8458, "HP Z2 G4 mini premium", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 46f88dc7b7e8..8b3ac690efa3 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -57,10 +57,11 @@ MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
#define is_geminilake(codec) (((codec)->core.vendor_id == 0x8086280d) || \
((codec)->core.vendor_id == 0x80862800))
#define is_cannonlake(codec) ((codec)->core.vendor_id == 0x8086280c)
+#define is_icelake(codec) ((codec)->core.vendor_id == 0x8086280f)
#define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec) \
|| is_skylake(codec) || is_broxton(codec) \
- || is_kabylake(codec)) || is_geminilake(codec) \
- || is_cannonlake(codec)
+ || is_kabylake(codec) || is_geminilake(codec) \
+ || is_cannonlake(codec) || is_icelake(codec))
#define is_valleyview(codec) ((codec)->core.vendor_id == 0x80862882)
#define is_cherryview(codec) ((codec)->core.vendor_id == 0x80862883)
#define is_valleyview_plus(codec) (is_valleyview(codec) || is_cherryview(codec))
@@ -181,6 +182,8 @@ struct hdmi_spec {
struct hdac_chmap chmap;
hda_nid_t vendor_nid;
+ const int *port_map;
+ int port_num;
};
#ifdef CONFIG_SND_HDA_COMPONENT
@@ -1865,7 +1868,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
hda_nid_t pin_nid;
struct snd_pcm_runtime *runtime = substream->runtime;
bool non_pcm;
- int pinctl;
+ int pinctl, stripe;
int err = 0;
mutex_lock(&spec->pcm_lock);
@@ -1909,6 +1912,14 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
per_pin->channels = substream->runtime->channels;
per_pin->setup = true;
+ if (get_wcaps(codec, cvt_nid) & AC_WCAP_STRIPE) {
+ stripe = snd_hdac_get_stream_stripe_ctl(&codec->bus->core,
+ substream);
+ snd_hda_codec_write(codec, cvt_nid, 0,
+ AC_VERB_SET_STRIPE_CONTROL,
+ stripe);
+ }
+
hdmi_setup_audio_infoframe(codec, per_pin, non_pcm);
mutex_unlock(&per_pin->lock);
if (spec->dyn_pin_out) {
@@ -2410,12 +2421,11 @@ static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids);
}
-#define INTEL_VENDOR_NID 0x08
-#define INTEL_GLK_VENDOR_NID 0x0B
-#define INTEL_GET_VENDOR_VERB 0xf81
-#define INTEL_SET_VENDOR_VERB 0x781
-#define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */
-#define INTEL_EN_ALL_PIN_CVTS 0x01 /* enable 2nd & 3rd pins and convertors */
+#define INTEL_GET_VENDOR_VERB 0xf81
+#define INTEL_GET_VENDOR_VERB 0xf81
+#define INTEL_SET_VENDOR_VERB 0x781
+#define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */
+#define INTEL_EN_ALL_PIN_CVTS 0x01 /* enable 2nd & 3rd pins and convertors */
static void intel_haswell_enable_all_pins(struct hda_codec *codec,
bool update_tree)
@@ -2495,11 +2505,29 @@ static int intel_base_nid(struct hda_codec *codec)
static int intel_pin2port(void *audio_ptr, int pin_nid)
{
- int base_nid = intel_base_nid(audio_ptr);
+ struct hda_codec *codec = audio_ptr;
+ struct hdmi_spec *spec = codec->spec;
+ int base_nid, i;
- if (WARN_ON(pin_nid < base_nid || pin_nid >= base_nid + 3))
- return -1;
- return pin_nid - base_nid + 1; /* intel port is 1-based */
+ if (!spec->port_num) {
+ base_nid = intel_base_nid(codec);
+ if (WARN_ON(pin_nid < base_nid || pin_nid >= base_nid + 3))
+ return -1;
+ return pin_nid - base_nid + 1; /* intel port is 1-based */
+ }
+
+ /*
+ * looking for the pin number in the mapping table and return
+ * the index which indicate the port number
+ */
+ for (i = 0; i < spec->port_num; i++) {
+ if (pin_nid == spec->port_map[i])
+ return i + 1;
+ }
+
+ /* return -1 if pin number exceeds our expectation */
+ codec_info(codec, "Can't find the HDMI/DP port for pin %d\n", pin_nid);
+ return -1;
}
static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
@@ -2600,7 +2628,8 @@ static int parse_intel_hdmi(struct hda_codec *codec)
}
/* Intel Haswell and onwards; audio component with eld notifier */
-static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid)
+static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
+ const int *port_map, int port_num)
{
struct hdmi_spec *spec;
int err;
@@ -2612,6 +2641,8 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid)
codec->dp_mst = true;
spec->dyn_pcm_assign = true;
spec->vendor_nid = vendor_nid;
+ spec->port_map = port_map;
+ spec->port_num = port_num;
intel_haswell_enable_all_pins(codec, true);
intel_haswell_fixup_enable_dp12(codec);
@@ -2630,12 +2661,23 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid)
static int patch_i915_hsw_hdmi(struct hda_codec *codec)
{
- return intel_hsw_common_init(codec, INTEL_VENDOR_NID);
+ return intel_hsw_common_init(codec, 0x08, NULL, 0);
}
static int patch_i915_glk_hdmi(struct hda_codec *codec)
{
- return intel_hsw_common_init(codec, INTEL_GLK_VENDOR_NID);
+ return intel_hsw_common_init(codec, 0x0b, NULL, 0);
+}
+
+static int patch_i915_icl_hdmi(struct hda_codec *codec)
+{
+ /*
+ * pin to port mapping table where the value indicate the pin number and
+ * the index indicate the port number with 1 base.
+ */
+ static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb};
+
+ return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map));
}
/* Intel Baytrail and Braswell; with eld notifier */
@@ -3878,6 +3920,7 @@ HDA_CODEC_ENTRY(0x11069f81, "VX900 HDMI/DP", patch_via_hdmi),
HDA_CODEC_ENTRY(0x11069f84, "VX11 HDMI/DP", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x11069f85, "VX11 HDMI/DP", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x80860054, "IbexPeak HDMI", patch_i915_cpt_hdmi),
+HDA_CODEC_ENTRY(0x80862800, "Geminilake HDMI", patch_i915_glk_hdmi),
HDA_CODEC_ENTRY(0x80862801, "Bearlake HDMI", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x80862802, "Cantiga HDMI", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x80862803, "Eaglelake HDMI", patch_generic_hdmi),
@@ -3891,7 +3934,7 @@ HDA_CODEC_ENTRY(0x8086280a, "Broxton HDMI", patch_i915_hsw_hdmi),
HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI", patch_i915_hsw_hdmi),
HDA_CODEC_ENTRY(0x8086280c, "Cannonlake HDMI", patch_i915_glk_hdmi),
HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_glk_hdmi),
-HDA_CODEC_ENTRY(0x80862800, "Geminilake HDMI", patch_i915_glk_hdmi),
+HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi),
HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi),
HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi),
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index b4f472157ebd..384719d5c44e 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -117,6 +117,8 @@ struct alc_spec {
int codec_variant; /* flag for other variants */
unsigned int has_alc5505_dsp:1;
unsigned int no_depop_delay:1;
+ unsigned int done_hp_init:1;
+ unsigned int no_shutup_pins:1;
/* for PLL fix */
hda_nid_t pll_nid;
@@ -475,6 +477,14 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
set_eapd(codec, *p, on);
}
+static void alc_shutup_pins(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ if (!spec->no_shutup_pins)
+ snd_hda_shutup_pins(codec);
+}
+
/* generic shutup callback;
* just turning off EAPD and a little pause for avoiding pop-noise
*/
@@ -485,7 +495,7 @@ static void alc_eapd_shutup(struct hda_codec *codec)
alc_auto_setup_eapd(codec, false);
if (!spec->no_depop_delay)
msleep(200);
- snd_hda_shutup_pins(codec);
+ alc_shutup_pins(codec);
}
/* generic EAPD initialization */
@@ -514,6 +524,15 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
}
}
+/* get a primary headphone pin if available */
+static hda_nid_t alc_get_hp_pin(struct alc_spec *spec)
+{
+ if (spec->gen.autocfg.hp_pins[0])
+ return spec->gen.autocfg.hp_pins[0];
+ if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
+ return spec->gen.autocfg.line_out_pins[0];
+ return 0;
+}
/*
* Realtek SSID verification
@@ -724,9 +743,7 @@ do_sku:
* 15 : 1 --> enable the function "Mute internal speaker
* when the external headphone out jack is plugged"
*/
- if (!spec->gen.autocfg.hp_pins[0] &&
- !(spec->gen.autocfg.line_out_pins[0] &&
- spec->gen.autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
+ if (!alc_get_hp_pin(spec)) {
hda_nid_t nid;
tmp = (ass >> 11) & 0x3; /* HP to chassis */
nid = ports[tmp];
@@ -806,7 +823,7 @@ static inline void alc_shutup(struct hda_codec *codec)
if (spec && spec->shutup)
spec->shutup(codec);
else
- snd_hda_shutup_pins(codec);
+ alc_shutup_pins(codec);
}
static void alc_reboot_notify(struct hda_codec *codec)
@@ -1847,6 +1864,8 @@ enum {
ALC887_FIXUP_BASS_CHMAP,
ALC1220_FIXUP_GB_DUAL_CODECS,
ALC1220_FIXUP_CLEVO_P950,
+ ALC1220_FIXUP_SYSTEM76_ORYP5,
+ ALC1220_FIXUP_SYSTEM76_ORYP5_PINS,
};
static void alc889_fixup_coef(struct hda_codec *codec,
@@ -2048,6 +2067,17 @@ static void alc1220_fixup_clevo_p950(struct hda_codec *codec,
snd_hda_override_conn_list(codec, 0x1b, 1, conn1);
}
+static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action);
+
+static void alc1220_fixup_system76_oryp5(struct hda_codec *codec,
+ const struct hda_fixup *fix,
+ int action)
+{
+ alc1220_fixup_clevo_p950(codec, fix, action);
+ alc_fixup_headset_mode_no_hp_mic(codec, fix, action);
+}
+
static const struct hda_fixup alc882_fixups[] = {
[ALC882_FIXUP_ABIT_AW9D_MAX] = {
.type = HDA_FIXUP_PINS,
@@ -2292,6 +2322,19 @@ static const struct hda_fixup alc882_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc1220_fixup_clevo_p950,
},
+ [ALC1220_FIXUP_SYSTEM76_ORYP5] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc1220_fixup_system76_oryp5,
+ },
+ [ALC1220_FIXUP_SYSTEM76_ORYP5_PINS] = {
+ .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 = ALC1220_FIXUP_SYSTEM76_ORYP5,
+ },
};
static const struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -2368,6 +2411,8 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", 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, 0x96e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_SYSTEM76_ORYP5_PINS),
+ SND_PCI_QUIRK(0x1558, 0x97e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_SYSTEM76_ORYP5_PINS),
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),
@@ -2914,7 +2959,7 @@ static void alc269_shutup(struct hda_codec *codec)
(alc_get_coef0(codec) & 0x00ff) == 0x018) {
msleep(150);
}
- snd_hda_shutup_pins(codec);
+ alc_shutup_pins(codec);
}
static struct coef_fw alc282_coefs[] = {
@@ -2958,7 +3003,7 @@ static void alc282_restore_default_value(struct hda_codec *codec)
static void alc282_init(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
bool hp_pin_sense;
int coef78;
@@ -2995,7 +3040,7 @@ static void alc282_init(struct hda_codec *codec)
static void alc282_shutup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
bool hp_pin_sense;
int coef78;
@@ -3017,14 +3062,15 @@ static void alc282_shutup(struct hda_codec *codec)
if (hp_pin_sense)
msleep(85);
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+ if (!spec->no_shutup_pins)
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
if (hp_pin_sense)
msleep(100);
alc_auto_setup_eapd(codec, false);
- snd_hda_shutup_pins(codec);
+ alc_shutup_pins(codec);
alc_write_coef_idx(codec, 0x78, coef78);
}
@@ -3073,14 +3119,9 @@ static void alc283_restore_default_value(struct hda_codec *codec)
static void alc283_init(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
bool hp_pin_sense;
- if (!spec->gen.autocfg.hp_outs) {
- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
- hp_pin = spec->gen.autocfg.line_out_pins[0];
- }
-
alc283_restore_default_value(codec);
if (!hp_pin)
@@ -3114,14 +3155,9 @@ static void alc283_init(struct hda_codec *codec)
static void alc283_shutup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
bool hp_pin_sense;
- if (!spec->gen.autocfg.hp_outs) {
- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
- hp_pin = spec->gen.autocfg.line_out_pins[0];
- }
-
if (!hp_pin) {
alc269_shutup(codec);
return;
@@ -3140,22 +3176,23 @@ static void alc283_shutup(struct hda_codec *codec)
if (hp_pin_sense)
msleep(100);
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+ if (!spec->no_shutup_pins)
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
if (hp_pin_sense)
msleep(100);
alc_auto_setup_eapd(codec, false);
- snd_hda_shutup_pins(codec);
+ alc_shutup_pins(codec);
alc_write_coef_idx(codec, 0x43, 0x9614);
}
static void alc256_init(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
bool hp_pin_sense;
if (!hp_pin)
@@ -3191,7 +3228,7 @@ static void alc256_init(struct hda_codec *codec)
static void alc256_shutup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
bool hp_pin_sense;
if (!hp_pin) {
@@ -3214,20 +3251,21 @@ static void alc256_shutup(struct hda_codec *codec)
/* NOTE: call this before clearing the pin, otherwise codec stalls */
alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+ if (!spec->no_shutup_pins)
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
if (hp_pin_sense)
msleep(100);
alc_auto_setup_eapd(codec, false);
- snd_hda_shutup_pins(codec);
+ alc_shutup_pins(codec);
}
static void alc225_init(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
bool hp1_pin_sense, hp2_pin_sense;
if (!hp_pin)
@@ -3270,7 +3308,7 @@ static void alc225_init(struct hda_codec *codec)
static void alc225_shutup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
bool hp1_pin_sense, hp2_pin_sense;
if (!hp_pin) {
@@ -3308,13 +3346,13 @@ static void alc225_shutup(struct hda_codec *codec)
msleep(100);
alc_auto_setup_eapd(codec, false);
- snd_hda_shutup_pins(codec);
+ alc_shutup_pins(codec);
}
static void alc_default_init(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
bool hp_pin_sense;
if (!hp_pin)
@@ -3343,7 +3381,7 @@ static void alc_default_init(struct hda_codec *codec)
static void alc_default_shutup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
bool hp_pin_sense;
if (!hp_pin) {
@@ -3362,14 +3400,60 @@ static void alc_default_shutup(struct hda_codec *codec)
if (hp_pin_sense)
msleep(85);
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+ if (!spec->no_shutup_pins)
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
if (hp_pin_sense)
msleep(100);
alc_auto_setup_eapd(codec, false);
- snd_hda_shutup_pins(codec);
+ alc_shutup_pins(codec);
+}
+
+static void alc294_hp_init(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
+ int i, val;
+
+ if (!hp_pin)
+ return;
+
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+
+ msleep(100);
+
+ if (!spec->no_shutup_pins)
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+
+ alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
+ alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
+
+ /* Wait for depop procedure finish */
+ val = alc_read_coefex_idx(codec, 0x58, 0x01);
+ for (i = 0; i < 20 && val & 0x0080; i++) {
+ msleep(50);
+ val = alc_read_coefex_idx(codec, 0x58, 0x01);
+ }
+ /* Set HP depop to auto mode */
+ alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
+ msleep(50);
+}
+
+static void alc294_init(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ /* required only at boot or S4 resume time */
+ if (!spec->done_hp_init ||
+ codec->core.dev.power.power_state.event == PM_EVENT_RESTORE) {
+ alc294_hp_init(codec);
+ spec->done_hp_init = true;
+ }
+ alc_default_init(codec);
}
static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
@@ -4737,7 +4821,7 @@ static void alc_update_headset_mode(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
int new_headset_mode;
@@ -4939,16 +5023,12 @@ static void alc_fixup_auto_mute_via_amp(struct hda_codec *codec,
}
}
-static void alc_no_shutup(struct hda_codec *codec)
-{
-}
-
static void alc_fixup_no_shutup(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
struct alc_spec *spec = codec->spec;
- spec->shutup = alc_no_shutup;
+ spec->no_shutup_pins = 1;
}
}
@@ -5016,7 +5096,7 @@ static void alc_fixup_tpt470_dock(struct hda_codec *codec,
static void alc_shutup_dell_xps13(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- int hp_pin = spec->gen.autocfg.hp_pins[0];
+ int hp_pin = alc_get_hp_pin(spec);
/* Prevent pop noises when headphones are plugged in */
snd_hda_codec_write(codec, hp_pin, 0,
@@ -5109,7 +5189,7 @@ static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
if (action == HDA_FIXUP_ACT_PROBE) {
int mic_pin = find_ext_mic_pin(codec);
- int hp_pin = spec->gen.autocfg.hp_pins[0];
+ int hp_pin = alc_get_hp_pin(spec);
if (snd_BUG_ON(!mic_pin || !hp_pin))
return;
@@ -5411,7 +5491,7 @@ static void alc_headset_btn_callback(struct hda_codec *codec,
jack->jack->button_state = report;
}
-static void alc_fixup_headset_jack(struct hda_codec *codec,
+static void alc295_fixup_chromebook(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@@ -5421,6 +5501,16 @@ static void alc_fixup_headset_jack(struct hda_codec *codec,
alc_headset_btn_callback);
snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack", false,
SND_JACK_HEADSET, alc_headset_btn_keymap);
+ 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;
+ }
break;
case HDA_FIXUP_ACT_INIT:
switch (codec->core.vendor_id) {
@@ -5590,7 +5680,13 @@ enum {
ALC294_FIXUP_ASUS_MIC,
ALC294_FIXUP_ASUS_HEADSET_MIC,
ALC294_FIXUP_ASUS_SPK,
- ALC225_FIXUP_HEADSET_JACK,
+ ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
+ ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE,
+ ALC255_FIXUP_ACER_HEADSET_MIC,
+ ALC295_FIXUP_CHROME_BOOK,
+ ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE,
+ ALC225_FIXUP_WYSE_AUTO_MUTE,
+ ALC225_FIXUP_WYSE_DISABLE_MIC_VREF,
};
static const struct hda_fixup alc269_fixups[] = {
@@ -6533,9 +6629,61 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC
},
- [ALC225_FIXUP_HEADSET_JACK] = {
+ [ALC295_FIXUP_CHROME_BOOK] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc295_fixup_chromebook,
+ },
+ [ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
+ },
+ [ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* Disable PCBEEP-IN passthrough */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x36 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x57d7 },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC285_FIXUP_LENOVO_HEADPHONE_NOISE
+ },
+ [ALC255_FIXUP_ACER_HEADSET_MIC] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x19, 0x03a11130 },
+ { 0x1a, 0x90a60140 }, /* use as internal mic */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC
+ },
+ [ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x16, 0x01011020 }, /* Rear Line out */
+ { 0x19, 0x01a1913c }, /* use as Front headset mic, without its own jack detect */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC225_FIXUP_WYSE_AUTO_MUTE
+ },
+ [ALC225_FIXUP_WYSE_AUTO_MUTE] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc_fixup_auto_mute_via_amp,
+ .chained = true,
+ .chain_id = ALC225_FIXUP_WYSE_DISABLE_MIC_VREF
+ },
+ [ALC225_FIXUP_WYSE_DISABLE_MIC_VREF] = {
.type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_jack,
+ .v.func = alc_fixup_disable_mic_vref,
+ .chained = true,
+ .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
},
};
@@ -6556,6 +6704,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x128f, "Acer Veriton Z6860G", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC),
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
SND_PCI_QUIRK(0x1028, 0x05bd, "Dell Latitude E6440", ALC292_FIXUP_DELL_E7X),
@@ -6587,6 +6736,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
SND_PCI_QUIRK(0x1028, 0x0706, "Dell Inspiron 7559", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER),
SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE),
+ SND_PCI_QUIRK(0x1028, 0x0738, "Dell Precision 5820", ALC269_FIXUP_NO_SHUTUP),
SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
SND_PCI_QUIRK(0x1028, 0x075c, "Dell XPS 27 7760", ALC298_FIXUP_SPK_VOLUME),
SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME),
@@ -6599,6 +6749,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
SND_PCI_QUIRK(0x1028, 0x0872, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
SND_PCI_QUIRK(0x1028, 0x0873, "Dell Precision 3930", ALC255_FIXUP_DUMMY_LINEOUT_VERB),
+ 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, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -6661,11 +6813,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
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, 0x82bf, "HP", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x82c0, "HP", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
+ 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(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
@@ -6681,7 +6835,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", 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, 0x14a1, "ASUS UX533FD", ALC294_FIXUP_ASUS_SPK),
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, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
@@ -6715,6 +6868,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
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(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
@@ -6945,7 +7099,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{.id = ALC255_FIXUP_DUMMY_LINEOUT_VERB, .name = "alc255-dummy-lineout"},
{.id = ALC255_FIXUP_DELL_HEADSET_MIC, .name = "alc255-dell-headset"},
{.id = ALC295_FIXUP_HP_X360, .name = "alc295-hp-x360"},
- {.id = ALC225_FIXUP_HEADSET_JACK, .name = "alc-sense-combo"},
+ {.id = ALC295_FIXUP_CHROME_BOOK, .name = "alc-sense-combo"},
{}
};
#define ALC225_STANDARD_PINS \
@@ -7221,7 +7375,7 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
{0x12, 0x90a60130},
{0x19, 0x03a11020},
{0x21, 0x0321101f}),
- SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_HEADPHONE_NOISE,
+ SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE,
{0x12, 0x90a60130},
{0x14, 0x90170110},
{0x19, 0x04a11040},
@@ -7300,6 +7454,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_SPK,
{0x12, 0x90a60130},
{0x17, 0x90170110},
+ {0x21, 0x03211020}),
+ SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_SPK,
+ {0x12, 0x90a60130},
+ {0x17, 0x90170110},
{0x21, 0x04211020}),
SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC295_STANDARD_PINS,
@@ -7373,37 +7531,6 @@ static void alc269_fill_coef(struct hda_codec *codec)
alc_update_coef_idx(codec, 0x4, 0, 1<<11);
}
-static void alc294_hp_init(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
- int i, val;
-
- if (!hp_pin)
- return;
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- msleep(100);
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
-
- alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
- alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
-
- /* Wait for depop procedure finish */
- val = alc_read_coefex_idx(codec, 0x58, 0x01);
- for (i = 0; i < 20 && val & 0x0080; i++) {
- msleep(50);
- val = alc_read_coefex_idx(codec, 0x58, 0x01);
- }
- /* Set HP depop to auto mode */
- alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
- msleep(50);
-}
-
/*
*/
static int patch_alc269(struct hda_codec *codec)
@@ -7529,7 +7656,7 @@ static int patch_alc269(struct hda_codec *codec)
spec->codec_variant = ALC269_TYPE_ALC294;
spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */
alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */
- alc294_hp_init(codec);
+ spec->init_hook = alc294_init;
break;
case 0x10ec0300:
spec->codec_variant = ALC269_TYPE_ALC300;
@@ -7541,7 +7668,7 @@ static int patch_alc269(struct hda_codec *codec)
spec->codec_variant = ALC269_TYPE_ALC700;
spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack auto trigger control */
- alc294_hp_init(codec);
+ spec->init_hook = alc294_init;
break;
}
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
index b8af747ecb43..7646c93e8268 100644
--- a/sound/pci/ice1712/ews.c
+++ b/sound/pci/ice1712/ews.c
@@ -826,7 +826,12 @@ static int snd_ice1712_6fire_read_pca(struct snd_ice1712 *ice, unsigned char reg
snd_i2c_lock(ice->i2c);
byte = reg;
- snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_6FIRE], &byte, 1);
+ if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_6FIRE], &byte, 1)) {
+ snd_i2c_unlock(ice->i2c);
+ dev_err(ice->card->dev, "cannot send pca\n");
+ return -EIO;
+ }
+
byte = 0;
if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_6FIRE], &byte, 1) != 1) {
snd_i2c_unlock(ice->i2c);
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index f1fe497c2f9d..fa7d90ee6e2d 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -1603,10 +1603,7 @@ static void snd_ice1712_proc_read(struct snd_info_entry *entry,
static void snd_ice1712_proc_init(struct snd_ice1712 *ice)
{
- struct snd_info_entry *entry;
-
- if (!snd_card_proc_new(ice->card, "ice1712", &entry))
- snd_info_set_text_ops(entry, ice, snd_ice1712_proc_read);
+ snd_card_ro_proc_new(ice->card, "ice1712", ice, snd_ice1712_proc_read);
}
/*
@@ -2792,9 +2789,6 @@ static int snd_ice1712_suspend(struct device *dev)
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(ice->pcm);
- snd_pcm_suspend_all(ice->pcm_pro);
- snd_pcm_suspend_all(ice->pcm_ds);
snd_ac97_suspend(ice->ac97);
spin_lock_irq(&ice->reg_lock);
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 057c2f394ea7..a7d640ee4a17 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -1571,10 +1571,7 @@ static void snd_vt1724_proc_read(struct snd_info_entry *entry,
static void snd_vt1724_proc_init(struct snd_ice1712 *ice)
{
- struct snd_info_entry *entry;
-
- if (!snd_card_proc_new(ice->card, "ice1724", &entry))
- snd_info_set_text_ops(entry, ice, snd_vt1724_proc_read);
+ snd_card_ro_proc_new(ice->card, "ice1724", ice, snd_vt1724_proc_read);
}
/*
@@ -2804,9 +2801,6 @@ static int snd_vt1724_suspend(struct device *dev)
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(ice->pcm);
- snd_pcm_suspend_all(ice->pcm_pro);
- snd_pcm_suspend_all(ice->pcm_ds);
snd_ac97_suspend(ice->ac97);
spin_lock_irq(&ice->reg_lock);
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index 93b8cfc6636f..f499f1e8d0c9 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -659,12 +659,8 @@ static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buff
static void wm_proc_init(struct snd_ice1712 *ice)
{
- struct snd_info_entry *entry;
- if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) {
- snd_info_set_text_ops(entry, ice, wm_proc_regs_read);
- entry->mode |= 0200;
- entry->c.text.write = wm_proc_regs_write;
- }
+ snd_card_rw_proc_new(ice->card, "wm_codec", ice, wm_proc_regs_read,
+ wm_proc_regs_write);
}
static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
@@ -684,9 +680,7 @@ static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buff
static void cs_proc_init(struct snd_ice1712 *ice)
{
- struct snd_info_entry *entry;
- if (! snd_card_proc_new(ice->card, "cs_codec", &entry))
- snd_info_set_text_ops(entry, ice, cs_proc_regs_read);
+ snd_card_ro_proc_new(ice->card, "cs_codec", ice, cs_proc_regs_read);
}
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index 3919aed39ca0..d243309029d3 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -651,9 +651,8 @@ static void stac9460_proc_regs_read(struct snd_info_entry *entry,
static void stac9460_proc_init(struct snd_ice1712 *ice)
{
- struct snd_info_entry *entry;
- if (!snd_card_proc_new(ice->card, "stac9460_codec", &entry))
- snd_info_set_text_ops(entry, ice, stac9460_proc_regs_read);
+ snd_card_ro_proc_new(ice->card, "stac9460_codec", ice,
+ stac9460_proc_regs_read);
}
diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c
index c97b5528e4b8..72f252c936e5 100644
--- a/sound/pci/ice1712/prodigy_hifi.c
+++ b/sound/pci/ice1712/prodigy_hifi.c
@@ -904,12 +904,8 @@ static void wm_proc_regs_read(struct snd_info_entry *entry,
static void wm_proc_init(struct snd_ice1712 *ice)
{
- struct snd_info_entry *entry;
- if (!snd_card_proc_new(ice->card, "wm_codec", &entry)) {
- snd_info_set_text_ops(entry, ice, wm_proc_regs_read);
- entry->mode |= 0200;
- entry->c.text.write = wm_proc_regs_write;
- }
+ snd_card_rw_proc_new(ice->card, "wm_codec", ice, wm_proc_regs_read,
+ wm_proc_regs_write);
}
static int prodigy_hifi_add_controls(struct snd_ice1712 *ice)
diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c
index 5bc836241c97..8ad964ee0b65 100644
--- a/sound/pci/ice1712/quartet.c
+++ b/sound/pci/ice1712/quartet.c
@@ -502,9 +502,7 @@ static void proc_regs_read(struct snd_info_entry *entry,
static void proc_init(struct snd_ice1712 *ice)
{
- struct snd_info_entry *entry;
- if (!snd_card_proc_new(ice->card, "quartet", &entry))
- snd_info_set_text_ops(entry, ice, proc_regs_read);
+ snd_card_ro_proc_new(ice->card, "quartet", ice, proc_regs_read);
}
static int qtet_mute_get(struct snd_kcontrol *kcontrol,
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index ffddcdfe0c66..2784bf48cf5a 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -2614,8 +2614,6 @@ static int intel8x0_suspend(struct device *dev)
int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- for (i = 0; i < chip->pcm_devs; i++)
- snd_pcm_suspend_all(chip->pcm[i]);
for (i = 0; i < chip->ncodecs; i++)
snd_ac97_suspend(chip->ac97[i]);
if (chip->device_type == DEVICE_INTEL_ICH4)
@@ -2865,10 +2863,8 @@ static void snd_intel8x0_proc_read(struct snd_info_entry * entry,
static void snd_intel8x0_proc_init(struct intel8x0 *chip)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(chip->card, "intel8x0", &entry))
- snd_info_set_text_ops(entry, chip, snd_intel8x0_proc_read);
+ snd_card_ro_proc_new(chip->card, "intel8x0", chip,
+ snd_intel8x0_proc_read);
}
static int snd_intel8x0_dev_free(struct snd_device *device)
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index c84629190cba..43c654e15452 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -1025,11 +1025,8 @@ static int intel8x0m_suspend(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
struct intel8x0m *chip = card->private_data;
- int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- for (i = 0; i < chip->pcm_devs; i++)
- snd_pcm_suspend_all(chip->pcm[i]);
snd_ac97_suspend(chip->ac97);
if (chip->irq >= 0) {
free_irq(chip->irq, chip);
@@ -1087,10 +1084,8 @@ static void snd_intel8x0m_proc_read(struct snd_info_entry * entry,
static void snd_intel8x0m_proc_init(struct intel8x0m *chip)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(chip->card, "intel8x0m", &entry))
- snd_info_set_text_ops(entry, chip, snd_intel8x0m_proc_read);
+ snd_card_ro_proc_new(chip->card, "intel8x0m", chip,
+ snd_intel8x0m_proc_read);
}
static int snd_intel8x0m_dev_free(struct snd_device *device)
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 4e189a93f475..fe4aba8a08ea 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2090,10 +2090,8 @@ static void snd_korg1212_proc_read(struct snd_info_entry *entry,
static void snd_korg1212_proc_init(struct snd_korg1212 *korg1212)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(korg1212->card, "korg1212", &entry))
- snd_info_set_text_ops(entry, korg1212, snd_korg1212_proc_read);
+ snd_card_ro_proc_new(korg1212->card, "korg1212", korg1212,
+ snd_korg1212_proc_read);
}
static int
diff --git a/sound/pci/lola/lola_proc.c b/sound/pci/lola/lola_proc.c
index 904e3c4f4dfe..1603f9c81897 100644
--- a/sound/pci/lola/lola_proc.c
+++ b/sound/pci/lola/lola_proc.c
@@ -208,15 +208,9 @@ static void lola_proc_regs_read(struct snd_info_entry *entry,
void lola_proc_debug_new(struct lola *chip)
{
- struct snd_info_entry *entry;
-
- if (!snd_card_proc_new(chip->card, "codec", &entry))
- snd_info_set_text_ops(entry, chip, lola_proc_codec_read);
- if (!snd_card_proc_new(chip->card, "codec_rw", &entry)) {
- snd_info_set_text_ops(entry, chip, lola_proc_codec_rw_read);
- entry->mode |= 0200;
- entry->c.text.write = lola_proc_codec_rw_write;
- }
- if (!snd_card_proc_new(chip->card, "regs", &entry))
- snd_info_set_text_ops(entry, chip, lola_proc_regs_read);
+ snd_card_ro_proc_new(chip->card, "codec", chip, lola_proc_codec_read);
+ snd_card_rw_proc_new(chip->card, "codec_rw", chip,
+ lola_proc_codec_rw_read,
+ lola_proc_codec_rw_write);
+ snd_card_ro_proc_new(chip->card, "regs", chip, lola_proc_regs_read);
}
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
index 54f6252faca6..ae23a2dfbdea 100644
--- a/sound/pci/lx6464es/lx6464es.c
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -854,11 +854,9 @@ static int lx_pcm_create(struct lx6464es *chip)
pcm->nonatomic = true;
strcpy(pcm->name, card_name);
- err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(chip->pci),
- size, size);
- if (err < 0)
- return err;
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ size, size);
chip->pcm = pcm;
chip->capture_stream.is_capture = 1;
@@ -948,13 +946,7 @@ static void lx_proc_levels_read(struct snd_info_entry *entry,
static int lx_proc_create(struct snd_card *card, struct lx6464es *chip)
{
- struct snd_info_entry *entry;
- int err = snd_card_proc_new(card, "levels", &entry);
- if (err < 0)
- return err;
-
- snd_info_set_text_ops(entry, chip, lx_proc_levels_read);
- return 0;
+ return snd_card_ro_proc_new(card, "levels", chip, lx_proc_levels_read);
}
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 62962178a9d7..1a9468c14aaf 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -2422,7 +2422,6 @@ static int m3_suspend(struct device *dev)
chip->in_suspend = 1;
cancel_work_sync(&chip->hwvol_work);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
snd_ac97_suspend(chip->ac97);
msleep(10); /* give the assp a chance to idle.. */
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 9cd297a42f24..92f616df3863 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1220,10 +1220,8 @@ static void snd_mixart_proc_init(struct snd_mixart *chip)
struct snd_info_entry *entry;
/* text interface to read perf and temp meters */
- if (! snd_card_proc_new(chip->card, "board_info", &entry)) {
- entry->private_data = chip;
- entry->c.text.read = snd_mixart_proc_read;
- }
+ snd_card_ro_proc_new(chip->card, "board_info", chip,
+ snd_mixart_proc_read);
if (! snd_card_proc_new(chip->card, "mixart_BA0", &entry)) {
entry->content = SNDRV_INFO_CONTENT_DATA;
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index b97f4ea6b56c..85e46ff44ac3 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -1413,7 +1413,6 @@ static int nm256_suspend(struct device *dev)
struct nm256 *chip = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
snd_ac97_suspend(chip->ac97);
chip->coeffs_current = 0;
return 0;
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index b4ef5804212d..3ae9dd4b39e8 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -244,10 +244,7 @@ static void oxygen_proc_read(struct snd_info_entry *entry,
static void oxygen_proc_init(struct oxygen *chip)
{
- struct snd_info_entry *entry;
-
- if (!snd_card_proc_new(chip->card, "oxygen", &entry))
- snd_info_set_text_ops(entry, chip, oxygen_proc_read);
+ snd_card_ro_proc_new(chip->card, "oxygen", chip, oxygen_proc_read);
}
static const struct pci_device_id *
@@ -373,7 +370,7 @@ static void oxygen_init(struct oxygen *chip)
for (i = 0; i < 8; ++i)
chip->dac_volume[i] = chip->model.dac_volume_min;
chip->dac_mute = 1;
- chip->spdif_playback_enable = 1;
+ chip->spdif_playback_enable = 0;
chip->spdif_bits = OXYGEN_SPDIF_C | OXYGEN_SPDIF_ORIGINAL |
(IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT);
chip->spdif_pcm_bits = chip->spdif_bits;
@@ -744,13 +741,10 @@ static int oxygen_pci_suspend(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
struct oxygen *chip = card->private_data;
- unsigned int i, saved_interrupt_mask;
+ unsigned int saved_interrupt_mask;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- for (i = 0; i < PCM_COUNT; ++i)
- snd_pcm_suspend(chip->streams[i]);
-
if (chip->model.suspend)
chip->model.suspend(chip);
diff --git a/sound/pci/oxygen/pcm1796.h b/sound/pci/oxygen/pcm1796.h
index 34d07dd2d22e..d5dcb09e44cd 100644
--- a/sound/pci/oxygen/pcm1796.h
+++ b/sound/pci/oxygen/pcm1796.h
@@ -10,7 +10,6 @@
#define PCM1796_MUTE 0x01
#define PCM1796_DME 0x02
#define PCM1796_DMF_MASK 0x0c
-#define PCM1796_DMF_DISABLED 0x00
#define PCM1796_DMF_48 0x04
#define PCM1796_DMF_441 0x08
#define PCM1796_DMF_32 0x0c
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c
index 24109d37ca09..a1c6b98b191e 100644
--- a/sound/pci/oxygen/xonar_pcm179x.c
+++ b/sound/pci/oxygen/xonar_pcm179x.c
@@ -331,7 +331,7 @@ static void pcm1796_init(struct oxygen *chip)
struct xonar_pcm179x *data = chip->model_data;
data->pcm1796_regs[0][18 - PCM1796_REG_BASE] =
- PCM1796_DMF_DISABLED | PCM1796_FMT_24_I2S | PCM1796_ATLD;
+ PCM1796_FMT_24_I2S | PCM1796_ATLD;
if (!data->broken_i2c)
data->pcm1796_regs[0][18 - PCM1796_REG_BASE] |= PCM1796_MUTE;
data->pcm1796_regs[0][19 - PCM1796_REG_BASE] =
@@ -621,6 +621,23 @@ static void update_pcm1796_oversampling(struct oxygen *chip)
pcm1796_write_cached(chip, i, 20, reg);
}
+static void update_pcm1796_deemph(struct oxygen *chip)
+{
+ struct xonar_pcm179x *data = chip->model_data;
+ unsigned int i;
+ u8 reg;
+
+ reg = data->pcm1796_regs[0][18 - PCM1796_REG_BASE] & ~PCM1796_DMF_MASK;
+ if (data->current_rate == 48000)
+ reg |= PCM1796_DMF_48;
+ else if (data->current_rate == 44100)
+ reg |= PCM1796_DMF_441;
+ else if (data->current_rate == 32000)
+ reg |= PCM1796_DMF_32;
+ for (i = 0; i < data->dacs; ++i)
+ pcm1796_write_cached(chip, i, 18, reg);
+}
+
static void set_pcm1796_params(struct oxygen *chip,
struct snd_pcm_hw_params *params)
{
@@ -629,6 +646,7 @@ static void set_pcm1796_params(struct oxygen *chip,
msleep(1);
data->current_rate = params_rate(params);
update_pcm1796_oversampling(chip);
+ update_pcm1796_deemph(chip);
}
static void update_pcm1796_volume(struct oxygen *chip)
@@ -653,9 +671,11 @@ static void update_pcm1796_mute(struct oxygen *chip)
unsigned int i;
u8 value;
- value = PCM1796_DMF_DISABLED | PCM1796_FMT_24_I2S | PCM1796_ATLD;
+ value = data->pcm1796_regs[0][18 - PCM1796_REG_BASE];
if (chip->dac_mute)
value |= PCM1796_MUTE;
+ else
+ value &= ~PCM1796_MUTE;
for (i = 0; i < data->dacs; ++i)
pcm1796_write_cached(chip, i, 18, value);
}
@@ -777,6 +797,49 @@ static const struct snd_kcontrol_new rolloff_control = {
.put = rolloff_put,
};
+static int deemph_get(struct snd_kcontrol *ctl,
+ struct snd_ctl_elem_value *value)
+{
+ struct oxygen *chip = ctl->private_data;
+ struct xonar_pcm179x *data = chip->model_data;
+
+ value->value.integer.value[0] =
+ !!(data->pcm1796_regs[0][18 - PCM1796_REG_BASE] & PCM1796_DME);
+ return 0;
+}
+
+static int deemph_put(struct snd_kcontrol *ctl,
+ struct snd_ctl_elem_value *value)
+{
+ struct oxygen *chip = ctl->private_data;
+ struct xonar_pcm179x *data = chip->model_data;
+ unsigned int i;
+ int changed;
+ u8 reg;
+
+ mutex_lock(&chip->mutex);
+ reg = data->pcm1796_regs[0][18 - PCM1796_REG_BASE];
+ if (!value->value.integer.value[0])
+ reg &= ~PCM1796_DME;
+ else
+ reg |= PCM1796_DME;
+ changed = reg != data->pcm1796_regs[0][18 - PCM1796_REG_BASE];
+ if (changed) {
+ for (i = 0; i < data->dacs; ++i)
+ pcm1796_write(chip, i, 18, reg);
+ }
+ mutex_unlock(&chip->mutex);
+ return changed;
+}
+
+static const struct snd_kcontrol_new deemph_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "De-emphasis Playback Switch",
+ .info = snd_ctl_boolean_mono_info,
+ .get = deemph_get,
+ .put = deemph_put,
+};
+
static const struct snd_kcontrol_new hdav_hdmi_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "HDMI Playback Switch",
@@ -1011,6 +1074,10 @@ static int add_pcm1796_controls(struct oxygen *chip)
snd_ctl_new1(&rolloff_control, chip));
if (err < 0)
return err;
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&deemph_control, chip));
+ if (err < 0)
+ return err;
}
return 0;
}
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index e57da4036231..4ab7efc6e9f7 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -1454,21 +1454,14 @@ static void pcxhr_proc_ltc(struct snd_info_entry *entry,
static void pcxhr_proc_init(struct snd_pcxhr *chip)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(chip->card, "info", &entry))
- snd_info_set_text_ops(entry, chip, pcxhr_proc_info);
- if (! snd_card_proc_new(chip->card, "sync", &entry))
- snd_info_set_text_ops(entry, chip, pcxhr_proc_sync);
+ snd_card_ro_proc_new(chip->card, "info", chip, pcxhr_proc_info);
+ snd_card_ro_proc_new(chip->card, "sync", chip, pcxhr_proc_sync);
/* gpio available on stereo sound cards only */
- if (chip->mgr->is_hr_stereo &&
- !snd_card_proc_new(chip->card, "gpio", &entry)) {
- snd_info_set_text_ops(entry, chip, pcxhr_proc_gpio_read);
- entry->c.text.write = pcxhr_proc_gpo_write;
- entry->mode |= 0200;
- }
- if (!snd_card_proc_new(chip->card, "ltc", &entry))
- snd_info_set_text_ops(entry, chip, pcxhr_proc_ltc);
+ if (chip->mgr->is_hr_stereo)
+ snd_card_rw_proc_new(chip->card, "gpio", chip,
+ pcxhr_proc_gpio_read,
+ pcxhr_proc_gpo_write);
+ snd_card_ro_proc_new(chip->card, "ltc", chip, pcxhr_proc_ltc);
}
/* end of proc interface */
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 23017e3bc76c..8d1a56a9bcfd 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1158,7 +1158,6 @@ static int riptide_suspend(struct device *dev)
chip->in_suspend = 1;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
snd_ac97_suspend(chip->ac97);
return 0;
}
@@ -1974,10 +1973,8 @@ snd_riptide_proc_read(struct snd_info_entry *entry,
static void snd_riptide_proc_init(struct snd_riptide *chip)
{
- struct snd_info_entry *entry;
-
- if (!snd_card_proc_new(chip->card, "riptide", &entry))
- snd_info_set_text_ops(entry, chip, snd_riptide_proc_read);
+ snd_card_ro_proc_new(chip->card, "riptide", chip,
+ snd_riptide_proc_read);
}
static int snd_riptide_mixer(struct snd_riptide *chip)
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 3ac8c71d567c..c6bcc0715716 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1568,10 +1568,7 @@ snd_rme32_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffe
static void snd_rme32_proc_init(struct rme32 *rme32)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(rme32->card, "rme32", &entry))
- snd_info_set_text_ops(entry, rme32, snd_rme32_proc_read);
+ snd_card_ro_proc_new(rme32->card, "rme32", rme32, snd_rme32_proc_read);
}
/*
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index dcfa4d7a73e2..42c6b5e09072 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -1868,10 +1868,7 @@ snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer
static void snd_rme96_proc_init(struct rme96 *rme96)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(rme96->card, "rme96", &entry))
- snd_info_set_text_ops(entry, rme96, snd_rme96_proc_read);
+ snd_card_ro_proc_new(rme96->card, "rme96", rme96, snd_rme96_proc_read);
}
/*
@@ -2388,8 +2385,6 @@ static int rme96_suspend(struct device *dev)
struct rme96 *rme96 = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend(rme96->playback_substream);
- snd_pcm_suspend(rme96->capture_substream);
/* save capture & playback pointers */
rme96->playback_pointer = readl(rme96->iobase + RME96_IO_GET_PLAY_POS)
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index ba99ff0e93e0..29bef48a3af3 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -3708,10 +3708,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
static void snd_hdsp_proc_init(struct hdsp *hdsp)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(hdsp->card, "hdsp", &entry))
- snd_info_set_text_ops(entry, hdsp, snd_hdsp_proc_read);
+ snd_card_ro_proc_new(hdsp->card, "hdsp", hdsp, snd_hdsp_proc_read);
}
static void snd_hdsp_free_buffers(struct hdsp *hdsp)
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 679ad0415e3b..1209cf0b05e0 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -5287,44 +5287,35 @@ static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
static void snd_hdspm_proc_init(struct hdspm *hdspm)
{
- struct snd_info_entry *entry;
+ void (*read)(struct snd_info_entry *, struct snd_info_buffer *) = NULL;
- if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
- switch (hdspm->io_type) {
- case AES32:
- snd_info_set_text_ops(entry, hdspm,
- snd_hdspm_proc_read_aes32);
- break;
- case MADI:
- snd_info_set_text_ops(entry, hdspm,
- snd_hdspm_proc_read_madi);
- break;
- case MADIface:
- /* snd_info_set_text_ops(entry, hdspm,
- snd_hdspm_proc_read_madiface); */
- break;
- case RayDAT:
- snd_info_set_text_ops(entry, hdspm,
- snd_hdspm_proc_read_raydat);
- break;
- case AIO:
- break;
- }
- }
-
- if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
- snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
+ switch (hdspm->io_type) {
+ case AES32:
+ read = snd_hdspm_proc_read_aes32;
+ break;
+ case MADI:
+ read = snd_hdspm_proc_read_madi;
+ break;
+ case MADIface:
+ /* read = snd_hdspm_proc_read_madiface; */
+ break;
+ case RayDAT:
+ read = snd_hdspm_proc_read_raydat;
+ break;
+ case AIO:
+ break;
}
- if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
- snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
- }
+ snd_card_ro_proc_new(hdspm->card, "hdspm", hdspm, read);
+ snd_card_ro_proc_new(hdspm->card, "ports.in", hdspm,
+ snd_hdspm_proc_ports_in);
+ snd_card_ro_proc_new(hdspm->card, "ports.out", hdspm,
+ snd_hdspm_proc_ports_out);
#ifdef CONFIG_SND_DEBUG
/* debug file to read all hdspm registers */
- if (!snd_card_proc_new(hdspm->card, "debug", &entry))
- snd_info_set_text_ops(entry, hdspm,
- snd_hdspm_proc_read_debug);
+ snd_card_ro_proc_new(hdspm->card, "debug", hdspm,
+ snd_hdspm_proc_read_debug);
#endif
}
@@ -6411,7 +6402,6 @@ static int snd_hdspm_create_hwdep(struct snd_card *card,
------------------------------------------------------------*/
static int snd_hdspm_preallocate_memory(struct hdspm *hdspm)
{
- int err;
struct snd_pcm *pcm;
size_t wanted;
@@ -6419,21 +6409,10 @@ static int snd_hdspm_preallocate_memory(struct hdspm *hdspm)
wanted = HDSPM_DMA_AREA_BYTES;
- err =
- snd_pcm_lib_preallocate_pages_for_all(pcm,
- SNDRV_DMA_TYPE_DEV_SG,
- snd_dma_pci_data(hdspm->pci),
- wanted,
- wanted);
- if (err < 0) {
- dev_dbg(hdspm->card->dev,
- "Could not preallocate %zd Bytes\n", wanted);
-
- return err;
- } else
- dev_dbg(hdspm->card->dev,
- " Preallocated %zd Bytes\n", wanted);
-
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+ snd_dma_pci_data(hdspm->pci),
+ wanted, wanted);
+ dev_dbg(hdspm->card->dev, " Preallocated %zd Bytes\n", wanted);
return 0;
}
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index edd765e22377..5228b982da5a 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -1737,10 +1737,8 @@ snd_rme9652_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buff
static void snd_rme9652_proc_init(struct snd_rme9652 *rme9652)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(rme9652->card, "rme9652", &entry))
- snd_info_set_text_ops(entry, rme9652, snd_rme9652_proc_read);
+ snd_card_ro_proc_new(rme9652->card, "rme9652", rme9652,
+ snd_rme9652_proc_read);
}
static void snd_rme9652_free_buffers(struct snd_rme9652 *rme9652)
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index 964acf302479..6b27980d77a8 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -1214,7 +1214,6 @@ static int sis_suspend(struct device *dev)
int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(sis->pcm);
if (sis->codecs_present & SIS_PRIMARY_CODEC_PRESENT)
snd_ac97_suspend(sis->ac97[0]);
if (sis->codecs_present & SIS_SECONDARY_CODEC_PRESENT)
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 7218f38b59db..71d5ad3cffd6 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -1171,10 +1171,8 @@ static void snd_sonicvibes_proc_read(struct snd_info_entry *entry,
static void snd_sonicvibes_proc_init(struct sonicvibes *sonic)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(sonic->card, "sonicvibes", &entry))
- snd_info_set_text_ops(entry, sonic, snd_sonicvibes_proc_read);
+ snd_card_ro_proc_new(sonic->card, "sonicvibes", sonic,
+ snd_sonicvibes_proc_read);
}
/*
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 5523e193d556..0ff32d3f5d3b 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -3320,13 +3320,11 @@ static void snd_trident_proc_read(struct snd_info_entry *entry,
static void snd_trident_proc_init(struct snd_trident *trident)
{
- struct snd_info_entry *entry;
const char *s = "trident";
if (trident->device == TRIDENT_DEVICE_ID_SI7018)
s = "sis7018";
- if (! snd_card_proc_new(trident->card, s, &entry))
- snd_info_set_text_ops(entry, trident, snd_trident_proc_read);
+ snd_card_ro_proc_new(trident->card, s, trident, snd_trident_proc_read);
}
static int snd_trident_dev_free(struct snd_device *device)
@@ -3915,10 +3913,6 @@ static int snd_trident_suspend(struct device *dev)
trident->in_suspend = 1;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(trident->pcm);
- snd_pcm_suspend_all(trident->foldback);
- snd_pcm_suspend_all(trident->spdif);
-
snd_ac97_suspend(trident->ac97);
snd_ac97_suspend(trident->ac97_sec);
return 0;
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index c488c5afa195..dee1c487d6ba 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -2144,10 +2144,8 @@ static void snd_via82xx_proc_read(struct snd_info_entry *entry,
static void snd_via82xx_proc_init(struct via82xx *chip)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(chip->card, "via82xx", &entry))
- snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read);
+ snd_card_ro_proc_new(chip->card, "via82xx", chip,
+ snd_via82xx_proc_read);
}
/*
@@ -2278,8 +2276,6 @@ static int snd_via82xx_suspend(struct device *dev)
int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- for (i = 0; i < 2; i++)
- snd_pcm_suspend_all(chip->pcms[i]);
for (i = 0; i < chip->num_devs; i++)
snd_via82xx_channel_reset(chip, &chip->devs[i]);
synchronize_irq(chip->irq);
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index b13c8688cc8d..7e0bebce7b77 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -865,11 +865,9 @@ static int snd_via686_pcm_new(struct via82xx_modem *chip)
init_viadev(chip, 0, VIA_REG_MO_STATUS, 0);
init_viadev(chip, 1, VIA_REG_MI_STATUS, 1);
- if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
- snd_dma_pci_data(chip->pci),
- 64*1024, 128*1024)) < 0)
- return err;
-
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+ snd_dma_pci_data(chip->pci),
+ 64*1024, 128*1024);
return 0;
}
@@ -937,10 +935,8 @@ static void snd_via82xx_proc_read(struct snd_info_entry *entry, struct snd_info_
static void snd_via82xx_proc_init(struct via82xx_modem *chip)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(chip->card, "via82xx", &entry))
- snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read);
+ snd_card_ro_proc_new(chip->card, "via82xx", chip,
+ snd_via82xx_proc_read);
}
/*
@@ -1038,8 +1034,6 @@ static int snd_via82xx_suspend(struct device *dev)
int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- for (i = 0; i < 2; i++)
- snd_pcm_suspend_all(chip->pcms[i]);
for (i = 0; i < chip->num_devs; i++)
snd_via82xx_channel_reset(chip, &chip->devs[i]);
synchronize_irq(chip->irq);
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index a4926fb03991..4d48877f211f 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -1985,11 +1985,7 @@ static void snd_ymfpci_proc_read(struct snd_info_entry *entry,
static int snd_ymfpci_proc_init(struct snd_card *card, struct snd_ymfpci *chip)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(card, "ymfpci", &entry))
- snd_info_set_text_ops(entry, chip, snd_ymfpci_proc_read);
- return 0;
+ return snd_card_ro_proc_new(card, "ymfpci", chip, snd_ymfpci_proc_read);
}
/*
@@ -2304,10 +2300,6 @@ static int snd_ymfpci_suspend(struct device *dev)
unsigned int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
- snd_pcm_suspend_all(chip->pcm2);
- snd_pcm_suspend_all(chip->pcm_spdif);
- snd_pcm_suspend_all(chip->pcm_4ch);
snd_ac97_suspend(chip->ac97);
for (i = 0; i < YDSXGR_NUM_SAVED_REGS; i++)
chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]);
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
index d724ab0653cf..910478275fd9 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
@@ -148,10 +148,7 @@ static void pdacf_proc_read(struct snd_info_entry * entry,
static void pdacf_proc_init(struct snd_pdacf *chip)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(chip->card, "pdaudiocf", &entry))
- snd_info_set_text_ops(entry, chip, pdacf_proc_read);
+ snd_card_ro_proc_new(chip->card, "pdaudiocf", chip, pdacf_proc_read);
}
struct snd_pdacf *snd_pdacf_create(struct snd_card *card)
@@ -265,7 +262,6 @@ int snd_pdacf_suspend(struct snd_pdacf *chip)
u16 val;
snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
/* disable interrupts, but use direct write to preserve old register value in chip->regmap */
val = inw(chip->port + PDAUDIOCF_REG_IER);
val &= ~(PDAUDIOCF_IRQOVREN|PDAUDIOCF_IRQAKMEN|PDAUDIOCF_IRQLVLEN0|PDAUDIOCF_IRQLVLEN1);
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index d692e4070167..6d420bd3ae17 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -1365,7 +1365,6 @@ void snd_pmac_suspend(struct snd_pmac *chip)
snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
if (chip->suspend)
chip->suspend(chip);
- snd_pcm_suspend_all(chip->pcm);
spin_lock_irqsave(&chip->reg_lock, flags);
snd_pmac_beep_stop(chip);
spin_unlock_irqrestore(&chip->reg_lock, flags);
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c
index abe031c9d592..521236efcc4d 100644
--- a/sound/ppc/snd_ps3.c
+++ b/sound/ppc/snd_ps3.c
@@ -1024,15 +1024,11 @@ static int snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
the_card.pcm->info_flags = SNDRV_PCM_INFO_NONINTERLEAVED;
/* pre-alloc PCM DMA buffer*/
- ret = snd_pcm_lib_preallocate_pages_for_all(the_card.pcm,
+ snd_pcm_lib_preallocate_pages_for_all(the_card.pcm,
SNDRV_DMA_TYPE_DEV,
&dev->core,
SND_PS3_PCM_PREALLOC_SIZE,
SND_PS3_PCM_PREALLOC_SIZE);
- if (ret < 0) {
- pr_info("%s: prealloc failed\n", __func__);
- goto clean_card;
- }
/*
* allocate null buffer
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 6d7ffffcce95..78e5798ae967 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -1371,6 +1371,7 @@ int snd_pmac_tumbler_init(struct snd_pmac *chip)
mix->anded_reset = 1;
if (of_get_property(np, "layout-id", NULL))
mix->reset_on_sleep = 0;
+ of_node_put(np);
break;
}
}
diff --git a/sound/sh/aica.c b/sound/sh/aica.c
index 2b26311405a4..e7fef3fce44a 100644
--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -464,14 +464,12 @@ static int __init snd_aicapcmchip(struct snd_card_aica
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
&snd_aicapcm_playback_ops);
/* Allocate the DMA buffers */
- err =
- snd_pcm_lib_preallocate_pages_for_all(pcm,
- SNDRV_DMA_TYPE_CONTINUOUS,
- snd_dma_continuous_data
- (GFP_KERNEL),
- AICA_BUFFER_SIZE,
- AICA_BUFFER_SIZE);
- return err;
+ snd_pcm_lib_preallocate_pages_for_all(pcm,
+ SNDRV_DMA_TYPE_CONTINUOUS,
+ snd_dma_continuous_data(GFP_KERNEL),
+ AICA_BUFFER_SIZE,
+ AICA_BUFFER_SIZE);
+ return 0;
}
/* Mixer controls */
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index f4011bebc7ec..2391c7f1dd2d 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -1142,7 +1142,6 @@ static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
static int acp_dma_new(struct snd_soc_pcm_runtime *rtd)
{
- int ret;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd,
DRV_NAME);
struct audio_drv_data *adata = dev_get_drvdata(component->dev);
@@ -1150,24 +1149,21 @@ static int acp_dma_new(struct snd_soc_pcm_runtime *rtd)
switch (adata->asic_type) {
case CHIP_STONEY:
- ret = snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
- SNDRV_DMA_TYPE_DEV,
- parent,
- ST_MIN_BUFFER,
- ST_MAX_BUFFER);
+ snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
+ SNDRV_DMA_TYPE_DEV,
+ parent,
+ ST_MIN_BUFFER,
+ ST_MAX_BUFFER);
break;
default:
- ret = snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
- SNDRV_DMA_TYPE_DEV,
- parent,
- MIN_BUFFER,
- MAX_BUFFER);
+ snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
+ SNDRV_DMA_TYPE_DEV,
+ parent,
+ MIN_BUFFER,
+ MAX_BUFFER);
break;
}
- if (ret < 0)
- dev_err(component->dev,
- "buffer preallocation failure error:%d\n", ret);
- return ret;
+ return 0;
}
static int acp_dma_close(struct snd_pcm_substream *substream)
diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index 3d58338fa3cf..1a2e15ff1456 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -367,10 +367,10 @@ static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream)
static int acp3x_dma_new(struct snd_soc_pcm_runtime *rtd)
{
- return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
- SNDRV_DMA_TYPE_DEV,
- NULL, MIN_BUFFER,
- MAX_BUFFER);
+ snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+ rtd->pcm->card->dev,
+ MIN_BUFFER, MAX_BUFFER);
+ return 0;
}
static int acp3x_dma_hw_free(struct snd_pcm_substream *substream)
diff --git a/sound/soc/dwc/dwc-pcm.c b/sound/soc/dwc/dwc-pcm.c
index 2cc9632024fc..a9ae91c4597f 100644
--- a/sound/soc/dwc/dwc-pcm.c
+++ b/sound/soc/dwc/dwc-pcm.c
@@ -249,9 +249,10 @@ static int dw_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
size_t size = dw_pcm_hardware.buffer_bytes_max;
- return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
+ snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
SNDRV_DMA_TYPE_CONTINUOUS,
snd_dma_continuous_data(GFP_KERNEL), size, size);
+ return 0;
}
static void dw_pcm_free(struct snd_pcm *pcm)
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index b0873fea23ab..08cea5b5cda9 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
@@ -687,20 +687,15 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
- int retval = 0;
if (dai->driver->playback.channels_min ||
dai->driver->capture.channels_min) {
- retval = snd_pcm_lib_preallocate_pages_for_all(pcm,
+ snd_pcm_lib_preallocate_pages_for_all(pcm,
SNDRV_DMA_TYPE_CONTINUOUS,
snd_dma_continuous_data(GFP_DMA),
SST_MIN_BUFFER, SST_MAX_BUFFER);
- if (retval) {
- dev_err(rtd->dev, "dma buffer allocation failure\n");
- return retval;
- }
}
- return retval;
+ return 0;
}
static int sst_soc_probe(struct snd_soc_component *component)
diff --git a/sound/soc/intel/baytrail/sst-baytrail-pcm.c b/sound/soc/intel/baytrail/sst-baytrail-pcm.c
index 498fb5346f1a..5373605de0af 100644
--- a/sound/soc/intel/baytrail/sst-baytrail-pcm.c
+++ b/sound/soc/intel/baytrail/sst-baytrail-pcm.c
@@ -327,23 +327,16 @@ static int sst_byt_pcm_new(struct snd_soc_pcm_runtime *rtd)
size_t size;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct sst_pdata *pdata = dev_get_platdata(component->dev);
- int ret = 0;
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream ||
pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
size = sst_byt_pcm_hardware.buffer_bytes_max;
- ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
- SNDRV_DMA_TYPE_DEV,
- pdata->dma_dev,
- size, size);
- if (ret) {
- dev_err(rtd->dev, "dma buffer allocation failed %d\n",
- ret);
- return ret;
- }
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ pdata->dma_dev,
+ size, size);
}
- return ret;
+ return 0;
}
static struct snd_soc_dai_driver byt_dais[] = {
diff --git a/sound/soc/intel/haswell/sst-haswell-pcm.c b/sound/soc/intel/haswell/sst-haswell-pcm.c
index 2debcc2ed99a..e023c4c3e5a9 100644
--- a/sound/soc/intel/haswell/sst-haswell-pcm.c
+++ b/sound/soc/intel/haswell/sst-haswell-pcm.c
@@ -946,27 +946,21 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd)
struct sst_pdata *pdata = dev_get_platdata(component->dev);
struct hsw_priv_data *priv_data = dev_get_drvdata(component->dev);
struct device *dev = pdata->dma_dev;
- int ret = 0;
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream ||
pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
+ snd_pcm_lib_preallocate_pages_for_all(pcm,
SNDRV_DMA_TYPE_DEV_SG,
dev,
hsw_pcm_hardware.buffer_bytes_max,
hsw_pcm_hardware.buffer_bytes_max);
- if (ret) {
- dev_err(rtd->dev, "dma buffer allocation failed %d\n",
- ret);
- return ret;
- }
}
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
priv_data->pcm[rtd->cpu_dai->id][SNDRV_PCM_STREAM_PLAYBACK].hsw_pcm = pcm;
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream)
priv_data->pcm[rtd->cpu_dai->id][SNDRV_PCM_STREAM_CAPTURE].hsw_pcm = pcm;
- return ret;
+ return 0;
}
#define HSW_FORMATS \
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c
index bb463ee6ff84..56099db8f86d 100644
--- a/sound/soc/intel/skylake/skl-pcm.c
+++ b/sound/soc/intel/skylake/skl-pcm.c
@@ -1298,7 +1298,6 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
struct hdac_bus *bus = dev_get_drvdata(dai->dev);
struct snd_pcm *pcm = rtd->pcm;
unsigned int size;
- int retval = 0;
struct skl *skl = bus_to_skl(bus);
if (dai->driver->playback.channels_min ||
@@ -1307,17 +1306,13 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024;
if (size > MAX_PREALLOC_SIZE)
size = MAX_PREALLOC_SIZE;
- retval = snd_pcm_lib_preallocate_pages_for_all(pcm,
+ snd_pcm_lib_preallocate_pages_for_all(pcm,
SNDRV_DMA_TYPE_DEV_SG,
snd_dma_pci_data(skl->pci),
size, MAX_PREALLOC_SIZE);
- if (retval) {
- dev_err(dai->dev, "dma buffer allocation fail\n");
- return retval;
- }
}
- return retval;
+ return 0;
}
static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig)
diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.c b/sound/soc/mediatek/common/mtk-afe-platform-driver.c
index 697aa50aff9a..3ce527ce30ce 100644
--- a/sound/soc/mediatek/common/mtk-afe-platform-driver.c
+++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.c
@@ -126,9 +126,9 @@ int mtk_afe_pcm_new(struct snd_soc_pcm_runtime *rtd)
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
size = afe->mtk_afe_hardware->buffer_bytes_max;
- return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- afe->dev,
- size, size);
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ afe->dev, size, size);
+ return 0;
}
EXPORT_SYMBOL_GPL(mtk_afe_pcm_new);
diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c
index 0e4f65e654c4..75e5e480fda2 100644
--- a/sound/soc/meson/axg-fifo.c
+++ b/sound/soc/meson/axg-fifo.c
@@ -267,9 +267,10 @@ int axg_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd, unsigned int type)
struct snd_card *card = rtd->card->snd_card;
size_t size = axg_fifo_hw.buffer_bytes_max;
- return snd_pcm_lib_preallocate_pages(rtd->pcm->streams[type].substream,
- SNDRV_DMA_TYPE_DEV, card->dev,
- size, size);
+ snd_pcm_lib_preallocate_pages(rtd->pcm->streams[type].substream,
+ SNDRV_DMA_TYPE_DEV, card->dev,
+ size, size);
+ return 0;
}
EXPORT_SYMBOL_GPL(axg_fifo_pcm_new);
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index db929b00ae5e..3447dbdba1f1 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -1768,11 +1768,12 @@ static const struct snd_pcm_ops fsi_pcm_ops = {
static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
- return snd_pcm_lib_preallocate_pages_for_all(
+ snd_pcm_lib_preallocate_pages_for_all(
rtd->pcm,
SNDRV_DMA_TYPE_DEV,
rtd->card->snd_card->dev,
PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
+ return 0;
}
/*
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 8d3758f862f1..4fe83e611c01 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -1575,7 +1575,6 @@ static int rsnd_preallocate_pages(struct snd_soc_pcm_runtime *rtd,
struct rsnd_priv *priv = rsnd_io_to_priv(io);
struct device *dev = rsnd_priv_to_dev(priv);
struct snd_pcm_substream *substream;
- int err;
/*
* use Audio-DMAC dev if we can use IPMMU
@@ -1588,12 +1587,10 @@ static int rsnd_preallocate_pages(struct snd_soc_pcm_runtime *rtd,
for (substream = rtd->pcm->streams[stream].substream;
substream;
substream = substream->next) {
- err = snd_pcm_lib_preallocate_pages(substream,
+ snd_pcm_lib_preallocate_pages(substream,
SNDRV_DMA_TYPE_DEV,
dev,
PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
- if (err < 0)
- return err;
}
return 0;
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
index e263757e4a69..78c3145b4109 100644
--- a/sound/soc/sh/siu_pcm.c
+++ b/sound/soc/sh/siu_pcm.c
@@ -541,15 +541,9 @@ static int siu_pcm_new(struct snd_soc_pcm_runtime *rtd)
if (ret < 0)
return ret;
- ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
- SNDRV_DMA_TYPE_DEV, NULL,
+ snd_pcm_lib_preallocate_pages_for_all(pcm,
+ SNDRV_DMA_TYPE_DEV, card->dev,
SIU_BUFFER_BYTES_MAX, SIU_BUFFER_BYTES_MAX);
- if (ret < 0) {
- dev_err(card->dev,
- "snd_pcm_lib_preallocate_pages_for_all() err=%d",
- ret);
- goto fail;
- }
(*port_info)->pcm = pcm;
@@ -562,11 +556,6 @@ static int siu_pcm_new(struct snd_soc_pcm_runtime *rtd)
dev_info(card->dev, "SuperH SIU driver initialized.\n");
return 0;
-
-fail:
- siu_free_port(siu_ports[pdev->id]);
- dev_err(card->dev, "SIU: failed to initialize.\n");
- return ret;
}
static void siu_pcm_free(struct snd_pcm *pcm)
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index f1ab6285a085..748f5f641002 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -269,7 +269,6 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
size_t prealloc_buffer_size;
size_t max_buffer_size;
unsigned int i;
- int ret;
if (config && config->prealloc_buffer_size) {
prealloc_buffer_size = config->prealloc_buffer_size;
@@ -299,13 +298,11 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
return -EINVAL;
}
- ret = snd_pcm_lib_preallocate_pages(substream,
+ snd_pcm_lib_preallocate_pages(substream,
SNDRV_DMA_TYPE_DEV_IRAM,
dmaengine_dma_dev(pcm, substream),
prealloc_buffer_size,
max_buffer_size);
- if (ret)
- return ret;
if (!dmaengine_pcm_can_report_residue(dev, pcm->chan[i]))
pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE;
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 90504c149931..7fe5321000e8 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -3174,6 +3174,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
}
pcm->private_free = soc_pcm_private_free;
+ pcm->no_device_suspend = true;
out:
dev_info(rtd->card->dev, "%s <-> %s mapping ok\n",
(rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name,
diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c
index 706ff005234f..47901983a6ff 100644
--- a/sound/soc/stm/stm32_adfsdm.c
+++ b/sound/soc/stm/stm32_adfsdm.c
@@ -262,8 +262,9 @@ static int stm32_adfsdm_pcm_new(struct snd_soc_pcm_runtime *rtd)
snd_soc_dai_get_drvdata(rtd->cpu_dai);
unsigned int size = DFSDM_MAX_PERIODS * DFSDM_MAX_PERIOD_SIZE;
- return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- priv->dev, size, size);
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ priv->dev, size, size);
+ return 0;
}
static void stm32_adfsdm_pcm_free(struct snd_pcm *pcm)
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
index 8d31fe628e2f..089bd7518606 100644
--- a/sound/soc/txx9/txx9aclc.c
+++ b/sound/soc/txx9/txx9aclc.c
@@ -313,8 +313,10 @@ static int txx9aclc_pcm_new(struct snd_soc_pcm_runtime *rtd)
if (ret)
goto exit;
}
- return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
card->dev, 64 * 1024, 4 * 1024 * 1024);
+ return 0;
exit:
for (i = 0; i < 2; i++) {
diff --git a/sound/soc/uniphier/aio-dma.c b/sound/soc/uniphier/aio-dma.c
index 4ec6b65bfb44..fa001d3c1a88 100644
--- a/sound/soc/uniphier/aio-dma.c
+++ b/sound/soc/uniphier/aio-dma.c
@@ -235,10 +235,11 @@ static int uniphier_aiodma_new(struct snd_soc_pcm_runtime *rtd)
if (ret)
return ret;
- return snd_pcm_lib_preallocate_pages_for_all(pcm,
+ snd_pcm_lib_preallocate_pages_for_all(pcm,
SNDRV_DMA_TYPE_DEV, dev,
uniphier_aiodma_hw.buffer_bytes_max,
uniphier_aiodma_hw.buffer_bytes_max);
+ return 0;
}
static void uniphier_aiodma_free(struct snd_pcm *pcm)
diff --git a/sound/soc/xilinx/xlnx_formatter_pcm.c b/sound/soc/xilinx/xlnx_formatter_pcm.c
index 97177d35652e..dc8721f4f56b 100644
--- a/sound/soc/xilinx/xlnx_formatter_pcm.c
+++ b/sound/soc/xilinx/xlnx_formatter_pcm.c
@@ -536,10 +536,11 @@ static int xlnx_formatter_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd,
DRV_NAME);
- return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
+ snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
SNDRV_DMA_TYPE_DEV, component->dev,
xlnx_pcm_hardware.buffer_bytes_max,
xlnx_pcm_hardware.buffer_bytes_max);
+ return 0;
}
static const struct snd_pcm_ops xlnx_formatter_pcm_ops = {
diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c
index 503560916620..2f20a02c8d46 100644
--- a/sound/soc/xtensa/xtfpga-i2s.c
+++ b/sound/soc/xtensa/xtfpga-i2s.c
@@ -469,9 +469,9 @@ static int xtfpga_pcm_new(struct snd_soc_pcm_runtime *rtd)
struct snd_card *card = rtd->card->snd_card;
size_t size = xtfpga_pcm_hardware.buffer_bytes_max;
- return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
- SNDRV_DMA_TYPE_DEV,
- card->dev, size, size);
+ snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+ card->dev, size, size);
+ return 0;
}
static const struct snd_pcm_ops xtfpga_pcm_ops = {
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 9e71d7cda999..2b8ef5fe6688 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -2243,12 +2243,9 @@ static int snd_dbri_pcm(struct snd_card *card)
pcm->info_flags = 0;
strcpy(pcm->name, card->shortname);
- if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm,
- SNDRV_DMA_TYPE_CONTINUOUS,
- snd_dma_continuous_data(GFP_KERNEL),
- 64 * 1024, 64 * 1024)) < 0)
- return err;
-
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+ snd_dma_continuous_data(GFP_KERNEL),
+ 64 * 1024, 64 * 1024);
return 0;
}
@@ -2510,16 +2507,10 @@ static void dbri_debug_read(struct snd_info_entry *entry,
static void snd_dbri_proc(struct snd_card *card)
{
struct snd_dbri *dbri = card->private_data;
- struct snd_info_entry *entry;
-
- if (!snd_card_proc_new(card, "regs", &entry))
- snd_info_set_text_ops(entry, dbri, dbri_regs_read);
+ snd_card_ro_proc_new(card, "regs", dbri, dbri_regs_read);
#ifdef DBRI_DEBUG
- if (!snd_card_proc_new(card, "debug", &entry)) {
- snd_info_set_text_ops(entry, dbri, dbri_debug_read);
- entry->mode = S_IFREG | 0444; /* Readable only. */
- }
+ snd_card_ro_proc_new(card, "debug", dbri, dbri_debug_read);
#endif
}
diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index 1ef52edeb538..8707e0108471 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -350,7 +350,7 @@ static int snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &at73c213_playback_ops);
- retval = snd_pcm_lib_preallocate_pages_for_all(chip->pcm,
+ snd_pcm_lib_preallocate_pages_for_all(chip->pcm,
SNDRV_DMA_TYPE_DEV, &chip->ssc->pdev->dev,
64 * 1024, 64 * 1024);
out:
diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c
index a82b4053bee8..c14781ac7941 100644
--- a/sound/synth/emux/emux_proc.c
+++ b/sound/synth/emux/emux_proc.c
@@ -115,10 +115,6 @@ void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device)
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->private_data = emu;
entry->c.text.read = snd_emux_proc_info_read;
- if (snd_info_register(entry) < 0)
- snd_info_free_entry(entry);
- else
- emu->proc = entry;
}
void snd_emux_proc_free(struct snd_emux *emu)
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 746a72e23cf9..719e10034553 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -811,7 +811,6 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
if (!chip->num_suspended_intf++) {
list_for_each_entry(as, &chip->pcm_list, list) {
- snd_pcm_suspend_all(as->pcm);
snd_usb_pcm_suspend(as);
as->substream[0].need_setup_ep =
as->substream[1].need_setup_ep = true;
diff --git a/sound/usb/card.h b/sound/usb/card.h
index ac785d15ced4..79fa2a19fb7b 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -14,6 +14,7 @@ struct audioformat {
u64 formats; /* ALSA format bits */
unsigned int channels; /* # channels */
unsigned int fmt_type; /* USB audio format type (1-3) */
+ unsigned int fmt_bits; /* number of significant bits */
unsigned int frame_size; /* samples per frame for non-audio */
int iface; /* interface number */
unsigned char altsetting; /* corresponding alternate setting */
diff --git a/sound/usb/format.c b/sound/usb/format.c
index fd13ac11b136..3ee7d6f853b7 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -87,6 +87,8 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
}
}
+ fp->fmt_bits = sample_width;
+
if ((pcm_formats == 0) &&
(format == 0 || format == (1 << UAC_FORMAT_TYPE_I_UNDEFINED))) {
/* some devices don't define this correctly... */
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index c1376bfdc90b..7afe8fae4939 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -849,10 +849,8 @@ int line6_suspend(struct usb_interface *interface, pm_message_t message)
if (line6->properties->capabilities & LINE6_CAP_CONTROL)
line6_stop_listen(line6);
- if (line6pcm != NULL) {
- snd_pcm_suspend_all(line6pcm->pcm);
+ if (line6pcm != NULL)
line6pcm->flags = 0;
- }
return 0;
}
diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c
index 020c81818951..ce45b6dab651 100644
--- a/sound/usb/line6/pod.c
+++ b/sound/usb/line6/pod.c
@@ -320,7 +320,8 @@ static void pod_startup4(struct work_struct *work)
line6_read_serial_number(&pod->line6, &pod->serial_number);
/* ALSA audio interface: */
- snd_card_register(line6->card);
+ if (snd_card_register(line6->card))
+ dev_err(line6->ifcdev, "Failed to register POD card.\n");
}
/* POD special files: */
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index e7d441d0e839..73d7dff425c1 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1835,7 +1835,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
{
int channels, i, j;
struct usb_audio_term iterm;
- unsigned int master_bits, first_ch_bits;
+ unsigned int master_bits;
int err, csize;
struct uac_feature_unit_descriptor *hdr = _ftr;
__u8 *bmaControls;
@@ -1926,10 +1926,6 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
break;
}
- if (channels > 0)
- first_ch_bits = snd_usb_combine_bytes(bmaControls + csize, csize);
- else
- first_ch_bits = 0;
if (state->mixer->protocol == UAC_VERSION_1) {
/* check all control types */
@@ -3445,7 +3441,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
.dev_free = snd_usb_mixer_dev_free
};
struct usb_mixer_interface *mixer;
- struct snd_info_entry *entry;
int err;
strcpy(chip->card->mixername, "USB Mixer");
@@ -3501,9 +3496,9 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
if (err < 0)
goto _error;
- if (list_empty(&chip->mixer_list) &&
- !snd_card_proc_new(chip->card, "usbmixer", &entry))
- snd_info_set_text_ops(entry, chip, snd_usb_mixer_proc_read);
+ if (list_empty(&chip->mixer_list))
+ snd_card_ro_proc_new(chip->card, "usbmixer", chip,
+ snd_usb_mixer_proc_read);
list_add(&mixer->list, &chip->mixer_list);
return 0;
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 85ae0ff2382a..a751a18ca4c2 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -2195,7 +2195,6 @@ static int snd_rme_controls_create(struct usb_mixer_interface *mixer)
int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
{
int err = 0;
- struct snd_info_entry *entry;
err = snd_usb_soundblaster_remote_init(mixer);
if (err < 0)
@@ -2214,9 +2213,8 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
err = snd_audigy2nx_controls_create(mixer);
if (err < 0)
break;
- if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry))
- snd_info_set_text_ops(entry, mixer,
- snd_audigy2nx_proc_read);
+ snd_card_ro_proc_new(mixer->chip->card, "audigy2nx",
+ mixer, snd_audigy2nx_proc_read);
break;
/* EMU0204 */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 382847154227..056af0a57b22 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -314,6 +314,9 @@ static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
return 0;
}
+/* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk
+ * applies. Returns 1 if a quirk was found.
+ */
static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
struct usb_device *dev,
struct usb_interface_descriptor *altsd,
@@ -351,6 +354,10 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
ep = 0x81;
ifnum = 1;
goto add_sync_ep_from_ifnum;
+ case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II */
+ ep = 0x84;
+ ifnum = 0;
+ goto add_sync_ep_from_ifnum;
}
if (attr == USB_ENDPOINT_SYNC_ASYNC &&
@@ -384,7 +391,7 @@ add_sync_ep:
subs->data_endpoint->sync_master = subs->sync_endpoint;
- return 0;
+ return 1;
}
static int set_sync_endpoint(struct snd_usb_substream *subs,
@@ -423,6 +430,10 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
if (err < 0)
return err;
+ /* endpoint set by quirk */
+ if (err > 0)
+ return 0;
+
if (altsd->bNumEndpoints < 2)
return 0;
diff --git a/sound/usb/proc.c b/sound/usb/proc.c
index 0ac89e294d31..ef9190530fd2 100644
--- a/sound/usb/proc.c
+++ b/sound/usb/proc.c
@@ -61,11 +61,10 @@ static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_
void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
{
- struct snd_info_entry *entry;
- if (!snd_card_proc_new(chip->card, "usbbus", &entry))
- snd_info_set_text_ops(entry, chip, proc_audio_usbbus_read);
- if (!snd_card_proc_new(chip->card, "usbid", &entry))
- snd_info_set_text_ops(entry, chip, proc_audio_usbid_read);
+ snd_card_ro_proc_new(chip->card, "usbbus", chip,
+ proc_audio_usbbus_read);
+ snd_card_ro_proc_new(chip->card, "usbid", chip,
+ proc_audio_usbid_read);
}
/*
@@ -110,6 +109,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
if (subs->speed != USB_SPEED_FULL)
snd_iprintf(buffer, " Data packet interval: %d us\n",
125 * (1 << fp->datainterval));
+ snd_iprintf(buffer, " Bits: %d\n", fp->fmt_bits);
// snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize);
// snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes);
}
@@ -167,12 +167,10 @@ static void proc_pcm_format_read(struct snd_info_entry *entry, struct snd_info_b
void snd_usb_proc_pcm_format_add(struct snd_usb_stream *stream)
{
- struct snd_info_entry *entry;
char name[32];
struct snd_card *card = stream->chip->card;
sprintf(name, "stream%d", stream->pcm_index);
- if (!snd_card_proc_new(card, name, &entry))
- snd_info_set_text_ops(entry, stream, proc_pcm_format_read);
+ snd_card_ro_proc_new(card, name, stream, proc_pcm_format_read);
}
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index b345beb447bd..86e80916a029 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3398,5 +3398,70 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
.ifnum = QUIRK_NO_INTERFACE
}
},
+/* MOTU Microbook II */
+{
+ USB_DEVICE(0x07fd, 0x0004),
+ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+ .vendor_name = "MOTU",
+ .product_name = "MicroBookII",
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_STANDARD_MIXER,
+ },
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3BE,
+ .channels = 6,
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .attributes = 0,
+ .endpoint = 0x84,
+ .rates = SNDRV_PCM_RATE_96000,
+ .ep_attr = USB_ENDPOINT_XFER_ISOC |
+ USB_ENDPOINT_SYNC_ASYNC,
+ .rate_min = 96000,
+ .rate_max = 96000,
+ .nr_rates = 1,
+ .maxpacksize = 0x00d8,
+ .rate_table = (unsigned int[]) {
+ 96000
+ }
+ }
+ },
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3BE,
+ .channels = 8,
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .attributes = 0,
+ .endpoint = 0x03,
+ .rates = SNDRV_PCM_RATE_96000,
+ .ep_attr = USB_ENDPOINT_XFER_ISOC |
+ USB_ENDPOINT_SYNC_ASYNC,
+ .rate_min = 96000,
+ .rate_max = 96000,
+ .nr_rates = 1,
+ .maxpacksize = 0x0120,
+ .rate_table = (unsigned int[]) {
+ 96000
+ }
+ }
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
#undef USB_DEVICE_VENDOR_SPEC
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index ebbadb3a7094..e6ce1bbe6ca6 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1000,6 +1000,105 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev)
return 0;
}
+
+#define MICROBOOK_BUF_SIZE 128
+
+static int snd_usb_motu_microbookii_communicate(struct usb_device *dev, u8 *buf,
+ int buf_size, int *length)
+{
+ int err, actual_length;
+
+ err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x01), buf, *length,
+ &actual_length, 1000);
+ if (err < 0)
+ return err;
+
+ print_hex_dump(KERN_DEBUG, "MicroBookII snd: ", DUMP_PREFIX_NONE, 16, 1,
+ buf, actual_length, false);
+
+ memset(buf, 0, buf_size);
+
+ err = usb_interrupt_msg(dev, usb_rcvintpipe(dev, 0x82), buf, buf_size,
+ &actual_length, 1000);
+ if (err < 0)
+ return err;
+
+ print_hex_dump(KERN_DEBUG, "MicroBookII rcv: ", DUMP_PREFIX_NONE, 16, 1,
+ buf, actual_length, false);
+
+ *length = actual_length;
+ return 0;
+}
+
+static int snd_usb_motu_microbookii_boot_quirk(struct usb_device *dev)
+{
+ int err, actual_length, poll_attempts = 0;
+ static const u8 set_samplerate_seq[] = { 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0b, 0x14,
+ 0x00, 0x00, 0x00, 0x01 };
+ static const u8 poll_ready_seq[] = { 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x0b, 0x18 };
+ u8 *buf = kzalloc(MICROBOOK_BUF_SIZE, GFP_KERNEL);
+
+ if (!buf)
+ return -ENOMEM;
+
+ dev_info(&dev->dev, "Waiting for MOTU Microbook II to boot up...\n");
+
+ /* First we tell the device which sample rate to use. */
+ memcpy(buf, set_samplerate_seq, sizeof(set_samplerate_seq));
+ actual_length = sizeof(set_samplerate_seq);
+ err = snd_usb_motu_microbookii_communicate(dev, buf, MICROBOOK_BUF_SIZE,
+ &actual_length);
+
+ if (err < 0) {
+ dev_err(&dev->dev,
+ "failed setting the sample rate for Motu MicroBook II: %d\n",
+ err);
+ goto free_buf;
+ }
+
+ /* Then we poll every 100 ms until the device informs of its readiness. */
+ while (true) {
+ if (++poll_attempts > 100) {
+ dev_err(&dev->dev,
+ "failed booting Motu MicroBook II: timeout\n");
+ err = -ENODEV;
+ goto free_buf;
+ }
+
+ memset(buf, 0, MICROBOOK_BUF_SIZE);
+ memcpy(buf, poll_ready_seq, sizeof(poll_ready_seq));
+
+ actual_length = sizeof(poll_ready_seq);
+ err = snd_usb_motu_microbookii_communicate(
+ dev, buf, MICROBOOK_BUF_SIZE, &actual_length);
+ if (err < 0) {
+ dev_err(&dev->dev,
+ "failed booting Motu MicroBook II: communication error %d\n",
+ err);
+ goto free_buf;
+ }
+
+ /* the device signals its readiness through a message of the
+ * form
+ * XX 06 00 00 00 00 0b 18 00 00 00 01
+ * If the device is not yet ready to accept audio data, the
+ * last byte of that sequence is 00.
+ */
+ if (actual_length == 12 && buf[actual_length - 1] == 1)
+ break;
+
+ msleep(100);
+ }
+
+ dev_info(&dev->dev, "MOTU MicroBook II ready\n");
+
+free_buf:
+ kfree(buf);
+ return err;
+}
+
/*
* Setup quirks
*/
@@ -1177,6 +1276,8 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
return snd_usb_gamecon780_boot_quirk(dev);
case USB_ID(0x2466, 0x8010): /* Fractal Audio Axe-Fx 3 */
return snd_usb_axefx3_boot_quirk(dev);
+ case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II */
+ return snd_usb_motu_microbookii_boot_quirk(dev);
}
return 0;
@@ -1479,10 +1580,6 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
/* XMOS based USB DACs */
switch (chip->usb_id) {
case USB_ID(0x1511, 0x0037): /* AURALiC VEGA */
- case USB_ID(0x20b1, 0x0002): /* Wyred 4 Sound DAC-2 DSD */
- case USB_ID(0x20b1, 0x2004): /* Matrix Audio X-SPDIF 2 */
- case USB_ID(0x20b1, 0x2008): /* Matrix Audio X-Sabre */
- case USB_ID(0x20b1, 0x300a): /* Matrix Audio Mini-i Pro */
case USB_ID(0x22d9, 0x0416): /* OPPO HA-1 */
case USB_ID(0x22d9, 0x0436): /* OPPO Sonica */
case USB_ID(0x22d9, 0x0461): /* OPPO UDP-205 */
@@ -1492,22 +1589,13 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
break;
- case USB_ID(0x152a, 0x85de): /* SMSL D1 DAC */
- case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */
+ case USB_ID(0x10cb, 0x0103): /* The Bit Opus #3; with fp->dsd_raw */
case USB_ID(0x16b0, 0x06b2): /* NuPrime DAC-10 */
+ case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
case USB_ID(0x16d0, 0x0733): /* Furutech ADL Stratos */
case USB_ID(0x16d0, 0x09db): /* NuPrime Audio DAC-9 */
case USB_ID(0x1db5, 0x0003): /* Bryston BDA3 */
- case USB_ID(0x20b1, 0x000a): /* Gustard DAC-X20U */
- case USB_ID(0x20b1, 0x2005): /* Denafrips Ares DAC */
- case USB_ID(0x20b1, 0x2009): /* DIYINHK DSD DXD 384kHz USB to I2S/DSD */
- case USB_ID(0x20b1, 0x2023): /* JLsounds I2SoverUSB */
- case USB_ID(0x20b1, 0x3021): /* Eastern El. MiniMax Tube DAC Supreme */
- case USB_ID(0x20b1, 0x3023): /* Aune X1S 32BIT/384 DSD DAC */
- case USB_ID(0x20b1, 0x302d): /* Unison Research Unico CD Due */
- case USB_ID(0x20b1, 0x307b): /* CH Precision C1 DAC */
- case USB_ID(0x20b1, 0x3086): /* Singxer F-1 converter board */
case USB_ID(0x22d9, 0x0426): /* OPPO HA-2 */
case USB_ID(0x22e1, 0xca01): /* HDTA Serenade DSD */
case USB_ID(0x249c, 0x9326): /* M2Tech Young MkIII */
@@ -1566,6 +1654,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
case 0x20b1: /* XMOS based devices */
case 0x152a: /* Thesycon devices */
case 0x25ce: /* Mytek devices */
+ case 0x2ab6: /* T+A devices */
if (fp->dsd_raw)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
break;
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c
index b0f8979ff2d2..221adf68bd0c 100644
--- a/sound/usb/usx2y/usb_stream.c
+++ b/sound/usb/usx2y/usb_stream.c
@@ -104,7 +104,12 @@ static int init_urbs(struct usb_stream_kernel *sk, unsigned use_packsize,
for (u = 0; u < USB_STREAM_NURBS; ++u) {
sk->inurb[u] = usb_alloc_urb(sk->n_o_ps, GFP_KERNEL);
+ if (!sk->inurb[u])
+ return -ENOMEM;
+
sk->outurb[u] = usb_alloc_urb(sk->n_o_ps, GFP_KERNEL);
+ if (!sk->outurb[u])
+ return -ENOMEM;
}
if (init_pipe_urbs(sk, use_packsize, sk->inurb, indata, dev, in_pipe) ||
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 2b833054e3b0..58974d094b27 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -981,18 +981,17 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint,
sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usX2Y(card)->pcm_devs);
- if ((playback_endpoint &&
- 0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
- SNDRV_DMA_TYPE_CONTINUOUS,
- snd_dma_continuous_data(GFP_KERNEL),
- 64*1024, 128*1024))) ||
- 0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
- SNDRV_DMA_TYPE_CONTINUOUS,
- snd_dma_continuous_data(GFP_KERNEL),
- 64*1024, 128*1024))) {
- snd_usX2Y_pcm_private_free(pcm);
- return err;
+ if (playback_endpoint) {
+ snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+ SNDRV_DMA_TYPE_CONTINUOUS,
+ snd_dma_continuous_data(GFP_KERNEL),
+ 64*1024, 128*1024);
}
+
+ snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+ SNDRV_DMA_TYPE_CONTINUOUS,
+ snd_dma_continuous_data(GFP_KERNEL),
+ 64*1024, 128*1024);
usX2Y(card)->pcm_devs++;
return 0;
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index 4fd9276b8e50..714cf50d4a4c 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -736,17 +736,14 @@ int usX2Y_hwdep_pcm_new(struct snd_card *card)
pcm->info_flags = 0;
sprintf(pcm->name, NAME_ALLCAPS" hwdep Audio");
- if (0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
- SNDRV_DMA_TYPE_CONTINUOUS,
- snd_dma_continuous_data(GFP_KERNEL),
- 64*1024, 128*1024)) ||
- 0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
- SNDRV_DMA_TYPE_CONTINUOUS,
- snd_dma_continuous_data(GFP_KERNEL),
- 64*1024, 128*1024))) {
- return err;
- }
-
+ snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+ SNDRV_DMA_TYPE_CONTINUOUS,
+ snd_dma_continuous_data(GFP_KERNEL),
+ 64*1024, 128*1024);
+ snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+ SNDRV_DMA_TYPE_CONTINUOUS,
+ snd_dma_continuous_data(GFP_KERNEL),
+ 64*1024, 128*1024);
return 0;
}
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c
index 00c92eb854ce..80f79ecffc71 100644
--- a/sound/x86/intel_hdmi_audio.c
+++ b/sound/x86/intel_hdmi_audio.c
@@ -1651,18 +1651,6 @@ static int had_create_jack(struct snd_intelhad *ctx,
static int __maybe_unused hdmi_lpe_audio_suspend(struct device *dev)
{
struct snd_intelhad_card *card_ctx = dev_get_drvdata(dev);
- int port;
-
- for_each_port(card_ctx, port) {
- struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port];
- struct snd_pcm_substream *substream;
-
- substream = had_substream_get(ctx);
- if (substream) {
- snd_pcm_suspend(substream);
- had_substream_put(ctx);
- }
- }
snd_power_change_state(card_ctx->card, SNDRV_CTL_POWER_D3hot);
@@ -1824,7 +1812,8 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
* try to allocate 600k buffer as default which is large enough
*/
snd_pcm_lib_preallocate_pages_for_all(pcm,
- SNDRV_DMA_TYPE_DEV_UC, NULL,
+ SNDRV_DMA_TYPE_DEV_UC,
+ card->dev,
HAD_DEFAULT_BUFFER, HAD_MAX_BUFFER);
/* create controls */