Merge tag 'asoc-v5.1-2' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie...
authorTakashi Iwai <tiwai@suse.de>
Thu, 28 Feb 2019 12:30:55 +0000 (13:30 +0100)
committerTakashi Iwai <tiwai@suse.de>
Thu, 28 Feb 2019 12:30:55 +0000 (13:30 +0100)
ASoC: More changes for v5.1

Another batch of changes for ASoC, no big core changes - it's mainly
small fixes and improvements for individual drivers.

 - A big refresh and cleanup of the Samsung drivers, fixing a number of
   issues which allow the driver to be used with a wider range of
   userspaces.
 - Fixes for the Intel drivers to make them more standard so less likely
   to get bitten by core issues.
 - New driver for Cirrus Logic CS35L26.

198 files changed:
Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.txt
Documentation/sound/hd-audio/models.rst
Documentation/sound/kernel-api/writing-an-alsa-driver.rst
arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
arch/arm64/boot/dts/nvidia/tegra194-p2972-0000.dts
arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
drivers/media/pci/solo6x10/solo6x10-g723.c
drivers/media/pci/tw686x/tw686x-audio.c
include/sound/core.h
include/sound/hda_register.h
include/sound/hda_verbs.h
include/sound/hdaudio.h
include/sound/info.h
include/sound/memalloc.h
include/sound/pcm.h
sound/ac97/bus.c
sound/aoa/core/gpio-feature.c
sound/aoa/soundbus/i2sbus/core.c
sound/arm/aaci.c
sound/arm/pxa2xx-ac97.c
sound/atmel/ac97c.c
sound/core/compress_offload.c
sound/core/info.c
sound/core/init.c
sound/core/memalloc.c
sound/core/oss/pcm_oss.c
sound/core/pcm.c
sound/core/pcm_lib.c
sound/core/pcm_local.h
sound/core/pcm_memory.c
sound/core/pcm_native.c
sound/drivers/aloop.c
sound/drivers/dummy.c
sound/drivers/opl4/opl4_proc.c
sound/drivers/pcsp/pcsp.c
sound/drivers/vx/vx_core.c
sound/firewire/Kconfig
sound/firewire/bebob/bebob.c
sound/firewire/bebob/bebob_proc.c
sound/firewire/dice/dice-proc.c
sound/firewire/dice/dice.c
sound/firewire/digi00x/digi00x-proc.c
sound/firewire/fireface/Makefile
sound/firewire/fireface/ff-midi.c
sound/firewire/fireface/ff-pcm.c
sound/firewire/fireface/ff-proc.c
sound/firewire/fireface/ff-protocol-ff400.c [deleted file]
sound/firewire/fireface/ff-protocol-ff800.c [deleted file]
sound/firewire/fireface/ff-protocol-former.c [new file with mode: 0644]
sound/firewire/fireface/ff-protocol-latter.c [new file with mode: 0644]
sound/firewire/fireface/ff-stream.c
sound/firewire/fireface/ff-transaction.c
sound/firewire/fireface/ff.c
sound/firewire/fireface/ff.h
sound/firewire/fireworks/fireworks_proc.c
sound/firewire/motu/amdtp-motu.c
sound/firewire/motu/motu-proc.c
sound/firewire/oxfw/oxfw-proc.c
sound/firewire/tascam/tascam-proc.c
sound/hda/hdac_controller.c
sound/hda/hdac_i915.c
sound/hda/hdac_stream.c
sound/i2c/other/ak4113.c
sound/i2c/other/ak4114.c
sound/i2c/other/ak4xxx-adda.c
sound/isa/ad1816a/ad1816a_lib.c
sound/isa/als100.c
sound/isa/cmi8328.c
sound/isa/cmi8330.c
sound/isa/es1688/es1688.c
sound/isa/es1688/es1688_lib.c
sound/isa/es18xx.c
sound/isa/gus/gus_irq.c
sound/isa/gus/gus_main.c
sound/isa/gus/gus_mem.c
sound/isa/gus/gus_pcm.c
sound/isa/opti9xx/miro.c
sound/isa/sb/jazz16.c
sound/isa/sb/sb16.c
sound/isa/sb/sb16_csp.c
sound/isa/sb/sb16_main.c
sound/isa/sb/sb8.c
sound/isa/sb/sb8_main.c
sound/isa/sscape.c
sound/isa/wss/wss_lib.c
sound/mips/hal2.c
sound/mips/sgio2audio.c
sound/parisc/harmony.c
sound/pci/ac97/ac97_proc.c
sound/pci/ad1889.c
sound/pci/ak4531_codec.c
sound/pci/ali5451/ali5451.c
sound/pci/als300.c
sound/pci/als4000.c
sound/pci/asihpi/asihpi.c
sound/pci/atiixp.c
sound/pci/atiixp_modem.c
sound/pci/aw2/aw2-alsa.c
sound/pci/azt3328.c
sound/pci/bt87x.c
sound/pci/ca0106/ca0106_main.c
sound/pci/ca0106/ca0106_proc.c
sound/pci/cmipci.c
sound/pci/cs4281.c
sound/pci/cs46xx/cs46xx_dsp_spos.h
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/cs46xx/dsp_spos.c
sound/pci/cs46xx/dsp_spos_scb_lib.c
sound/pci/cs5535audio/cs5535audio_pm.c
sound/pci/ctxfi/ctatc.c
sound/pci/echoaudio/echoaudio.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/emu10k1/emupcm.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/p16v.c
sound/pci/ens1370.c
sound/pci/es1938.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/hda_beep.c
sound/pci/hda/hda_beep.h
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_proc.c
sound/pci/hda/hda_tegra.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/ice1712/ews.c
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1724.c
sound/pci/ice1712/pontis.c
sound/pci/ice1712/prodigy192.c
sound/pci/ice1712/prodigy_hifi.c
sound/pci/ice1712/quartet.c
sound/pci/intel8x0.c
sound/pci/intel8x0m.c
sound/pci/korg1212/korg1212.c
sound/pci/lola/lola_proc.c
sound/pci/lx6464es/lx6464es.c
sound/pci/maestro3.c
sound/pci/mixart/mixart.c
sound/pci/nm256/nm256.c
sound/pci/oxygen/oxygen_lib.c
sound/pci/oxygen/pcm1796.h
sound/pci/oxygen/xonar_pcm179x.c
sound/pci/pcxhr/pcxhr.c
sound/pci/riptide/riptide.c
sound/pci/rme32.c
sound/pci/rme96.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/pci/rme9652/rme9652.c
sound/pci/sis7019.c
sound/pci/sonicvibes.c
sound/pci/trident/trident_main.c
sound/pci/via82xx.c
sound/pci/via82xx_modem.c
sound/pci/ymfpci/ymfpci_main.c
sound/pcmcia/pdaudiocf/pdaudiocf_core.c
sound/ppc/pmac.c
sound/ppc/snd_ps3.c
sound/ppc/tumbler.c
sound/sh/aica.c
sound/soc/amd/acp-pcm-dma.c
sound/soc/amd/raven/acp3x-pcm-dma.c
sound/soc/dwc/dwc-pcm.c
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/soc/intel/baytrail/sst-baytrail-pcm.c
sound/soc/intel/haswell/sst-haswell-pcm.c
sound/soc/intel/skylake/skl-pcm.c
sound/soc/mediatek/common/mtk-afe-platform-driver.c
sound/soc/meson/axg-fifo.c
sound/soc/sh/fsi.c
sound/soc/sh/rcar/core.c
sound/soc/sh/siu_pcm.c
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-pcm.c
sound/soc/stm/stm32_adfsdm.c
sound/soc/txx9/txx9aclc.c
sound/soc/uniphier/aio-dma.c
sound/soc/xilinx/xlnx_formatter_pcm.c
sound/soc/xtensa/xtfpga-i2s.c
sound/sparc/dbri.c
sound/spi/at73c213.c
sound/synth/emux/emux_proc.c
sound/usb/card.c
sound/usb/card.h
sound/usb/format.c
sound/usb/line6/driver.c
sound/usb/line6/pod.c
sound/usb/mixer.c
sound/usb/mixer_quirks.c
sound/usb/proc.c
sound/usb/quirks.c
sound/usb/usx2y/usbusx2yaudio.c
sound/usb/usx2y/usx2yhwdeppcm.c
sound/x86/intel_hdmi_audio.c

index 44d27456e8a4862a11e67785b459fd5ef721cc82..21cd310963b1243d974ae3ca20ba498925737fed 100644 (file)
@@ -13,6 +13,10 @@ Required properties:
   See ../reset/reset.txt for details.
 - reset-names : Must include the following entries: hda, hda2hdmi, hda2codec_2x
 
+Optional properties:
+- nvidia,model : The user-visible name of this sound complex. Since the property
+  is optional, legacy boards can use default name provided in hda driver.
+
 Example:
 
 hda@70030000 {
@@ -27,4 +31,5 @@ hda@70030000 {
                 <&tegra_car 128>, /* hda2hdmi */
                 <&tegra_car 111>; /* hda2codec_2x */
        reset-names = "hda", "hda2hdmi", "hda2codec_2x";
+       nvidia,model = "jetson-tk1-hda";
 };
index 368a07a165f5a7d4a1c5e47213b9d7dd61516be6..7d7c191102a73baf4eb1e72b01119458a2d3b53f 100644 (file)
@@ -254,10 +254,12 @@ alc274-dell-aio
     ALC274 fixups on Dell AIO machines
 alc255-dummy-lineout
     Dell Precision 3930 fixups
-alc255-dell-headset"},
+alc255-dell-headset
     Dell Precision 3630 fixups
 alc295-hp-x360
     HP Spectre X360 fixups
+alc-sense-combo
+    Headset button support for Chrome platform
 
 ALC66x/67x/892
 ==============
index b37234afdfa1cdf9f6966480e859dd501cf3fc3e..6b154dbb02cc76eb991c809af4bec52528114c84 100644 (file)
@@ -3520,14 +3520,14 @@ allocator will try to get an area as large as possible within the
 given size.
 
 The second argument (type) and the third argument (device pointer) are
-dependent on the bus. In the case of the ISA bus, pass
-:c:func:`snd_dma_isa_data()` as the third argument with
+dependent on the bus. For normal devices, pass the device pointer
+(typically identical as ``card->dev``) to the third argument with
 ``SNDRV_DMA_TYPE_DEV`` type. For the continuous buffer unrelated to the
 bus can be pre-allocated with ``SNDRV_DMA_TYPE_CONTINUOUS`` type and the
 ``snd_dma_continuous_data(GFP_KERNEL)`` device pointer, where
-``GFP_KERNEL`` is the kernel allocation flag to use. For the PCI
-scatter-gather buffers, use ``SNDRV_DMA_TYPE_DEV_SG`` with
-``snd_dma_pci_data(pci)`` (see the `Non-Contiguous Buffers`_
+``GFP_KERNEL`` is the kernel allocation flag to use. For the
+scatter-gather buffers, use ``SNDRV_DMA_TYPE_DEV_SG`` with the device
+pointer (see the `Non-Contiguous Buffers`_
 section).
 
 Once the buffer is pre-allocated, you can use the allocator in the
@@ -3924,15 +3924,12 @@ The scheme of the real suspend job is as follows.
 2. Call :c:func:`snd_power_change_state()` with
    ``SNDRV_CTL_POWER_D3hot`` to change the power status.
 
-3. Call :c:func:`snd_pcm_suspend_all()` to suspend the running
-   PCM streams.
-
-4. If AC97 codecs are used, call :c:func:`snd_ac97_suspend()` for
+3. If AC97 codecs are used, call :c:func:`snd_ac97_suspend()` for
    each codec.
 
-5. Save the register values if necessary.
+4. Save the register values if necessary.
 
-6. Stop the hardware if necessary.
+5. Stop the hardware if necessary.
 
 A typical code would be like:
 
@@ -3946,12 +3943,10 @@ A typical code would be like:
           /* (2) */
           snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
           /* (3) */
-          snd_pcm_suspend_all(chip->pcm);
-          /* (4) */
           snd_ac97_suspend(chip->ac97);
-          /* (5) */
+          /* (4) */
           snd_mychip_save_registers(chip);
-          /* (6) */
+          /* (5) */
           snd_mychip_stop_hardware(chip);
           return 0;
   }
@@ -3994,13 +3989,9 @@ A typical code would be like:
           return 0;
   }
 
-As shown in the above, it's better to save registers after suspending
-the PCM operations via :c:func:`snd_pcm_suspend_all()` or
-:c:func:`snd_pcm_suspend()`. It means that the PCM streams are
-already stopped when the register snapshot is taken. But, remember that
-you don't have to restart the PCM stream in the resume callback. It'll
-be restarted via trigger call with ``SNDRV_PCM_TRIGGER_RESUME`` when
-necessary.
+Note that, at the time this callback gets called, the PCM stream has
+been already suspended via its own PM ops calling
+:c:func:`snd_pcm_suspend_all()` internally.
 
 OK, we have all callbacks now. Let's set them up. In the initialization
 of the card, make sure that you can get the chip data from the card
index 65487eee2ce61d7aa587be9614d53f43d4dc7942..05611eff53f68356d47874374119187d995191ca 100644 (file)
@@ -52,6 +52,7 @@
        };
 
        hda@3510000 {
+               nvidia,model = "jetson-tx2-hda";
                status = "okay";
        };
 
index adf351010ff5384c98d1c864911404dba9992732..39c61673723283fe21efcc3e3bf892e28dff8d8e 100644 (file)
@@ -25,6 +25,7 @@
                };
 
                hda@3510000 {
+                       nvidia,model = "jetson-xavier-hda";
                        status = "okay";
                };
 
index a96e6ee70c2152e878c2b537b9eb1df8575611f4..6096dfb7e17a72f7729dc3a854d971ad711b3895 100644 (file)
        };
 
        hda@70030000 {
+               nvidia,model = "jetson-tx1-hda";
                status = "okay";
        };
 
index cf3f0caf9c632fe47dd5f48999031100e12cf68c..ed7af7518b52be0d08c290bfdd5495fdbc782832 100644 (file)
@@ -614,7 +614,6 @@ static int snd_dw_hdmi_suspend(struct device *dev)
        struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
 
        snd_power_change_state(dw->card, SNDRV_CTL_POWER_D3cold);
-       snd_pcm_suspend_all(dw->pcm);
 
        return 0;
 }
index 2cc05a9d57ac17e854533c1a8d68e5c6e5de1e04..a16242a9206fb6a99f474b11bb194d17e94f4451 100644 (file)
@@ -360,13 +360,11 @@ static int solo_snd_pcm_init(struct solo_dev *solo_dev)
             ss; ss = ss->next, i++)
                sprintf(ss->name, "Camera #%d Audio", i);
 
-       ret = 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_KERNEL),
                                        G723_PERIOD_BYTES * PERIODS,
                                        G723_PERIOD_BYTES * PERIODS);
-       if (ret < 0)
-               return ret;
 
        solo_dev->snd_pcm = pcm;
 
index a28329698e205a86720b519b8e92612abe9e99a3..fb0e7573b5aea3929a047214d61a1dadd02048d9 100644 (file)
@@ -301,11 +301,12 @@ static int tw686x_snd_pcm_init(struct tw686x_dev *dev)
             ss; ss = ss->next, i++)
                snprintf(ss->name, sizeof(ss->name), "vch%u audio", i);
 
-       return snd_pcm_lib_preallocate_pages_for_all(pcm,
+       snd_pcm_lib_preallocate_pages_for_all(pcm,
                                SNDRV_DMA_TYPE_DEV,
                                snd_dma_pci_data(dev->pci_dev),
                                TW686X_AUDIO_PAGE_MAX * AUDIO_DMA_SIZE_MAX,
                                TW686X_AUDIO_PAGE_MAX * AUDIO_DMA_SIZE_MAX);
+       return 0;
 }
 
 static void tw686x_audio_dma_free(struct tw686x_dev *dev,
index 36a5934cf4b10fc5083cc08f420a091bb9c24075..e923c23e05dd779bd7b40b35f4b51bc0b569b6d1 100644 (file)
@@ -120,7 +120,6 @@ struct snd_card {
        struct list_head ctl_files;     /* active control files */
 
        struct snd_info_entry *proc_root;       /* root for soundcard specific files */
-       struct snd_info_entry *proc_id; /* the card id */
        struct proc_dir_entry *proc_root_link;  /* number link to real id */
 
        struct list_head files_list;    /* all files associated to this card */
index 2ab39fb52d7a122b622a033361c647fbac4f14b0..0fd39295b426b0306e62bd7fd5e837c578f87f1c 100644 (file)
@@ -79,6 +79,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 
 /* stream register offsets from stream base */
 #define AZX_REG_SD_CTL                 0x00
+#define AZX_REG_SD_CTL_3B              0x02 /* 3rd byte of SD_CTL register */
 #define AZX_REG_SD_STS                 0x03
 #define AZX_REG_SD_LPIB                        0x04
 #define AZX_REG_SD_CBL                 0x08
@@ -165,6 +166,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define SD_INT_COMPLETE                0x04    /* completion interrupt */
 #define SD_INT_MASK            (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|\
                                 SD_INT_COMPLETE)
+#define SD_CTL_STRIPE_MASK     0x3     /* stripe control mask */
 
 /* SD_STS */
 #define SD_STS_FIFO_READY      0x20    /* FIFO ready */
index 2a8573a00ea60d4b1b5606e7504b100f53757e46..e36b77531c5c38692f99dca0f218a92cd08b6ba0 100644 (file)
@@ -66,6 +66,7 @@ enum {
 #define AC_VERB_GET_CONFIG_DEFAULT             0x0f1c
 /* f20: AFG/MFG */
 #define AC_VERB_GET_SUBSYSTEM_ID               0x0f20
+#define AC_VERB_GET_STRIPE_CONTROL             0x0f24
 #define AC_VERB_GET_CVT_CHAN_COUNT             0x0f2d
 #define AC_VERB_GET_HDMI_DIP_SIZE              0x0f2e
 #define AC_VERB_GET_HDMI_ELDD                  0x0f2f
@@ -110,6 +111,7 @@ enum {
 #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3     0x71f
 #define AC_VERB_SET_EAPD                               0x788
 #define AC_VERB_SET_CODEC_RESET                        0x7ff
+#define AC_VERB_SET_STRIPE_CONTROL             0x724
 #define AC_VERB_SET_CVT_CHAN_COUNT             0x72d
 #define AC_VERB_SET_HDMI_DIP_INDEX             0x730
 #define AC_VERB_SET_HDMI_DIP_DATA              0x731
index b4fa1c7752510b5216a92f6d663d4fc0d1da3b39..45f944d57982800cc176ed782aedbf9b1d30f1fe 100644 (file)
@@ -539,6 +539,9 @@ void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start,
                          unsigned int streams);
 void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev,
                                      unsigned int streams);
+int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
+                               struct snd_pcm_substream *substream);
+
 /*
  * macros for easy use
  */
index becdf66d2825e9c5a65ff5cbcf63868bf29eac9d..97fdda41e0763ac57f5aa4e9cc1300d77c71702b 100644 (file)
@@ -82,7 +82,6 @@ struct snd_info_entry {
                struct snd_info_entry_ops *ops;
        } c;
        struct snd_info_entry *parent;
-       struct snd_card *card;
        struct module *module;
        void *private_data;
        void (*private_free)(struct snd_info_entry *entry);
@@ -160,6 +159,13 @@ static inline void snd_info_set_text_ops(struct snd_info_entry *entry,
        entry->c.text.read = read;
 }
 
+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));
+
 int snd_info_check_reserved_words(const char *str);
 
 #else
@@ -189,10 +195,38 @@ static inline int snd_card_proc_new(struct snd_card *card, const char *name,
 static inline void snd_info_set_text_ops(struct snd_info_entry *entry __attribute__((unused)),
                                         void *private_data,
                                         void (*read)(struct snd_info_entry *, struct snd_info_buffer *)) {}
+static inline 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))
+{
+       return 0;
+}
 static inline int snd_info_check_reserved_words(const char *str) { return 1; }
 
 #endif
 
+/**
+ * snd_card_ro_proc_new - Create a read-only 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
+ *
+ * This proc file entry will be registered via snd_card_register() call, and
+ * it will be removed automatically at the card removal, too.
+ */
+static inline int
+snd_card_ro_proc_new(struct snd_card *card, const char *name,
+                    void *private_data,
+                    void (*read)(struct snd_info_entry *,
+                                 struct snd_info_buffer *))
+{
+       return snd_card_rw_proc_new(card, name, private_data, read, NULL);
+}
+
 /*
  * OSS info part
  */
index af3fa577fa066ae3aa0ed712e12d7c45eeac0b50..1ac0dd82a9163847dc5280aa55efbead4f671bdb 100644 (file)
@@ -37,7 +37,6 @@ struct snd_dma_device {
 };
 
 #define snd_dma_pci_data(pci)  (&(pci)->dev)
-#define snd_dma_isa_data()     NULL
 #define snd_dma_continuous_data(x)     ((struct device *)(__force unsigned long)(x))
 
 
index d6bd3caf68787490074cd859f980dcac057abf28..465d7d033c4c61446bb288bc76f844304bb285d3 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/mm.h>
 #include <linux/bitops.h>
 #include <linux/pm_qos.h>
+#include <linux/refcount.h>
 
 #define snd_pcm_substream_chip(substream) ((substream)->private_data)
 #define snd_pcm_chip(pcm) ((pcm)->private_data)
@@ -439,7 +440,7 @@ struct snd_pcm_group {              /* keep linked substreams */
        spinlock_t lock;
        struct mutex mutex;
        struct list_head substreams;
-       int count;
+       refcount_t refs;
 };
 
 struct pid;
@@ -470,7 +471,6 @@ struct snd_pcm_substream {
        struct snd_pcm_group self_group;        /* fake group for non linked substream (with substream lock inside) */
        struct snd_pcm_group *group;            /* pointer to current group */
        /* -- assigned files -- */
-       void *file;
        int ref_count;
        atomic_t mmap_count;
        unsigned int f_flags;
@@ -482,15 +482,6 @@ struct snd_pcm_substream {
 #endif
 #ifdef CONFIG_SND_VERBOSE_PROCFS
        struct snd_info_entry *proc_root;
-       struct snd_info_entry *proc_info_entry;
-       struct snd_info_entry *proc_hw_params_entry;
-       struct snd_info_entry *proc_sw_params_entry;
-       struct snd_info_entry *proc_status_entry;
-       struct snd_info_entry *proc_prealloc_entry;
-       struct snd_info_entry *proc_prealloc_max_entry;
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
-       struct snd_info_entry *proc_xrun_injection_entry;
-#endif
 #endif /* CONFIG_SND_VERBOSE_PROCFS */
        /* misc flags */
        unsigned int hw_opened: 1;
@@ -512,10 +503,8 @@ struct snd_pcm_str {
 #endif
 #ifdef CONFIG_SND_VERBOSE_PROCFS
        struct snd_info_entry *proc_root;
-       struct snd_info_entry *proc_info_entry;
 #ifdef CONFIG_SND_PCM_XRUN_DEBUG
        unsigned int xrun_debug;        /* 0 = disabled, 1 = verbose, 2 = stacktrace */
-       struct snd_info_entry *proc_xrun_debug_entry;
 #endif
 #endif
        struct snd_kcontrol *chmap_kctl; /* channel-mapping controls */
@@ -538,6 +527,7 @@ struct snd_pcm {
        void (*private_free) (struct snd_pcm *pcm);
        bool internal; /* pcm is for internal use only */
        bool nonatomic; /* whole PCM operations are in non-atomic context */
+       bool no_device_suspend; /* don't invoke device PM suspend */
 #if IS_ENABLED(CONFIG_SND_PCM_OSS)
        struct snd_pcm_oss oss;
 #endif
@@ -581,13 +571,8 @@ int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t status);
 int snd_pcm_drain_done(struct snd_pcm_substream *substream);
 int snd_pcm_stop_xrun(struct snd_pcm_substream *substream);
 #ifdef CONFIG_PM
-int snd_pcm_suspend(struct snd_pcm_substream *substream);
 int snd_pcm_suspend_all(struct snd_pcm *pcm);
 #else
-static inline int snd_pcm_suspend(struct snd_pcm_substream *substream)
-{
-       return 0;
-}
 static inline int snd_pcm_suspend_all(struct snd_pcm *pcm)
 {
        return 0;
@@ -1200,12 +1185,12 @@ static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime,
  *  Memory
  */
 
-int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream);
-int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm);
-int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
+void snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream);
+void snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm);
+void snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
                                  int type, struct device *data,
                                  size_t size, size_t max);
-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);
 int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size);
index 9f0c480489ef04384445b35f8786c020dfc9d7fa..9cbf6927abe96a735f0e188cfd735710c1d989ad 100644 (file)
@@ -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;
index 65557421fe0bad1c02d7975c545828d7e5bb4ec4..c3ff721e46607183f21afe6526db6cbcf0cd3956 100644 (file)
@@ -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;
index 40ebde2e1ab1bb2eee05a5c902fe18ea051f37df..904659d149888e00ef6f2e6278b202f879f7cee4 100644 (file)
@@ -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;
index 0114ffed56dd4d2655d89e950774869dc2780d05..a2d4b41096e019583c920c023678d782fe4db5d3 100644 (file)
@@ -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;
index 1f72672262d06406d21ea4fc00c400fac24fd94b..68fe5bb11eea69f68b5609fcb293615644fd64ae 100644 (file)
@@ -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);
index 380025887aef61e2aa87a7845d12a7d1ba9b85ae..33c87a0547a96e9dd034287067ab4f748fe818bc 100644 (file)
@@ -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;
index f7d2b373da0aaebd869b06773c24b7994c0cb472..a1a6fd75cfe50003b7ee2cf8af80cdf83d042ef3 100644 (file)
@@ -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;
index fe502bc5e6d20e8d800739bbca65a16b6085f155..96a074019c33c28b5587d7d833110eced98669c0 100644 (file)
@@ -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);
+
 /*
 
  */
index 4849c611c0fe3a94d98aa3eef778f3da5538575f..0c4dc40376a709ff2e8aabd2f9ac4d25660389be 100644 (file)
@@ -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);
index 59a4adc286ed77bb647788706a6ebd9323a1b640..eb974235c92bdfba19d706735a88a9cf95897664 100644 (file)
@@ -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;
index 467039b342b511c7c4fb95f0d7c316f7715d7c70..d5b0d7ba83c4204db42df492a5e35f54a67c470c 100644 (file)
@@ -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);
        }
        
index 01b9d62eef14db9f22bd1fb67bcaf5456f791d38..7b63aee124af3e3394c3f9646747f61f97cb141c 100644 (file)
@@ -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;
index 6c0b30391ba99ced198ee7f7c943083899c4b93d..345ab1ab2cac49f2ee639858de03a33a684a73b6 100644 (file)
@@ -2176,6 +2176,10 @@ 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 &&
            size >= runtime->start_threshold) {
@@ -2214,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,
index c515612969a474485b2a843591a15a42605e8a0a..0b4b5dfaec181924423eff390866ab95ec8044c3 100644 (file)
@@ -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 */
index 4b5356a1031599afb2158f4f703dbdc1998d68cb..ed73be80bd297157009b5c86656447f7dcedcf24 100644 (file)
@@ -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);
 
index 818dff1de545fad25669adf1144cbd49e5934067..f731f904e8ccb4e9671523e3b68e7825c779d8d8 100644 (file)
@@ -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;
index 1e34e6381baad1f8aec5789418e3aef6207176bd..8c3fbe1276be141c79af15acba98287ac8ebf46b 100644 (file)
@@ -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;
 }
        
index 9af154db530a803943c9dc420d06e5a180d0789f..2672c2e13334dd99e959bf74fce5dd0a9692c3ae 100644 (file)
@@ -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;
 }
        
index 16b24091d79932bc6c21093a6259790dc3ef5e0e..f1b839a0e7b7d6bb1c75880a68b80afe403e45fc 100644 (file)
@@ -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;
index 0dd3f46eb03e804da8f8af663d3e270a96dc6aa1..d83ad3820f02a29b81d56afe559bb35bf89ef8d2 100644 (file)
@@ -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;
 }
 
index 04368dd59a4c8dd80503bae67ca3acfa12cc5a0d..543945643a76604faddbb81cb18ef2c469271271 100644 (file)
@@ -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;
 }
index 052e005902590c41247bff33f415b430e0c8744d..b9e96d0b3a0a232f20661eaf04bf533351741d56 100644 (file)
@@ -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
index d91874275d2c371f078f1601c2c2627e875627f3..5b46e8dcc2dd334151b67de70a707df2f587b269 100644 (file)
@@ -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),
index 8096891af9137a509e415cea4242a639a21c329b..05e2a1c6326cb597af0d3061f47db5c019a1246c 100644 (file)
@@ -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);
index bb870fc73f99f08ac34d4a921c88c8f26a63b4b7..9b1d509c6320c528f76520432409ad7f300b4be3 100644 (file)
@@ -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);
index ed50b222d36ea0d4dd7ddd4440ca8f62ce0e7d8a..eee184b05d937f093a641137bce9ad2b1f6eec69 100644 (file)
@@ -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,
index 6996d5a6ff5f7ce61cb97a803a18313cd46bc3f9..d22e8675b10fa02012b5a33689d1866615fb880e 100644 (file)
@@ -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);
 }
index 79a7d6d99d7287b0735a0aaf1d690429ae7c2cad..d64f4e2a10966eb7310ba40bd436ea5497e2bf44 100644 (file)
@@ -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
index 6a49611ee46250a0534c4cd1455dc9a15972fc18..5b44e1c4569a334357ef734ce3d22bdfdf16fc6b 100644 (file)
@@ -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);
index d0bc96b20a65d45e10b12010d220745b80c3bc7b..5adf04b95c04cf27091edbe200ac85781f314dca 100644 (file)
@@ -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;
 
index a0c550dabe9ace95a4186f71cbad32eaf5e84c57..b886b541c94baaa5e16e8515990510e0662f9bae 100644 (file)
 
 #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 (file)
index 2280fab..0000000
+++ /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 (file)
index 2acbf60..0000000
+++ /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 (file)
index 0000000..8d1c2c6
--- /dev/null
@@ -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 (file)
index 0000000..c8236ff
--- /dev/null
@@ -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,
+};
index a490e45537212d75a48c82b24bd6dbd9815511b9..a8a90f1ae09e218ac13a976dd259b66342a01ce3 100644 (file)
@@ -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;
        }
index 5f4ddfd55403a35ae4cb2f29f82ff23ee585292f..0d6ad19363b80c57a2369a492d362f9b2f2b68ae 100644 (file)
@@ -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;
index 36575f4159d13cc0be238ba25704521fb718e711..a9611157f4c8533baeda5ea674160af84e502db2 100644 (file)
@@ -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);
index 7dfc7745a9141f2780db3d3ba432ad2c3d2b5b11..ed8fea0ff5e182ed109ba65ec9c536cecbffd445 100644 (file)
 #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);
 
index 779ecec5af62abc8b4bad53bbecb1b07049e01d5..9fa5c34a95726ad5850bdc44c4f42459ba2e3ad5 100644 (file)
@@ -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);
index f0555a24d90ed1e6df27ea65b7eec57721c4751a..6c9b743ea74bb7d00683abbfdafd31a8498933eb 100644 (file)
@@ -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++;
                }
index ab6830a6d242f00048d3451549bb50b81f9e6fad..94327853620a3d357768d739d596ba16302babbd 100644 (file)
@@ -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);
index 27dac071bc7394969c671c9406b93f917c498766..644107e3782e854aad3018b35d812b8ee0ba08c4 100644 (file)
@@ -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);
 }
index fee3bf32a0daa2747b367f67fed759de3fa18507..8bc8d277394a332d8c32fc1a8a488b5a98f784ce 100644 (file)
@@ -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);
 }
index 74244d8e2909090cfb3bfc54c57c9591332decdd..b2e9454f5816a042c8218e0d76b770277e6eeedb 100644 (file)
@@ -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 */
index 617ff1aa818f991a01091a9e03aa7952978c0b92..27eb0270a711f4db55511d6924db13656bc67276 100644 (file)
@@ -144,9 +144,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");
index eee422390d8e260fae1e784262598133254f023c..f5dd288d1a7a39d9454bd1cf94a8e744601c07c1 100644 (file)
 #include <sound/hda_register.h>
 #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
@@ -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,13 @@ 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 */
+       stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream);
+       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 +114,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);
index 4099e6062d3c4992970bbb740c04e7d931b76516..573599d0378d28036f1648527e475bf2c53fd2ae 100644 (file)
@@ -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,
index 7fb1aeb46915fa435c7d4934e22bca87f6a07cb3..76afb975782d5c7f0adedb59955ecb9d9c13917a 100644 (file)
@@ -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,
index 7f2761a2e7c8c6f2ff6f62e5d2f59ac6aac785c3..62a6c5fa96b5d1922ee2e9fc589af4a36606547e 100644 (file)
@@ -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)
index fba6d22f7f4bdfa3591a47c7ad364a293c038549..94b381a78e9e5a5850419476ae35007c2839fc0a 100644 (file)
@@ -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;
index f63142ec287ebb094b85189cd398f1d9d66ed31b..571108021e9dea82cc68bfd2114ac9a77667050d 100644 (file)
@@ -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;
 }
index de6ef1b1cf0eb0718ed0420cf2599451646f5a3b..6179775162019e68a354f67b39d3a4da77644bd9 100644 (file)
@@ -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;
index 6b8c46942efb4b660b508c55ffe93d0d1bd76e0b..1868b73aa49cdbdc95d0a1d8691ee9db0e9d27c7 100644 (file)
@@ -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;
index 3dfe7e592c251968739f2df86cf0475530674da6..87527627e059789300c7a0df6bc2c9283ffc927b 100644 (file)
@@ -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;
 }
 
index 50cdce0e89468610349b853f62247795a075c98d..1d9556c045e9ba46f2ad8861c67ebf7e042dcc7d 100644 (file)
@@ -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;
 }
index 0d103d6f805e3282d4c4be73d8df8ee99801fd63..07abc7f7840c22a6821f222447b1b63eee433b7d 100644 (file)
@@ -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);
index 2055aff71b50ff4a50613a66905e007620aa876f..0ca6c38e2ed97fae71af37c9fa4963aeff52c3ce 100644 (file)
@@ -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
index 3b8a0c880db50da15879e43f510360285e9b99ee..33c8b66d5c8ad3c0ce5fa8cc563a45d93287ba82 100644 (file)
@@ -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);
+       }
 }
 
 /*
index af888a022fc0807a8011a3b28f1738c6f07723de..4ac76f46dd76259629b9ea0e9e0ea1e0c02f24c5 100644 (file)
@@ -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;
 }
index 131b28997e1d1e1c097122770e1562d8cb13c7a9..b9efc6dff45dcd68657f3e89efad3f446e5a8c36 100644 (file)
@@ -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);
index c6136c6b021474dabdd30b023fd9fb8de0d042c9..997cdfd7b1eaab6914b43c97eb42b885b16de883 100644 (file)
@@ -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);
 }
 
 /*
index bfa0055e1fd6677dc2395f8b45918454ee6b2619..7a313ff589c781578a8ef0920979f66cc73f6e4a 100644 (file)
@@ -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;
 }
index 8f9ebeb998f6df3416917124e6effc706416eccf..3844d4c02f49a917101dd283919e4b369a8e39b6 100644 (file)
@@ -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;
 }
index bf3db0d2ea12bfcceef9991eaa929e2d01a8e12e..a09ad57b83137b2b46ba2b7c3524de4b7a03b1c6 100644 (file)
@@ -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;
 }
 
index 37e6ce7b0b13a284c3a91d54078363faf6cf687b..473ec74ae48ca359656d301884f739400734f9a4 100644 (file)
@@ -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;
 }
index d77dcba276b544b750c452b622981c6c7a0ff585..aa2a83eb81a988a5e5947d9edce8afae4c91cf6f 100644 (file)
@@ -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;
 }
index 8288fae90085c8c4d36f793a5fb8791ca43076f4..97645a732a7104cba67844568a9767869299bd7d 100644 (file)
@@ -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;
index 733adee5afbf94915b2460a82723e8cf9a1dcf19..8181db4db019d06a2539906482e9d9da1959d4e1 100644 (file)
@@ -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);
index 3a5008837576030685f0018f0aafe71ba8fb8697..0dfb8065b4034fe5dbd1b10a30256fab28807c2f 100644 (file)
@@ -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;
index a4ed54aeaf1de60ccb9f9b3c4ffb179d6de73277..d63e1565b62bf2349b30534951cc9697b6379046 100644 (file)
@@ -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);
 }
 
index 3ec9391a4736d670eb8404d995c40d1f95b068c6..53a4ee01c522c091072d11e5a8969cc418b980df 100644 (file)
@@ -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");
index f36e7006e00cab443d3072a5feb1146246e29022..a4264b8943f05791e72d44b03a7e0a9c775a62ff 100644 (file)
@@ -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);
index e120a11c69e87866a0f19db45834cc73f680b22c..20516b6907b5477fa60e12658aafe26a3a1e44cb 100644 (file)
@@ -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;
 }
 
index d9c54c08e2dbde1e46421dd42f5647f57e329590..fef07ae648e6bde9b781f5e977099a6a6d4d6162 100644 (file)
@@ -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[] = {
index 2fb1fbba3e5ec7066d7ec7bd17b6152fcef3fc88..11e902cac71b4eeee6d2890be7f6d965c127153f 100644 (file)
@@ -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);
 }
index 9f569379b77ed40f72247dc80bb8d81327ccb285..f7fbe05836b378f486baa572c447fa099838e9bc 100644 (file)
@@ -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)
index eaa2d853d9223cdbb5f288002b28c291501dbe93..516b3d9cbfdfd9eadd5c8b6e2303ca5298af8070 100644 (file)
@@ -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;
 }
index 26b097edec8c90f55686dea0001925a257dfe333..45fa38382e79e9b00e2073925745722501229b72 100644 (file)
@@ -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;
 }
index aad74e80979728db913a25628d7663d1966981c3..32b2f9802479dc0e653a169bdb67ef611ab7c506 100644 (file)
@@ -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);
 }
 
 /*------------------------------------------------------------
index 1a41f8c802436c92dbe91e4a2993ea33913367b0..169763c88f5e2b47d40a0a9895e948a7be871336 100644 (file)
@@ -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);
 }
 
 
index dc1de860cedf287d0ea991b9a181adeb9cebafa1..cece66bb3644e04af57918fd52b0c4b0878e1ef3 100644 (file)
@@ -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);
 }
 
 
index 9a49e4243a9c0b3c3cc0f23fbbf8a202243c80ad..b07c5fc1da56bc4228b29a872cea03a332ccf3a9 100644 (file)
@@ -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));
index fc18c29a817302256da1dda0aa7d8feeaf2c2104..90348817f0969f65ff7037f7ea532fea9cf66432 100644 (file)
@@ -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,
index ba971042f87162ef945f7858ef299253f82f1e9b..0adcba10c067c1fa0c0f6363080ec43363a0d4e1 100644 (file)
@@ -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,
index cd27b5536654431643a108dd04887f1f76696a65..11ef0d6364054344021c984c1eb2df9aaf719d5b 100644 (file)
@@ -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);
index a2c85cc37972306e60adb71abe0e53590c7cad1b..f5b8934db735acfdf7f8a98684e46bd60c4eae66 100644 (file)
@@ -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;
 }
index 452cc79b44af3f1dbd77efcf07e92099f770ea70..701be04aed538033512e9c5cb66190c368dd6d69 100644 (file)
@@ -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]);
index ec4247638fa14a6748de8c949cd553846bada13d..15bbf9564c82de285c4cb85008ab0575a163b139 100644 (file)
@@ -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);
 
index 8008c59288a6869efca9a2a7c5f049ae9256d5f7..a02e1e19c021006bf72cdba83f903cdcb9126e4f 100644 (file)
@@ -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;
index 750eec437a795757d109e8ced727f2df36910777..a77d4cc44028a9f0c5d42c67c2e2ed2899b87051 100644 (file)
@@ -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);
 
index 5fc497c6d7384ec4886e56446439f1efab16aff7..c28e58602679c8372ec4f9c4f1536096f960a0ad 100644 (file)
@@ -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;
index 8d0a3d357345776658610abb7c314018a38a5b10..1d9d610262ded6b0558dc0c8457d857928079375 100644 (file)
@@ -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;
index 82bd10b68a77826caeef5a0026c09a354a3808ec..446ef1f1b45a0116d0a215c8813ec76dea98fd73 100644 (file)
@@ -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];
index 2ada8444abd99ba4d5d4ab14a59285eed87b61fb..e622613ea94728669b6ebd7c4a791cf4df28f2b8 100644 (file)
@@ -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);
index 907cf1a467128bf44256da495d1d9e76d2f11498..ea876b0b02b9f0d8400a7ee08291ff283999dbc6 100644 (file)
@@ -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)
index d3203df50a1a5cbc0c2c05beb4591282db80b534..3c41a0edcfb07105b861dbc7967874086c1090cd 100644 (file)
@@ -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);
index 611589cbdad65d2ebf44ecaaaf6ea5c6c990a8a3..576c7bd03a1a9e149295b450764627a7b03d22cd 100644 (file)
@@ -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;
 }
 
index 30b3472d0b75b4f82a227535ab5ac6ff6b6747b6..f6b4cb9ac75c2cbc17215b6c498f2a0ddcca11b3 100644 (file)
@@ -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;
 }
index b5700803179211575cb57eff5dee71b7cf2f4fd2..a3d9f06e8e6ae0d4fdd765e325b27a40b6042cf8 100644 (file)
@@ -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;
 }
index 4948b95f66653320e86c4a9d8abe29ce48ec7085..672017cac4c7950e77896044110e6f3ca922c811 100644 (file)
@@ -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);
index 727eb3da1fda1efac90db415342af678854316a2..1cfff35e370ea52440399cc408280b3526698dc3 100644 (file)
@@ -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
index 9d248eb2e26cd7ecb9faca4eefdcd74561121b5f..84d07bce581cb796e7da0955e5c13ec3fc129b63 100644 (file)
@@ -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++)
index 0b1845ca6005a187e6a567e5beda7582f44bca1a..9dcb698fc8c7124e166ddc74f1449677c78de107 100644 (file)
@@ -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;
index e3fb9c61017c6535e3d8fb4cb4f9694bce2e2bb1..1317f3183eb1b598a9a23194cf6da2c967da4051 100644 (file)
@@ -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);
        }
index 066b5b59c4d7cc50c7c50de2a2f4d20cc07cf166..b7d9160ed868873eba09797c60a2cb6147b80fdb 100644 (file)
@@ -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);
index f1457c6b39695bd314b07e0a605102fcec1e4db2..a25358a4807abfbc581e352b8ce63811da4f172b 100644 (file)
@@ -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
index 9f8d59e7e89f4625afab833adf3e0f31fe6d1420..5f2005098a60bed87fd16248c295aaff66b1c67d 100644 (file)
@@ -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)
 };
index a657404196502ec4a5424981369f33842fcd9579..853842987fa1c8f93f76f8a1faf396a899de1e38 100644 (file)
@@ -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);
 }
 
index 97a176d817a0cbd7feb49283f24415f1e9196b27..dbd8da5685cb5bb8ad18c4e366795ef0fa8c73d4 100644 (file)
@@ -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>
@@ -232,40 +233,72 @@ static void hda_tegra_disable_clocks(struct hda_tegra *data)
 static int 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 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;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM
+static int 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 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 */
+#endif /* CONFIG_PM */
 
 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 +336,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 +370,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 +380,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 +440,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 +514,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 +534,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 +565,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 +587,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)
index 46f88dc7b7e8fb1e0b215eae8fe1c2e7e4a5cd31..73d7042ff8841b9c68216be084905be0d91ee660 100644 (file)
@@ -1865,7 +1865,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 +1909,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) {
index 1ffa36e987b40d4dc65c5f12c23c8ca109f626b2..c8413d44973ca38e62e0d008dcc34b938f9553ec 100644 (file)
@@ -118,6 +118,7 @@ struct alc_spec {
        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;
@@ -476,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
  */
@@ -486,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 */
@@ -814,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)
@@ -2950,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[] = {
@@ -3053,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);
 }
 
@@ -3166,15 +3176,16 @@ 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);
 }
 
@@ -3240,14 +3251,15 @@ 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)
@@ -3334,7 +3346,7 @@ 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)
@@ -3388,14 +3400,15 @@ 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)
@@ -3412,8 +3425,9 @@ static void alc294_hp_init(struct hda_codec *codec)
 
        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, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
        alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
@@ -3433,7 +3447,9 @@ static void alc294_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
-       if (!spec->done_hp_init) {
+       /* 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;
        }
@@ -5007,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;
        }
 }
 
@@ -6677,6 +6689,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),
@@ -6771,7 +6784,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),
@@ -7388,6 +7400,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x14, 0x90170110},
                {0x1b, 0x90a70130},
                {0x21, 0x04211020}),
+       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},
index b8af747ecb43c63a2dc991039ece1e13b54ba32a..7646c93e82686ff312cb3adf024dc401d7b44106 100644 (file)
@@ -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);
index f1fe497c2f9df79be49ac64c3faec849d8c50cfa..fa7d90ee6e2d0d4fe070dd74f249f948522b002b 100644 (file)
@@ -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);
index 057c2f394ea7223eed508cf2e1d08cfcb8e647eb..a7d640ee4a170a611a8ce2c24fe1b67d8b83d0f9 100644 (file)
@@ -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);
index 93b8cfc6636fc804cc4a395256c22d8dfedcf0f2..f499f1e8d0c9270c0d69562d833df2d3214ada9d 100644 (file)
@@ -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);
 }
 
 
index 3919aed39ca03ab3005e0bfec8ffd2e65f20a147..d243309029d34159e0825af083943bbb03be8f8c 100644 (file)
@@ -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);
 }
 
 
index c97b5528e4b80b421d3cb322a0dbdc883c0bc908..72f252c936e578748f2dcef45157b21a0c1b1c8a 100644 (file)
@@ -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)
index 5bc836241c977feb517e7c8d1e049a62271a5470..8ad964ee0b65fe88afb808c31f06a955baa8d77a 100644 (file)
@@ -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,
index ffddcdfe0c6688efa4a027cc702cea82aa8876c6..2784bf48cf5a2e0d69c2020785323cf1f07e993e 100644 (file)
@@ -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)
index c84629190cbaf72fecb4769b5fd596a25fce1fbc..43c654e154529b7e9752a05ea7252eae22370394 100644 (file)
@@ -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)
index 4e189a93f475ee268673264fd306483662309b5f..fe4aba8a08ea7f9f57e680fbc94de56cc5bf582f 100644 (file)
@@ -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
index 904e3c4f4dfec25020276dd45577bb3fbebce4dc..1603f9c81897bcb03a462cf93ca31aac6d77edf9 100644 (file)
@@ -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);
 }
index 54f6252faca684b23ef91617318c8ae11e3de04e..ae23a2dfbdea36fca8c30102a571ba2c9f11f5c5 100644 (file)
@@ -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);
 }
 
 
index 62962178a9d72bee14767b00e5104ebaec0b127f..1a9468c14aaf6dc0d39f5338d582b9ac8d8c9845 100644 (file)
@@ -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.. */
index 9cd297a42f24dfc258634583d395a8a7950a7a2b..92f616df3863c257ca0e7c9dc45fe8e642ae7fa1 100644 (file)
@@ -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;
index b97f4ea6b56c810948fc39ca0845eec0a060ca87..85e46ff44ac359b0ebf96ee090e890ef91a1a1cf 100644 (file)
@@ -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;
index b4ef5804212db5b6580afbe002b446f2ac0d6cd7..3ae9dd4b39e861d635e87a53802153d5d67dbaa1 100644 (file)
@@ -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);
 
index 34d07dd2d22e506562f28587f5c17791b93ab2ac..d5dcb09e44cd650fa18d60f4a61c8fcbb8e48ca6 100644 (file)
@@ -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
index 24109d37ca09783e09b243044506c852d4cee94d..a1c6b98b191e5631c6042d87978f6de61bce1357 100644 (file)
@@ -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;
 }
index e57da403623166a6c4c7a27c566a1fa2660a6599..4ab7efc6e9f733f36305db55bb4d755d1241373d 100644 (file)
@@ -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 */
 
index 23017e3bc76cc4c7abde2d1481d82e0d703c75f1..8d1a56a9bcfd52d37b21c84b5b95feaadadf5ac1 100644 (file)
@@ -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)
index 3ac8c71d567c8758070cb3d8f8734335ad75180b..c6bcc07157166a874642a6e494b7b22940b2d87b 100644 (file)
@@ -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);
 }
 
 /*
index dcfa4d7a73e2bcb86e5e67fb495abe8dd26cdab6..42c6b5e090729cbe50c0593a328b5216d2fa4011 100644 (file)
@@ -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)
index ba99ff0e93e0307aebc79d7dd2e59fb2d7a3b5fb..29bef48a3af3cf8574af306c78d2fd89e01e4227 100644 (file)
@@ -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)
index 679ad0415e3b30461b53ce08e22dfd48b0f4a27d..1209cf0b05e00a677b66694e57c770a68d1b973b 100644 (file)
@@ -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;
 }
 
index edd765e2237707ea468455723d542eb74e97bf0f..5228b982da5a80e3657426315c0190996f7df66d 100644 (file)
@@ -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)
index 964acf302479ae45159fd930e540dca231ff7d98..6b27980d77a8d6d657a3d07f3b9f3a74aa0e58fc 100644 (file)
@@ -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)
index 7218f38b59dbb999fc0f3034f086a2285edd26b6..71d5ad3cffd610840a02a737cd4b56dd2510f1a8 100644 (file)
@@ -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);
 }
 
 /*
index 5523e193d556185837371378507150cfa95966ab..0ff32d3f5d3b01212f6e05a86ace0e507cac66ee 100644 (file)
@@ -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;
index c488c5afa19591410d4c872bd3decf531f0c4555..dee1c487d6bad2547c8cc38442c7cef2971766d5 100644 (file)
@@ -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);
index b13c8688cc8d98b947910a6a86653fc5b8b0d1ab..7e0bebce7b772270ca0dda702d73145da000430f 100644 (file)
@@ -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);
index a4926fb03991fb216706697e4523662eefaa9744..4d48877f211f218aed59df25b914f76e93f92f09 100644 (file)
@@ -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]);
index d724ab0653cfcd9eee87d87299653f860583bf3c..910478275fd92c1cd64144e9bec09370847c14d0 100644 (file)
@@ -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);
index d692e4070167bff00d714cd93c8a8a9d366cd692..6d420bd3ae17d3c2ac52a3f3d195ad435146d940 100644 (file)
@@ -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);
index abe031c9d592c53ad7a27edd8e2267e5b3b86ac1..521236efcc4d24e8654695eb1129990fd3708d2a 100644 (file)
@@ -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
index 6d7ffffcce95b6a7b97e1ca046eefb2f30309841..78e5798ae96715555b7546f2ec83ff80429dead4 100644 (file)
@@ -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;
                }
        }
index 2b26311405a422206e869ce186bd17255a847d0a..e7fef3fce44a7467dfebc8efb355373f3f0cba8f 100644 (file)
@@ -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 */
index f4011bebc7ec0fec945464ad62f9986b76256e87..2391c7f1dd2dbcf2c69feddd8780041f02dd7370 100644 (file)
@@ -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)
index 3d58338fa3cf79b3d9c28351cfd9411167fe51a5..1a2e15ff145648abb2b914b9c0625875da1e2424 100644 (file)
@@ -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)
index 2cc9632024fc39575a05b18d3385b449546c0cdb..a9ae91c4597f254794cc1ae582a236b0708941c8 100644 (file)
@@ -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)
index b0873fea23ab4e0a9c28e594b1675ba57d780296..08cea5b5cda9fa9f6f617213c1fba5beef4bd489 100644 (file)
@@ -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)
index 498fb5346f1a81cfd63a0cdfdc1e4b9ab32ed3b7..5373605de0af7e5afd2009f220c5aab2d2cf75ff 100644 (file)
@@ -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[] = {
index 2debcc2ed99a1ffb4bd02d0588869659f216d02b..e023c4c3e5a941d6bc0427881d5e2881fc70e1b8 100644 (file)
@@ -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 \
index a4284778f117d6480737062b400941c90091c1b2..1ae83f4ccc3615bfa42e28d08d43f27870526ded 100644 (file)
@@ -1289,7 +1289,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 ||
@@ -1298,17 +1297,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)
index 697aa50aff9a7fc6b78ab809a40b721bd5ae0f3f..3ce527ce30ce0610ee107a37a0543aa14dce7fb8 100644 (file)
@@ -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);
 
index 0e4f65e654c4be38130a0e81add85142f06e9d6d..75e5e480fda285dd0103c461330b3a2c1dcdf945 100644 (file)
@@ -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);
 
index db929b00ae5e15f2b4e46cf40a2fe759e47fef6b..3447dbdba1f1798822988417c3e63efa57b90e6d 100644 (file)
@@ -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;
 }
 
 /*
index 9834474684b1babedccd1c10256e3535bf109087..022996d2db1301d16619ef8ead029a19fce1b75b 100644 (file)
@@ -1573,7 +1573,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
@@ -1586,12 +1585,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;
index e263757e4a69153695ce6366769007339461b3b5..78c3145b4109ff3ecd4bb93a9430c636c1b7d9de 100644 (file)
@@ -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)
index f1ab6285a085104b4c52505b64a314fd1df403b6..748f5f641002e91f0ab9e8246734b84a4af72083 100644 (file)
@@ -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;
index a5b40e82dea4ac2bce93fe7dba18f799adc20d04..0d5ec68a1e50869e00ea6abb13b229c79b903329 100644 (file)
@@ -3159,6 +3159,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,
index 706ff005234f34f04bb586d076503855e84d8b08..47901983a6ff88706dd847376a42d5aeb2c3a4c6 100644 (file)
@@ -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)
index 8d31fe628e2f5fdc9a18fc2b4e6ba8dcde316c4c..089bd751860643a432fee7525e15285058ede106 100644 (file)
@@ -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++) {
index 4ec6b65bfb4498facd55d168f13e1daa7e029fa8..fa001d3c1a88705e729a2db401583067c52cd3fd 100644 (file)
@@ -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)
index 97177d35652e482f94bb352dd73c350e426e8382..dc8721f4f56bf4620c25013bc8e7276cda9a6217 100644 (file)
@@ -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 = {
index 5035609166202da0fcdc6b9d383b95eba79f14be..2f20a02c8d4674cda4ae9c849cc75bcc9e12c28d 100644 (file)
@@ -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 = {
index 9e71d7cda99928d7d5511546d504baa2fc8fc593..2b8ef5fe668818a7eca24c4daa9d98e91fd0276e 100644 (file)
@@ -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
 }
 
index 1ef52edeb5384cea2daa4d701b660a28fc2de6d2..8707e0108471f51f886e93cb5dbd93789b57d94e 100644 (file)
@@ -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:
index a82b4053bee855be16ed74e2b1f6bc3fc548ac04..c14781ac794179a66e09835e30c90d8c04856f43 100644 (file)
@@ -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)
index 746a72e23cf9f704e0acaf50a407c56f9f96f84b..719e1003455372e1e411a533ab99e6f02ef6c56b 100644 (file)
@@ -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;
index ac785d15ced4d5d5e6095f64db5c6e586f91f89f..79fa2a19fb7b7262928a6df127c5f665b3d1005d 100644 (file)
@@ -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 */
index fd13ac11b13674e1c06500f7ab3eef151b1226e2..3ee7d6f853b71c3ab57262fa553da68e5d0afd23 100644 (file)
@@ -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... */
index c1376bfdc90b2add14a7f9e2804b4e6ac6c9e534..7afe8fae49391a1e8e18ed34c39b79260c5a2a47 100644 (file)
@@ -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;
 }
index 020c81818951d37a6ff2beb3ef72f6dcc2c7ec27..ce45b6dab651718b6da3ee24f169063d2cadae85 100644 (file)
@@ -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: */
index e7d441d0e839faa261e83e8c6782c178339cd625..73d7dff425c1f80b1e2171c8f215d56ad9e101db 100644 (file)
@@ -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;
index 85ae0ff2382a28433f3d30bfc69e490e654438d9..a751a18ca4c286bfa3d5b27f7af226142909d40b 100644 (file)
@@ -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 */
index 0ac89e294d31d50895f57aa20d1805b31adf9572..ef9190530fd208ae9c0b3c122321300eb002c174 100644 (file)
@@ -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);
 }
 
index 7e65fe853ee3accb793b22cf321cbddeb81e6265..f372c624bbf4ee2d3546ab5107cebb94a388418a 100644 (file)
@@ -1479,10 +1479,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,23 +1488,13 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
 
-       case USB_ID(0x10cb, 0x0103): /* The Bit Opus #3; with fp->dsd_raw */
-       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 */
index 2b833054e3b0d04236472e0df44ce2eef1a3fe97..58974d094b2720990c6937d2e45d04f8366dbbbd 100644 (file)
@@ -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;
index 4fd9276b8e501a198443ac0db59439365fd10c89..714cf50d4a4c6baefd6b17b63237fc891413dd98 100644 (file)
@@ -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;
 }
index 00c92eb854ce7b65daedc7c3fa98f69f9b891d86..80f79ecffc7108e2818812eb151e62670987d297 100644 (file)
@@ -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 */