Merge tag 'asoc-fix-v5.15-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git...
authorTakashi Iwai <tiwai@suse.de>
Wed, 8 Sep 2021 15:52:23 +0000 (17:52 +0200)
committerTakashi Iwai <tiwai@suse.de>
Wed, 8 Sep 2021 15:52:23 +0000 (17:52 +0200)
ASoC: Fixes for v5.15

A collection of fixes that came in during the merge window, nothing too
remarkable but a reasonably large number of fixes.

196 files changed:
Documentation/sound/alsa-configuration.rst
Documentation/sound/hd-audio/notes.rst
Documentation/sound/kernel-api/writing-an-alsa-driver.rst
include/sound/compress_driver.h
include/sound/core.h
include/sound/emu10k1.h
include/sound/emu8000.h
include/sound/hda_codec.h
include/sound/hdaudio_ext.h
include/sound/memalloc.h
include/sound/pcm.h
include/sound/pxa2xx-lib.h
include/uapi/sound/asound.h
sound/arm/pxa2xx-ac97.c
sound/arm/pxa2xx-pcm-lib.c
sound/core/compress_offload.c
sound/core/control_led.c
sound/core/init.c
sound/core/isadma.c
sound/core/memalloc.c
sound/core/memalloc_local.h
sound/core/pcm_lib.c
sound/core/pcm_memory.c
sound/core/pcm_native.c
sound/core/seq/seq_dummy.c
sound/core/sgbuf.c
sound/drivers/Kconfig
sound/drivers/aloop.c
sound/drivers/dummy.c
sound/drivers/mpu401/mpu401.c
sound/drivers/mtpav.c
sound/drivers/pcsp/pcsp.c
sound/drivers/pcsp/pcsp_input.c
sound/drivers/pcsp/pcsp_input.h
sound/drivers/serial-u16550.c
sound/drivers/virmidi.c
sound/drivers/vx/vx_core.c
sound/firewire/motu/motu-protocol-v2.c
sound/firewire/motu/motu.c
sound/firewire/motu/motu.h
sound/isa/ad1816a/ad1816a.c
sound/isa/ad1816a/ad1816a_lib.c
sound/isa/ad1848/ad1848.c
sound/isa/adlib.c
sound/isa/als100.c
sound/isa/azt2320.c
sound/isa/cmi8328.c
sound/isa/cmi8330.c
sound/isa/cs423x/cs4231.c
sound/isa/cs423x/cs4236.c
sound/isa/cs423x/cs4236_lib.c
sound/isa/es1688/es1688.c
sound/isa/es18xx.c
sound/isa/galaxy/galaxy.c
sound/isa/gus/gusclassic.c
sound/isa/gus/gusextreme.c
sound/isa/gus/gusmax.c
sound/isa/gus/interwave.c
sound/isa/msnd/msnd.c
sound/isa/msnd/msnd_pinnacle.c
sound/isa/opl3sa2.c
sound/isa/opti9xx/miro.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/isa/sb/emu8000.c
sound/isa/sb/jazz16.c
sound/isa/sb/sb16.c
sound/isa/sb/sb8.c
sound/isa/sb/sb_common.c
sound/isa/sc6000.c
sound/isa/sscape.c
sound/isa/wavefront/wavefront.c
sound/isa/wss/wss_lib.c
sound/parisc/harmony.c
sound/pci/ad1889.c
sound/pci/ali5451/ali5451.c
sound/pci/als300.c
sound/pci/als4000.c
sound/pci/atiixp.c
sound/pci/atiixp_modem.c
sound/pci/au88x0/au88x0.c
sound/pci/aw2/aw2-alsa.c
sound/pci/azt3328.c
sound/pci/bt87x.c
sound/pci/ca0106/ca0106.h
sound/pci/ca0106/ca0106_main.c
sound/pci/cmipci.c
sound/pci/cs4281.c
sound/pci/cs46xx/cs46xx.c
sound/pci/cs46xx/cs46xx.h
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/cs5530.c
sound/pci/cs5535audio/cs5535audio.c
sound/pci/cs5535audio/cs5535audio_olpc.c
sound/pci/echoaudio/echoaudio.c
sound/pci/echoaudio/echoaudio.h
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emu10k1x.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/Kconfig
sound/pci/hda/Makefile
sound/pci/hda/hda_auto_parser.c
sound/pci/hda/hda_bind.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_controller.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.h
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_cs8409-tables.c [new file with mode: 0644]
sound/pci/hda/patch_cs8409.c [new file with mode: 0644]
sound/pci/hda/patch_cs8409.h [new file with mode: 0644]
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1724.c
sound/pci/intel8x0.c
sound/pci/intel8x0m.c
sound/pci/korg1212/korg1212.c
sound/pci/lola/lola.c
sound/pci/lola/lola.h
sound/pci/lola/lola_pcm.c
sound/pci/lx6464es/lx6464es.c
sound/pci/maestro3.c
sound/pci/nm256/nm256.c
sound/pci/oxygen/oxygen.c
sound/pci/oxygen/oxygen.h
sound/pci/oxygen/oxygen_lib.c
sound/pci/oxygen/se6x.c
sound/pci/oxygen/virtuoso.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.c
sound/pci/trident/trident.h
sound/pci/trident/trident_main.c
sound/pci/trident/trident_memory.c
sound/pci/via82xx.c
sound/pci/via82xx_modem.c
sound/pci/vx222/vx222.c
sound/pci/ymfpci/ymfpci.c
sound/pci/ymfpci/ymfpci.h
sound/pci/ymfpci/ymfpci_main.c
sound/pcmcia/vx/vxpocket.c
sound/soc/bcm/bcm63xx-pcm-whistler.c
sound/soc/fsl/fsl_asrc_dma.c
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/imx-pcm-fiq.c
sound/soc/fsl/imx-pcm-rpmsg.c
sound/soc/fsl/mpc5200_dma.c
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/soc/pxa/pxa-ssp.c
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/pxa/pxa2xx-i2s.c
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/qcom/lpass-platform.c
sound/soc/qcom/qdsp6/q6asm-dai.c
sound/soc/soc-compress.c
sound/soc/sprd/sprd-pcm-dma.c
sound/soc/tegra/tegra210_admaif.c
sound/soc/tegra/tegra_pcm.c
sound/soc/tegra/tegra_pcm.h
sound/usb/card.c
sound/usb/card.h
sound/usb/clock.c
sound/usb/endpoint.c
sound/usb/format.c
sound/usb/implicit.c
sound/usb/mixer.c
sound/usb/mixer.h
sound/usb/mixer_maps.c
sound/usb/mixer_quirks.c
sound/usb/pcm.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/quirks.h
sound/usb/stream.c
sound/usb/usbaudio.h
sound/x86/intel_hdmi_audio.c
sound/x86/intel_hdmi_audio.h

index b36af65..65f6169 100644 (file)
@@ -1059,6 +1059,12 @@ The model name ``generic`` is treated as a special case.  When this
 model is given, the driver uses the generic codec parser without
 "codec-patch".  It's sometimes good for testing and debugging.
 
+The model option can be used also for aliasing to another PCI or codec
+SSID.  When it's passed in the form of ``model=XXXX:YYYY`` where XXXX
+and YYYY are the sub-vendor and sub-device IDs in hex numbers,
+respectively, the driver will refer to that SSID as a reference to the
+quirk table.
+
 If the default configuration doesn't work and one of the above
 matches with your device, report it together with alsa-info.sh
 output (with ``--no-upload`` option) to kernel bugzilla or alsa-devel
@@ -2252,6 +2258,27 @@ delayed_register
     The driver prints a message like "Found post-registration device
     assignment: 1234abcd:04" for such a device, so that user can
     notice the need.
+quirk_flags
+    Contains the bit flags for various device specific workarounds.
+    Applied to the corresponding card index.
+
+        * bit 0: Skip reading sample rate for devices
+        * bit 1: Create Media Controller API entries
+        * bit 2: Allow alignment on audio sub-slot at transfer
+        * bit 3: Add length specifier to transfers
+        * bit 4: Start playback stream at first in implement feedback mode
+        * bit 5: Skip clock selector setup
+        * bit 6: Ignore errors from clock source search
+        * bit 7: Indicates ITF-USB DSD based DACs
+        * bit 8: Add a delay of 20ms at each control message handling
+        * bit 9: Add a delay of 1-2ms at each control message handling
+        * bit 10: Add a delay of 5-6ms at each control message handling
+        * bit 11: Add a delay of 50ms at each interface setup
+        * bit 12: Perform sample rate validations at probe
+        * bit 13: Disable runtime PM autosuspend
+        * bit 14: Ignore errors for mixer access
+        * bit 15: Support generic DSD raw U32_BE format
+        * bit 16: Set up the interface at first like UAC1
 
 This module supports multiple devices, autoprobe and hotplugging.
 
@@ -2261,11 +2288,14 @@ check.
 
 NB: ``ignore_ctl_error=1`` may help when you get an error at accessing
 the mixer element such as URB error -22.  This happens on some
-buggy USB device or the controller.
+buggy USB device or the controller.  This workaround corresponds to
+the ``quirk_flags`` bit 14, too.
 
-NB: quirk_alias option is provided only for testing / development.
+NB: ``quirk_alias`` option is provided only for testing / development.
 If you want to have a proper support, contact to upstream for
 adding the matching quirk in the driver code statically.
+Ditto for ``quirk_flags``.  If a device is known to require specific
+workarounds, please report to the upstream.
 
 Module snd-usb-caiaq
 --------------------
index cf4d715..d118b6f 100644 (file)
@@ -215,6 +215,17 @@ There are a few special model option values:
 * when ``generic`` is passed, the codec-specific parser is skipped and
   only the generic parser is used.
 
+A new style for the model option that was introduced since 5.15 kernel
+is to pass the PCI or codec SSID in the form of ``model=XXXX:YYYY``
+where XXXX and YYYY are the sub-vendor and sub-device IDs in hex
+numbers, respectively.  This is a kind of aliasing to another device;
+when this form is given, the driver will refer to that SSID as a
+reference to the quirk table.  It'd be useful especially when the
+target quirk isn't listed in the model table.  For example, passing
+model=103c:8862 will apply the quirk for HP ProBook 445 G8 (which
+isn't found in the model table as of writing) as long as the device is
+handled equivalently by the same driver.
+
 
 Speaker and Headphone Output
 ----------------------------
index 01d59b8..255b7d3 100644 (file)
@@ -4172,6 +4172,39 @@ module license as GPL, etc., otherwise the system is shown as “tainted”.
   MODULE_LICENSE("GPL");
 
 
+Device-Managed Resources
+========================
+
+In the examples above, all resources are allocated and released
+manually.  But human beings are lazy in nature, especially developers
+are lazier.  So there are some ways to automate the release part; it's
+the (device-)managed resources aka devres or devm family.  For
+example, an object allocated via :c:func:`devm_kmalloc()` will be
+freed automatically at unbinding the device.
+
+ALSA core provides also the device-managed helper, namely,
+:c:func:`snd_devm_card_new()` for creating a card object.
+Call this functions instead of the normal :c:func:`snd_card_new()`,
+and you can forget the explicit :c:func:`snd_card_free()` call, as
+it's called automagically at error and removal paths.
+
+One caveat is that the call of :c:func:`snd_card_free()` would be put
+at the beginning of the call chain only after you call
+:c:func:`snd_card_register()`.
+
+Also, the ``private_free`` callback is always called at the card free,
+so be careful to put the hardware clean-up procedure in
+``private_free`` callback.  It might be called even before you
+actually set up at an earlier error path.  For avoiding such an
+invalid initialization, you can set ``private_free`` callback after
+:c:func:`snd_card_register()` call succeeds.
+
+Another thing to be remarked is that you should use device-managed
+helpers for each component as much as possible once when you manage
+the card in that way.  Mixing up with the normal and the managed
+resources may screw up the release order.
+
+
 How To Put Your Driver Into ALSA Tree
 =====================================
 
index 277087f..d91289c 100644 (file)
@@ -165,8 +165,6 @@ struct snd_compr {
 };
 
 /* compress device register APIs */
-int snd_compress_register(struct snd_compr *device);
-int snd_compress_deregister(struct snd_compr *device);
 int snd_compress_new(struct snd_card *card, int device,
                        int type, const char *id, struct snd_compr *compr);
 
index c4ade12..b7e9b58 100644 (file)
@@ -117,6 +117,8 @@ struct snd_card {
        struct device card_dev;         /* cardX object for sysfs */
        const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */
        bool registered;                /* card_dev is registered? */
+       bool managed;                   /* managed via devres */
+       bool releasing;                 /* during card free process */
        int sync_irq;                   /* assigned irq, used for PCM sync */
        wait_queue_head_t remove_sleep;
 
@@ -274,6 +276,9 @@ extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd);
 int snd_card_new(struct device *parent, int idx, const char *xid,
                 struct module *module, int extra_size,
                 struct snd_card **card_ret);
+int snd_devm_card_new(struct device *parent, int idx, const char *xid,
+                     struct module *module, size_t extra_size,
+                     struct snd_card **card_ret);
 
 int snd_card_disconnect(struct snd_card *card);
 void snd_card_disconnect_sync(struct snd_card *card);
@@ -324,6 +329,7 @@ int snd_device_get_state(struct snd_card *card, void *device_data);
 void snd_dma_program(unsigned long dma, unsigned long addr, unsigned int size, unsigned short mode);
 void snd_dma_disable(unsigned long dma);
 unsigned int snd_dma_pointer(unsigned long dma, unsigned int size);
+int snd_devm_request_dma(struct device *dev, int dma, const char *name);
 #endif
 
 /* misc.c */
index 468e38c..39787fe 100644 (file)
@@ -1701,7 +1701,7 @@ struct snd_emu10k1 {
        struct snd_dma_buffer silent_page;      /* silent page */
        struct snd_dma_buffer ptb_pages;        /* page table pages */
        struct snd_dma_device p16v_dma_dev;
-       struct snd_dma_buffer p16v_buffer;
+       struct snd_dma_buffer *p16v_buffer;
 
        struct snd_util_memhdr *memhdr;         /* page allocation list */
 
@@ -1796,14 +1796,12 @@ int snd_emu10k1_create(struct snd_card *card,
                       unsigned short extout_mask,
                       long max_cache_bytes,
                       int enable_ir,
-                      uint subsystem,
-                      struct snd_emu10k1 ** remu);
+                      uint subsystem);
 
 int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device);
 int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device);
 int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device);
 int snd_p16v_pcm(struct snd_emu10k1 *emu, int device);
-int snd_p16v_free(struct snd_emu10k1 * emu);
 int snd_p16v_mixer(struct snd_emu10k1 * emu);
 int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device);
 int snd_emu10k1_fx8010_pcm(struct snd_emu10k1 *emu, int device);
index ad0365d..072791b 100644 (file)
@@ -56,9 +56,6 @@ struct snd_emu8000 {
        unsigned long port1;    /* Port usually base+0 */
        unsigned long port2;    /* Port usually at base+0x400 */
        unsigned long port3;    /* Port usually at base+0x800 */
-       struct resource *res_port1;
-       struct resource *res_port2;
-       struct resource *res_port3;
        unsigned short last_reg;/* Last register command */
        spinlock_t reg_lock;
 
index 2e8d519..01570db 100644 (file)
@@ -114,7 +114,6 @@ struct hda_codec_ops {
        int (*resume)(struct hda_codec *codec);
        int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid);
 #endif
-       void (*reboot_notify)(struct hda_codec *codec);
        void (*stream_pm)(struct hda_codec *codec, hda_nid_t nid, bool on);
 };
 
index a125e38..3755816 100644 (file)
@@ -51,7 +51,7 @@ enum hdac_ext_stream_type {
  * @decoupled: stream host and link is decoupled
  * @link_locked: link is locked
  * @link_prepared: link is prepared
- * link_substream: link substream
+ * @link_substream: link substream
  */
 struct hdac_ext_stream {
        struct hdac_stream hstream;
index 44d8777..b197e3f 100644 (file)
@@ -31,13 +31,13 @@ struct snd_dma_device {
 #define SNDRV_DMA_TYPE_UNKNOWN         0       /* not defined */
 #define SNDRV_DMA_TYPE_CONTINUOUS      1       /* continuous no-DMA memory */
 #define SNDRV_DMA_TYPE_DEV             2       /* generic device continuous */
-#define SNDRV_DMA_TYPE_DEV_UC          5       /* continuous non-cahced */
+#define SNDRV_DMA_TYPE_DEV_WC          5       /* continuous write-combined */
 #ifdef CONFIG_SND_DMA_SGBUF
 #define SNDRV_DMA_TYPE_DEV_SG          3       /* generic device SG-buffer */
-#define SNDRV_DMA_TYPE_DEV_UC_SG       6       /* SG non-cached */
+#define SNDRV_DMA_TYPE_DEV_WC_SG       6       /* SG write-combined */
 #else
 #define SNDRV_DMA_TYPE_DEV_SG  SNDRV_DMA_TYPE_DEV /* no SG-buf support */
-#define SNDRV_DMA_TYPE_DEV_UC_SG       SNDRV_DMA_TYPE_DEV_UC
+#define SNDRV_DMA_TYPE_DEV_WC_SG       SNDRV_DMA_TYPE_DEV_WC
 #endif
 #ifdef CONFIG_GENERIC_ALLOCATOR
 #define SNDRV_DMA_TYPE_DEV_IRAM                4       /* generic device iram-buffer */
@@ -79,5 +79,9 @@ struct page *snd_sgbuf_get_page(struct snd_dma_buffer *dmab, size_t offset);
 unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
                                      unsigned int ofs, unsigned int size);
 
+/* device-managed memory allocator */
+struct snd_dma_buffer *snd_devm_alloc_pages(struct device *dev, int type,
+                                           size_t size);
+
 #endif /* __SOUND_MEMALLOC_H */
 
index 938f360..33451f8 100644 (file)
@@ -1204,11 +1204,48 @@ void snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
 int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size);
 int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream);
 
-void snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
-                               struct device *data, size_t size, size_t max);
-void snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
-                                   struct device *data,
-                                   size_t size, size_t max);
+int snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
+                              struct device *data, size_t size, size_t max);
+int snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
+                                  struct device *data,
+                                  size_t size, size_t max);
+
+/**
+ * snd_pcm_set_fixed_buffer - Preallocate and set up the fixed size PCM buffer
+ * @substream: the pcm substream instance
+ * @type: DMA type (SNDRV_DMA_TYPE_*)
+ * @data: DMA type dependent data
+ * @size: the requested pre-allocation size in bytes
+ *
+ * This is a variant of snd_pcm_set_managed_buffer(), but this pre-allocates
+ * only the given sized buffer and doesn't allow re-allocation nor dynamic
+ * allocation of a larger buffer unlike the standard one.
+ * The function may return -ENOMEM error, hence the caller must check it.
+ */
+static inline int __must_check
+snd_pcm_set_fixed_buffer(struct snd_pcm_substream *substream, int type,
+                                struct device *data, size_t size)
+{
+       return snd_pcm_set_managed_buffer(substream, type, data, size, 0);
+}
+
+/**
+ * snd_pcm_set_fixed_buffer_all - Preallocate and set up the fixed size PCM buffer
+ * @pcm: the pcm instance
+ * @type: DMA type (SNDRV_DMA_TYPE_*)
+ * @data: DMA type dependent data
+ * @size: the requested pre-allocation size in bytes
+ *
+ * Apply the set up of the fixed buffer via snd_pcm_set_fixed_buffer() for
+ * all substream.  If any of allocation fails, it returns -ENOMEM, hence the
+ * caller must check the return value.
+ */
+static inline int __must_check
+snd_pcm_set_fixed_buffer_all(struct snd_pcm *pcm, int type,
+                            struct device *data, size_t size)
+{
+       return snd_pcm_set_managed_buffer_all(pcm, type, data, size, 0);
+}
 
 int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
                                      size_t size, gfp_t gfp_flags);
index 0feaf16..95100cf 100644 (file)
@@ -14,18 +14,12 @@ struct snd_soc_component;
 
 extern int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params);
-extern int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream);
 extern int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
 extern snd_pcm_uframes_t pxa2xx_pcm_pointer(struct snd_pcm_substream *substream);
 extern int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream);
 extern int pxa2xx_pcm_open(struct snd_pcm_substream *substream);
 extern int pxa2xx_pcm_close(struct snd_pcm_substream *substream);
-extern int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
-       struct vm_area_struct *vma);
-extern int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream);
-extern void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm);
-extern void pxa2xx_soc_pcm_free(struct snd_soc_component *component,
-                               struct snd_pcm *pcm);
+extern int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm);
 extern int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
                              struct snd_soc_pcm_runtime *rtd);
 extern int pxa2xx_soc_pcm_open(struct snd_soc_component *component,
@@ -35,8 +29,6 @@ extern int pxa2xx_soc_pcm_close(struct snd_soc_component *component,
 extern int pxa2xx_soc_pcm_hw_params(struct snd_soc_component *component,
                                    struct snd_pcm_substream *substream,
                                    struct snd_pcm_hw_params *params);
-extern int pxa2xx_soc_pcm_hw_free(struct snd_soc_component *component,
-                                 struct snd_pcm_substream *substream);
 extern int pxa2xx_soc_pcm_prepare(struct snd_soc_component *component,
                                  struct snd_pcm_substream *substream);
 extern int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component,
@@ -44,9 +36,6 @@ extern int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component,
 extern snd_pcm_uframes_t
 pxa2xx_soc_pcm_pointer(struct snd_soc_component *component,
                       struct snd_pcm_substream *substream);
-extern int pxa2xx_soc_pcm_mmap(struct snd_soc_component *component,
-                              struct snd_pcm_substream *substream,
-                              struct vm_area_struct *vma);
 
 /* AC97 */
 
index d17c061..1d84ec9 100644 (file)
@@ -299,6 +299,7 @@ typedef int __bitwise snd_pcm_subformat_t;
 #define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME     0x02000000  /* report absolute hardware link audio time, not reset on startup */
 #define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME    0x04000000  /* report estimated link audio time */
 #define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000  /* report synchronized audio/system time */
+#define SNDRV_PCM_INFO_EXPLICIT_SYNC   0x10000000      /* needs explicit sync of pointers and data */
 
 #define SNDRV_PCM_INFO_DRAIN_TRIGGER   0x40000000              /* internal kernel flag - trigger in drain */
 #define SNDRV_PCM_INFO_FIFO_IN_FRAMES  0x80000000      /* internal kernel flag - FIFO size is in frames */
index a67e668..c17a19f 100644 (file)
@@ -172,38 +172,28 @@ static const struct snd_pcm_ops pxa2xx_ac97_pcm_ops = {
        .open           = pxa2xx_ac97_pcm_open,
        .close          = pxa2xx_ac97_pcm_close,
        .hw_params      = pxa2xx_pcm_hw_params,
-       .hw_free        = pxa2xx_pcm_hw_free,
        .prepare        = pxa2xx_ac97_pcm_prepare,
        .trigger        = pxa2xx_pcm_trigger,
        .pointer        = pxa2xx_pcm_pointer,
-       .mmap           = pxa2xx_pcm_mmap,
 };
 
 
 static int pxa2xx_ac97_pcm_new(struct snd_card *card)
 {
        struct snd_pcm *pcm;
-       int stream, ret;
+       int ret;
 
        ret = snd_pcm_new(card, "PXA2xx-PCM", 0, 1, 1, &pcm);
        if (ret)
                goto out;
 
-       pcm->private_free = pxa2xx_pcm_free_dma_buffers;
-
        ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
        if (ret)
                goto out;
 
-       stream = SNDRV_PCM_STREAM_PLAYBACK;
-       snd_pcm_set_ops(pcm, stream, &pxa2xx_ac97_pcm_ops);
-       ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
-       if (ret)
-               goto out;
-
-       stream = SNDRV_PCM_STREAM_CAPTURE;
-       snd_pcm_set_ops(pcm, stream, &pxa2xx_ac97_pcm_ops);
-       ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pxa2xx_ac97_pcm_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pxa2xx_ac97_pcm_ops);
+       ret = pxa2xx_pcm_preallocate_dma_buffer(pcm);
        if (ret)
                goto out;
 
index e81083e..0a48805 100644 (file)
@@ -54,19 +54,10 @@ int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
        if (ret)
                return ret;
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
        return 0;
 }
 EXPORT_SYMBOL(pxa2xx_pcm_hw_params);
 
-int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       snd_pcm_set_runtime_buffer(substream, NULL);
-       return 0;
-}
-EXPORT_SYMBOL(pxa2xx_pcm_hw_free);
-
 int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        return snd_dmaengine_pcm_trigger(substream, cmd);
@@ -131,56 +122,14 @@ int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
 }
 EXPORT_SYMBOL(pxa2xx_pcm_close);
 
-int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
-       struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
-                          runtime->dma_addr, runtime->dma_bytes);
-}
-EXPORT_SYMBOL(pxa2xx_pcm_mmap);
-
-int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm)
 {
-       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-       struct snd_dma_buffer *buf = &substream->dma_buffer;
        size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
-       buf->dev.type = SNDRV_DMA_TYPE_DEV;
-       buf->dev.dev = pcm->card->dev;
-       buf->private_data = NULL;
-       buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL);
-       if (!buf->area)
-               return -ENOMEM;
-       buf->bytes = size;
-       return 0;
-}
-EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer);
 
-void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       struct snd_dma_buffer *buf;
-       int stream;
-
-       for (stream = 0; stream < 2; stream++) {
-               substream = pcm->streams[stream].substream;
-               if (!substream)
-                       continue;
-               buf = &substream->dma_buffer;
-               if (!buf->area)
-                       continue;
-               dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr);
-               buf->area = NULL;
-       }
-}
-EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers);
-
-void pxa2xx_soc_pcm_free(struct snd_soc_component *component,
-                        struct snd_pcm *pcm)
-{
-       pxa2xx_pcm_free_dma_buffers(pcm);
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
+                                           pcm->card->dev, size);
 }
-EXPORT_SYMBOL(pxa2xx_soc_pcm_free);
+EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer);
 
 int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
                       struct snd_soc_pcm_runtime *rtd)
@@ -193,21 +142,7 @@ int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
        if (ret)
                return ret;
 
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
-                       SNDRV_PCM_STREAM_PLAYBACK);
-               if (ret)
-                       goto out;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
-                       SNDRV_PCM_STREAM_CAPTURE);
-               if (ret)
-                       goto out;
-       }
- out:
-       return ret;
+       return pxa2xx_pcm_preallocate_dma_buffer(pcm);
 }
 EXPORT_SYMBOL(pxa2xx_soc_pcm_new);
 
@@ -233,13 +168,6 @@ int pxa2xx_soc_pcm_hw_params(struct snd_soc_component *component,
 }
 EXPORT_SYMBOL(pxa2xx_soc_pcm_hw_params);
 
-int pxa2xx_soc_pcm_hw_free(struct snd_soc_component *component,
-                          struct snd_pcm_substream *substream)
-{
-       return pxa2xx_pcm_hw_free(substream);
-}
-EXPORT_SYMBOL(pxa2xx_soc_pcm_hw_free);
-
 int pxa2xx_soc_pcm_prepare(struct snd_soc_component *component,
                           struct snd_pcm_substream *substream)
 {
@@ -262,14 +190,6 @@ pxa2xx_soc_pcm_pointer(struct snd_soc_component *component,
 }
 EXPORT_SYMBOL(pxa2xx_soc_pcm_pointer);
 
-int pxa2xx_soc_pcm_mmap(struct snd_soc_component *component,
-                       struct snd_pcm_substream *substream,
-                       struct vm_area_struct *vma)
-{
-       return pxa2xx_pcm_mmap(substream, vma);
-}
-EXPORT_SYMBOL(pxa2xx_soc_pcm_mmap);
-
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("Intel PXA2xx sound library");
 MODULE_LICENSE("GPL");
index 21ce4c0..de514ec 100644 (file)
@@ -47,8 +47,6 @@
  *     driver should be able to register multiple nodes
  */
 
-static DEFINE_MUTEX(device_mutex);
-
 struct snd_compr_file {
        unsigned long caps;
        struct snd_compr_stream stream;
@@ -1179,6 +1177,7 @@ int snd_compress_new(struct snd_card *card, int device,
        compr->card = card;
        compr->device = device;
        compr->direction = dirn;
+       mutex_init(&compr->lock);
 
        snd_compress_set_id(compr, id);
 
@@ -1193,72 +1192,6 @@ int snd_compress_new(struct snd_card *card, int device,
 }
 EXPORT_SYMBOL_GPL(snd_compress_new);
 
-static int snd_compress_add_device(struct snd_compr *device)
-{
-       int ret;
-
-       if (!device->card)
-               return -EINVAL;
-
-       /* register the card */
-       ret = snd_card_register(device->card);
-       if (ret)
-               goto out;
-       return 0;
-
-out:
-       pr_err("failed with %d\n", ret);
-       return ret;
-
-}
-
-static int snd_compress_remove_device(struct snd_compr *device)
-{
-       return snd_card_free(device->card);
-}
-
-/**
- * snd_compress_register - register compressed device
- *
- * @device: compressed device to register
- */
-int snd_compress_register(struct snd_compr *device)
-{
-       int retval;
-
-       if (device->name == NULL || device->ops == NULL)
-               return -EINVAL;
-
-       pr_debug("Registering compressed device %s\n", device->name);
-       if (snd_BUG_ON(!device->ops->open))
-               return -EINVAL;
-       if (snd_BUG_ON(!device->ops->free))
-               return -EINVAL;
-       if (snd_BUG_ON(!device->ops->set_params))
-               return -EINVAL;
-       if (snd_BUG_ON(!device->ops->trigger))
-               return -EINVAL;
-
-       mutex_init(&device->lock);
-
-       /* register a compressed card */
-       mutex_lock(&device_mutex);
-       retval = snd_compress_add_device(device);
-       mutex_unlock(&device_mutex);
-       return retval;
-}
-EXPORT_SYMBOL_GPL(snd_compress_register);
-
-int snd_compress_deregister(struct snd_compr *device)
-{
-       pr_debug("Removing compressed device %s\n", device->name);
-       mutex_lock(&device_mutex);
-       snd_compress_remove_device(device);
-       mutex_unlock(&device_mutex);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(snd_compress_deregister);
-
 MODULE_DESCRIPTION("ALSA Compressed offload framework");
 MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
 MODULE_LICENSE("GPL v2");
index 764058c..a95332b 100644 (file)
@@ -564,7 +564,7 @@ static ssize_t set_led_id(struct snd_ctl_led_card *led_card, const char *buf, si
                        else {
                                for (; *s >= ' '; s++);
                                *s = '\0';
-                               strlcpy(id.name, buf2, sizeof(id.name));
+                               strscpy(id.name, buf2, sizeof(id.name));
                        }
                        break;
                }
index 1490568..ac335f5 100644 (file)
@@ -134,6 +134,9 @@ void snd_device_initialize(struct device *dev, struct snd_card *card)
 }
 EXPORT_SYMBOL_GPL(snd_device_initialize);
 
+static int snd_card_init(struct snd_card *card, struct device *parent,
+                        int idx, const char *xid, struct module *module,
+                        size_t extra_size);
 static int snd_card_do_free(struct snd_card *card);
 static const struct attribute_group card_dev_attr_group;
 
@@ -163,9 +166,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
 {
        struct snd_card *card;
        int err;
-#ifdef CONFIG_SND_DEBUG
-       char name[8];
-#endif
 
        if (snd_BUG_ON(!card_ret))
                return -EINVAL;
@@ -176,6 +176,74 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
        card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
        if (!card)
                return -ENOMEM;
+
+       err = snd_card_init(card, parent, idx, xid, module, extra_size);
+       if (err < 0) {
+               kfree(card);
+               return err;
+       }
+
+       *card_ret = card;
+       return 0;
+}
+EXPORT_SYMBOL(snd_card_new);
+
+static void __snd_card_release(struct device *dev, void *data)
+{
+       snd_card_free(data);
+}
+
+/**
+ * snd_devm_card_new - managed snd_card object creation
+ * @parent: the parent device object
+ * @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
+ * @xid: card identification (ASCII string)
+ * @module: top level module for locking
+ * @extra_size: allocate this extra size after the main soundcard structure
+ * @card_ret: the pointer to store the created card instance
+ *
+ * This function works like snd_card_new() but manages the allocated resource
+ * via devres, i.e. you don't need to free explicitly.
+ *
+ * When a snd_card object is created with this function and registered via
+ * snd_card_register(), the very first devres action to call snd_card_free()
+ * is added automatically.  In that way, the resource disconnection is assured
+ * at first, then released in the expected order.
+ */
+int snd_devm_card_new(struct device *parent, int idx, const char *xid,
+                     struct module *module, size_t extra_size,
+                     struct snd_card **card_ret)
+{
+       struct snd_card *card;
+       int err;
+
+       *card_ret = NULL;
+       card = devres_alloc(__snd_card_release, sizeof(*card) + extra_size,
+                           GFP_KERNEL);
+       if (!card)
+               return -ENOMEM;
+       card->managed = true;
+       err = snd_card_init(card, parent, idx, xid, module, extra_size);
+       if (err < 0) {
+               devres_free(card);
+               return err;
+       }
+
+       devres_add(parent, card);
+       *card_ret = card;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_devm_card_new);
+
+static int snd_card_init(struct snd_card *card, struct device *parent,
+                        int idx, const char *xid, struct module *module,
+                        size_t extra_size)
+{
+       int err;
+#ifdef CONFIG_SND_DEBUG
+       char name[8];
+#endif
+
        if (extra_size > 0)
                card->private_data = (char *)card + sizeof(struct snd_card);
        if (xid)
@@ -197,7 +265,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
                mutex_unlock(&snd_card_mutex);
                dev_err(parent, "cannot find the slot for index %d (range 0-%i), error: %d\n",
                         idx, snd_ecards_limit - 1, err);
-               kfree(card);
                return err;
        }
        set_bit(idx, snd_cards_lock);           /* lock it */
@@ -256,8 +323,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
        sprintf(name, "card%d", idx);
        card->debugfs_root = debugfs_create_dir(name, sound_debugfs_root);
 #endif
-
-       *card_ret = card;
        return 0;
 
       __error_ctl:
@@ -266,7 +331,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
        put_device(&card->card_dev);
        return err;
 }
-EXPORT_SYMBOL(snd_card_new);
 
 /**
  * snd_card_ref - Get the card object from the index
@@ -481,6 +545,7 @@ EXPORT_SYMBOL_GPL(snd_card_disconnect_sync);
 
 static int snd_card_do_free(struct snd_card *card)
 {
+       card->releasing = true;
 #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
        if (snd_mixer_oss_notify_callback)
                snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
@@ -498,7 +563,8 @@ static int snd_card_do_free(struct snd_card *card)
 #endif
        if (card->release_completion)
                complete(card->release_completion);
-       kfree(card);
+       if (!card->managed)
+               kfree(card);
        return 0;
 }
 
@@ -539,6 +605,15 @@ int snd_card_free(struct snd_card *card)
        DECLARE_COMPLETION_ONSTACK(released);
        int ret;
 
+       /* The call of snd_card_free() is allowed from various code paths;
+        * a manual call from the driver and the call via devres_free, and
+        * we need to avoid double-free. Moreover, the release via devres
+        * may call snd_card_free() twice due to its nature, we need to have
+        * the check here at the beginning.
+        */
+       if (card->releasing)
+               return 0;
+
        card->release_completion = &released;
        ret = snd_card_free_when_closed(card);
        if (ret)
@@ -745,6 +820,11 @@ int snd_card_add_dev_attr(struct snd_card *card,
 }
 EXPORT_SYMBOL_GPL(snd_card_add_dev_attr);
 
+static void trigger_card_free(void *data)
+{
+       snd_card_free(data);
+}
+
 /**
  *  snd_card_register - register the soundcard
  *  @card: soundcard structure
@@ -768,6 +848,15 @@ int snd_card_register(struct snd_card *card)
                if (err < 0)
                        return err;
                card->registered = true;
+       } else {
+               if (card->managed)
+                       devm_remove_action(card->dev, trigger_card_free, card);
+       }
+
+       if (card->managed) {
+               err = devm_add_action(card->dev, trigger_card_free, card);
+               if (err < 0)
+                       return err;
        }
 
        err = snd_device_register_all(card);
index c3d789e..1f45ede 100644 (file)
@@ -97,3 +97,41 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
                return size - result;
 }
 EXPORT_SYMBOL(snd_dma_pointer);
+
+struct snd_dma_data {
+       int dma;
+};
+
+static void __snd_release_dma(struct device *dev, void *data)
+{
+       struct snd_dma_data *p = data;
+
+       snd_dma_disable(p->dma);
+       free_dma(p->dma);
+}
+
+/**
+ * snd_devm_request_dma - the managed version of request_dma()
+ * @dev: the device pointer
+ * @dma: the dma number
+ * @name: the name string of the requester
+ *
+ * Returns zero on success, or a negative error code.
+ * The requested DMA will be automatically released at unbinding via devres.
+ */
+int snd_devm_request_dma(struct device *dev, int dma, const char *name)
+{
+       struct snd_dma_data *p;
+
+       if (request_dma(dma, name))
+               return -EBUSY;
+       p = devres_alloc(__snd_release_dma, sizeof(*p), GFP_KERNEL);
+       if (!p) {
+               free_dma(dma);
+               return -ENOMEM;
+       }
+       p->dma = dma;
+       devres_add(dev, p);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_devm_request_dma);
index 439a358..c7c943c 100644 (file)
@@ -29,12 +29,12 @@ static inline gfp_t snd_mem_get_gfp_flags(const struct snd_dma_buffer *dmab,
                return (__force gfp_t)(unsigned long)dmab->dev.dev;
 }
 
-static int __snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
+static void *__snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
 {
        const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
 
        if (WARN_ON_ONCE(!ops || !ops->alloc))
-               return -EINVAL;
+               return NULL;
        return ops->alloc(dmab, size);
 }
 
@@ -54,8 +54,6 @@ static int __snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
 int snd_dma_alloc_pages(int type, struct device *device, size_t size,
                        struct snd_dma_buffer *dmab)
 {
-       int err;
-
        if (WARN_ON(!size))
                return -ENXIO;
        if (WARN_ON(!dmab))
@@ -65,12 +63,9 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
        dmab->dev.type = type;
        dmab->dev.dev = device;
        dmab->bytes = 0;
-       dmab->area = NULL;
        dmab->addr = 0;
        dmab->private_data = NULL;
-       err = __snd_dma_alloc_pages(dmab, size);
-       if (err < 0)
-               return err;
+       dmab->area = __snd_dma_alloc_pages(dmab, size);
        if (!dmab->area)
                return -ENOMEM;
        dmab->bytes = size;
@@ -127,6 +122,52 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
 }
 EXPORT_SYMBOL(snd_dma_free_pages);
 
+/* called by devres */
+static void __snd_release_pages(struct device *dev, void *res)
+{
+       snd_dma_free_pages(res);
+}
+
+/**
+ * snd_devm_alloc_pages - allocate the buffer and manage with devres
+ * @dev: the device pointer
+ * @type: the DMA buffer type
+ * @size: the buffer size to allocate
+ *
+ * Allocate buffer pages depending on the given type and manage using devres.
+ * The pages will be released automatically at the device removal.
+ *
+ * Unlike snd_dma_alloc_pages(), this function requires the real device pointer,
+ * hence it can't work with SNDRV_DMA_TYPE_CONTINUOUS or
+ * SNDRV_DMA_TYPE_VMALLOC type.
+ *
+ * The function returns the snd_dma_buffer object at success, or NULL if failed.
+ */
+struct snd_dma_buffer *
+snd_devm_alloc_pages(struct device *dev, int type, size_t size)
+{
+       struct snd_dma_buffer *dmab;
+       int err;
+
+       if (WARN_ON(type == SNDRV_DMA_TYPE_CONTINUOUS ||
+                   type == SNDRV_DMA_TYPE_VMALLOC))
+               return NULL;
+
+       dmab = devres_alloc(__snd_release_pages, sizeof(*dmab), GFP_KERNEL);
+       if (!dmab)
+               return NULL;
+
+       err = snd_dma_alloc_pages(type, dev, size, dmab);
+       if (err < 0) {
+               devres_free(dmab);
+               return NULL;
+       }
+
+       devres_add(dev, dmab);
+       return dmab;
+}
+EXPORT_SYMBOL_GPL(snd_devm_alloc_pages);
+
 /**
  * snd_dma_buffer_mmap - perform mmap of the given DMA buffer
  * @dmab: buffer allocation information
@@ -198,12 +239,14 @@ EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);
 /*
  * Continuous pages allocator
  */
-static int snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
        gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL);
+       void *p = alloc_pages_exact(size, gfp);
 
-       dmab->area = alloc_pages_exact(size, gfp);
-       return 0;
+       if (p)
+               dmab->addr = page_to_phys(virt_to_page(p));
+       return p;
 }
 
 static void snd_dma_continuous_free(struct snd_dma_buffer *dmab)
@@ -215,7 +258,7 @@ static int snd_dma_continuous_mmap(struct snd_dma_buffer *dmab,
                                   struct vm_area_struct *area)
 {
        return remap_pfn_range(area, area->vm_start,
-                              page_to_pfn(virt_to_page(dmab->area)),
+                              dmab->addr >> PAGE_SHIFT,
                               area->vm_end - area->vm_start,
                               area->vm_page_prot);
 }
@@ -229,12 +272,11 @@ static const struct snd_malloc_ops snd_dma_continuous_ops = {
 /*
  * VMALLOC allocator
  */
-static int snd_dma_vmalloc_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_vmalloc_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
        gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL | __GFP_HIGHMEM);
 
-       dmab->area = __vmalloc(size, gfp);
-       return 0;
+       return __vmalloc(size, gfp);
 }
 
 static void snd_dma_vmalloc_free(struct snd_dma_buffer *dmab)
@@ -248,11 +290,13 @@ static int snd_dma_vmalloc_mmap(struct snd_dma_buffer *dmab,
        return remap_vmalloc_range(area, dmab->area, 0);
 }
 
+#define get_vmalloc_page_addr(dmab, offset) \
+       page_to_phys(vmalloc_to_page((dmab)->area + (offset)))
+
 static dma_addr_t snd_dma_vmalloc_get_addr(struct snd_dma_buffer *dmab,
                                           size_t offset)
 {
-       return page_to_phys(vmalloc_to_page(dmab->area + offset)) +
-               offset % PAGE_SIZE;
+       return get_vmalloc_page_addr(dmab, offset) + offset % PAGE_SIZE;
 }
 
 static struct page *snd_dma_vmalloc_get_page(struct snd_dma_buffer *dmab,
@@ -265,11 +309,23 @@ static unsigned int
 snd_dma_vmalloc_get_chunk_size(struct snd_dma_buffer *dmab,
                               unsigned int ofs, unsigned int size)
 {
-       ofs %= PAGE_SIZE;
-       size += ofs;
-       if (size > PAGE_SIZE)
-               size = PAGE_SIZE;
-       return size - ofs;
+       unsigned int start, end;
+       unsigned long addr;
+
+       start = ALIGN_DOWN(ofs, PAGE_SIZE);
+       end = ofs + size - 1; /* the last byte address */
+       /* check page continuity */
+       addr = get_vmalloc_page_addr(dmab, start);
+       for (;;) {
+               start += PAGE_SIZE;
+               if (start > end)
+                       break;
+               addr += PAGE_SIZE;
+               if (get_vmalloc_page_addr(dmab, start) != addr)
+                       return start - ofs;
+       }
+       /* ok, all on continuous pages */
+       return size;
 }
 
 static const struct snd_malloc_ops snd_dma_vmalloc_ops = {
@@ -286,20 +342,20 @@ static const struct snd_malloc_ops snd_dma_vmalloc_ops = {
  * IRAM allocator
  */
 #ifdef CONFIG_GENERIC_ALLOCATOR
-static int snd_dma_iram_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_iram_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
        struct device *dev = dmab->dev.dev;
        struct gen_pool *pool;
+       void *p;
 
        if (dev->of_node) {
                pool = of_gen_pool_get(dev->of_node, "iram", 0);
                /* Assign the pool into private_data field */
                dmab->private_data = pool;
 
-               dmab->area = gen_pool_dma_alloc_align(pool, size, &dmab->addr,
-                                                     PAGE_SIZE);
-               if (dmab->area)
-                       return 0;
+               p = gen_pool_dma_alloc_align(pool, size, &dmab->addr, PAGE_SIZE);
+               if (p)
+                       return p;
        }
 
        /* Internal memory might have limited size and no enough space,
@@ -334,31 +390,31 @@ static const struct snd_malloc_ops snd_dma_iram_ops = {
 };
 #endif /* CONFIG_GENERIC_ALLOCATOR */
 
+#define DEFAULT_GFP \
+       (GFP_KERNEL | \
+        __GFP_COMP |    /* compound page lets parts be mapped */ \
+        __GFP_NORETRY | /* don't trigger OOM-killer */ \
+        __GFP_NOWARN)   /* no stack trace print - this call is non-critical */
+
 /*
  * Coherent device pages allocator
  */
-static int snd_dma_dev_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_dev_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
-       gfp_t gfp_flags;
-
-       gfp_flags = GFP_KERNEL
-               | __GFP_COMP    /* compound page lets parts be mapped */
-               | __GFP_NORETRY /* don't trigger OOM-killer */
-               | __GFP_NOWARN; /* no stack trace print - this call is non-critical */
-       dmab->area = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr,
-                                       gfp_flags);
+       void *p;
+
+       p = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
 #ifdef CONFIG_X86
-       if (dmab->area && dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
-               set_memory_wc((unsigned long)dmab->area,
-                             PAGE_ALIGN(size) >> PAGE_SHIFT);
+       if (p && dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
+               set_memory_wc((unsigned long)p, PAGE_ALIGN(size) >> PAGE_SHIFT);
 #endif
-       return 0;
+       return p;
 }
 
 static void snd_dma_dev_free(struct snd_dma_buffer *dmab)
 {
 #ifdef CONFIG_X86
-       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
                set_memory_wb((unsigned long)dmab->area,
                              PAGE_ALIGN(dmab->bytes) >> PAGE_SHIFT);
 #endif
@@ -368,6 +424,10 @@ static void snd_dma_dev_free(struct snd_dma_buffer *dmab)
 static int snd_dma_dev_mmap(struct snd_dma_buffer *dmab,
                            struct vm_area_struct *area)
 {
+#ifdef CONFIG_X86
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
+               area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+#endif
        return dma_mmap_coherent(dmab->dev.dev, area,
                                 dmab->area, dmab->addr, dmab->bytes);
 }
@@ -377,6 +437,37 @@ static const struct snd_malloc_ops snd_dma_dev_ops = {
        .free = snd_dma_dev_free,
        .mmap = snd_dma_dev_mmap,
 };
+
+/*
+ * Write-combined pages
+ */
+#ifdef CONFIG_X86
+/* On x86, share the same ops as the standard dev ops */
+#define snd_dma_wc_ops snd_dma_dev_ops
+#else /* CONFIG_X86 */
+static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
+{
+       return dma_alloc_wc(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
+}
+
+static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
+{
+       dma_free_wc(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
+}
+
+static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
+                          struct vm_area_struct *area)
+{
+       return dma_mmap_wc(dmab->dev.dev, area,
+                          dmab->area, dmab->addr, dmab->bytes);
+}
+
+static const struct snd_malloc_ops snd_dma_wc_ops = {
+       .alloc = snd_dma_wc_alloc,
+       .free = snd_dma_wc_free,
+       .mmap = snd_dma_wc_mmap,
+};
+#endif /* CONFIG_X86 */
 #endif /* CONFIG_HAS_DMA */
 
 /*
@@ -387,14 +478,14 @@ static const struct snd_malloc_ops *dma_ops[] = {
        [SNDRV_DMA_TYPE_VMALLOC] = &snd_dma_vmalloc_ops,
 #ifdef CONFIG_HAS_DMA
        [SNDRV_DMA_TYPE_DEV] = &snd_dma_dev_ops,
-       [SNDRV_DMA_TYPE_DEV_UC] = &snd_dma_dev_ops,
+       [SNDRV_DMA_TYPE_DEV_WC] = &snd_dma_wc_ops,
 #ifdef CONFIG_GENERIC_ALLOCATOR
        [SNDRV_DMA_TYPE_DEV_IRAM] = &snd_dma_iram_ops,
 #endif /* CONFIG_GENERIC_ALLOCATOR */
 #endif /* CONFIG_HAS_DMA */
 #ifdef CONFIG_SND_DMA_SGBUF
        [SNDRV_DMA_TYPE_DEV_SG] = &snd_dma_sg_ops,
-       [SNDRV_DMA_TYPE_DEV_UC_SG] = &snd_dma_sg_ops,
+       [SNDRV_DMA_TYPE_DEV_WC_SG] = &snd_dma_sg_ops,
 #endif
 };
 
index dbea7f2..9f2e0a6 100644 (file)
@@ -3,7 +3,7 @@
 #define __MEMALLOC_LOCAL_H
 
 struct snd_malloc_ops {
-       int (*alloc)(struct snd_dma_buffer *dmab, size_t size);
+       void *(*alloc)(struct snd_dma_buffer *dmab, size_t size);
        void (*free)(struct snd_dma_buffer *dmab);
        dma_addr_t (*get_addr)(struct snd_dma_buffer *dmab, size_t offset);
        struct page *(*get_page)(struct snd_dma_buffer *dmab, size_t offset);
index 7d58834..a144a3f 100644 (file)
@@ -1746,7 +1746,7 @@ static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream,
                channels = params_channels(params);
                frame_size = snd_pcm_format_size(format, channels);
                if (frame_size > 0)
-                       params->fifo_size /= (unsigned)frame_size;
+                       params->fifo_size /= frame_size;
        }
        return 0;
 }
index d7621ed..7fbd1cc 100644 (file)
@@ -67,7 +67,8 @@ static void do_free_pages(struct snd_card *card, struct snd_dma_buffer *dmab)
  *
  * the minimum size is snd_minimum_buffer.  it should be power of 2.
  */
-static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t size)
+static int preallocate_pcm_pages(struct snd_pcm_substream *substream,
+                                size_t size, bool no_fallback)
 {
        struct snd_dma_buffer *dmab = &substream->dma_buffer;
        struct snd_card *card = substream->pcm->card;
@@ -79,6 +80,8 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz
                                     size, dmab);
                if (err != -ENOMEM)
                        return err;
+               if (no_fallback)
+                       break;
                size >>= 1;
        } while (size >= snd_minimum_buffer);
        dmab->bytes = 0; /* tell error */
@@ -86,7 +89,7 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz
                substream->pcm->card->number, substream->pcm->device,
                substream->stream ? 'c' : 'p', substream->number,
                substream->pcm->name, orig_size);
-       return 0;
+       return -ENOMEM;
 }
 
 /**
@@ -222,18 +225,31 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
 /*
  * pre-allocate the buffer and create a proc file for the substream
  */
-static void preallocate_pages(struct snd_pcm_substream *substream,
+static int preallocate_pages(struct snd_pcm_substream *substream,
                              int type, struct device *data,
                              size_t size, size_t max, bool managed)
 {
+       int err;
+
        if (snd_BUG_ON(substream->dma_buffer.dev.type))
-               return;
+               return -EINVAL;
 
        substream->dma_buffer.dev.type = type;
        substream->dma_buffer.dev.dev = data;
 
-       if (size > 0 && preallocate_dma && substream->number < maximum_substreams)
-               preallocate_pcm_pages(substream, size);
+       if (size > 0) {
+               if (!max) {
+                       /* no fallback, only also inform -ENOMEM */
+                       err = preallocate_pcm_pages(substream, size, true);
+                       if (err < 0)
+                               return err;
+               } else if (preallocate_dma &&
+                          substream->number < maximum_substreams) {
+                       err = preallocate_pcm_pages(substream, size, false);
+                       if (err < 0 && err != -ENOMEM)
+                               return err;
+               }
+       }
 
        if (substream->dma_buffer.bytes > 0)
                substream->buffer_bytes_max = substream->dma_buffer.bytes;
@@ -242,17 +258,22 @@ static void preallocate_pages(struct snd_pcm_substream *substream,
                preallocate_info_init(substream);
        if (managed)
                substream->managed_buffer_alloc = 1;
+       return 0;
 }
 
-static void preallocate_pages_for_all(struct snd_pcm *pcm, int type,
+static int preallocate_pages_for_all(struct snd_pcm *pcm, int type,
                                      void *data, size_t size, size_t max,
                                      bool managed)
 {
        struct snd_pcm_substream *substream;
-       int stream;
+       int stream, err;
 
-       for_each_pcm_substream(pcm, stream, substream)
-               preallocate_pages(substream, type, data, size, max, managed);
+       for_each_pcm_substream(pcm, stream, substream) {
+               err = preallocate_pages(substream, type, data, size, max, managed);
+               if (err < 0)
+                       return err;
+       }
+       return 0;
 }
 
 /**
@@ -309,11 +330,22 @@ EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
  * When a buffer is actually allocated before the PCM hw_params call, it
  * turns on the runtime buffer_changed flag for drivers changing their h/w
  * parameters accordingly.
+ *
+ * When @size is non-zero and @max is zero, this tries to allocate for only
+ * the exact buffer size without fallback, and may return -ENOMEM.
+ * Otherwise, the function tries to allocate smaller chunks if the allocation
+ * fails.  This is the behavior of snd_pcm_set_fixed_buffer().
+ *
+ * When both @size and @max are zero, the function only sets up the buffer
+ * for later dynamic allocations. It's used typically for buffers with
+ * SNDRV_DMA_TYPE_VMALLOC type.
+ *
+ * Upon successful buffer allocation and setup, the function returns 0.
  */
-void snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
+int snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
                                struct device *data, size_t size, size_t max)
 {
-       preallocate_pages(substream, type, data, size, max, true);
+       return preallocate_pages(substream, type, data, size, max, true);
 }
 EXPORT_SYMBOL(snd_pcm_set_managed_buffer);
 
@@ -329,11 +361,11 @@ EXPORT_SYMBOL(snd_pcm_set_managed_buffer);
  * Do pre-allocation to all substreams of the given pcm for the specified DMA
  * type and size, and set the managed_buffer_alloc flag to each substream.
  */
-void snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
-                                   struct device *data,
-                                   size_t size, size_t max)
+int snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
+                                  struct device *data,
+                                  size_t size, size_t max)
 {
-       preallocate_pages_for_all(pcm, type, data, size, max, true);
+       return preallocate_pages_for_all(pcm, type, data, size, max, true);
 }
 EXPORT_SYMBOL(snd_pcm_set_managed_buffer_all);
 
@@ -376,6 +408,9 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
            substream->dma_buffer.bytes >= size) {
                dmab = &substream->dma_buffer; /* use the pre-allocated buffer */
        } else {
+               /* dma_max=0 means the fixed size preallocation */
+               if (substream->dma_buffer.area && !substream->dma_max)
+                       return -ENOMEM;
                dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
                if (! dmab)
                        return -ENOMEM;
index 71323d8..d233cb3 100644 (file)
@@ -243,13 +243,18 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
 
 static bool hw_support_mmap(struct snd_pcm_substream *substream)
 {
+       struct snd_dma_buffer *dmabuf;
+
        if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
                return false;
 
        if (substream->ops->mmap || substream->ops->page)
                return true;
 
-       switch (substream->dma_buffer.dev.type) {
+       dmabuf = snd_pcm_get_dma_buf(substream);
+       if (!dmabuf)
+               dmabuf = &substream->dma_buffer;
+       switch (dmabuf->dev.type) {
        case SNDRV_DMA_TYPE_UNKNOWN:
                /* we can't know the device, so just assume that the driver does
                 * everything right
@@ -259,7 +264,7 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
        case SNDRV_DMA_TYPE_VMALLOC:
                return true;
        default:
-               return dma_can_mmap(substream->dma_buffer.dev.dev);
+               return dma_can_mmap(dmabuf->dev.dev);
        }
 }
 
@@ -3616,6 +3621,12 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
 
 static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
 {
+       /* If drivers require the explicit sync (typically for non-coherent
+        * pages), we have to disable the mmap of status and control data
+        * to enforce the control via SYNC_PTR ioctl.
+        */
+       if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_EXPLICIT_SYNC)
+               return false;
        /* See pcm_control_mmap_allowed() below.
         * Since older alsa-lib requires both status and control mmaps to be
         * coupled, we have to disable the status mmap for old alsa-lib, too.
@@ -3630,6 +3641,9 @@ static bool pcm_control_mmap_allowed(struct snd_pcm_file *pcm_file)
 {
        if (pcm_file->no_compat_mmap)
                return false;
+       /* see above */
+       if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_EXPLICIT_SYNC)
+               return false;
        /* Disallow the control mmap when SYNC_APPLPTR flag is set;
         * it enforces the user-space to fall back to snd_pcm_sync_ptr(),
         * thus it effectively assures the manual update of appl_ptr.
index ac760b1..8c18d8c 100644 (file)
   are redirected to output port immediately.
   The routing can be done via aconnect program in alsa-utils.
 
-  Each client has a static client number 62 (= SNDRV_SEQ_CLIENT_DUMMY).
+  Each client has a static client number 14 (= SNDRV_SEQ_CLIENT_DUMMY).
   If you want to auto-load this module, you may add the following alias
   in your /etc/conf.modules file.
 
-       alias snd-seq-client-62  snd-seq-dummy
+       alias snd-seq-client-14  snd-seq-dummy
 
-  The module is loaded on demand for client 62, or /proc/asound/seq/
+  The module is loaded on demand for client 14, or /proc/asound/seq/
   is accessed.  If you don't need this module to be loaded, alias
-  snd-seq-client-62 as "off".  This will help modprobe.
+  snd-seq-client-14 as "off".  This will help modprobe.
 
   The number of ports to be created can be specified via the module
   parameter "ports".  For example, to create four ports, add the
index 232cf3f..8352a5c 100644 (file)
@@ -43,8 +43,8 @@ static void snd_dma_sg_free(struct snd_dma_buffer *dmab)
        dmab->area = NULL;
 
        tmpb.dev.type = SNDRV_DMA_TYPE_DEV;
-       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC_SG)
-               tmpb.dev.type = SNDRV_DMA_TYPE_DEV_UC;
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
+               tmpb.dev.type = SNDRV_DMA_TYPE_DEV_WC;
        tmpb.dev.dev = sgbuf->dev;
        for (i = 0; i < sgbuf->pages; i++) {
                if (!(sgbuf->table[i].addr & ~PAGE_MASK))
@@ -63,7 +63,7 @@ static void snd_dma_sg_free(struct snd_dma_buffer *dmab)
 
 #define MAX_ALLOC_PAGES                32
 
-static int snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
        struct snd_sg_buf *sgbuf;
        unsigned int i, pages, chunk, maxpages;
@@ -72,12 +72,13 @@ static int snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
        struct page **pgtable;
        int type = SNDRV_DMA_TYPE_DEV;
        pgprot_t prot = PAGE_KERNEL;
+       void *area;
 
        dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
        if (!sgbuf)
-               return -ENOMEM;
-       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC_SG) {
-               type = SNDRV_DMA_TYPE_DEV_UC;
+               return NULL;
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG) {
+               type = SNDRV_DMA_TYPE_DEV_WC;
 #ifdef pgprot_noncached
                prot = pgprot_noncached(PAGE_KERNEL);
 #endif
@@ -127,14 +128,14 @@ static int snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
        }
 
        sgbuf->size = size;
-       dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, prot);
-       if (! dmab->area)
+       area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, prot);
+       if (!area)
                goto _failed;
-       return 0;
+       return area;
 
  _failed:
        snd_dma_sg_free(dmab); /* free the table */
-       return -ENOMEM;
+       return NULL;
 }
 
 static dma_addr_t snd_dma_sg_get_addr(struct snd_dma_buffer *dmab,
@@ -182,10 +183,19 @@ static unsigned int snd_dma_sg_get_chunk_size(struct snd_dma_buffer *dmab,
        return size;
 }
 
+static int snd_dma_sg_mmap(struct snd_dma_buffer *dmab,
+                          struct vm_area_struct *area)
+{
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
+               area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+       return -ENOENT; /* continue with the default mmap handler */
+}
+
 const struct snd_malloc_ops snd_dma_sg_ops = {
        .alloc = snd_dma_sg_alloc,
        .free = snd_dma_sg_free,
        .get_addr = snd_dma_sg_get_addr,
        .get_page = snd_dma_sg_get_page,
        .get_chunk_size = snd_dma_sg_get_chunk_size,
+       .mmap = snd_dma_sg_mmap,
 };
index 7141f73..ca4cdf6 100644 (file)
@@ -102,7 +102,7 @@ config SND_ALOOP
          configured number of substreams (see the pcm_substreams module
          parameter).
 
-         The loopback device allows time sychronization with an external
+         The loopback device allows time synchronization with an external
          timing source using the time shift universal control (+-20%
          of system time).
 
index 80b814b..9b4a7cd 100644 (file)
@@ -1712,8 +1712,8 @@ static int loopback_probe(struct platform_device *devptr)
        int dev = devptr->id;
        int err;
 
-       err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct loopback), &card);
+       err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct loopback), &card);
        if (err < 0)
                return err;
        loopback = card->private_data;
@@ -1730,13 +1730,13 @@ static int loopback_probe(struct platform_device *devptr)
 
        err = loopback_pcm_new(loopback, 0, pcm_substreams[dev]);
        if (err < 0)
-               goto __nodev;
+               return err;
        err = loopback_pcm_new(loopback, 1, pcm_substreams[dev]);
        if (err < 0)
-               goto __nodev;
+               return err;
        err = loopback_mixer_new(loopback, pcm_notify[dev] ? 1 : 0);
        if (err < 0)
-               goto __nodev;
+               return err;
        loopback_cable_proc_new(loopback, 0);
        loopback_cable_proc_new(loopback, 1);
        loopback_timer_source_proc_new(loopback);
@@ -1744,18 +1744,9 @@ static int loopback_probe(struct platform_device *devptr)
        strcpy(card->shortname, "Loopback");
        sprintf(card->longname, "Loopback %i", dev + 1);
        err = snd_card_register(card);
-       if (!err) {
-               platform_set_drvdata(devptr, card);
-               return 0;
-       }
-      __nodev:
-       snd_card_free(card);
-       return err;
-}
-
-static int loopback_remove(struct platform_device *devptr)
-{
-       snd_card_free(platform_get_drvdata(devptr));
+       if (err < 0)
+               return err;
+       platform_set_drvdata(devptr, card);
        return 0;
 }
 
@@ -1786,7 +1777,6 @@ static SIMPLE_DEV_PM_OPS(loopback_pm, loopback_suspend, loopback_resume);
 
 static struct platform_driver loopback_driver = {
        .probe          = loopback_probe,
-       .remove         = loopback_remove,
        .driver         = {
                .name   = SND_LOOPBACK_DRIVER,
                .pm     = LOOPBACK_PM_OPS,
index 01a3eab..2a7fc49 100644 (file)
@@ -1025,8 +1025,8 @@ static int snd_dummy_probe(struct platform_device *devptr)
        int idx, err;
        int dev = devptr->id;
 
-       err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_dummy), &card);
+       err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_dummy), &card);
        if (err < 0)
                return err;
        dummy = card->private_data;
@@ -1047,7 +1047,7 @@ static int snd_dummy_probe(struct platform_device *devptr)
                        pcm_substreams[dev] = MAX_PCM_SUBSTREAMS;
                err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev]);
                if (err < 0)
-                       goto __nodev;
+                       return err;
        }
 
        dummy->pcm_hw = dummy_pcm_hardware;
@@ -1078,7 +1078,7 @@ static int snd_dummy_probe(struct platform_device *devptr)
 
        err = snd_card_dummy_new_mixer(dummy);
        if (err < 0)
-               goto __nodev;
+               return err;
        strcpy(card->driver, "Dummy");
        strcpy(card->shortname, "Dummy");
        sprintf(card->longname, "Dummy %i", dev + 1);
@@ -1086,18 +1086,9 @@ static int snd_dummy_probe(struct platform_device *devptr)
        dummy_proc_init(dummy);
 
        err = snd_card_register(card);
-       if (err == 0) {
-               platform_set_drvdata(devptr, card);
-               return 0;
-       }
-      __nodev:
-       snd_card_free(card);
-       return err;
-}
-
-static int snd_dummy_remove(struct platform_device *devptr)
-{
-       snd_card_free(platform_get_drvdata(devptr));
+       if (err < 0)
+               return err;
+       platform_set_drvdata(devptr, card);
        return 0;
 }
 
@@ -1128,7 +1119,6 @@ static SIMPLE_DEV_PM_OPS(snd_dummy_pm, snd_dummy_suspend, snd_dummy_resume);
 
 static struct platform_driver snd_dummy_driver = {
        .probe          = snd_dummy_probe,
-       .remove         = snd_dummy_remove,
        .driver         = {
                .name   = SND_DUMMY_DRIVER,
                .pm     = SND_DUMMY_PM_OPS,
index d0b55db..3398aee 100644 (file)
@@ -59,8 +59,8 @@ static int snd_mpu401_create(struct device *devptr, int dev,
                snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n");
 
        *rcard = NULL;
-       err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
+                               0, &card);
        if (err < 0)
                return err;
        strcpy(card->driver, "MPU-401 UART");
@@ -76,15 +76,11 @@ static int snd_mpu401_create(struct device *devptr, int dev,
                                  irq[dev], NULL);
        if (err < 0) {
                printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
-               goto _err;
+               return err;
        }
 
        *rcard = card;
        return 0;
-
- _err:
-       snd_card_free(card);
-       return err;
 }
 
 static int snd_mpu401_probe(struct platform_device *devptr)
@@ -105,25 +101,16 @@ static int snd_mpu401_probe(struct platform_device *devptr)
        if (err < 0)
                return err;
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        platform_set_drvdata(devptr, card);
        return 0;
 }
 
-static int snd_mpu401_remove(struct platform_device *devptr)
-{
-       snd_card_free(platform_get_drvdata(devptr));
-       return 0;
-}
-
 #define SND_MPU401_DRIVER      "snd_mpu401"
 
 static struct platform_driver snd_mpu401_driver = {
        .probe          = snd_mpu401_probe,
-       .remove         = snd_mpu401_remove,
        .driver         = {
                .name   = SND_MPU401_DRIVER,
        },
@@ -184,10 +171,8 @@ static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
                if (err < 0)
                        return err;
                err = snd_card_register(card);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
                pnp_set_drvdata(pnp_dev, card);
                snd_mpu401_devices++;
                ++dev;
@@ -196,19 +181,10 @@ static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
        return -ENODEV;
 }
 
-static void snd_mpu401_pnp_remove(struct pnp_dev *dev)
-{
-       struct snd_card *card = (struct snd_card *) pnp_get_drvdata(dev);
-
-       snd_card_disconnect(card);
-       snd_card_free_when_closed(card);
-}
-
 static struct pnp_driver snd_mpu401_pnp_driver = {
        .name = "mpu401",
        .id_table = snd_mpu401_pnpids,
        .probe = snd_mpu401_pnp_probe,
-       .remove = snd_mpu401_pnp_remove,
 };
 #else
 static struct pnp_driver snd_mpu401_pnp_driver;
index 0e95b08..11235ba 100644 (file)
@@ -566,13 +566,15 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id)
  */
 static int snd_mtpav_get_ISA(struct mtpav *mcard)
 {
-       mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI");
+       mcard->res_port = devm_request_region(mcard->card->dev, port, 3,
+                                             "MotuMTPAV MIDI");
        if (!mcard->res_port) {
                snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port);
                return -EBUSY;
        }
        mcard->port = port;
-       if (request_irq(irq, snd_mtpav_irqh, 0, "MOTU MTPAV", mcard)) {
+       if (devm_request_irq(mcard->card->dev, irq, snd_mtpav_irqh, 0,
+                            "MOTU MTPAV", mcard)) {
                snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq);
                return -EBUSY;
        }
@@ -667,9 +669,6 @@ static void snd_mtpav_free(struct snd_card *card)
        if (crd->istimer > 0)
                snd_mtpav_remove_output_timer(crd);
        spin_unlock_irqrestore(&crd->spinlock, flags);
-       if (crd->irq >= 0)
-               free_irq(crd->irq, (void *)crd);
-       release_and_free_resource(crd->res_port);
 }
 
 /*
@@ -680,8 +679,8 @@ static int snd_mtpav_probe(struct platform_device *dev)
        int err;
        struct mtpav *mtp_card;
 
-       err = snd_card_new(&dev->dev, index, id, THIS_MODULE,
-                          sizeof(*mtp_card), &card);
+       err = snd_devm_card_new(&dev->dev, index, id, THIS_MODULE,
+                               sizeof(*mtp_card), &card);
        if (err < 0)
                return err;
 
@@ -698,13 +697,13 @@ static int snd_mtpav_probe(struct platform_device *dev)
 
        err = snd_mtpav_get_RAWMIDI(mtp_card);
        if (err < 0)
-               goto __error;
+               return err;
 
        mtp_card->inmidiport = mtp_card->num_ports + MTPAV_PIDX_BROADCAST;
 
        err = snd_mtpav_get_ISA(mtp_card);
        if (err < 0)
-               goto __error;
+               return err;
 
        strcpy(card->driver, "MTPAV");
        strcpy(card->shortname, "MTPAV on parallel port");
@@ -715,28 +714,17 @@ static int snd_mtpav_probe(struct platform_device *dev)
 
        err = snd_card_register(mtp_card->card);
        if (err < 0)
-               goto __error;
+               return err;
 
        platform_set_drvdata(dev, card);
        printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port);
        return 0;
-
- __error:
-       snd_card_free(card);
-       return err;
-}
-
-static int snd_mtpav_remove(struct platform_device *devptr)
-{
-       snd_card_free(platform_get_drvdata(devptr));
-       return 0;
 }
 
 #define SND_MTPAV_DRIVER       "snd_mtpav"
 
 static struct platform_driver snd_mtpav_driver = {
        .probe          = snd_mtpav_probe,
-       .remove         = snd_mtpav_remove,
        .driver         = {
                .name   = SND_MTPAV_DRIVER,
        },
index 7689fa2..c7be1c3 100644 (file)
@@ -42,9 +42,8 @@ struct snd_pcsp pcsp_chip;
 
 static int snd_pcsp_create(struct snd_card *card)
 {
-       static const struct snd_device_ops ops = { };
        unsigned int resolution = hrtimer_resolution;
-       int err, div, min_div, order;
+       int div, min_div, order;
 
        if (!nopcm) {
                if (resolution > PCSP_MAX_PERIOD_NS) {
@@ -83,15 +82,18 @@ static int snd_pcsp_create(struct snd_card *card)
        pcsp_chip.port = 0x61;
        pcsp_chip.irq = -1;
        pcsp_chip.dma = -1;
-
-       /* Register device */
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, &pcsp_chip, &ops);
-       if (err < 0)
-               return err;
+       card->private_data = &pcsp_chip;
 
        return 0;
 }
 
+static void pcsp_stop_beep(struct snd_pcsp *chip);
+
+static void alsa_card_pcsp_free(struct snd_card *card)
+{
+       pcsp_stop_beep(card->private_data);
+}
+
 static int snd_card_pcsp_probe(int devnum, struct device *dev)
 {
        struct snd_card *card;
@@ -103,22 +105,22 @@ static int snd_card_pcsp_probe(int devnum, struct device *dev)
        hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        pcsp_chip.timer.function = pcsp_do_timer;
 
-       err = snd_card_new(dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(dev, index, id, THIS_MODULE, 0, &card);
        if (err < 0)
                return err;
 
        err = snd_pcsp_create(card);
        if (err < 0)
-               goto free_card;
+               return err;
 
        if (!nopcm) {
                err = snd_pcsp_new_pcm(&pcsp_chip);
                if (err < 0)
-                       goto free_card;
+                       return err;
        }
        err = snd_pcsp_new_mixer(&pcsp_chip, nopcm);
        if (err < 0)
-               goto free_card;
+               return err;
 
        strcpy(card->driver, "PC-Speaker");
        strcpy(card->shortname, "pcsp");
@@ -127,13 +129,10 @@ static int snd_card_pcsp_probe(int devnum, struct device *dev)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto free_card;
+               return err;
+       card->private_free = alsa_card_pcsp_free;
 
        return 0;
-
-free_card:
-       snd_card_free(card);
-       return err;
 }
 
 static int alsa_card_pcsp_init(struct device *dev)
@@ -155,11 +154,6 @@ static int alsa_card_pcsp_init(struct device *dev)
        return 0;
 }
 
-static void alsa_card_pcsp_exit(struct snd_pcsp *chip)
-{
-       snd_card_free(chip->card);
-}
-
 static int pcsp_probe(struct platform_device *dev)
 {
        int err;
@@ -169,23 +163,13 @@ static int pcsp_probe(struct platform_device *dev)
                return err;
 
        err = alsa_card_pcsp_init(&dev->dev);
-       if (err < 0) {
-               pcspkr_input_remove(pcsp_chip.input_dev);
+       if (err < 0)
                return err;
-       }
 
        platform_set_drvdata(dev, &pcsp_chip);
        return 0;
 }
 
-static int pcsp_remove(struct platform_device *dev)
-{
-       struct snd_pcsp *chip = platform_get_drvdata(dev);
-       pcspkr_input_remove(chip->input_dev);
-       alsa_card_pcsp_exit(chip);
-       return 0;
-}
-
 static void pcsp_stop_beep(struct snd_pcsp *chip)
 {
        pcsp_sync_stop(chip);
@@ -218,7 +202,6 @@ static struct platform_driver pcsp_platform_driver = {
                .pm     = PCSP_PM_OPS,
        },
        .probe          = pcsp_probe,
-       .remove         = pcsp_remove,
        .shutdown       = pcsp_shutdown,
 };
 
index e79603f..5a799f7 100644 (file)
@@ -78,7 +78,7 @@ int pcspkr_input_init(struct input_dev **rdev, struct device *dev)
 {
        int err;
 
-       struct input_dev *input_dev = input_allocate_device();
+       struct input_dev *input_dev = devm_input_allocate_device(dev);
        if (!input_dev)
                return -ENOMEM;
 
@@ -95,19 +95,9 @@ int pcspkr_input_init(struct input_dev **rdev, struct device *dev)
        input_dev->event = pcspkr_input_event;
 
        err = input_register_device(input_dev);
-       if (err) {
-               input_free_device(input_dev);
+       if (err)
                return err;
-       }
 
        *rdev = input_dev;
        return 0;
 }
-
-int pcspkr_input_remove(struct input_dev *dev)
-{
-       pcspkr_stop_sound();
-       input_unregister_device(dev);   /* this also does kfree() */
-
-       return 0;
-}
index e80079b..42bfc9e 100644 (file)
@@ -9,7 +9,6 @@
 #define __PCSP_INPUT_H__
 
 int pcspkr_input_init(struct input_dev **rdev, struct device *dev);
-int pcspkr_input_remove(struct input_dev *dev);
 void pcspkr_stop_sound(void);
 
 #endif
index da9983c..3cbc7a4 100644 (file)
@@ -115,7 +115,6 @@ struct snd_uart16550 {
        int irq;
 
        unsigned long base;
-       struct resource *res_base;
 
        unsigned int speed;
        unsigned int speed_base;
@@ -323,8 +322,7 @@ static int snd_uart16550_detect(struct snd_uart16550 *uart)
                return -ENODEV; /* Not configured */
        }
 
-       uart->res_base = request_region(io_base, 8, "Serial MIDI");
-       if (uart->res_base == NULL) {
+       if (!devm_request_region(uart->card->dev, io_base, 8, "Serial MIDI")) {
                snd_printk(KERN_ERR "u16550: can't grab port 0x%lx\n", io_base);
                return -EBUSY;
        }
@@ -752,21 +750,6 @@ static const struct snd_rawmidi_ops snd_uart16550_input =
        .trigger =      snd_uart16550_input_trigger,
 };
 
-static int snd_uart16550_free(struct snd_uart16550 *uart)
-{
-       if (uart->irq >= 0)
-               free_irq(uart->irq, uart);
-       release_and_free_resource(uart->res_base);
-       kfree(uart);
-       return 0;
-};
-
-static int snd_uart16550_dev_free(struct snd_device *device)
-{
-       struct snd_uart16550 *uart = device->device_data;
-       return snd_uart16550_free(uart);
-}
-
 static int snd_uart16550_create(struct snd_card *card,
                                unsigned long iobase,
                                int irq,
@@ -776,14 +759,11 @@ static int snd_uart16550_create(struct snd_card *card,
                                int droponfull,
                                struct snd_uart16550 **ruart)
 {
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_uart16550_dev_free,
-       };
        struct snd_uart16550 *uart;
        int err;
 
 
-       uart = kzalloc(sizeof(*uart), GFP_KERNEL);
+       uart = devm_kzalloc(card->dev, sizeof(*uart), GFP_KERNEL);
        if (!uart)
                return -ENOMEM;
        uart->adaptor = adaptor;
@@ -796,13 +776,12 @@ static int snd_uart16550_create(struct snd_card *card,
        err = snd_uart16550_detect(uart);
        if (err <= 0) {
                printk(KERN_ERR "no UART detected at 0x%lx\n", iobase);
-               snd_uart16550_free(uart);
                return -ENODEV;
        }
 
        if (irq >= 0 && irq != SNDRV_AUTO_IRQ) {
-               if (request_irq(irq, snd_uart16550_interrupt,
-                               0, "Serial MIDI", uart)) {
+               if (devm_request_irq(card->dev, irq, snd_uart16550_interrupt,
+                                    0, "Serial MIDI", uart)) {
                        snd_printk(KERN_WARNING
                                   "irq %d busy. Using Polling.\n", irq);
                } else {
@@ -819,13 +798,6 @@ static int snd_uart16550_create(struct snd_card *card,
        timer_setup(&uart->buffer_timer, snd_uart16550_buffer_timer, 0);
        uart->timer_running = 0;
 
-       /* Register device */
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, uart, &ops);
-       if (err < 0) {
-               snd_uart16550_free(uart);
-               return err;
-       }
-
        switch (uart->adaptor) {
        case SNDRV_SERIAL_MS124W_SA:
        case SNDRV_SERIAL_MS124W_MB:
@@ -927,8 +899,8 @@ static int snd_serial_probe(struct platform_device *devptr)
                return -ENODEV;
        }
 
-       err  = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
-                           0, &card);
+       err  = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
+                                0, &card);
        if (err < 0)
                return err;
 
@@ -939,11 +911,11 @@ static int snd_serial_probe(struct platform_device *devptr)
                                   base[dev], adaptor[dev], droponfull[dev],
                                   &uart);
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi);
        if (err < 0)
-               goto _err;
+               return err;
 
        sprintf(card->longname, "%s [%s] at %#lx, irq %d",
                card->shortname,
@@ -953,27 +925,16 @@ static int snd_serial_probe(struct platform_device *devptr)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto _err;
+               return err;
 
        platform_set_drvdata(devptr, card);
        return 0;
-
- _err:
-       snd_card_free(card);
-       return err;
-}
-
-static int snd_serial_remove(struct platform_device *devptr)
-{
-       snd_card_free(platform_get_drvdata(devptr));
-       return 0;
 }
 
 #define SND_SERIAL_DRIVER      "snd_serial_u16550"
 
 static struct platform_driver snd_serial_driver = {
        .probe          = snd_serial_probe,
-       .remove         =  snd_serial_remove,
        .driver         = {
                .name   = SND_SERIAL_DRIVER,
        },
index 4206d93..7f7eed6 100644 (file)
@@ -75,8 +75,8 @@ static int snd_virmidi_probe(struct platform_device *devptr)
        int idx, err;
        int dev = devptr->id;
 
-       err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_card_virmidi), &card);
+       err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_card_virmidi), &card);
        if (err < 0)
                return err;
        vmidi = card->private_data;
@@ -94,7 +94,7 @@ static int snd_virmidi_probe(struct platform_device *devptr)
 
                err = snd_virmidi_new(card, idx, &rmidi);
                if (err < 0)
-                       goto __nodev;
+                       return err;
                rdev = rmidi->private_data;
                vmidi->midi[idx] = rmidi;
                strcpy(rmidi->name, "Virtual Raw MIDI");
@@ -106,18 +106,10 @@ static int snd_virmidi_probe(struct platform_device *devptr)
        sprintf(card->longname, "Virtual MIDI Card %i", dev + 1);
 
        err = snd_card_register(card);
-       if (!err) {
-               platform_set_drvdata(devptr, card);
-               return 0;
-       }
-__nodev:
-       snd_card_free(card);
-       return err;
-}
+       if (err)
+               return err;
 
-static int snd_virmidi_remove(struct platform_device *devptr)
-{
-       snd_card_free(platform_get_drvdata(devptr));
+       platform_set_drvdata(devptr, card);
        return 0;
 }
 
@@ -125,7 +117,6 @@ static int snd_virmidi_remove(struct platform_device *devptr)
 
 static struct platform_driver snd_virmidi_driver = {
        .probe          = snd_virmidi_probe,
-       .remove         = snd_virmidi_remove,
        .driver         = {
                .name   = SND_VIRMIDI_DRIVER,
        },
index a10449a..18901e5 100644 (file)
@@ -774,6 +774,11 @@ int snd_vx_resume(struct vx_core *chip)
 EXPORT_SYMBOL(snd_vx_resume);
 #endif
 
+static void snd_vx_release(struct device *dev, void *data)
+{
+       snd_vx_free_firmware(data);
+}
+
 /**
  * snd_vx_create - constructor for struct vx_core
  * @card: card instance
@@ -784,6 +789,8 @@ EXPORT_SYMBOL(snd_vx_resume);
  * this function allocates the instance and prepare for the hardware
  * initialization.
  *
+ * The object is managed via devres, and will be automatically released.
+ *
  * return the instance pointer if successful, NULL in error.
  */
 struct vx_core *snd_vx_create(struct snd_card *card,
@@ -796,8 +803,9 @@ struct vx_core *snd_vx_create(struct snd_card *card,
        if (snd_BUG_ON(!card || !hw || !ops))
                return NULL;
 
-       chip = kzalloc(sizeof(*chip) + extra_size, GFP_KERNEL);
-       if (! chip)
+       chip = devres_alloc(snd_vx_release, sizeof(*chip) + extra_size,
+                           GFP_KERNEL);
+       if (!chip)
                return NULL;
        mutex_init(&chip->lock);
        chip->irq = -1;
index 93d5df1..2bd4485 100644 (file)
 #define  V2_CLOCK_RATE_SHIFT                   3
 #define  V2_CLOCK_SRC_MASK                     0x00000007
 #define  V2_CLOCK_SRC_SHIFT                    0
-#define   V2_CLOCK_SRC_AESEBU_ON_XLR           0x07
+#define   V2_CLOCK_SRC_AESEBU_ON_XLR           0x07    // In Traveler.
 #define   V2_CLOCK_SRC_ADAT_ON_DSUB            0x05
 #define   V2_CLOCK_SRC_WORD_ON_BNC             0x04
 #define   V2_CLOCK_SRC_SPH                     0x03
-#define   V2_CLOCK_SRC_SPDIF                   0x02    // on either coaxial or optical
+#define   V2_CLOCK_SRC_SPDIF                   0x02    // on either coaxial or optical. AES/EBU in 896HD.
 #define   V2_CLOCK_SRC_ADAT_ON_OPT             0x01
 #define   V2_CLOCK_SRC_INTERNAL                        0x00
 #define  V2_CLOCK_FETCH_ENABLE                 0x02000000
@@ -100,7 +100,9 @@ static int get_clock_source(struct snd_motu *motu, u32 data,
                bool support_iec60958_on_opt = (motu->spec == &snd_motu_spec_828mk2 ||
                                                motu->spec == &snd_motu_spec_traveler);
 
-               if (!support_iec60958_on_opt) {
+               if (motu->spec == &snd_motu_spec_896hd) {
+                       *src = SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR;
+               } else if (!support_iec60958_on_opt) {
                        *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
                } else {
                        __be32 reg;
@@ -129,6 +131,7 @@ static int get_clock_source(struct snd_motu *motu, u32 data,
                *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB;
                break;
        case V2_CLOCK_SRC_AESEBU_ON_XLR:
+               // For Traveler.
                *src = SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR;
                break;
        default:
@@ -153,7 +156,7 @@ int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu,
        return get_clock_source(motu, be32_to_cpu(reg), src);
 }
 
-// Expected for Traveler and 896HD, which implements Altera Cyclone EP1C3.
+// Expected for Traveler, which implements Altera Cyclone EP1C3.
 static int switch_fetching_mode_cyclone(struct snd_motu *motu, u32 *data,
                                        bool enable)
 {
@@ -190,6 +193,9 @@ int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu,
        if (motu->spec == &snd_motu_spec_828mk2) {
                // 828mkII implements Altera ACEX 1K EP1K30. Nothing to do.
                return 0;
+       } else if (motu->spec == &snd_motu_spec_896hd) {
+               // 896HD implements Altera Cyclone EP1C3 but nothing to do.
+               return 0;
        } else {
                __be32 reg;
                u32 data;
@@ -274,6 +280,14 @@ const struct snd_motu_spec snd_motu_spec_828mk2 = {
        .rx_fixed_pcm_chunks = {14, 14, 0},
 };
 
+const struct snd_motu_spec snd_motu_spec_896hd = {
+       .name = "896HD",
+       .protocol_version = SND_MOTU_PROTOCOL_V2,
+       // No support for MIDI.
+       .tx_fixed_pcm_chunks = {14, 14, 8},
+       .rx_fixed_pcm_chunks = {14, 14, 8},
+};
+
 const struct snd_motu_spec snd_motu_spec_traveler = {
        .name = "Traveler",
        .protocol_version = SND_MOTU_PROTOCOL_V2,
index 5431365..f654262 100644 (file)
@@ -153,6 +153,7 @@ static const struct ieee1394_device_id motu_id_table[] = {
        SND_MOTU_DEV_ENTRY(0x000001, &snd_motu_spec_828),
        SND_MOTU_DEV_ENTRY(0x000002, &snd_motu_spec_896),
        SND_MOTU_DEV_ENTRY(0x000003, &snd_motu_spec_828mk2),
+       SND_MOTU_DEV_ENTRY(0x000005, &snd_motu_spec_896hd),
        SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler),
        SND_MOTU_DEV_ENTRY(0x00000d, &snd_motu_spec_ultralite),
        SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre),
index 73f36d1..f1a830b 100644 (file)
@@ -126,6 +126,7 @@ extern const struct snd_motu_spec snd_motu_spec_828;
 extern const struct snd_motu_spec snd_motu_spec_896;
 
 extern const struct snd_motu_spec snd_motu_spec_828mk2;
+extern const struct snd_motu_spec snd_motu_spec_896hd;
 extern const struct snd_motu_spec snd_motu_spec_traveler;
 extern const struct snd_motu_spec snd_motu_spec_ultralite;
 extern const struct snd_motu_spec snd_motu_spec_8pre;
index fa5bed0..9ac8737 100644 (file)
@@ -124,28 +124,24 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
        struct snd_ad1816a *chip;
        struct snd_opl3 *opl3;
 
-       error = snd_card_new(&pcard->card->dev,
-                            index[dev], id[dev], THIS_MODULE,
-                            sizeof(struct snd_ad1816a), &card);
+       error = snd_devm_card_new(&pcard->card->dev,
+                                 index[dev], id[dev], THIS_MODULE,
+                                 sizeof(struct snd_ad1816a), &card);
        if (error < 0)
                return error;
        chip = card->private_data;
 
        error = snd_card_ad1816a_pnp(dev, pcard, pid);
-       if (error) {
-               snd_card_free(card);
+       if (error)
                return error;
-       }
 
        error = snd_ad1816a_create(card, port[dev],
                                   irq[dev],
                                   dma1[dev],
                                   dma2[dev],
                                   chip);
-       if (error) {
-               snd_card_free(card);
+       if (error)
                return error;
-       }
        if (clockfreq[dev] >= 5000 && clockfreq[dev] <= 100000)
                chip->clock_freq = clockfreq[dev];
 
@@ -155,22 +151,16 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
                card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
 
        error = snd_ad1816a_pcm(chip, 0);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        error = snd_ad1816a_mixer(chip);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        error = snd_ad1816a_timer(chip, 0);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        if (mpu_port[dev] > 0) {
                if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
@@ -186,18 +176,14 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
                        printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx.\n", fm_port[dev], fm_port[dev] + 2);
                } else {
                        error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-                       if (error < 0) {
-                               snd_card_free(card);
+                       if (error < 0)
                                return error;
-                       }
                }
        }
 
        error = snd_card_register(card);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        pnp_set_card_drvdata(pcard, card);
        return 0;
 }
@@ -223,12 +209,6 @@ static int snd_ad1816a_pnp_detect(struct pnp_card_link *card,
         return -ENODEV;
 }
 
-static void snd_ad1816a_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_ad1816a_pnp_suspend(struct pnp_card_link *pcard,
                                   pm_message_t state)
@@ -255,7 +235,6 @@ static struct pnp_card_driver ad1816a_pnpc_driver = {
        .name           = "ad1816a",
        .id_table       = snd_ad1816a_pnpids,
        .probe          = snd_ad1816a_pnp_detect,
-       .remove         = snd_ad1816a_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_ad1816a_pnp_suspend,
        .resume         = snd_ad1816a_pnp_resume,
index 6d4999b..132a095 100644 (file)
@@ -541,28 +541,6 @@ static int snd_ad1816a_probe(struct snd_ad1816a *chip)
        return 0;
 }
 
-static int snd_ad1816a_free(struct snd_ad1816a *chip)
-{
-       release_and_free_resource(chip->res_port);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, (void *) chip);
-       if (chip->dma1 >= 0) {
-               snd_dma_disable(chip->dma1);
-               free_dma(chip->dma1);
-       }
-       if (chip->dma2 >= 0) {
-               snd_dma_disable(chip->dma2);
-               free_dma(chip->dma2);
-       }
-       return 0;
-}
-
-static int snd_ad1816a_dev_free(struct snd_device *device)
-{
-       struct snd_ad1816a *chip = device->device_data;
-       return snd_ad1816a_free(chip);
-}
-
 static const char *snd_ad1816a_chip_id(struct snd_ad1816a *chip)
 {
        switch (chip->hardware) {
@@ -580,37 +558,31 @@ int snd_ad1816a_create(struct snd_card *card,
                       unsigned long port, int irq, int dma1, int dma2,
                       struct snd_ad1816a *chip)
 {
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_ad1816a_dev_free,
-       };
        int error;
 
        chip->irq = -1;
        chip->dma1 = -1;
        chip->dma2 = -1;
 
-       chip->res_port = request_region(port, 16, "AD1816A");
+       chip->res_port = devm_request_region(card->dev, port, 16, "AD1816A");
        if (!chip->res_port) {
                snd_printk(KERN_ERR "ad1816a: can't grab port 0x%lx\n", port);
-               snd_ad1816a_free(chip);
                return -EBUSY;
        }
-       if (request_irq(irq, snd_ad1816a_interrupt, 0, "AD1816A", (void *) chip)) {
+       if (devm_request_irq(card->dev, irq, snd_ad1816a_interrupt, 0,
+                            "AD1816A", (void *) chip)) {
                snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq);
-               snd_ad1816a_free(chip);
                return -EBUSY;
        }
        chip->irq = irq;
        card->sync_irq = chip->irq;
-       if (request_dma(dma1, "AD1816A - 1")) {
+       if (snd_devm_request_dma(card->dev, dma1, "AD1816A - 1")) {
                snd_printk(KERN_ERR "ad1816a: can't grab DMA1 %d\n", dma1);
-               snd_ad1816a_free(chip);
                return -EBUSY;
        }
        chip->dma1 = dma1;
-       if (request_dma(dma2, "AD1816A - 2")) {
+       if (snd_devm_request_dma(card->dev, dma2, "AD1816A - 2")) {
                snd_printk(KERN_ERR "ad1816a: can't grab DMA2 %d\n", dma2);
-               snd_ad1816a_free(chip);
                return -EBUSY;
        }
        chip->dma2 = dma2;
@@ -620,20 +592,11 @@ int snd_ad1816a_create(struct snd_card *card,
        spin_lock_init(&chip->lock);
 
        error = snd_ad1816a_probe(chip);
-       if (error) {
-               snd_ad1816a_free(chip);
+       if (error)
                return error;
-       }
 
        snd_ad1816a_init(chip);
 
-       /* Register device */
-       error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (error < 0) {
-               snd_ad1816a_free(chip);
-               return error;
-       }
-
        return 0;
 }
 
index edafb49..c471ac2 100644 (file)
@@ -72,7 +72,7 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n)
        struct snd_wss *chip;
        int error;
 
-       error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
+       error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
        if (error < 0)
                return error;
 
@@ -80,17 +80,17 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n)
                        thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT,
                        0, &chip);
        if (error < 0)
-               goto out;
+               return error;
 
        card->private_data = chip;
 
        error = snd_wss_pcm(chip, 0);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_wss_mixer(chip);
        if (error < 0)
-               goto out;
+               return error;
 
        strscpy(card->driver, "AD1848", sizeof(card->driver));
        strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
@@ -106,18 +106,10 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n)
 
        error = snd_card_register(card);
        if (error < 0)
-               goto out;
+               return error;
 
        dev_set_drvdata(dev, card);
        return 0;
-
-out:   snd_card_free(card);
-       return error;
-}
-
-static void snd_ad1848_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 #ifdef CONFIG_PM
@@ -145,7 +137,6 @@ static int snd_ad1848_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_ad1848_driver = {
        .match          = snd_ad1848_match,
        .probe          = snd_ad1848_probe,
-       .remove         = snd_ad1848_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_ad1848_suspend,
        .resume         = snd_ad1848_resume,
index e6cd7c4..f079ba4 100644 (file)
@@ -43,30 +43,23 @@ static int snd_adlib_match(struct device *dev, unsigned int n)
        return 1;
 }
 
-static void snd_adlib_free(struct snd_card *card)
-{
-       release_and_free_resource(card->private_data);
-}
-
 static int snd_adlib_probe(struct device *dev, unsigned int n)
 {
        struct snd_card *card;
        struct snd_opl3 *opl3;
        int error;
 
-       error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
+       error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
        if (error < 0) {
                dev_err(dev, "could not create card\n");
                return error;
        }
 
-       card->private_data = request_region(port[n], 4, CRD_NAME);
+       card->private_data = devm_request_region(dev, port[n], 4, CRD_NAME);
        if (!card->private_data) {
                dev_err(dev, "could not grab ports\n");
-               error = -EBUSY;
-               goto out;
+               return -EBUSY;
        }
-       card->private_free = snd_adlib_free;
 
        strcpy(card->driver, DEV_NAME);
        strcpy(card->shortname, CRD_NAME);
@@ -75,37 +68,28 @@ static int snd_adlib_probe(struct device *dev, unsigned int n)
        error = snd_opl3_create(card, port[n], port[n] + 2, OPL3_HW_AUTO, 1, &opl3);
        if (error < 0) {
                dev_err(dev, "could not create OPL\n");
-               goto out;
+               return error;
        }
 
        error = snd_opl3_hwdep_new(opl3, 0, 0, NULL);
        if (error < 0) {
                dev_err(dev, "could not create FM\n");
-               goto out;
+               return error;
        }
 
        error = snd_card_register(card);
        if (error < 0) {
                dev_err(dev, "could not register card\n");
-               goto out;
+               return error;
        }
 
        dev_set_drvdata(dev, card);
        return 0;
-
-out:   snd_card_free(card);
-       return error;
-}
-
-static void snd_adlib_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 static struct isa_driver snd_adlib_driver = {
        .match          = snd_adlib_match,
        .probe          = snd_adlib_probe,
-       .remove         = snd_adlib_remove,
 
        .driver         = {
                .name   = DEV_NAME
index d4597fd..d582eff 100644 (file)
@@ -170,18 +170,16 @@ static int snd_card_als100_probe(int dev,
        struct snd_card_als100 *acard;
        struct snd_opl3 *opl3;
 
-       error = snd_card_new(&pcard->card->dev,
-                            index[dev], id[dev], THIS_MODULE,
-                            sizeof(struct snd_card_als100), &card);
+       error = snd_devm_card_new(&pcard->card->dev,
+                                 index[dev], id[dev], THIS_MODULE,
+                                 sizeof(struct snd_card_als100), &card);
        if (error < 0)
                return error;
        acard = card->private_data;
 
        error = snd_card_als100_pnp(dev, acard, pcard, pid);
-       if (error) {
-               snd_card_free(card);
+       if (error)
                return error;
-       }
 
        if (pid->driver_data == SB_HW_DT019X)
                dma16[dev] = -1;
@@ -191,10 +189,8 @@ static int snd_card_als100_probe(int dev,
                                  dma8[dev], dma16[dev],
                                  pid->driver_data,
                                  &chip);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        acard->chip = chip;
 
        if (pid->driver_data == SB_HW_DT019X) {
@@ -213,16 +209,12 @@ static int snd_card_als100_probe(int dev,
        }
 
        error = snd_sb16dsp_pcm(chip, 0);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        error = snd_sbmixer_new(chip);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
                int mpu_type = MPU401_HW_ALS100;
@@ -249,23 +241,17 @@ static int snd_card_als100_probe(int dev,
                                   fm_port[dev], fm_port[dev] + 2);
                } else {
                        error = snd_opl3_timer_new(opl3, 0, 1);
-                       if (error < 0) {
-                               snd_card_free(card);
+                       if (error < 0)
                                return error;
-                       }
                        error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-                       if (error < 0) {
-                               snd_card_free(card);
+                       if (error < 0)
                                return error;
-                       }
                }
        }
 
        error = snd_card_register(card);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        pnp_set_card_drvdata(pcard, card);
        return 0;
 }
@@ -291,12 +277,6 @@ static int snd_als100_pnp_detect(struct pnp_card_link *card,
        return -ENODEV;
 }
 
-static void snd_als100_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_als100_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -327,7 +307,6 @@ static struct pnp_card_driver als100_pnpc_driver = {
        .name           = "als100",
         .id_table       = snd_als100_pnpids,
         .probe          = snd_als100_pnp_detect,
-       .remove         = snd_als100_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_als100_pnp_suspend,
        .resume         = snd_als100_pnp_resume,
index dd5c059..761cd19 100644 (file)
@@ -169,33 +169,27 @@ static int snd_card_azt2320_probe(int dev,
        struct snd_wss *chip;
        struct snd_opl3 *opl3;
 
-       error = snd_card_new(&pcard->card->dev,
-                            index[dev], id[dev], THIS_MODULE,
-                            sizeof(struct snd_card_azt2320), &card);
+       error = snd_devm_card_new(&pcard->card->dev,
+                                 index[dev], id[dev], THIS_MODULE,
+                                 sizeof(struct snd_card_azt2320), &card);
        if (error < 0)
                return error;
        acard = card->private_data;
 
        error = snd_card_azt2320_pnp(dev, acard, pcard, pid);
-       if (error) {
-               snd_card_free(card);
+       if (error)
                return error;
-       }
 
        error = snd_card_azt2320_enable_wss(port[dev]);
-       if (error) {
-               snd_card_free(card);
+       if (error)
                return error;
-       }
 
        error = snd_wss_create(card, wss_port[dev], -1,
                               irq[dev],
                               dma1[dev], dma2[dev],
                               WSS_HW_DETECT, 0, &chip);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        strcpy(card->driver, "AZT2320");
        strcpy(card->shortname, "Aztech AZT2320");
@@ -203,20 +197,14 @@ static int snd_card_azt2320_probe(int dev,
                card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
 
        error = snd_wss_pcm(chip, 0);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        error = snd_wss_mixer(chip);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        error = snd_wss_timer(chip, 0);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
                if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320,
@@ -233,23 +221,17 @@ static int snd_card_azt2320_probe(int dev,
                                   fm_port[dev], fm_port[dev] + 2);
                } else {
                        error = snd_opl3_timer_new(opl3, 1, 2);
-                       if (error < 0) {
-                               snd_card_free(card);
+                       if (error < 0)
                                return error;
-                       }
                        error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-                       if (error < 0) {
-                               snd_card_free(card);
+                       if (error < 0)
                                return error;
-                       }
                }
        }
 
        error = snd_card_register(card);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        pnp_set_card_drvdata(pcard, card);
        return 0;
 }
@@ -275,12 +257,6 @@ static int snd_azt2320_pnp_detect(struct pnp_card_link *card,
         return -ENODEV;
 }
 
-static void snd_azt2320_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_azt2320_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -310,7 +286,6 @@ static struct pnp_card_driver azt2320_pnpc_driver = {
        .name           = "azt2320",
        .id_table       = snd_azt2320_pnpids,
        .probe          = snd_azt2320_pnp_detect,
-       .remove         = snd_azt2320_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_azt2320_pnp_suspend,
        .resume         = snd_azt2320_pnp_resume,
index 3b9fbb0..8902cfb 100644 (file)
@@ -294,8 +294,8 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
        }
        outb(val, port);
 
-       err = snd_card_new(pdev, index[ndev], id[ndev], THIS_MODULE,
-                          sizeof(struct snd_cmi8328), &card);
+       err = snd_devm_card_new(pdev, index[ndev], id[ndev], THIS_MODULE,
+                               sizeof(struct snd_cmi8328), &card);
        if (err < 0)
                return err;
        cmi = card->private_data;
@@ -306,18 +306,18 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
        err = snd_wss_create(card, port + 4, -1, irq[ndev], dma1[ndev],
                        dma2[ndev], WSS_HW_DETECT, 0, &cmi->wss);
        if (err < 0)
-               goto error;
+               return err;
 
        err = snd_wss_pcm(cmi->wss, 0);
        if (err < 0)
-               goto error;
+               return err;
 
        err = snd_wss_mixer(cmi->wss);
        if (err < 0)
-               goto error;
+               return err;
        err = snd_cmi8328_mixer(cmi->wss);
        if (err < 0)
-               goto error;
+               return err;
 
        if (snd_wss_timer(cmi->wss, 0) < 0)
                snd_printk(KERN_WARNING "error initializing WSS timer\n");
@@ -371,24 +371,21 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
        dev_set_drvdata(pdev, card);
        err = snd_card_register(card);
        if (err < 0)
-               goto error;
+               return err;
 #ifdef SUPPORT_JOYSTICK
        if (!gameport[ndev])
                return 0;
        /* gameport is hardwired to 0x200 */
-       res = request_region(0x200, 8, "CMI8328 gameport");
+       res = devm_request_region(pdev, 0x200, 8, "CMI8328 gameport");
        if (!res)
                snd_printk(KERN_WARNING "unable to allocate gameport I/O port\n");
        else {
                struct gameport *gp = cmi->gameport = gameport_allocate_port();
-               if (!cmi->gameport)
-                       release_and_free_resource(res);
-               else {
+               if (cmi->gameport) {
                        gameport_set_name(gp, "CMI8328 Gameport");
                        gameport_set_phys(gp, "%s/gameport0", dev_name(pdev));
                        gameport_set_dev_parent(gp, pdev);
                        gp->io = 0x200;
-                       gameport_set_port_data(gp, res);
                        /* Enable gameport */
                        snd_cmi8328_cfg_write(port, CFG1,
                                        CFG1_SB_DISABLE | CFG1_GAMEPORT);
@@ -397,10 +394,6 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
        }
 #endif
        return 0;
-error:
-       snd_card_free(card);
-
-       return err;
 }
 
 static void snd_cmi8328_remove(struct device *pdev, unsigned int dev)
@@ -409,17 +402,13 @@ static void snd_cmi8328_remove(struct device *pdev, unsigned int dev)
        struct snd_cmi8328 *cmi = card->private_data;
 
 #ifdef SUPPORT_JOYSTICK
-       if (cmi->gameport) {
-               struct resource *res = gameport_get_port_data(cmi->gameport);
+       if (cmi->gameport)
                gameport_unregister_port(cmi->gameport);
-               release_and_free_resource(res);
-       }
 #endif
        /* disable everything */
        snd_cmi8328_cfg_write(cmi->port, CFG1, CFG1_SB_DISABLE);
        snd_cmi8328_cfg_write(cmi->port, CFG2, 0);
        snd_cmi8328_cfg_write(cmi->port, CFG3, 0);
-       snd_card_free(card);
 }
 
 #ifdef CONFIG_PM
index ef6d0a2..f209b16 100644 (file)
@@ -507,8 +507,8 @@ static int snd_cmi8330_card_new(struct device *pdev, int dev,
        struct snd_cmi8330 *acard;
        int err;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_cmi8330), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_cmi8330), &card);
        if (err < 0) {
                snd_printk(KERN_ERR PFX "could not get a new card\n");
                return err;
@@ -629,20 +629,12 @@ static int snd_cmi8330_isa_probe(struct device *pdev,
        if (err < 0)
                return err;
        err = snd_cmi8330_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        dev_set_drvdata(pdev, card);
        return 0;
 }
 
-static void snd_cmi8330_isa_remove(struct device *devptr,
-                                 unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-}
-
 #ifdef CONFIG_PM
 static int snd_cmi8330_isa_suspend(struct device *dev, unsigned int n,
                                   pm_message_t state)
@@ -661,7 +653,6 @@ static int snd_cmi8330_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_cmi8330_driver = {
        .match          = snd_cmi8330_isa_match,
        .probe          = snd_cmi8330_isa_probe,
-       .remove         = snd_cmi8330_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cmi8330_isa_suspend,
        .resume         = snd_cmi8330_isa_resume,
@@ -693,25 +684,16 @@ static int snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
        res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid);
        if (res < 0) {
                snd_printk(KERN_ERR PFX "PnP detection failed\n");
-               snd_card_free(card);
                return res;
        }
        res = snd_cmi8330_probe(card, dev);
-       if (res < 0) {
-               snd_card_free(card);
+       if (res < 0)
                return res;
-       }
        pnp_set_card_drvdata(pcard, card);
        dev++;
        return 0;
 }
 
-static void snd_cmi8330_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_cmi8330_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -729,7 +711,6 @@ static struct pnp_card_driver cmi8330_pnpc_driver = {
        .name = "cmi8330",
        .id_table = snd_cmi8330_pnpids,
        .probe = snd_cmi8330_pnp_detect,
-       .remove = snd_cmi8330_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cmi8330_pnp_suspend,
        .resume         = snd_cmi8330_pnp_resume,
index ec054b9..1e89233 100644 (file)
@@ -79,20 +79,20 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n)
        struct snd_wss *chip;
        int error;
 
-       error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
+       error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
        if (error < 0)
                return error;
 
        error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n],
                        WSS_HW_DETECT, 0, &chip);
        if (error < 0)
-               goto out;
+               return error;
 
        card->private_data = chip;
 
        error = snd_wss_pcm(chip, 0);
        if (error < 0)
-               goto out;
+               return error;
 
        strscpy(card->driver, "CS4231", sizeof(card->driver));
        strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
@@ -108,11 +108,11 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n)
 
        error = snd_wss_mixer(chip);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_wss_timer(chip, 0);
        if (error < 0)
-               goto out;
+               return error;
 
        if (mpu_port[n] > 0 && mpu_port[n] != SNDRV_AUTO_PORT) {
                if (mpu_irq[n] == SNDRV_AUTO_IRQ)
@@ -125,18 +125,10 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n)
 
        error = snd_card_register(card);
        if (error < 0)
-               goto out;
+               return error;
 
        dev_set_drvdata(dev, card);
        return 0;
-
-out:   snd_card_free(card);
-       return error;
-}
-
-static void snd_cs4231_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 #ifdef CONFIG_PM
@@ -164,7 +156,6 @@ static int snd_cs4231_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_cs4231_driver = {
        .match          = snd_cs4231_match,
        .probe          = snd_cs4231_probe,
-       .remove         = snd_cs4231_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cs4231_suspend,
        .resume         = snd_cs4231_resume,
index 0b7fd17..b6bdebd 100644 (file)
@@ -76,7 +76,6 @@ static int pnp_registered;
 
 struct snd_card_cs4236 {
        struct snd_wss *chip;
-       struct resource *res_sb_port;
 #ifdef CONFIG_PNP
        struct pnp_dev *wss;
        struct pnp_dev *ctrl;
@@ -309,24 +308,16 @@ static int snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard,
 #define is_isapnp_selected(dev)                0
 #endif
 
-static void snd_card_cs4236_free(struct snd_card *card)
-{
-       struct snd_card_cs4236 *acard = card->private_data;
-
-       release_and_free_resource(acard->res_sb_port);
-}
-
 static int snd_cs423x_card_new(struct device *pdev, int dev,
                               struct snd_card **cardp)
 {
        struct snd_card *card;
        int err;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_card_cs4236), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_card_cs4236), &card);
        if (err < 0)
                return err;
-       card->private_free = snd_card_cs4236_free;
        *cardp = card;
        return 0;
 }
@@ -340,8 +331,8 @@ static int snd_cs423x_probe(struct snd_card *card, int dev)
 
        acard = card->private_data;
        if (sb_port[dev] > 0 && sb_port[dev] != SNDRV_AUTO_PORT) {
-               acard->res_sb_port = request_region(sb_port[dev], 16, IDENT " SB");
-               if (!acard->res_sb_port) {
+               if (!devm_request_region(card->dev, sb_port[dev], 16,
+                                        IDENT " SB")) {
                        printk(KERN_ERR IDENT ": unable to register SB port at 0x%lx\n", sb_port[dev]);
                        return -EBUSY;
                }
@@ -448,21 +439,12 @@ static int snd_cs423x_isa_probe(struct device *pdev,
        if (err < 0)
                return err;
        err = snd_cs423x_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
-
        dev_set_drvdata(pdev, card);
        return 0;
 }
 
-static void snd_cs423x_isa_remove(struct device *pdev,
-                                unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(pdev));
-}
-
 #ifdef CONFIG_PM
 static int snd_cs423x_suspend(struct snd_card *card)
 {
@@ -495,7 +477,6 @@ static int snd_cs423x_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver cs423x_isa_driver = {
        .match          = snd_cs423x_isa_match,
        .probe          = snd_cs423x_isa_probe,
-       .remove         = snd_cs423x_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cs423x_isa_suspend,
        .resume         = snd_cs423x_isa_resume,
@@ -539,24 +520,16 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
        err = snd_card_cs423x_pnp(dev, card->private_data, pdev, cdev);
        if (err < 0) {
                printk(KERN_ERR "PnP BIOS detection failed for " IDENT "\n");
-               snd_card_free(card);
                return err;
        }
        err = snd_cs423x_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pnp_set_drvdata(pdev, card);
        dev++;
        return 0;
 }
 
-static void snd_cs423x_pnp_remove(struct pnp_dev *pdev)
-{
-       snd_card_free(pnp_get_drvdata(pdev));
-}
-
 #ifdef CONFIG_PM
 static int snd_cs423x_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
 {
@@ -573,7 +546,6 @@ static struct pnp_driver cs423x_pnp_driver = {
        .name = "cs423x-pnpbios",
        .id_table = snd_cs423x_pnpbiosids,
        .probe = snd_cs423x_pnpbios_detect,
-       .remove = snd_cs423x_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cs423x_pnp_suspend,
        .resume         = snd_cs423x_pnp_resume,
@@ -601,25 +573,16 @@ static int snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
        if (res < 0) {
                printk(KERN_ERR "isapnp detection failed and probing for " IDENT
                       " is not supported\n");
-               snd_card_free(card);
                return res;
        }
        res = snd_cs423x_probe(card, dev);
-       if (res < 0) {
-               snd_card_free(card);
+       if (res < 0)
                return res;
-       }
        pnp_set_card_drvdata(pcard, card);
        dev++;
        return 0;
 }
 
-static void snd_cs423x_pnpc_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_cs423x_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -637,7 +600,6 @@ static struct pnp_card_driver cs423x_pnpc_driver = {
        .name = CS423X_ISAPNP_DRIVER,
        .id_table = snd_cs423x_pnpids,
        .probe = snd_cs423x_pnpc_detect,
-       .remove = snd_cs423x_pnpc_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cs423x_pnpc_suspend,
        .resume         = snd_cs423x_pnpc_resume,
index 63957ae..35f2591 100644 (file)
@@ -298,7 +298,6 @@ int snd_cs4236_create(struct snd_card *card,
        if (cport < 0x100 || cport == SNDRV_AUTO_PORT) {
                snd_printk(KERN_ERR "please, specify control port "
                           "for CS4236+ chips\n");
-               snd_device_free(card, chip);
                return -ENODEV;
        }
        ver1 = snd_cs4236_ctrl_in(chip, 1);
@@ -308,7 +307,6 @@ int snd_cs4236_create(struct snd_card *card,
        if (ver1 != ver2) {
                snd_printk(KERN_ERR "CS4236+ chip detected, but "
                           "control port 0x%lx is not valid\n", cport);
-               snd_device_free(card, chip);
                return -ENODEV;
        }
        snd_cs4236_ctrl_out(chip, 0, 0x00);
index 750d499..f935b56 100644 (file)
@@ -166,36 +166,27 @@ static int snd_es1688_isa_probe(struct device *dev, unsigned int n)
        struct snd_card *card;
        int error;
 
-       error = snd_card_new(dev, index[n], id[n], THIS_MODULE,
-                            sizeof(struct snd_es1688), &card);
+       error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE,
+                                 sizeof(struct snd_es1688), &card);
        if (error < 0)
                return error;
 
        error = snd_es1688_legacy_create(card, dev, n);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_es1688_probe(card, n);
        if (error < 0)
-               goto out;
+               return error;
 
        dev_set_drvdata(dev, card);
 
        return 0;
-out:
-       snd_card_free(card);
-       return error;
-}
-
-static void snd_es1688_isa_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 static struct isa_driver snd_es1688_driver = {
        .match          = snd_es1688_match,
        .probe          = snd_es1688_isa_probe,
-       .remove         = snd_es1688_isa_remove,
 #if 0  /* FIXME */
        .suspend        = snd_es1688_suspend,
        .resume         = snd_es1688_resume,
@@ -249,22 +240,18 @@ static int snd_es968_pnp_detect(struct pnp_card_link *pcard,
        if (dev == SNDRV_CARDS)
                return -ENODEV;
 
-       error = snd_card_new(&pcard->card->dev,
-                            index[dev], id[dev], THIS_MODULE,
-                            sizeof(struct snd_es1688), &card);
+       error = snd_devm_card_new(&pcard->card->dev,
+                                 index[dev], id[dev], THIS_MODULE,
+                                 sizeof(struct snd_es1688), &card);
        if (error < 0)
                return error;
 
        error = snd_card_es968_pnp(card, dev, pcard, pid);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        error = snd_es1688_probe(card, dev);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        pnp_set_card_drvdata(pcard, card);
        snd_es968_pnp_is_probed = 1;
        return 0;
@@ -272,8 +259,6 @@ static int snd_es968_pnp_detect(struct pnp_card_link *pcard,
 
 static void snd_es968_pnp_remove(struct pnp_card_link *pcard)
 {
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
        snd_es968_pnp_is_probed = 0;
 }
 
index 68b9c59..3fcd168 100644 (file)
@@ -87,9 +87,6 @@
 struct snd_es18xx {
        unsigned long port;             /* port of ESS chip */
        unsigned long ctrl_port;        /* Control port of ESS chip */
-       struct resource *res_port;
-       struct resource *res_mpu_port;
-       struct resource *res_ctrl_port;
        int irq;                        /* IRQ number of ESS chip */
        int dma1;                       /* DMA1 */
        int dma2;                       /* DMA2 */
@@ -1531,7 +1528,7 @@ static int snd_es18xx_initialize(struct snd_es18xx *chip,
         return 0;
 }
 
-static int snd_es18xx_identify(struct snd_es18xx *chip)
+static int snd_es18xx_identify(struct snd_card *card, struct snd_es18xx *chip)
 {
        int hi,lo;
 
@@ -1573,8 +1570,8 @@ static int snd_es18xx_identify(struct snd_es18xx *chip)
                udelay(10);
                chip->ctrl_port += inb(chip->port + 0x05);
 
-               chip->res_ctrl_port = request_region(chip->ctrl_port, 8, "ES18xx - CTRL");
-               if (!chip->res_ctrl_port) {
+               if (!devm_request_region(card->dev, chip->ctrl_port, 8,
+                                        "ES18xx - CTRL")) {
                        snd_printk(KERN_ERR PFX "unable go grab port 0x%lx\n", chip->ctrl_port);
                        return -EBUSY;
                }
@@ -1601,11 +1598,12 @@ static int snd_es18xx_identify(struct snd_es18xx *chip)
        return 0;
 }
 
-static int snd_es18xx_probe(struct snd_es18xx *chip,
+static int snd_es18xx_probe(struct snd_card *card,
+                           struct snd_es18xx *chip,
                            unsigned long mpu_port,
                            unsigned long fm_port)
 {
-       if (snd_es18xx_identify(chip) < 0) {
+       if (snd_es18xx_identify(card, chip) < 0) {
                snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port);
                 return -ENODEV;
        }
@@ -1722,31 +1720,6 @@ static int snd_es18xx_resume(struct snd_card *card)
 }
 #endif /* CONFIG_PM */
 
-static int snd_es18xx_free(struct snd_card *card)
-{
-       struct snd_es18xx *chip = card->private_data;
-
-       release_and_free_resource(chip->res_port);
-       release_and_free_resource(chip->res_ctrl_port);
-       release_and_free_resource(chip->res_mpu_port);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, (void *) card);
-       if (chip->dma1 >= 0) {
-               disable_dma(chip->dma1);
-               free_dma(chip->dma1);
-       }
-       if (chip->dma2 >= 0 && chip->dma1 != chip->dma2) {
-               disable_dma(chip->dma2);
-               free_dma(chip->dma2);
-       }
-       return 0;
-}
-
-static int snd_es18xx_dev_free(struct snd_device *device)
-{
-       return snd_es18xx_free(device->card);
-}
-
 static int snd_es18xx_new_device(struct snd_card *card,
                                 unsigned long port,
                                 unsigned long mpu_port,
@@ -1754,10 +1727,6 @@ static int snd_es18xx_new_device(struct snd_card *card,
                                 int irq, int dma1, int dma2)
 {
        struct snd_es18xx *chip = card->private_data;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_es18xx_dev_free,
-        };
-       int err;
 
        spin_lock_init(&chip->reg_lock);
        spin_lock_init(&chip->mixer_lock);
@@ -1768,45 +1737,34 @@ static int snd_es18xx_new_device(struct snd_card *card,
         chip->audio2_vol = 0x00;
        chip->active = 0;
 
-       chip->res_port = request_region(port, 16, "ES18xx");
-       if (chip->res_port == NULL) {
-               snd_es18xx_free(card);
+       if (!devm_request_region(card->dev, port, 16, "ES18xx")) {
                snd_printk(KERN_ERR PFX "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1);
                return -EBUSY;
        }
 
-       if (request_irq(irq, snd_es18xx_interrupt, 0, "ES18xx",
-                       (void *) card)) {
-               snd_es18xx_free(card);
+       if (devm_request_irq(card->dev, irq, snd_es18xx_interrupt, 0, "ES18xx",
+                            (void *) card)) {
                snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq);
                return -EBUSY;
        }
        chip->irq = irq;
        card->sync_irq = chip->irq;
 
-       if (request_dma(dma1, "ES18xx DMA 1")) {
-               snd_es18xx_free(card);
+       if (snd_devm_request_dma(card->dev, dma1, "ES18xx DMA 1")) {
                snd_printk(KERN_ERR PFX "unable to grap DMA1 %d\n", dma1);
                return -EBUSY;
        }
        chip->dma1 = dma1;
 
-       if (dma2 != dma1 && request_dma(dma2, "ES18xx DMA 2")) {
-               snd_es18xx_free(card);
+       if (dma2 != dma1 &&
+           snd_devm_request_dma(card->dev, dma2, "ES18xx DMA 2")) {
                snd_printk(KERN_ERR PFX "unable to grap DMA2 %d\n", dma2);
                return -EBUSY;
        }
        chip->dma2 = dma2;
 
-       if (snd_es18xx_probe(chip, mpu_port, fm_port) < 0) {
-               snd_es18xx_free(card);
+       if (snd_es18xx_probe(card, chip, mpu_port, fm_port) < 0)
                return -ENODEV;
-       }
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_es18xx_free(card);
-               return err;
-       }
         return 0;
 }
 
@@ -2088,8 +2046,8 @@ static int snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip,
 static int snd_es18xx_card_new(struct device *pdev, int dev,
                               struct snd_card **cardp)
 {
-       return snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                           sizeof(struct snd_es18xx), cardp);
+       return snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                                sizeof(struct snd_es18xx), cardp);
 }
 
 static int snd_audiodrive_probe(struct snd_card *card, int dev)
@@ -2164,10 +2122,8 @@ static int snd_es18xx_isa_probe1(int dev, struct device *devptr)
        if (err < 0)
                return err;
        err = snd_audiodrive_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        dev_set_drvdata(devptr, card);
        return 0;
 }
@@ -2215,12 +2171,6 @@ static int snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
        }
 }
 
-static void snd_es18xx_isa_remove(struct device *devptr,
-                                 unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-}
-
 #ifdef CONFIG_PM
 static int snd_es18xx_isa_suspend(struct device *dev, unsigned int n,
                                  pm_message_t state)
@@ -2239,7 +2189,6 @@ static int snd_es18xx_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_es18xx_isa_driver = {
        .match          = snd_es18xx_isa_match,
        .probe          = snd_es18xx_isa_probe,
-       .remove         = snd_es18xx_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_es18xx_isa_suspend,
        .resume         = snd_es18xx_isa_resume,
@@ -2271,25 +2220,16 @@ static int snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
        if (err < 0)
                return err;
        err = snd_audiodrive_pnp(dev, card->private_data, pdev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_audiodrive_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pnp_set_drvdata(pdev, card);
        dev++;
        return 0;
 }
 
-static void snd_audiodrive_pnp_remove(struct pnp_dev *pdev)
-{
-       snd_card_free(pnp_get_drvdata(pdev));
-}
-
 #ifdef CONFIG_PM
 static int snd_audiodrive_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
 {
@@ -2305,7 +2245,6 @@ static struct pnp_driver es18xx_pnp_driver = {
        .name = "es18xx-pnpbios",
        .id_table = snd_audiodrive_pnpbiosids,
        .probe = snd_audiodrive_pnp_detect,
-       .remove = snd_audiodrive_pnp_remove,
 #ifdef CONFIG_PM
        .suspend = snd_audiodrive_pnp_suspend,
        .resume = snd_audiodrive_pnp_resume,
@@ -2331,27 +2270,17 @@ static int snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
                return res;
 
        res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid);
-       if (res < 0) {
-               snd_card_free(card);
+       if (res < 0)
                return res;
-       }
        res = snd_audiodrive_probe(card, dev);
-       if (res < 0) {
-               snd_card_free(card);
+       if (res < 0)
                return res;
-       }
 
        pnp_set_card_drvdata(pcard, card);
        dev++;
        return 0;
 }
 
-static void snd_audiodrive_pnpc_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_audiodrive_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -2370,7 +2299,6 @@ static struct pnp_card_driver es18xx_pnpc_driver = {
        .name = "es18xx",
        .id_table = snd_audiodrive_pnpids,
        .probe = snd_audiodrive_pnpc_detect,
-       .remove = snd_audiodrive_pnpc_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_audiodrive_pnpc_suspend,
        .resume         = snd_audiodrive_pnpc_resume,
index d33d69f..ea001c8 100644 (file)
@@ -472,20 +472,10 @@ static void snd_galaxy_free(struct snd_card *card)
 {
        struct snd_galaxy *galaxy = card->private_data;
 
-       if (galaxy->wss_port) {
+       if (galaxy->wss_port)
                wss_set_config(galaxy->wss_port, 0);
-               ioport_unmap(galaxy->wss_port);
-               release_and_free_resource(galaxy->res_wss_port);
-       }
-       if (galaxy->config_port) {
+       if (galaxy->config_port)
                galaxy_set_config(galaxy, galaxy->config);
-               ioport_unmap(galaxy->config_port);
-               release_and_free_resource(galaxy->res_config_port);
-       }
-       if (galaxy->port) {
-               ioport_unmap(galaxy->port);
-               release_and_free_resource(galaxy->res_port);
-       }
 }
 
 static int snd_galaxy_probe(struct device *dev, unsigned int n)
@@ -496,56 +486,60 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n)
        u8 type;
        int err;
 
-       err = snd_card_new(dev, index[n], id[n], THIS_MODULE,
-                          sizeof(*galaxy), &card);
+       err = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE,
+                               sizeof(*galaxy), &card);
        if (err < 0)
                return err;
 
        card->private_free = snd_galaxy_free;
        galaxy = card->private_data;
 
-       galaxy->res_port = request_region(port[n], 16, DRV_NAME);
+       galaxy->res_port = devm_request_region(dev, port[n], 16, DRV_NAME);
        if (!galaxy->res_port) {
                dev_err(dev, "could not grab ports %#lx-%#lx\n", port[n],
                        port[n] + 15);
-               err = -EBUSY;
-               goto error;
+               return -EBUSY;
        }
-       galaxy->port = ioport_map(port[n], 16);
+       galaxy->port = devm_ioport_map(dev, port[n], 16);
+       if (!galaxy->port)
+               return -ENOMEM;
 
        err = galaxy_init(galaxy, &type);
        if (err < 0) {
                dev_err(dev, "did not find a Sound Galaxy at %#lx\n", port[n]);
-               goto error;
+               return err;
        }
        dev_info(dev, "Sound Galaxy (type %d) found at %#lx\n", type, port[n]);
 
-       galaxy->res_config_port = request_region(port[n] + GALAXY_PORT_CONFIG,
-                                                16, DRV_NAME);
+       galaxy->res_config_port =
+               devm_request_region(dev, port[n] + GALAXY_PORT_CONFIG, 16,
+                                   DRV_NAME);
        if (!galaxy->res_config_port) {
                dev_err(dev, "could not grab ports %#lx-%#lx\n",
                        port[n] + GALAXY_PORT_CONFIG,
                        port[n] + GALAXY_PORT_CONFIG + 15);
-               err = -EBUSY;
-               goto error;
+               return -EBUSY;
        }
-       galaxy->config_port = ioport_map(port[n] + GALAXY_PORT_CONFIG, 16);
-
+       galaxy->config_port =
+               devm_ioport_map(dev, port[n] + GALAXY_PORT_CONFIG, 16);
+       if (!galaxy->config_port)
+               return -ENOMEM;
        galaxy_config(galaxy, config[n]);
 
-       galaxy->res_wss_port = request_region(wss_port[n], 4, DRV_NAME);
+       galaxy->res_wss_port = devm_request_region(dev, wss_port[n], 4, DRV_NAME);
        if (!galaxy->res_wss_port)  {
                dev_err(dev, "could not grab ports %#lx-%#lx\n", wss_port[n],
                        wss_port[n] + 3);
-               err = -EBUSY;
-               goto error;
+               return -EBUSY;
        }
-       galaxy->wss_port = ioport_map(wss_port[n], 4);
+       galaxy->wss_port = devm_ioport_map(dev, wss_port[n], 4);
+       if (!galaxy->wss_port)
+               return -ENOMEM;
 
        err = galaxy_wss_config(galaxy, wss_config[n]);
        if (err < 0) {
                dev_err(dev, "could not configure WSS\n");
-               goto error;
+               return err;
        }
 
        strcpy(card->driver, DRV_NAME);
@@ -557,25 +551,25 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n)
        err = snd_wss_create(card, wss_port[n] + 4, -1, irq[n], dma1[n],
                             dma2[n], WSS_HW_DETECT, 0, &chip);
        if (err < 0)
-               goto error;
+               return err;
 
        err = snd_wss_pcm(chip, 0);
        if (err < 0)
-               goto error;
+               return err;
 
        err = snd_wss_mixer(chip);
        if (err < 0)
-               goto error;
+               return err;
 
        err = snd_wss_timer(chip, 0);
        if (err < 0)
-               goto error;
+               return err;
 
        if (mpu_port[n] >= 0) {
                err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
                                          mpu_port[n], 0, mpu_irq[n], NULL);
                if (err < 0)
-                       goto error;
+                       return err;
        }
 
        if (fm_port[n] >= 0) {
@@ -585,38 +579,28 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n)
                                      OPL3_HW_AUTO, 0, &opl3);
                if (err < 0) {
                        dev_err(dev, "no OPL device at %#lx\n", fm_port[n]);
-                       goto error;
+                       return err;
                }
                err = snd_opl3_timer_new(opl3, 1, 2);
                if (err < 0)
-                       goto error;
+                       return err;
 
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                if (err < 0)
-                       goto error;
+                       return err;
        }
 
        err = snd_card_register(card);
        if (err < 0)
-               goto error;
+               return err;
 
        dev_set_drvdata(dev, card);
        return 0;
-
-error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_galaxy_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 static struct isa_driver snd_galaxy_driver = {
        .match          = snd_galaxy_match,
        .probe          = snd_galaxy_probe,
-       .remove         = snd_galaxy_remove,
 
        .driver         = {
                .name   = DEV_NAME
index bca1caa..09cc53c 100644 (file)
@@ -135,7 +135,7 @@ static int snd_gusclassic_probe(struct device *dev, unsigned int n)
        struct snd_gus_card *gus;
        int error;
 
-       error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
+       error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
        if (error < 0)
                return error;
 
@@ -144,37 +144,37 @@ static int snd_gusclassic_probe(struct device *dev, unsigned int n)
 
        error = snd_gusclassic_create(card, dev, n, &gus);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_gusclassic_detect(gus);
        if (error < 0)
-               goto out;
+               return error;
 
        gus->joystick_dac = joystick_dac[n];
 
        error = snd_gus_initialize(gus);
        if (error < 0)
-               goto out;
+               return error;
 
        error = -ENODEV;
        if (gus->max_flag || gus->ess_flag) {
                dev_err(dev, "GUS Classic or ACE soundcard was "
                        "not detected at 0x%lx\n", gus->gf1.port);
-               goto out;
+               return error;
        }
 
        error = snd_gf1_new_mixer(gus);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_gf1_pcm_new(gus, 0, 0);
        if (error < 0)
-               goto out;
+               return error;
 
        if (!gus->ace_flag) {
                error = snd_gf1_rawmidi_new(gus, 0);
                if (error < 0)
-                       goto out;
+                       return error;
        }
 
        sprintf(card->longname + strlen(card->longname),
@@ -187,27 +187,17 @@ static int snd_gusclassic_probe(struct device *dev, unsigned int n)
 
        error = snd_card_register(card);
        if (error < 0)
-               goto out;
+               return error;
 
        dev_set_drvdata(dev, card);
        return 0;
-
-out:   snd_card_free(card);
-       return error;
-}
-
-static void snd_gusclassic_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 static struct isa_driver snd_gusclassic_driver = {
        .match          = snd_gusclassic_match,
        .probe          = snd_gusclassic_probe,
-       .remove         = snd_gusclassic_remove,
 #if 0  /* FIXME */
        .suspend        = snd_gusclassic_suspend,
-       .remove         = snd_gusclassic_remove,
 #endif
        .driver         = {
                .name   = DEV_NAME
index a409a4a..63d9f2d 100644 (file)
@@ -228,8 +228,8 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n)
        struct snd_opl3 *opl3;
        int error;
 
-       error = snd_card_new(dev, index[n], id[n], THIS_MODULE,
-                            sizeof(struct snd_es1688), &card);
+       error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE,
+                                 sizeof(struct snd_es1688), &card);
        if (error < 0)
                return error;
 
@@ -243,56 +243,56 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n)
 
        error = snd_gusextreme_es1688_create(card, es1688, dev, n);
        if (error < 0)
-               goto out;
+               return error;
 
        if (gf1_port[n] < 0)
                gf1_port[n] = es1688->port + 0x20;
 
        error = snd_gusextreme_gus_card_create(card, dev, n, &gus);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_gusextreme_detect(gus, es1688);
        if (error < 0)
-               goto out;
+               return error;
 
        gus->joystick_dac = joystick_dac[n];
 
        error = snd_gus_initialize(gus);
        if (error < 0)
-               goto out;
+               return error;
 
        error = -ENODEV;
        if (!gus->ess_flag) {
                dev_err(dev, "GUS Extreme soundcard was not "
                        "detected at 0x%lx\n", gus->gf1.port);
-               goto out;
+               return error;
        }
        gus->codec_flag = 1;
 
        error = snd_es1688_pcm(card, es1688, 0);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_es1688_mixer(card, es1688);
        if (error < 0)
-               goto out;
+               return error;
 
        snd_component_add(card, "ES1688");
 
        if (pcm_channels[n] > 0) {
                error = snd_gf1_pcm_new(gus, 1, 1);
                if (error < 0)
-                       goto out;
+                       return error;
        }
 
        error = snd_gf1_new_mixer(gus);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_gusextreme_mixer(card);
        if (error < 0)
-               goto out;
+               return error;
 
        if (snd_opl3_create(card, es1688->port, es1688->port + 2,
                        OPL3_HW_OPL3, 0, &opl3) < 0)
@@ -300,14 +300,14 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n)
        else {
                error = snd_opl3_hwdep_new(opl3, 0, 2, NULL);
                if (error < 0)
-                       goto out;
+                       return error;
        }
 
        if (es1688->mpu_port >= 0x300) {
                error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
                                es1688->mpu_port, 0, mpu_irq[n], NULL);
                if (error < 0)
-                       goto out;
+                       return error;
        }
 
        sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, "
@@ -316,24 +316,15 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n)
 
        error = snd_card_register(card);
        if (error < 0)
-               goto out;
+               return error;
 
        dev_set_drvdata(dev, card);
        return 0;
-
-out:   snd_card_free(card);
-       return error;
-}
-
-static void snd_gusextreme_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 static struct isa_driver snd_gusextreme_driver = {
        .match          = snd_gusextreme_match,
        .probe          = snd_gusextreme_probe,
-       .remove         = snd_gusextreme_remove,
 #if 0  /* FIXME */
        .suspend        = snd_gusextreme_suspend,
        .resume         = snd_gusextreme_resume,
index ad118d4..6834c05 100644 (file)
@@ -179,16 +179,6 @@ static int snd_gusmax_mixer(struct snd_wss *chip)
        return 0;
 }
 
-static void snd_gusmax_free(struct snd_card *card)
-{
-       struct snd_gusmax *maxcard = card->private_data;
-       
-       if (maxcard == NULL)
-               return;
-       if (maxcard->irq >= 0)
-               free_irq(maxcard->irq, (void *)maxcard);
-}
-
 static int snd_gusmax_match(struct device *pdev, unsigned int dev)
 {
        return enable[dev];
@@ -204,11 +194,10 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
        struct snd_wss *wss;
        struct snd_gusmax *maxcard;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_gusmax), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_gusmax), &card);
        if (err < 0)
                return err;
-       card->private_free = snd_gusmax_free;
        maxcard = card->private_data;
        maxcard->card = card;
        maxcard->irq = -1;
@@ -218,8 +207,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
                xirq = snd_legacy_find_free_irq(possible_irqs);
                if (xirq < 0) {
                        snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
-                       err = -EBUSY;
-                       goto _err;
+                       return -EBUSY;
                }
        }
        xdma1 = dma1[dev];
@@ -227,8 +215,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
                xdma1 = snd_legacy_find_free_dma(possible_dmas);
                if (xdma1 < 0) {
                        snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
-                       err = -EBUSY;
-                       goto _err;
+                       return -EBUSY;
                }
        }
        xdma2 = dma2[dev];
@@ -236,8 +223,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
                xdma2 = snd_legacy_find_free_dma(possible_dmas);
                if (xdma2 < 0) {
                        snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
-                       err = -EBUSY;
-                       goto _err;
+                       return -EBUSY;
                }
        }
 
@@ -267,29 +253,28 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
                }
        }
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_gusmax_detect(gus);
        if (err < 0)
-               goto _err;
+               return err;
 
        maxcard->gus_status_reg = gus->gf1.reg_irqstat;
        maxcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
        snd_gusmax_init(dev, card, gus);
        err = snd_gus_initialize(gus);
        if (err < 0)
-               goto _err;
+               return err;
 
        if (!gus->max_flag) {
                snd_printk(KERN_ERR PFX "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port);
-               err = -ENODEV;
-               goto _err;
+               return -ENODEV;
        }
 
-       if (request_irq(xirq, snd_gusmax_interrupt, 0, "GUS MAX", (void *)maxcard)) {
+       if (devm_request_irq(card->dev, xirq, snd_gusmax_interrupt, 0,
+                            "GUS MAX", (void *)maxcard)) {
                snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
-               err = -EBUSY;
-               goto _err;
+               return -EBUSY;
        }
        maxcard->irq = xirq;
        card->sync_irq = maxcard->irq;
@@ -303,32 +288,32 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
                             WSS_HWSHARE_DMA2,
                             &wss);
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_wss_pcm(wss, 0);
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_wss_mixer(wss);
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_wss_timer(wss, 2);
        if (err < 0)
-               goto _err;
+               return err;
 
        if (pcm_channels[dev] > 0) {
                err = snd_gf1_pcm_new(gus, 1, 1);
                if (err < 0)
-                       goto _err;
+                       return err;
        }
        err = snd_gusmax_mixer(wss);
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_gf1_rawmidi_new(gus, 0);
        if (err < 0)
-               goto _err;
+               return err;
 
        sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1);
        if (xdma2 >= 0)
@@ -336,22 +321,13 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto _err;
+               return err;
                
        maxcard->gus = gus;
        maxcard->wss = wss;
 
        dev_set_drvdata(pdev, card);
        return 0;
-
- _err:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_gusmax_remove(struct device *devptr, unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
 }
 
 #define DEV_NAME "gusmax"
@@ -359,7 +335,6 @@ static void snd_gusmax_remove(struct device *devptr, unsigned int dev)
 static struct isa_driver snd_gusmax_driver = {
        .match          = snd_gusmax_match,
        .probe          = snd_gusmax_probe,
-       .remove         = snd_gusmax_remove,
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = DEV_NAME
index 755de47..a04a9d3 100644 (file)
@@ -204,13 +204,15 @@ static int snd_interwave_detect_stb(struct snd_interwave *iwcard,
                        port = 0x360;
                }
                while (port <= 0x380) {
-                       iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)");
+                       iwcard->i2c_res = devm_request_region(card->dev, port, 1,
+                                                             "InterWave (I2C bus)");
                        if (iwcard->i2c_res)
                                break;
                        port += 0x10;
                }
        } else {
-               iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)");
+               iwcard->i2c_res = devm_request_region(card->dev, port, 1,
+                                                     "InterWave (I2C bus)");
        }
        if (iwcard->i2c_res == NULL) {
                snd_printk(KERN_ERR "interwave: can't grab i2c bus port\n");
@@ -598,19 +600,6 @@ static int snd_interwave_pnp(int dev, struct snd_interwave *iwcard,
 }
 #endif /* CONFIG_PNP */
 
-static void snd_interwave_free(struct snd_card *card)
-{
-       struct snd_interwave *iwcard = card->private_data;
-
-       if (iwcard == NULL)
-               return;
-#ifdef SNDRV_STB
-       release_and_free_resource(iwcard->i2c_res);
-#endif
-       if (iwcard->irq >= 0)
-               free_irq(iwcard->irq, (void *)iwcard);
-}
-
 static int snd_interwave_card_new(struct device *pdev, int dev,
                                  struct snd_card **cardp)
 {
@@ -618,24 +607,30 @@ static int snd_interwave_card_new(struct device *pdev, int dev,
        struct snd_interwave *iwcard;
        int err;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_interwave), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_interwave), &card);
        if (err < 0)
                return err;
        iwcard = card->private_data;
        iwcard->card = card;
        iwcard->irq = -1;
-       card->private_free = snd_interwave_free;
        *cardp = card;
        return 0;
 }
 
-static int snd_interwave_probe(struct snd_card *card, int dev)
+static int snd_interwave_probe_gus(struct snd_card *card, int dev,
+                                  struct snd_gus_card **gusp)
+{
+       return snd_gus_create(card, port[dev], -irq[dev], dma1[dev], dma2[dev],
+                             0, 32, pcm_channels[dev], effect[dev], gusp);
+}
+
+static int snd_interwave_probe(struct snd_card *card, int dev,
+                              struct snd_gus_card *gus)
 {
        int xirq, xdma1, xdma2;
        struct snd_interwave *iwcard = card->private_data;
        struct snd_wss *wss;
-       struct snd_gus_card *gus;
 #ifdef SNDRV_STB
        struct snd_i2c_bus *i2c_bus;
 #endif
@@ -646,14 +641,6 @@ static int snd_interwave_probe(struct snd_card *card, int dev)
        xdma1 = dma1[dev];
        xdma2 = dma2[dev];
 
-       err = snd_gus_create(card,
-                            port[dev],
-                            -xirq, xdma1, xdma2,
-                            0, 32,
-                            pcm_channels[dev], effect[dev], &gus);
-       if (err < 0)
-               return err;
-
        err = snd_interwave_detect(iwcard, gus, dev
 #ifdef SNDRV_STB
                                   , &i2c_bus
@@ -671,8 +658,8 @@ static int snd_interwave_probe(struct snd_card *card, int dev)
        if (err < 0)
                return err;
 
-       if (request_irq(xirq, snd_interwave_interrupt, 0,
-                       "InterWave", iwcard)) {
+       if (devm_request_irq(card->dev, xirq, snd_interwave_interrupt, 0,
+                            "InterWave", iwcard)) {
                snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
                return -EBUSY;
        }
@@ -769,24 +756,6 @@ static int snd_interwave_probe(struct snd_card *card, int dev)
        return 0;
 }
 
-static int snd_interwave_isa_probe1(int dev, struct device *devptr)
-{
-       struct snd_card *card;
-       int err;
-
-       err = snd_interwave_card_new(devptr, dev, &card);
-       if (err < 0)
-               return err;
-
-       err = snd_interwave_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
-               return err;
-       }
-       dev_set_drvdata(devptr, card);
-       return 0;
-}
-
 static int snd_interwave_isa_match(struct device *pdev,
                                   unsigned int dev)
 {
@@ -802,6 +771,8 @@ static int snd_interwave_isa_match(struct device *pdev,
 static int snd_interwave_isa_probe(struct device *pdev,
                                   unsigned int dev)
 {
+       struct snd_card *card;
+       struct snd_gus_card *gus;
        int err;
        static const int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
        static const int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1};
@@ -828,30 +799,36 @@ static int snd_interwave_isa_probe(struct device *pdev,
                }
        }
 
+       err = snd_interwave_card_new(pdev, dev, &card);
+       if (err < 0)
+               return err;
+
        if (port[dev] != SNDRV_AUTO_PORT)
-               return snd_interwave_isa_probe1(dev, pdev);
+               err = snd_interwave_probe_gus(card, dev, &gus);
        else {
                static const long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260};
                int i;
                for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
                        port[dev] = possible_ports[i];
-                       err = snd_interwave_isa_probe1(dev, pdev);
+                       err = snd_interwave_probe_gus(card, dev, &gus);
                        if (! err)
                                return 0;
                }
-               return err;
        }
-}
+       if (err < 0)
+               return err;
 
-static void snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
+       err = snd_interwave_probe(card, dev, gus);
+       if (err < 0)
+               return err;
+
+       dev_set_drvdata(pdev, card);
+       return 0;
 }
 
 static struct isa_driver snd_interwave_driver = {
        .match          = snd_interwave_isa_match,
        .probe          = snd_interwave_isa_probe,
-       .remove         = snd_interwave_isa_remove,
        /* FIXME: suspend,resume */
        .driver         = {
                .name   = INTERWAVE_DRIVER
@@ -864,6 +841,7 @@ static int snd_interwave_pnp_detect(struct pnp_card_link *pcard,
 {
        static int dev;
        struct snd_card *card;
+       struct snd_gus_card *gus;
        int res;
 
        for ( ; dev < SNDRV_CARDS; dev++) {
@@ -878,32 +856,24 @@ static int snd_interwave_pnp_detect(struct pnp_card_link *pcard,
                return res;
 
        res = snd_interwave_pnp(dev, card->private_data, pcard, pid);
-       if (res < 0) {
-               snd_card_free(card);
+       if (res < 0)
                return res;
-       }
-       res = snd_interwave_probe(card, dev);
-       if (res < 0) {
-               snd_card_free(card);
+       res = snd_interwave_probe_gus(card, dev, &gus);
+       if (res < 0)
+               return res;
+       res = snd_interwave_probe(card, dev, gus);
+       if (res < 0)
                return res;
-       }
        pnp_set_card_drvdata(pcard, card);
        dev++;
        return 0;
 }
 
-static void snd_interwave_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 static struct pnp_card_driver interwave_pnpc_driver = {
        .flags = PNP_DRIVER_RES_DISABLE,
        .name = INTERWAVE_PNP_DRIVER,
        .id_table = snd_interwave_pnpids,
        .probe = snd_interwave_pnp_detect,
-       .remove = snd_interwave_pnp_remove,
        /* FIXME: suspend,resume */
 };
 
index 4fbc22a..c3fd1eb 100644 (file)
@@ -425,7 +425,7 @@ static void snd_msnd_capture_reset_queue(struct snd_msnd *chip,
 }
 
 static const struct snd_pcm_hardware snd_msnd_playback = {
-       .info =                 SNDRV_PCM_INFO_MMAP |
+       .info =                 SNDRV_PCM_INFO_MMAP_IOMEM |
                                SNDRV_PCM_INFO_INTERLEAVED |
                                SNDRV_PCM_INFO_MMAP_VALID |
                                SNDRV_PCM_INFO_BATCH,
@@ -444,7 +444,7 @@ static const struct snd_pcm_hardware snd_msnd_playback = {
 };
 
 static const struct snd_pcm_hardware snd_msnd_capture = {
-       .info =                 SNDRV_PCM_INFO_MMAP |
+       .info =                 SNDRV_PCM_INFO_MMAP_IOMEM |
                                SNDRV_PCM_INFO_INTERLEAVED |
                                SNDRV_PCM_INFO_MMAP_VALID |
                                SNDRV_PCM_INFO_BATCH,
@@ -473,6 +473,7 @@ static int snd_msnd_playback_open(struct snd_pcm_substream *substream)
        snd_msnd_enable_irq(chip);
 
        runtime->dma_area = (__force void *)chip->mappedbase;
+       runtime->dma_addr = chip->base;
        runtime->dma_bytes = 0x3000;
 
        chip->playback_substream = substream;
@@ -566,6 +567,7 @@ static const struct snd_pcm_ops snd_msnd_playback_ops = {
        .prepare =      snd_msnd_playback_prepare,
        .trigger =      snd_msnd_playback_trigger,
        .pointer =      snd_msnd_playback_pointer,
+       .mmap =         snd_pcm_lib_mmap_iomem,
 };
 
 static int snd_msnd_capture_open(struct snd_pcm_substream *substream)
@@ -576,6 +578,7 @@ static int snd_msnd_capture_open(struct snd_pcm_substream *substream)
        set_bit(F_AUDIO_READ_INUSE, &chip->flags);
        snd_msnd_enable_irq(chip);
        runtime->dma_area = (__force void *)chip->mappedbase + 0x3000;
+       runtime->dma_addr = chip->base + 0x3000;
        runtime->dma_bytes = 0x3000;
        memset(runtime->dma_area, 0, runtime->dma_bytes);
        chip->capture_substream = substream;
@@ -662,6 +665,7 @@ static const struct snd_pcm_ops snd_msnd_capture_ops = {
        .prepare =      snd_msnd_capture_prepare,
        .trigger =      snd_msnd_capture_trigger,
        .pointer =      snd_msnd_capture_pointer,
+       .mmap =         snd_pcm_lib_mmap_iomem,
 };
 
 
index 69647b4..4433a92 100644 (file)
@@ -472,11 +472,6 @@ static int snd_msnd_dsp_full_reset(struct snd_card *card)
        return rv;
 }
 
-static int snd_msnd_dev_free(struct snd_device *device)
-{
-       snd_printdd("snd_msnd_chip_free()\n");
-       return 0;
-}
 
 static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd)
 {
@@ -528,58 +523,47 @@ static int snd_msnd_attach(struct snd_card *card)
 {
        struct snd_msnd *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =      snd_msnd_dev_free,
-               };
 
-       err = request_irq(chip->irq, snd_msnd_interrupt, 0, card->shortname,
-                         chip);
+       err = devm_request_irq(card->dev, chip->irq, snd_msnd_interrupt, 0,
+                              card->shortname, chip);
        if (err < 0) {
                printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq);
                return err;
        }
        card->sync_irq = chip->irq;
-       if (request_region(chip->io, DSP_NUMIO, card->shortname) == NULL) {
-               free_irq(chip->irq, chip);
+       if (!devm_request_region(card->dev, chip->io, DSP_NUMIO,
+                                card->shortname))
                return -EBUSY;
-       }
 
-       if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) {
+       if (!devm_request_mem_region(card->dev, chip->base, BUFFSIZE,
+                                    card->shortname)) {
                printk(KERN_ERR LOGNAME
                        ": unable to grab memory region 0x%lx-0x%lx\n",
                        chip->base, chip->base + BUFFSIZE - 1);
-               release_region(chip->io, DSP_NUMIO);
-               free_irq(chip->irq, chip);
                return -EBUSY;
        }
-       chip->mappedbase = ioremap(chip->base, 0x8000);
+       chip->mappedbase = devm_ioremap(card->dev, chip->base, 0x8000);
        if (!chip->mappedbase) {
                printk(KERN_ERR LOGNAME
                        ": unable to map memory region 0x%lx-0x%lx\n",
                        chip->base, chip->base + BUFFSIZE - 1);
-               err = -EIO;
-               goto err_release_region;
+               return -EIO;
        }
 
        err = snd_msnd_dsp_full_reset(card);
        if (err < 0)
-               goto err_release_region;
-
-       /* Register device */
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto err_release_region;
+               return err;
 
        err = snd_msnd_pcm(card, 0);
        if (err < 0) {
                printk(KERN_ERR LOGNAME ": error creating new PCM device\n");
-               goto err_release_region;
+               return err;
        }
 
        err = snd_msndmix_new(card);
        if (err < 0) {
                printk(KERN_ERR LOGNAME ": error creating new Mixer device\n");
-               goto err_release_region;
+               return err;
        }
 
 
@@ -595,7 +579,7 @@ static int snd_msnd_attach(struct snd_card *card)
                if (err < 0) {
                        printk(KERN_ERR LOGNAME
                                ": error creating new Midi device\n");
-                       goto err_release_region;
+                       return err;
                }
                mpu = chip->rmidi->private_data;
 
@@ -610,30 +594,12 @@ static int snd_msnd_attach(struct snd_card *card)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto err_release_region;
+               return err;
 
        return 0;
-
-err_release_region:
-       iounmap(chip->mappedbase);
-       release_mem_region(chip->base, BUFFSIZE);
-       release_region(chip->io, DSP_NUMIO);
-       free_irq(chip->irq, chip);
-       return err;
 }
 
 
-static void snd_msnd_unload(struct snd_card *card)
-{
-       struct snd_msnd *chip = card->private_data;
-
-       iounmap(chip->mappedbase);
-       release_mem_region(chip->base, BUFFSIZE);
-       release_region(chip->io, DSP_NUMIO);
-       free_irq(chip->irq, chip);
-       snd_card_free(card);
-}
-
 #ifndef MSND_CLASSIC
 
 /* Pinnacle/Fiji Logical Device Configuration */
@@ -892,8 +858,8 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
                return -ENODEV;
        }
 
-       err = snd_card_new(pdev, index[idx], id[idx], THIS_MODULE,
-                          sizeof(struct snd_msnd), &card);
+       err = snd_devm_card_new(pdev, index[idx], id[idx], THIS_MODULE,
+                               sizeof(struct snd_msnd), &card);
        if (err < 0)
                return err;
 
@@ -934,17 +900,15 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
        printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%lx\n",
                        cfg[idx]);
 
-       if (!request_region(cfg[idx], 2, "Pinnacle/Fiji Config")) {
+       if (!devm_request_region(card->dev, cfg[idx], 2,
+                                "Pinnacle/Fiji Config")) {
                printk(KERN_ERR LOGNAME ": Config port 0x%lx conflict\n",
                           cfg[idx]);
-               snd_card_free(card);
                return -EIO;
        }
        if (reset[idx])
-               if (snd_msnd_pinnacle_cfg_reset(cfg[idx])) {
-                       err = -EIO;
-                       goto cfg_error;
-               }
+               if (snd_msnd_pinnacle_cfg_reset(cfg[idx]))
+                       return -EIO;
 
        /* DSP */
        err = snd_msnd_write_cfg_logical(cfg[idx], 0,
@@ -952,7 +916,7 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
                                         irq[idx], mem[idx]);
 
        if (err)
-               goto cfg_error;
+               return err;
 
        /* The following are Pinnacle specific */
 
@@ -967,7 +931,7 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
                                                 mpu_irq[idx], 0);
 
                if (err)
-                       goto cfg_error;
+                       return err;
        }
 
        /* IDE */
@@ -982,7 +946,7 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
                                                 ide_irq[idx], 0);
 
                if (err)
-                       goto cfg_error;
+                       return err;
        }
 
        /* Joystick */
@@ -995,9 +959,8 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
                                                 0, 0);
 
                if (err)
-                       goto cfg_error;
+                       return err;
        }
-       release_region(cfg[idx], 2);
 
 #endif /* MSND_CLASSIC */
 
@@ -1027,37 +990,22 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
        err = snd_msnd_probe(card);
        if (err < 0) {
                printk(KERN_ERR LOGNAME ": Probe failed\n");
-               snd_card_free(card);
                return err;
        }
 
        err = snd_msnd_attach(card);
        if (err < 0) {
                printk(KERN_ERR LOGNAME ": Attach failed\n");
-               snd_card_free(card);
                return err;
        }
        dev_set_drvdata(pdev, card);
 
        return 0;
-
-#ifndef MSND_CLASSIC
-cfg_error:
-       release_region(cfg[idx], 2);
-       snd_card_free(card);
-       return err;
-#endif
-}
-
-static void snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
-{
-       snd_msnd_unload(dev_get_drvdata(pdev));
 }
 
 static struct isa_driver snd_msnd_driver = {
        .match          = snd_msnd_isa_match,
        .probe          = snd_msnd_isa_probe,
-       .remove         = snd_msnd_isa_remove,
        /* FIXME: suspend, resume */
        .driver         = {
                .name   = DEV_NAME
@@ -1107,9 +1055,9 @@ static int snd_msnd_pnp_detect(struct pnp_card_link *pcard,
         * Create a new ALSA sound card entry, in anticipation
         * of detecting our hardware ...
         */
-       ret = snd_card_new(&pcard->card->dev,
-                          index[idx], id[idx], THIS_MODULE,
-                          sizeof(struct snd_msnd), &card);
+       ret = snd_devm_card_new(&pcard->card->dev,
+                               index[idx], id[idx], THIS_MODULE,
+                               sizeof(struct snd_msnd), &card);
        if (ret < 0)
                return ret;
 
@@ -1151,28 +1099,18 @@ static int snd_msnd_pnp_detect(struct pnp_card_link *pcard,
        ret = snd_msnd_probe(card);
        if (ret < 0) {
                printk(KERN_ERR LOGNAME ": Probe failed\n");
-               goto _release_card;
+               return ret;
        }
 
        ret = snd_msnd_attach(card);
        if (ret < 0) {
                printk(KERN_ERR LOGNAME ": Attach failed\n");
-               goto _release_card;
+               return ret;
        }
 
        pnp_set_card_drvdata(pcard, card);
        ++idx;
        return 0;
-
-_release_card:
-       snd_card_free(card);
-       return ret;
-}
-
-static void snd_msnd_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_msnd_unload(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
 }
 
 static int isa_registered;
@@ -1191,7 +1129,6 @@ static struct pnp_card_driver msnd_pnpc_driver = {
        .name = "msnd_pinnacle",
        .id_table = msnd_pnpids,
        .probe = snd_msnd_pnp_detect,
-       .remove = snd_msnd_pnp_remove,
 };
 #endif /* CONFIG_PNP */
 
index 6f42f86..bad1490 100644 (file)
@@ -208,7 +208,8 @@ static int snd_opl3sa2_detect(struct snd_card *card)
        char str[2];
 
        port = chip->port;
-       chip->res_port = request_region(port, 2, "OPL3-SA control");
+       chip->res_port = devm_request_region(card->dev, port, 2,
+                                            "OPL3-SA control");
        if (!chip->res_port) {
                snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port);
                return -EBUSY;
@@ -609,14 +610,6 @@ static int snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip,
 }
 #endif /* CONFIG_PNP */
 
-static void snd_opl3sa2_free(struct snd_card *card)
-{
-       struct snd_opl3sa2 *chip = card->private_data;
-       if (chip->irq >= 0)
-               free_irq(chip->irq, card);
-       release_and_free_resource(chip->res_port);
-}
-
 static int snd_opl3sa2_card_new(struct device *pdev, int dev,
                                struct snd_card **cardp)
 {
@@ -624,8 +617,8 @@ static int snd_opl3sa2_card_new(struct device *pdev, int dev,
        struct snd_opl3sa2 *chip;
        int err;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_opl3sa2), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_opl3sa2), &card);
        if (err < 0)
                return err;
        strcpy(card->driver, "OPL3SA2");
@@ -633,7 +626,6 @@ static int snd_opl3sa2_card_new(struct device *pdev, int dev,
        chip = card->private_data;
        spin_lock_init(&chip->reg_lock);
        chip->irq = -1;
-       card->private_free = snd_opl3sa2_free;
        *cardp = card;
        return 0;
 }
@@ -658,8 +650,8 @@ static int snd_opl3sa2_probe(struct snd_card *card, int dev)
        err = snd_opl3sa2_detect(card);
        if (err < 0)
                return err;
-       err = request_irq(xirq, snd_opl3sa2_interrupt, 0,
-                         "OPL3-SA2", card);
+       err = devm_request_irq(card->dev, xirq, snd_opl3sa2_interrupt, 0,
+                              "OPL3-SA2", card);
        if (err) {
                snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq);
                return -ENODEV;
@@ -737,25 +729,16 @@ static int snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
        if (err < 0)
                return err;
        err = snd_opl3sa2_pnp(dev, card->private_data, pdev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_opl3sa2_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pnp_set_drvdata(pdev, card);
        dev++;
        return 0;
 }
 
-static void snd_opl3sa2_pnp_remove(struct pnp_dev *pdev)
-{
-       snd_card_free(pnp_get_drvdata(pdev));
-}
-
 #ifdef CONFIG_PM
 static int snd_opl3sa2_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
 {
@@ -771,7 +754,6 @@ static struct pnp_driver opl3sa2_pnp_driver = {
        .name = "snd-opl3sa2-pnpbios",
        .id_table = snd_opl3sa2_pnpbiosids,
        .probe = snd_opl3sa2_pnp_detect,
-       .remove = snd_opl3sa2_pnp_remove,
 #ifdef CONFIG_PM
        .suspend = snd_opl3sa2_pnp_suspend,
        .resume = snd_opl3sa2_pnp_resume,
@@ -803,26 +785,16 @@ static int snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
        if (err < 0)
                return err;
        err = snd_opl3sa2_pnp(dev, card->private_data, pdev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_opl3sa2_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pnp_set_card_drvdata(pcard, card);
        dev++;
        return 0;
 }
 
-static void snd_opl3sa2_pnp_cremove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_opl3sa2_pnp_csuspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -839,7 +811,6 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = {
        .name = "snd-opl3sa2-cpnp",
        .id_table = snd_opl3sa2_pnpids,
        .probe = snd_opl3sa2_pnp_cdetect,
-       .remove = snd_opl3sa2_pnp_cremove,
 #ifdef CONFIG_PM
        .suspend = snd_opl3sa2_pnp_csuspend,
        .resume = snd_opl3sa2_pnp_cresume,
@@ -885,20 +856,12 @@ static int snd_opl3sa2_isa_probe(struct device *pdev,
        if (err < 0)
                return err;
        err = snd_opl3sa2_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        dev_set_drvdata(pdev, card);
        return 0;
 }
 
-static void snd_opl3sa2_isa_remove(struct device *devptr,
-                                 unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-}
-
 #ifdef CONFIG_PM
 static int snd_opl3sa2_isa_suspend(struct device *dev, unsigned int n,
                                   pm_message_t state)
@@ -917,7 +880,6 @@ static int snd_opl3sa2_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_opl3sa2_isa_driver = {
        .match          = snd_opl3sa2_isa_match,
        .probe          = snd_opl3sa2_isa_probe,
-       .remove         = snd_opl3sa2_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_opl3sa2_isa_suspend,
        .resume         = snd_opl3sa2_isa_resume,
index e1fb756..59242ba 100644 (file)
@@ -1159,12 +1159,13 @@ __skip_mpu:
        return 0;
 }
 
-static int snd_miro_opti_check(struct snd_miro *chip)
+static int snd_miro_opti_check(struct snd_card *card, struct snd_miro *chip)
 {
        unsigned char value;
 
-       chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size,
-                                          "OPTi9xx MC");
+       chip->res_mc_base =
+               devm_request_region(card->dev, chip->mc_base,
+                                   chip->mc_base_size, "OPTi9xx MC");
        if (chip->res_mc_base == NULL)
                return -ENOMEM;
 
@@ -1173,7 +1174,7 @@ static int snd_miro_opti_check(struct snd_miro *chip)
                if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1)))
                        return 0;
 
-       release_and_free_resource(chip->res_mc_base);
+       devm_release_resource(card->dev, chip->res_mc_base);
        chip->res_mc_base = NULL;
 
        return -ENODEV;
@@ -1190,7 +1191,7 @@ static int snd_card_miro_detect(struct snd_card *card,
                if (err < 0)
                        return err;
 
-               err = snd_miro_opti_check(chip);
+               err = snd_miro_opti_check(card, chip);
                if (err == 0)
                        return 1;
        }
@@ -1214,7 +1215,8 @@ static int snd_card_miro_aci_detect(struct snd_card *card,
        regval=inb(miro->mc_base + 4);
        aci->aci_port = (regval & 0x10) ? 0x344 : 0x354;
 
-       miro->res_aci_port = request_region(aci->aci_port, 3, "miro aci");
+       miro->res_aci_port =
+               devm_request_region(card->dev, aci->aci_port, 3, "miro aci");
        if (miro->res_aci_port == NULL) {
                snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n", 
                           aci->aci_port, aci->aci_port+2);
@@ -1253,16 +1255,6 @@ static int snd_card_miro_aci_detect(struct snd_card *card,
        return 0;
 }
 
-static void snd_card_miro_free(struct snd_card *card)
-{
-       struct snd_miro *miro = card->private_data;
-
-       release_and_free_resource(miro->res_aci_port);
-       if (miro->aci)
-               miro->aci->aci_port = 0;
-       release_and_free_resource(miro->res_mc_base);
-}
-
 static int snd_miro_probe(struct snd_card *card)
 {
        int error;
@@ -1271,9 +1263,10 @@ static int snd_miro_probe(struct snd_card *card)
        struct snd_rawmidi *rmidi;
 
        if (!miro->res_mc_base) {
-               miro->res_mc_base = request_region(miro->mc_base,
-                                               miro->mc_base_size,
-                                               "miro (OPTi9xx MC)");
+               miro->res_mc_base = devm_request_region(card->dev,
+                                                       miro->mc_base,
+                                                       miro->mc_base_size,
+                                                       "miro (OPTi9xx MC)");
                if (miro->res_mc_base == NULL) {
                        snd_printk(KERN_ERR "request for OPTI9xx MC failed\n");
                        return -ENOMEM;
@@ -1408,17 +1401,15 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        struct snd_miro *miro;
        struct snd_card *card;
 
-       error = snd_card_new(devptr, index, id, THIS_MODULE,
-                            sizeof(struct snd_miro), &card);
+       error = snd_devm_card_new(devptr, index, id, THIS_MODULE,
+                                 sizeof(struct snd_miro), &card);
        if (error < 0)
                return error;
 
-       card->private_free = snd_card_miro_free;
        miro = card->private_data;
 
        error = snd_card_miro_detect(card, miro);
        if (error < 0) {
-               snd_card_free(card);
                snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n");
                return -ENODEV;
        }
@@ -1426,7 +1417,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        if (port == SNDRV_AUTO_PORT) {
                port = snd_legacy_find_free_ioport(possible_ports, 4);
                if (port < 0) {
-                       snd_card_free(card);
                        snd_printk(KERN_ERR "unable to find a free WSS port\n");
                        return -EBUSY;
                }
@@ -1435,7 +1425,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        if (mpu_port == SNDRV_AUTO_PORT) {
                mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2);
                if (mpu_port < 0) {
-                       snd_card_free(card);
                        snd_printk(KERN_ERR
                                   "unable to find a free MPU401 port\n");
                        return -EBUSY;
@@ -1445,7 +1434,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        if (irq == SNDRV_AUTO_IRQ) {
                irq = snd_legacy_find_free_irq(possible_irqs);
                if (irq < 0) {
-                       snd_card_free(card);
                        snd_printk(KERN_ERR "unable to find a free IRQ\n");
                        return -EBUSY;
                }
@@ -1453,7 +1441,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        if (mpu_irq == SNDRV_AUTO_IRQ) {
                mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs);
                if (mpu_irq < 0) {
-                       snd_card_free(card);
                        snd_printk(KERN_ERR
                                   "unable to find a free MPU401 IRQ\n");
                        return -EBUSY;
@@ -1462,7 +1449,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        if (dma1 == SNDRV_AUTO_DMA) {
                dma1 = snd_legacy_find_free_dma(possible_dma1s);
                if (dma1 < 0) {
-                       snd_card_free(card);
                        snd_printk(KERN_ERR "unable to find a free DMA1\n");
                        return -EBUSY;
                }
@@ -1470,34 +1456,24 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        if (dma2 == SNDRV_AUTO_DMA) {
                dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4]);
                if (dma2 < 0) {
-                       snd_card_free(card);
                        snd_printk(KERN_ERR "unable to find a free DMA2\n");
                        return -EBUSY;
                }
        }
 
        error = snd_miro_probe(card);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        dev_set_drvdata(devptr, card);
        return 0;
 }
 
-static void snd_miro_isa_remove(struct device *devptr,
-                              unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-}
-
 #define DEV_NAME "miro"
 
 static struct isa_driver snd_miro_driver = {
        .match          = snd_miro_isa_match,
        .probe          = snd_miro_isa_probe,
-       .remove         = snd_miro_isa_remove,
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = DEV_NAME
@@ -1578,39 +1554,31 @@ static int snd_miro_pnp_probe(struct pnp_card_link *pcard,
                return -EBUSY;
        if (!isapnp)
                return -ENODEV;
-       err = snd_card_new(&pcard->card->dev, index, id, THIS_MODULE,
-                          sizeof(struct snd_miro), &card);
+       err = snd_devm_card_new(&pcard->card->dev, index, id, THIS_MODULE,
+                               sizeof(struct snd_miro), &card);
        if (err < 0)
                return err;
 
-       card->private_free = snd_card_miro_free;
        miro = card->private_data;
 
        err = snd_card_miro_pnp(miro, pcard, pid);
-       if (err) {
-               snd_card_free(card);
+       if (err)
                return err;
-       }
 
        /* only miroSOUND PCM20 and PCM12 == OPTi924 */
        err = snd_miro_init(miro, OPTi9XX_HW_82C924);
-       if (err) {
-               snd_card_free(card);
+       if (err)
                return err;
-       }
 
-       err = snd_miro_opti_check(miro);
+       err = snd_miro_opti_check(card, miro);
        if (err) {
                snd_printk(KERN_ERR "OPTI chip not found\n");
-               snd_card_free(card);
                return err;
        }
 
        err = snd_miro_probe(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pnp_set_card_drvdata(pcard, card);
        snd_miro_pnp_is_probed = 1;
        return 0;
@@ -1618,8 +1586,6 @@ static int snd_miro_pnp_probe(struct pnp_card_link *pcard,
 
 static void snd_miro_pnp_remove(struct pnp_card_link *pcard)
 {
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
        snd_miro_pnp_is_probed = 0;
 }
 
index 4bd1dc6..4beeb32 100644 (file)
@@ -654,16 +654,18 @@ static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
 
 #endif /* OPTi93X */
 
-static int snd_opti9xx_read_check(struct snd_opti9xx *chip)
+static int snd_opti9xx_read_check(struct snd_card *card,
+                                 struct snd_opti9xx *chip)
 {
        unsigned char value;
 #ifdef OPTi93X
        unsigned long flags;
 #endif
 
-       chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size,
-                                          "OPTi9xx MC");
-       if (chip->res_mc_base == NULL)
+       chip->res_mc_base =
+               devm_request_region(card->dev, chip->mc_base,
+                                   chip->mc_base_size, "OPTi9xx MC");
+       if (!chip->res_mc_base)
                return -EBUSY;
 #ifndef OPTi93X
        value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1));
@@ -671,9 +673,10 @@ static int snd_opti9xx_read_check(struct snd_opti9xx *chip)
                if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)))
                        return 0;
 #else  /* OPTi93X */
-       chip->res_mc_indir = request_region(chip->mc_indir_index, 2,
-                                           "OPTi93x MC");
-       if (chip->res_mc_indir == NULL)
+       chip->res_mc_indir =
+               devm_request_region(card->dev, chip->mc_indir_index, 2,
+                                   "OPTi93x MC");
+       if (!chip->res_mc_indir)
                return -EBUSY;
 
        spin_lock_irqsave(&chip->lock, flags);
@@ -686,10 +689,10 @@ static int snd_opti9xx_read_check(struct snd_opti9xx *chip)
        if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value)
                return 0;
 
-       release_and_free_resource(chip->res_mc_indir);
+       devm_release_resource(card->dev, chip->res_mc_indir);
        chip->res_mc_indir = NULL;
 #endif /* OPTi93X */
-       release_and_free_resource(chip->res_mc_base);
+       devm_release_resource(card->dev, chip->res_mc_base);
        chip->res_mc_base = NULL;
 
        return -ENODEV;
@@ -709,7 +712,7 @@ static int snd_card_opti9xx_detect(struct snd_card *card,
                if (err < 0)
                        return err;
 
-               err = snd_opti9xx_read_check(chip);
+               err = snd_opti9xx_read_check(card, chip);
                if (err == 0)
                        return 1;
 #ifdef OPTi93X
@@ -789,22 +792,6 @@ static int snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
 }
 #endif /* CONFIG_PNP */
 
-static void snd_card_opti9xx_free(struct snd_card *card)
-{
-       struct snd_opti9xx *chip = card->private_data;
-
-       if (chip) {
-#ifdef OPTi93X
-               if (chip->irq > 0) {
-                       disable_irq(chip->irq);
-                       free_irq(chip->irq, chip);
-               }
-               release_and_free_resource(chip->res_mc_indir);
-#endif
-               release_and_free_resource(chip->res_mc_base);
-       }
-}
-
 static int snd_opti9xx_probe(struct snd_card *card)
 {
        static const long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
@@ -860,8 +847,8 @@ static int snd_opti9xx_probe(struct snd_card *card)
                return error;
 #endif
 #ifdef OPTi93X
-       error = request_irq(irq, snd_opti93x_interrupt,
-                           0, DEV_NAME" - WSS", chip);
+       error = devm_request_irq(card->dev, irq, snd_opti93x_interrupt,
+                                0, DEV_NAME" - WSS", chip);
        if (error < 0) {
                snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq);
                return error;
@@ -931,11 +918,10 @@ static int snd_opti9xx_card_new(struct device *pdev, struct snd_card **cardp)
        struct snd_card *card;
        int err;
 
-       err = snd_card_new(pdev, index, id, THIS_MODULE,
-                          sizeof(struct snd_opti9xx), &card);
+       err = snd_devm_card_new(pdev, index, id, THIS_MODULE,
+                               sizeof(struct snd_opti9xx), &card);
        if (err < 0)
                return err;
-       card->private_free = snd_card_opti9xx_free;
        *cardp = card;
        return 0;
 }
@@ -1012,25 +998,15 @@ static int snd_opti9xx_isa_probe(struct device *devptr,
                return error;
 
        error = snd_card_opti9xx_detect(card, card->private_data);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        error = snd_opti9xx_probe(card);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        dev_set_drvdata(devptr, card);
        return 0;
 }
 
-static void snd_opti9xx_isa_remove(struct device *devptr,
-                                  unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-}
-
 #ifdef CONFIG_PM
 static int snd_opti9xx_suspend(struct snd_card *card)
 {
@@ -1075,7 +1051,6 @@ static int snd_opti9xx_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_opti9xx_driver = {
        .match          = snd_opti9xx_isa_match,
        .probe          = snd_opti9xx_isa_probe,
-       .remove         = snd_opti9xx_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_opti9xx_isa_suspend,
        .resume         = snd_opti9xx_isa_resume,
@@ -1114,26 +1089,20 @@ static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
                hw = OPTi9XX_HW_82C931;
                break;
        default:
-               snd_card_free(card);
                return -ENODEV;
        }
 
        error = snd_opti9xx_init(chip, hw);
-       if (error) {
-               snd_card_free(card);
+       if (error)
                return error;
-       }
-       error = snd_opti9xx_read_check(chip);
+       error = snd_opti9xx_read_check(card, chip);
        if (error) {
                snd_printk(KERN_ERR "OPTI chip not found\n");
-               snd_card_free(card);
                return error;
        }
        error = snd_opti9xx_probe(card);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        pnp_set_card_drvdata(pcard, card);
        snd_opti9xx_pnp_is_probed = 1;
        return 0;
@@ -1141,8 +1110,6 @@ static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
 
 static void snd_opti9xx_pnp_remove(struct pnp_card_link *pcard)
 {
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
        snd_opti9xx_pnp_is_probed = 0;
 }
 
index 5e41879..e020296 100644 (file)
@@ -1048,27 +1048,6 @@ __error:
        return err;
 }
 
-
-/*
- * free resources
- */
-static int snd_emu8000_free(struct snd_emu8000 *hw)
-{
-       release_and_free_resource(hw->res_port1);
-       release_and_free_resource(hw->res_port2);
-       release_and_free_resource(hw->res_port3);
-       kfree(hw);
-       return 0;
-}
-
-/*
- */
-static int snd_emu8000_dev_free(struct snd_device *device)
-{
-       struct snd_emu8000 *hw = device->device_data;
-       return snd_emu8000_free(hw);
-}
-
 /*
  * initialize and register emu8000 synth device.
  */
@@ -1079,9 +1058,6 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
        struct snd_seq_device *awe;
        struct snd_emu8000 *hw;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_emu8000_dev_free,
-       };
 
        if (awe_ret)
                *awe_ret = NULL;
@@ -1089,7 +1065,7 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
        if (seq_ports <= 0)
                return 0;
 
-       hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+       hw = devm_kzalloc(card->dev, sizeof(*hw), GFP_KERNEL);
        if (hw == NULL)
                return -ENOMEM;
        spin_lock_init(&hw->reg_lock);
@@ -1097,12 +1073,10 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
        hw->port1 = port;
        hw->port2 = port + 0x400;
        hw->port3 = port + 0x800;
-       hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1");
-       hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2");
-       hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3");
-       if (!hw->res_port1 || !hw->res_port2 || !hw->res_port3) {
+       if (!devm_request_region(card->dev, hw->port1, 4, "Emu8000-1") ||
+           !devm_request_region(card->dev, hw->port2, 4, "Emu8000-2") ||
+           !devm_request_region(card->dev, hw->port3, 4, "Emu8000-3")) {
                snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3);
-               snd_emu8000_free(hw);
                return -EBUSY;
        }
        hw->mem_size = 0;
@@ -1115,23 +1089,13 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
        hw->fm_chorus_depth = 0;
        hw->fm_reverb_depth = 0;
 
-       if (snd_emu8000_detect(hw) < 0) {
-               snd_emu8000_free(hw);
+       if (snd_emu8000_detect(hw) < 0)
                return -ENODEV;
-       }
 
        snd_emu8000_init_hw(hw);
        err = snd_emu8000_create_mixer(card, hw);
-       if (err < 0) {
-               snd_emu8000_free(hw);
+       if (err < 0)
                return err;
-       }
-       
-       err = snd_device_new(card, SNDRV_DEV_CODEC, hw, &ops);
-       if (err < 0) {
-               snd_emu8000_free(hw);
-               return err;
-       }
 #if IS_ENABLED(CONFIG_SND_SEQUENCER)
        if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
                               sizeof(struct snd_emu8000*), &awe) >= 0) {
index 7ba5dd1..64936c9 100644 (file)
@@ -226,8 +226,8 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
        static const int possible_dmas16[] = {5, 7, -1};
        int err, xirq, xdma8, xdma16, xmpu_port, xmpu_irq;
 
-       err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_card_jazz16), &card);
+       err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_card_jazz16), &card);
        if (err < 0)
                return err;
 
@@ -238,8 +238,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
                xirq = snd_legacy_find_free_irq(possible_irqs);
                if (xirq < 0) {
                        snd_printk(KERN_ERR "unable to find a free IRQ\n");
-                       err = -EBUSY;
-                       goto err_free;
+                       return -EBUSY;
                }
        }
        xdma8 = dma8[dev];
@@ -247,8 +246,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
                xdma8 = snd_legacy_find_free_dma(possible_dmas8);
                if (xdma8 < 0) {
                        snd_printk(KERN_ERR "unable to find a free DMA8\n");
-                       err = -EBUSY;
-                       goto err_free;
+                       return -EBUSY;
                }
        }
        xdma16 = dma16[dev];
@@ -256,8 +254,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
                xdma16 = snd_legacy_find_free_dma(possible_dmas16);
                if (xdma16 < 0) {
                        snd_printk(KERN_ERR "unable to find a free DMA16\n");
-                       err = -EBUSY;
-                       goto err_free;
+                       return -EBUSY;
                }
        }
 
@@ -267,7 +264,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
        err = jazz16_detect_board(port[dev], xmpu_port);
        if (err < 0) {
                printk(KERN_ERR "Media Vision Jazz16 board not detected\n");
-               goto err_free;
+               return err;
        }
        err = snd_sbdsp_create(card, port[dev], irq[dev],
                               jazz16_interrupt,
@@ -275,7 +272,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
                               SB_HW_JAZZ16,
                               &chip);
        if (err < 0)
-               goto err_free;
+               return err;
 
        xmpu_irq = mpu_irq[dev];
        if (xmpu_irq == SNDRV_AUTO_IRQ || mpu_port[dev] == SNDRV_AUTO_PORT)
@@ -283,7 +280,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
        err = jazz16_configure_board(chip, xmpu_irq);
        if (err < 0) {
                printk(KERN_ERR "Media Vision Jazz16 configuration failed\n");
-               goto err_free;
+               return err;
        }
 
        jazz16->chip = chip;
@@ -296,10 +293,10 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
 
        err = snd_sb8dsp_pcm(chip, 0);
        if (err < 0)
-               goto err_free;
+               return err;
        err = snd_sbmixer_new(chip);
        if (err < 0)
-               goto err_free;
+               return err;
 
        err = snd_opl3_create(card, chip->port, chip->port + 2,
                              OPL3_HW_AUTO, 1, &opl3);
@@ -309,7 +306,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
        else {
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                if (err < 0)
-                       goto err_free;
+                       return err;
        }
        if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
                if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
@@ -326,21 +323,10 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto err_free;
+               return err;
 
        dev_set_drvdata(devptr, card);
        return 0;
-
-err_free:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_jazz16_remove(struct device *devptr, unsigned int dev)
-{
-       struct snd_card *card = dev_get_drvdata(devptr);
-
-       snd_card_free(card);
 }
 
 #ifdef CONFIG_PM
@@ -372,7 +358,6 @@ static int snd_jazz16_resume(struct device *pdev, unsigned int n)
 static struct isa_driver snd_jazz16_driver = {
        .match          = snd_jazz16_match,
        .probe          = snd_jazz16_probe,
-       .remove         = snd_jazz16_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_jazz16_suspend,
        .resume         = snd_jazz16_resume,
index d0f797c..e89b095 100644 (file)
@@ -285,15 +285,6 @@ __wt_error:
 
 #endif /* CONFIG_PNP */
 
-static void snd_sb16_free(struct snd_card *card)
-{
-       struct snd_card_sb16 *acard = card->private_data;
-        
-       if (acard == NULL)
-               return;
-       release_and_free_resource(acard->fm_res);
-}
-
 #ifdef CONFIG_PNP
 #define is_isapnp_selected(dev)                isapnp[dev]
 #else
@@ -306,11 +297,10 @@ static int snd_sb16_card_new(struct device *devptr, int dev,
        struct snd_card *card;
        int err;
 
-       err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_card_sb16), &card);
+       err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_card_sb16), &card);
        if (err < 0)
                return err;
-       card->private_free = snd_sb16_free;
        *cardp = card;
        return 0;
 }
@@ -482,17 +472,16 @@ static int snd_sb16_isa_probe1(int dev, struct device *pdev)
        /* non-PnP FM port address is hardwired with base port address */
        fm_port[dev] = port[dev];
        /* block the 0x388 port to avoid PnP conflicts */
-       acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
+       acard->fm_res = devm_request_region(card->dev, 0x388, 4,
+                                           "SoundBlaster FM");
 #ifdef SNDRV_SBAWE_EMU8000
        /* non-PnP AWE port address is hardwired with base port address */
        awe_port[dev] = port[dev] + 0x400;
 #endif
 
        err = snd_sb16_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        dev_set_drvdata(pdev, card);
        return 0;
 }
@@ -547,11 +536,6 @@ static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
        }
 }
 
-static void snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(pdev));
-}
-
 #ifdef CONFIG_PM
 static int snd_sb16_isa_suspend(struct device *dev, unsigned int n,
                                pm_message_t state)
@@ -574,7 +558,6 @@ static int snd_sb16_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_sb16_isa_driver = {
        .match          = snd_sb16_isa_match,
        .probe          = snd_sb16_isa_probe,
-       .remove         = snd_sb16_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_sb16_isa_suspend,
        .resume         = snd_sb16_isa_resume,
@@ -600,15 +583,11 @@ static int snd_sb16_pnp_detect(struct pnp_card_link *pcard,
                if (res < 0)
                        return res;
                res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid);
-               if (res < 0) {
-                       snd_card_free(card);
+               if (res < 0)
                        return res;
-               }
                res = snd_sb16_probe(card, dev);
-               if (res < 0) {
-                       snd_card_free(card);
+               if (res < 0)
                        return res;
-               }
                pnp_set_card_drvdata(pcard, card);
                dev++;
                return 0;
@@ -617,12 +596,6 @@ static int snd_sb16_pnp_detect(struct pnp_card_link *pcard,
        return -ENODEV;
 }
 
-static void snd_sb16_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_sb16_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -643,7 +616,6 @@ static struct pnp_card_driver sb16_pnpc_driver = {
 #endif
        .id_table = snd_sb16_pnpids,
        .probe = snd_sb16_pnp_detect,
-       .remove = snd_sb16_pnp_remove,
 #ifdef CONFIG_PM
        .suspend = snd_sb16_pnp_suspend,
        .resume = snd_sb16_pnp_resume,
index b08e6e7..e5ef177 100644 (file)
@@ -54,15 +54,6 @@ static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id)
        }
 }
 
-static void snd_sb8_free(struct snd_card *card)
-{
-       struct snd_sb8 *acard = card->private_data;
-
-       if (acard == NULL)
-               return;
-       release_and_free_resource(acard->fm_res);
-}
-
 static int snd_sb8_match(struct device *pdev, unsigned int dev)
 {
        if (!enable[dev])
@@ -86,26 +77,26 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
        struct snd_opl3 *opl3;
        int err;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_sb8), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_sb8), &card);
        if (err < 0)
                return err;
        acard = card->private_data;
-       card->private_free = snd_sb8_free;
 
        /*
         * Block the 0x388 port to avoid PnP conflicts.
         * No need to check this value after request_region,
         * as we never do anything with it.
         */
-       acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
+       acard->fm_res = devm_request_region(card->dev, 0x388, 4,
+                                           "SoundBlaster FM");
 
        if (port[dev] != SNDRV_AUTO_PORT) {
                err = snd_sbdsp_create(card, port[dev], irq[dev],
                                       snd_sb8_interrupt, dma8[dev],
                                       -1, SB_HW_AUTO, &chip);
                if (err < 0)
-                       goto _err;
+                       return err;
        } else {
                /* auto-probe legacy ports */
                static const unsigned long possible_ports[] = {
@@ -125,10 +116,8 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
                                break;
                        }
                }
-               if (i >= ARRAY_SIZE(possible_ports)) {
-                       err = -EINVAL;
-                       goto _err;
-               }
+               if (i >= ARRAY_SIZE(possible_ports))
+                       return -EINVAL;
        }
        acard->chip = chip;
                        
@@ -139,17 +128,16 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
                else
                        snd_printk(KERN_WARNING "SB 16 chip detected at 0x%lx, try snd-sb16 module\n",
                                   port[dev]);
-               err = -ENODEV;
-               goto _err;
+               return -ENODEV;
        }
 
        err = snd_sb8dsp_pcm(chip, 0);
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_sbmixer_new(chip);
        if (err < 0)
-               goto _err;
+               return err;
 
        if (chip->hardware == SB_HW_10 || chip->hardware == SB_HW_20) {
                err = snd_opl3_create(card, chip->port + 8, 0,
@@ -167,12 +155,12 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
        if (err >= 0) {
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                if (err < 0)
-                       goto _err;
+                       return err;
        }
 
        err = snd_sb8dsp_midi(chip, 0);
        if (err < 0)
-               goto _err;
+               return err;
 
        strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8");
        strcpy(card->shortname, chip->name);
@@ -183,19 +171,10 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto _err;
+               return err;
 
        dev_set_drvdata(pdev, card);
        return 0;
-
- _err:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_sb8_remove(struct device *pdev, unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(pdev));
 }
 
 #ifdef CONFIG_PM
@@ -229,7 +208,6 @@ static int snd_sb8_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_sb8_driver = {
        .match          = snd_sb8_match,
        .probe          = snd_sb8_probe,
-       .remove         = snd_sb8_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_sb8_suspend,
        .resume         = snd_sb8_resume,
index 5712121..c0e319d 100644 (file)
@@ -168,31 +168,6 @@ static int snd_sbdsp_probe(struct snd_sb * chip)
        return 0;
 }
 
-static int snd_sbdsp_free(struct snd_sb *chip)
-{
-       release_and_free_resource(chip->res_port);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, (void *) chip);
-#ifdef CONFIG_ISA
-       if (chip->dma8 >= 0) {
-               disable_dma(chip->dma8);
-               free_dma(chip->dma8);
-       }
-       if (chip->dma16 >= 0 && chip->dma16 != chip->dma8) {
-               disable_dma(chip->dma16);
-               free_dma(chip->dma16);
-       }
-#endif
-       kfree(chip);
-       return 0;
-}
-
-static int snd_sbdsp_dev_free(struct snd_device *device)
-{
-       struct snd_sb *chip = device->device_data;
-       return snd_sbdsp_free(chip);
-}
-
 int snd_sbdsp_create(struct snd_card *card,
                     unsigned long port,
                     int irq,
@@ -204,15 +179,12 @@ int snd_sbdsp_create(struct snd_card *card,
 {
        struct snd_sb *chip;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_sbdsp_dev_free,
-       };
 
        if (snd_BUG_ON(!r_chip))
                return -EINVAL;
        *r_chip = NULL;
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL)
+       chip = devm_kzalloc(card->dev, sizeof(*chip), GFP_KERNEL);
+       if (!chip)
                return -ENOMEM;
        spin_lock_init(&chip->reg_lock);
        spin_lock_init(&chip->open_lock);
@@ -223,13 +195,12 @@ int snd_sbdsp_create(struct snd_card *card,
        chip->dma16 = -1;
        chip->port = port;
        
-       if (request_irq(irq, irq_handler,
-                       (hardware == SB_HW_ALS4000 ||
-                        hardware == SB_HW_CS5530) ?
-                       IRQF_SHARED : 0,
-                       "SoundBlaster", (void *) chip)) {
+       if (devm_request_irq(card->dev, irq, irq_handler,
+                            (hardware == SB_HW_ALS4000 ||
+                             hardware == SB_HW_CS5530) ?
+                            IRQF_SHARED : 0,
+                            "SoundBlaster", (void *) chip)) {
                snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq);
-               snd_sbdsp_free(chip);
                return -EBUSY;
        }
        chip->irq = irq;
@@ -238,17 +209,17 @@ int snd_sbdsp_create(struct snd_card *card,
        if (hardware == SB_HW_ALS4000)
                goto __skip_allocation;
        
-       chip->res_port = request_region(port, 16, "SoundBlaster");
+       chip->res_port = devm_request_region(card->dev, port, 16,
+                                            "SoundBlaster");
        if (!chip->res_port) {
                snd_printk(KERN_ERR "sb: can't grab port 0x%lx\n", port);
-               snd_sbdsp_free(chip);
                return -EBUSY;
        }
 
 #ifdef CONFIG_ISA
-       if (dma8 >= 0 && request_dma(dma8, "SoundBlaster - 8bit")) {
+       if (dma8 >= 0 && snd_devm_request_dma(card->dev, dma8,
+                                             "SoundBlaster - 8bit")) {
                snd_printk(KERN_ERR "sb: can't grab DMA8 %d\n", dma8);
-               snd_sbdsp_free(chip);
                return -EBUSY;
        }
        chip->dma8 = dma8;
@@ -256,9 +227,9 @@ int snd_sbdsp_create(struct snd_card *card,
                if (hardware != SB_HW_ALS100 && (dma16 < 5 || dma16 > 7)) {
                        /* no duplex */
                        dma16 = -1;
-               } else if (request_dma(dma16, "SoundBlaster - 16bit")) {
+               } else if (snd_devm_request_dma(card->dev, dma16,
+                                               "SoundBlaster - 16bit")) {
                        snd_printk(KERN_ERR "sb: can't grab DMA16 %d\n", dma16);
-                       snd_sbdsp_free(chip);
                        return -EBUSY;
                }
        }
@@ -269,15 +240,8 @@ int snd_sbdsp_create(struct snd_card *card,
        chip->card = card;
        chip->hardware = hardware;
        err = snd_sbdsp_probe(chip);
-       if (err < 0) {
-               snd_sbdsp_free(chip);
+       if (err < 0)
                return err;
-       }
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_sbdsp_free(chip);
-               return err;
-       }
        *r_chip = chip;
        return 0;
 }
index 3462663..26ab7ff 100644 (file)
@@ -529,6 +529,14 @@ static int snd_sc6000_match(struct device *devptr, unsigned int dev)
        return 1;
 }
 
+static void snd_sc6000_free(struct snd_card *card)
+{
+       char __iomem *vport = (char __force __iomem *)card->private_data;
+
+       if (vport)
+               sc6000_setup_board(vport, 0);
+}
+
 static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
 {
        static const int possible_irqs[] = { 5, 7, 9, 10, 11, -1 };
@@ -539,22 +547,19 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
        struct snd_card *card;
        struct snd_wss *chip;
        struct snd_opl3 *opl3;
-       char __iomem **vport;
+       char __iomem *vport;
        char __iomem *vmss_port;
 
-
-       err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE,
-                          sizeof(vport), &card);
+       err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
+                               0, &card);
        if (err < 0)
                return err;
 
-       vport = card->private_data;
        if (xirq == SNDRV_AUTO_IRQ) {
                xirq = snd_legacy_find_free_irq(possible_irqs);
                if (xirq < 0) {
                        snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
-                       err = -EBUSY;
-                       goto err_exit;
+                       return -EBUSY;
                }
        }
 
@@ -562,68 +567,65 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
                xdma = snd_legacy_find_free_dma(possible_dmas);
                if (xdma < 0) {
                        snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
-                       err = -EBUSY;
-                       goto err_exit;
+                       return -EBUSY;
                }
        }
 
-       if (!request_region(port[dev], 0x10, DRV_NAME)) {
+       if (!devm_request_region(devptr, port[dev], 0x10, DRV_NAME)) {
                snd_printk(KERN_ERR PFX
                           "I/O port region is already in use.\n");
-               err = -EBUSY;
-               goto err_exit;
+               return -EBUSY;
        }
-       *vport = devm_ioport_map(devptr, port[dev], 0x10);
-       if (*vport == NULL) {
+       vport = devm_ioport_map(devptr, port[dev], 0x10);
+       if (!vport) {
                snd_printk(KERN_ERR PFX
                           "I/O port cannot be iomapped.\n");
-               err = -EBUSY;
-               goto err_unmap1;
+               return -EBUSY;
        }
+       card->private_data = (void __force *)vport;
 
        /* to make it marked as used */
-       if (!request_region(mss_port[dev], 4, DRV_NAME)) {
+       if (!devm_request_region(devptr, mss_port[dev], 4, DRV_NAME)) {
                snd_printk(KERN_ERR PFX
                           "SC-6000 port I/O port region is already in use.\n");
-               err = -EBUSY;
-               goto err_unmap1;
+               return -EBUSY;
        }
        vmss_port = devm_ioport_map(devptr, mss_port[dev], 4);
        if (!vmss_port) {
                snd_printk(KERN_ERR PFX
                           "MSS port I/O cannot be iomapped.\n");
-               err = -EBUSY;
-               goto err_unmap2;
+               return -EBUSY;
        }
 
        snd_printd("Initializing BASE[0x%lx] IRQ[%d] DMA[%d] MIRQ[%d]\n",
                   port[dev], xirq, xdma,
                   mpu_irq[dev] == SNDRV_AUTO_IRQ ? 0 : mpu_irq[dev]);
 
-       err = sc6000_init_board(*vport, vmss_port, dev);
+       err = sc6000_init_board(vport, vmss_port, dev);
        if (err < 0)
-               goto err_unmap2;
+               return err;
+       card->private_free = snd_sc6000_free;
 
        err = snd_wss_create(card, mss_port[dev] + 4,  -1, xirq, xdma, -1,
                             WSS_HW_DETECT, 0, &chip);
        if (err < 0)
-               goto err_unmap2;
+               return err;
 
        err = snd_wss_pcm(chip, 0);
        if (err < 0) {
                snd_printk(KERN_ERR PFX
                           "error creating new WSS PCM device\n");
-               goto err_unmap2;
+               return err;
        }
        err = snd_wss_mixer(chip);
        if (err < 0) {
                snd_printk(KERN_ERR PFX "error creating new WSS mixer\n");
-               goto err_unmap2;
+               return err;
        }
        err = snd_sc6000_mixer(chip);
        if (err < 0) {
                snd_printk(KERN_ERR PFX "the mixer rewrite failed\n");
-               goto err_unmap2;
+               return err;
        }
        if (snd_opl3_create(card,
                            0x388, 0x388 + 2,
@@ -633,7 +635,7 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
        } else {
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                if (err < 0)
-                       goto err_unmap2;
+                       return err;
        }
 
        if (mpu_port[dev] != SNDRV_AUTO_PORT) {
@@ -654,39 +656,15 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto err_unmap2;
+               return err;
 
        dev_set_drvdata(devptr, card);
        return 0;
-
-err_unmap2:
-       sc6000_setup_board(*vport, 0);
-       release_region(mss_port[dev], 4);
-err_unmap1:
-       release_region(port[dev], 0x10);
-err_exit:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_sc6000_remove(struct device *devptr, unsigned int dev)
-{
-       struct snd_card *card = dev_get_drvdata(devptr);
-       char __iomem **vport = card->private_data;
-
-       if (sc6000_setup_board(*vport, 0) < 0)
-               snd_printk(KERN_WARNING "sc6000_setup_board failed on exit!\n");
-
-       release_region(port[dev], 0x10);
-       release_region(mss_port[dev], 4);
-
-       snd_card_free(card);
 }
 
 static struct isa_driver snd_sc6000_driver = {
        .match          = snd_sc6000_match,
        .probe          = snd_sc6000_probe,
-       .remove         = snd_sc6000_remove,
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = DRV_NAME,
index e70ef9a..0bc0025 100644 (file)
@@ -327,17 +327,6 @@ static void activate_ad1845_unsafe(unsigned io_base)
        sscape_write_unsafe(io_base, GA_CDCFG_REG, 0x80);
 }
 
-/*
- * Do the necessary ALSA-level cleanup to deallocate our driver ...
- */
-static void soundscape_free(struct snd_card *c)
-{
-       struct soundscape *sscape = get_card_soundscape(c);
-       release_and_free_resource(sscape->io_res);
-       release_and_free_resource(sscape->wss_res);
-       free_dma(sscape->chip->dma1);
-}
-
 /*
  * Tell the SoundScape to begin a DMA transfer using the given channel.
  * All locking issues are left to the caller.
@@ -941,7 +930,7 @@ static int create_sscape(int dev, struct snd_card *card)
         * Grab IO ports that we will need to probe so that we
         * can detect and control this hardware ...
         */
-       io_res = request_region(port[dev], 8, "SoundScape");
+       io_res = devm_request_region(card->dev, port[dev], 8, "SoundScape");
        if (!io_res) {
                snd_printk(KERN_ERR
                           "sscape: can't grab port 0x%lx\n", port[dev]);
@@ -949,22 +938,22 @@ static int create_sscape(int dev, struct snd_card *card)
        }
        wss_res = NULL;
        if (sscape->type == SSCAPE_VIVO) {
-               wss_res = request_region(wss_port[dev], 4, "SoundScape");
+               wss_res = devm_request_region(card->dev, wss_port[dev], 4,
+                                             "SoundScape");
                if (!wss_res) {
                        snd_printk(KERN_ERR "sscape: can't grab port 0x%lx\n",
                                            wss_port[dev]);
-                       err = -EBUSY;
-                       goto _release_region;
+                       return -EBUSY;
                }
        }
 
        /*
         * Grab one DMA channel ...
         */
-       err = request_dma(dma[dev], "SoundScape");
+       err = snd_devm_request_dma(card->dev, dma[dev], "SoundScape");
        if (err < 0) {
                snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]);
-               goto _release_region;
+               return err;
        }
 
        spin_lock_init(&sscape->lock);
@@ -975,8 +964,7 @@ static int create_sscape(int dev, struct snd_card *card)
        if (!detect_sscape(sscape, wss_port[dev])) {
                printk(KERN_ERR "sscape: hardware not detected at 0x%x\n",
                        sscape->io_base);
-               err = -ENODEV;
-               goto _release_dma;
+               return -ENODEV;
        }
 
        switch (sscape->type) {
@@ -1006,15 +994,13 @@ static int create_sscape(int dev, struct snd_card *card)
        irq_cfg = get_irq_config(sscape->type, irq[dev]);
        if (irq_cfg == INVALID_IRQ) {
                snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
-               err = -ENXIO;
-               goto _release_dma;
+               return -ENXIO;
        }
 
        mpu_irq_cfg = get_irq_config(sscape->type, mpu_irq[dev]);
        if (mpu_irq_cfg == INVALID_IRQ) {
                snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
-               err = -ENXIO;
-               goto _release_dma;
+               return -ENXIO;
        }
 
        /*
@@ -1060,7 +1046,7 @@ static int create_sscape(int dev, struct snd_card *card)
                snd_printk(KERN_ERR
                                "sscape: No AD1845 device at 0x%lx, IRQ %d\n",
                                wss_port[dev], irq[dev]);
-               goto _release_dma;
+               return err;
        }
        strcpy(card->driver, "SoundScape");
        strcpy(card->shortname, name);
@@ -1082,7 +1068,7 @@ static int create_sscape(int dev, struct snd_card *card)
                                snd_printk(KERN_ERR "sscape: Failed to create "
                                                "MPU-401 device at 0x%lx\n",
                                                port[dev]);
-                               goto _release_dma;
+                               return err;
                        }
 
                        /*
@@ -1109,24 +1095,7 @@ static int create_sscape(int dev, struct snd_card *card)
                }
        }
 
-       /*
-        * Now that we have successfully created this sound card,
-        * it is safe to store the pointer.
-        * NOTE: we only register the sound card's "destructor"
-        *       function now that our "constructor" has completed.
-        */
-       card->private_free = soundscape_free;
-
        return 0;
-
-_release_dma:
-       free_dma(dma[dev]);
-
-_release_region:
-       release_and_free_resource(wss_res);
-       release_and_free_resource(io_res);
-
-       return err;
 }
 
 
@@ -1156,8 +1125,8 @@ static int snd_sscape_probe(struct device *pdev, unsigned int dev)
        struct soundscape *sscape;
        int ret;
 
-       ret = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct soundscape), &card);
+       ret = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct soundscape), &card);
        if (ret < 0)
                return ret;
 
@@ -1168,24 +1137,15 @@ static int snd_sscape_probe(struct device *pdev, unsigned int dev)
 
        ret = create_sscape(dev, card);
        if (ret < 0)
-               goto _release_card;
+               return ret;
 
        ret = snd_card_register(card);
        if (ret < 0) {
                snd_printk(KERN_ERR "sscape: Failed to register sound card\n");
-               goto _release_card;
+               return ret;
        }
        dev_set_drvdata(pdev, card);
        return 0;
-
-_release_card:
-       snd_card_free(card);
-       return ret;
-}
-
-static void snd_sscape_remove(struct device *devptr, unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
 }
 
 #define DEV_NAME "sscape"
@@ -1193,7 +1153,6 @@ static void snd_sscape_remove(struct device *devptr, unsigned int dev)
 static struct isa_driver snd_sscape_driver = {
        .match          = snd_sscape_match,
        .probe          = snd_sscape_probe,
-       .remove         = snd_sscape_remove,
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = DEV_NAME
@@ -1244,9 +1203,9 @@ static int sscape_pnp_detect(struct pnp_card_link *pcard,
         * Create a new ALSA sound card entry, in anticipation
         * of detecting our hardware ...
         */
-       ret = snd_card_new(&pcard->card->dev,
-                          index[idx], id[idx], THIS_MODULE,
-                          sizeof(struct soundscape), &card);
+       ret = snd_devm_card_new(&pcard->card->dev,
+                               index[idx], id[idx], THIS_MODULE,
+                               sizeof(struct soundscape), &card);
        if (ret < 0)
                return ret;
 
@@ -1277,27 +1236,17 @@ static int sscape_pnp_detect(struct pnp_card_link *pcard,
 
        ret = create_sscape(idx, card);
        if (ret < 0)
-               goto _release_card;
+               return ret;
 
        ret = snd_card_register(card);
        if (ret < 0) {
                snd_printk(KERN_ERR "sscape: Failed to register sound card\n");
-               goto _release_card;
+               return ret;
        }
 
        pnp_set_card_drvdata(pcard, card);
        ++idx;
        return 0;
-
-_release_card:
-       snd_card_free(card);
-       return ret;
-}
-
-static void sscape_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
 }
 
 static struct pnp_card_driver sscape_pnpc_driver = {
@@ -1305,7 +1254,6 @@ static struct pnp_card_driver sscape_pnpc_driver = {
        .name = "sscape",
        .id_table = sscape_pnpids,
        .probe = sscape_pnp_detect,
-       .remove = sscape_pnp_remove,
 };
 
 #endif /* CONFIG_PNP */
index dfdeaf7..e6e46a0 100644 (file)
@@ -308,18 +308,6 @@ static struct snd_rawmidi *snd_wavefront_new_midi(struct snd_card *card,
        return rmidi;
 }
 
-static void
-snd_wavefront_free(struct snd_card *card)
-{
-       snd_wavefront_card_t *acard = (snd_wavefront_card_t *)card->private_data;
-       
-       if (acard) {
-               release_and_free_resource(acard->wavefront.res_base);
-               if (acard->wavefront.irq > 0)
-                       free_irq(acard->wavefront.irq, (void *)acard);
-       }
-}
-
 static int snd_wavefront_card_new(struct device *pdev, int dev,
                                  struct snd_card **cardp)
 {
@@ -327,8 +315,8 @@ static int snd_wavefront_card_new(struct device *pdev, int dev,
        snd_wavefront_card_t *acard;
        int err;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(snd_wavefront_card_t), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(snd_wavefront_card_t), &card);
        if (err < 0)
                return err;
 
@@ -339,7 +327,6 @@ static int snd_wavefront_card_new(struct device *pdev, int dev,
        spin_lock_init(&acard->wavefront.midi.open);
        spin_lock_init(&acard->wavefront.midi.virtual);
        acard->wavefront.card = card;
-       card->private_free = snd_wavefront_free;
 
        *cardp = card;
        return 0;
@@ -394,15 +381,17 @@ snd_wavefront_probe (struct snd_card *card, int dev)
 
        /* ------- ICS2115 Wavetable synth ------- */
 
-       acard->wavefront.res_base = request_region(ics2115_port[dev], 16,
-                                                  "ICS2115");
+       acard->wavefront.res_base =
+               devm_request_region(card->dev, ics2115_port[dev], 16,
+                                   "ICS2115");
        if (acard->wavefront.res_base == NULL) {
                snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n",
                           ics2115_port[dev], ics2115_port[dev] + 16 - 1);
                return -EBUSY;
        }
-       if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt,
-                       0, "ICS2115", acard)) {
+       if (devm_request_irq(card->dev, ics2115_irq[dev],
+                            snd_wavefront_ics2115_interrupt,
+                            0, "ICS2115", acard)) {
                snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]);
                return -EBUSY;
        }
@@ -556,27 +545,18 @@ static int snd_wavefront_isa_probe(struct device *pdev,
        if (err < 0)
                return err;
        err = snd_wavefront_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        
        dev_set_drvdata(pdev, card);
        return 0;
 }
 
-static void snd_wavefront_isa_remove(struct device *devptr,
-                                   unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-}
-
 #define DEV_NAME "wavefront"
 
 static struct isa_driver snd_wavefront_driver = {
        .match          = snd_wavefront_isa_match,
        .probe          = snd_wavefront_isa_probe,
-       .remove         = snd_wavefront_isa_remove,
        /* FIXME: suspend, resume */
        .driver         = {
                .name   = DEV_NAME
@@ -606,7 +586,6 @@ static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
        if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) {
                if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
                        snd_printk (KERN_ERR "isapnp detection failed\n");
-                       snd_card_free (card);
                        return -ENODEV;
                }
        }
@@ -620,18 +599,11 @@ static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
        return 0;
 }
 
-static void snd_wavefront_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 static struct pnp_card_driver wavefront_pnpc_driver = {
        .flags          = PNP_DRIVER_RES_DISABLE,
        .name           = "wavefront",
        .id_table       = snd_wavefront_pnpids,
        .probe          = snd_wavefront_pnp_detect,
-       .remove         = snd_wavefront_pnp_remove,
        /* FIXME: suspend,resume */
 };
 
index 743e0f0..026061b 100644 (file)
@@ -1655,36 +1655,6 @@ static void snd_wss_resume(struct snd_wss *chip)
 }
 #endif /* CONFIG_PM */
 
-static int snd_wss_free(struct snd_wss *chip)
-{
-       release_and_free_resource(chip->res_port);
-       release_and_free_resource(chip->res_cport);
-       if (chip->irq >= 0) {
-               disable_irq(chip->irq);
-               if (!(chip->hwshare & WSS_HWSHARE_IRQ))
-                       free_irq(chip->irq, (void *) chip);
-       }
-       if (!(chip->hwshare & WSS_HWSHARE_DMA1) && chip->dma1 >= 0) {
-               snd_dma_disable(chip->dma1);
-               free_dma(chip->dma1);
-       }
-       if (!(chip->hwshare & WSS_HWSHARE_DMA2) &&
-           chip->dma2 >= 0 && chip->dma2 != chip->dma1) {
-               snd_dma_disable(chip->dma2);
-               free_dma(chip->dma2);
-       }
-       if (chip->timer)
-               snd_device_free(chip->card, chip->timer);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_wss_dev_free(struct snd_device *device)
-{
-       struct snd_wss *chip = device->device_data;
-       return snd_wss_free(chip);
-}
-
 const char *snd_wss_chip_id(struct snd_wss *chip)
 {
        switch (chip->hardware) {
@@ -1738,7 +1708,7 @@ static int snd_wss_new(struct snd_card *card,
        struct snd_wss *chip;
 
        *rchip = NULL;
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+       chip = devm_kzalloc(card->dev, sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
        chip->hardware = hardware;
@@ -1774,9 +1744,6 @@ int snd_wss_create(struct snd_card *card,
                      unsigned short hwshare,
                      struct snd_wss **rchip)
 {
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_wss_dev_free,
-       };
        struct snd_wss *chip;
        int err;
 
@@ -1788,42 +1755,39 @@ int snd_wss_create(struct snd_card *card,
        chip->dma1 = -1;
        chip->dma2 = -1;
 
-       chip->res_port = request_region(port, 4, "WSS");
+       chip->res_port = devm_request_region(card->dev, port, 4, "WSS");
        if (!chip->res_port) {
                snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port);
-               snd_wss_free(chip);
                return -EBUSY;
        }
        chip->port = port;
        if ((long)cport >= 0) {
-               chip->res_cport = request_region(cport, 8, "CS4232 Control");
+               chip->res_cport = devm_request_region(card->dev, cport, 8,
+                                                     "CS4232 Control");
                if (!chip->res_cport) {
                        snd_printk(KERN_ERR
                                "wss: can't grab control port 0x%lx\n", cport);
-                       snd_wss_free(chip);
                        return -ENODEV;
                }
        }
        chip->cport = cport;
        if (!(hwshare & WSS_HWSHARE_IRQ))
-               if (request_irq(irq, snd_wss_interrupt, 0,
-                               "WSS", (void *) chip)) {
+               if (devm_request_irq(card->dev, irq, snd_wss_interrupt, 0,
+                                    "WSS", (void *) chip)) {
                        snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
-                       snd_wss_free(chip);
                        return -EBUSY;
                }
        chip->irq = irq;
        card->sync_irq = chip->irq;
-       if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) {
+       if (!(hwshare & WSS_HWSHARE_DMA1) &&
+           snd_devm_request_dma(card->dev, dma1, "WSS - 1")) {
                snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1);
-               snd_wss_free(chip);
                return -EBUSY;
        }
        chip->dma1 = dma1;
-       if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 &&
-             dma2 >= 0 && request_dma(dma2, "WSS - 2")) {
+       if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 && dma2 >= 0 &&
+           snd_devm_request_dma(card->dev, dma2, "WSS - 2")) {
                snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2);
-               snd_wss_free(chip);
                return -EBUSY;
        }
        if (dma1 == dma2 || dma2 < 0) {
@@ -1839,10 +1803,8 @@ int snd_wss_create(struct snd_card *card,
        }
 
        /* global setup */
-       if (snd_wss_probe(chip) < 0) {
-               snd_wss_free(chip);
+       if (snd_wss_probe(chip) < 0)
                return -ENODEV;
-       }
        snd_wss_init(chip);
 
 #if 0
@@ -1853,13 +1815,6 @@ int snd_wss_create(struct snd_card *card,
        }
 #endif
 
-       /* Register device */
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_wss_free(chip);
-               return err;
-       }
-
 #ifdef CONFIG_PM
        /* Power Management */
        chip->suspend = snd_wss_suspend;
index 1440db8..ec4fda3 100644 (file)
@@ -563,22 +563,9 @@ snd_harmony_capture_close(struct snd_pcm_substream *ss)
         return 0;
 }
 
-static int 
-snd_harmony_hw_params(struct snd_pcm_substream *ss,
-                     struct snd_pcm_hw_params *hw)
-{
-       struct snd_harmony *h = snd_pcm_substream_chip(ss);
-       
-       if (h->dma.type == SNDRV_DMA_TYPE_CONTINUOUS)
-               ss->runtime->dma_addr = __pa(ss->runtime->dma_area);
-
-       return 0;
-}
-
 static const struct snd_pcm_ops snd_harmony_playback_ops = {
        .open = snd_harmony_playback_open,
        .close = snd_harmony_playback_close,
-       .hw_params = snd_harmony_hw_params,
        .prepare = snd_harmony_playback_prepare,
        .trigger = snd_harmony_playback_trigger,
        .pointer = snd_harmony_playback_pointer,
@@ -587,7 +574,6 @@ static const struct snd_pcm_ops snd_harmony_playback_ops = {
 static const struct snd_pcm_ops snd_harmony_capture_ops = {
         .open = snd_harmony_capture_open,
         .close = snd_harmony_capture_close,
-        .hw_params = snd_harmony_hw_params,
         .prepare = snd_harmony_capture_prepare,
         .trigger = snd_harmony_capture_trigger,
         .pointer = snd_harmony_capture_pointer,
index 5c78951..bba4dae 100644 (file)
@@ -740,20 +740,6 @@ snd_ad1889_ac97_xinit(struct snd_ad1889 *chip)
 
 }
 
-static void
-snd_ad1889_ac97_bus_free(struct snd_ac97_bus *bus)
-{
-       struct snd_ad1889 *chip = bus->private_data;
-       chip->ac97_bus = NULL;
-}
-
-static void
-snd_ad1889_ac97_free(struct snd_ac97 *ac97)
-{
-       struct snd_ad1889 *chip = ac97->private_data;
-       chip->ac97 = NULL;
-}
-
 static int
 snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
 {
@@ -771,11 +757,8 @@ snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
        if (err < 0)
                return err;
        
-       chip->ac97_bus->private_free = snd_ad1889_ac97_bus_free;
-
        memset(&ac97, 0, sizeof(ac97));
        ac97.private_data = chip;
-       ac97.private_free = snd_ad1889_ac97_free;
        ac97.pci = chip->pci;
 
        err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97);
@@ -787,11 +770,10 @@ snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
        return 0;
 }
 
-static int
-snd_ad1889_free(struct snd_ad1889 *chip)
+static void
+snd_ad1889_free(struct snd_card *card)
 {
-       if (chip->irq < 0)
-               goto skip_hw;
+       struct snd_ad1889 *chip = card->private_data;
 
        spin_lock_irq(&chip->lock);
 
@@ -805,125 +787,60 @@ snd_ad1889_free(struct snd_ad1889 *chip)
        ad1889_readl(chip, AD_DMA_DISR);        /* flush, dammit! */
 
        spin_unlock_irq(&chip->lock);
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-
-skip_hw:
-       iounmap(chip->iobase);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int
-snd_ad1889_dev_free(struct snd_device *device) 
-{
-       struct snd_ad1889 *chip = device->device_data;
-       return snd_ad1889_free(chip);
-}
-
-static int
-snd_ad1889_init(struct snd_ad1889 *chip) 
-{
-       ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
-       ad1889_readw(chip, AD_DS_CCS);  /* flush posted write */
-
-       usleep_range(10000, 11000);
-
-       /* enable Master and Target abort interrupts */
-       ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE);
-
-       return 0;
 }
 
 static int
-snd_ad1889_create(struct snd_card *card,
-                 struct pci_dev *pci,
-                 struct snd_ad1889 **rchip)
+snd_ad1889_create(struct snd_card *card, struct pci_dev *pci)
 {
+       struct snd_ad1889 *chip = card->private_data;
        int err;
 
-       struct snd_ad1889 *chip;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_ad1889_dev_free,
-       };
-
-       *rchip = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        /* check PCI availability (32bit DMA) */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_err(card->dev, "error setting 32-bit DMA mask.\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       /* allocate chip specific data with zero-filled memory */
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (!chip) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
-       card->private_data = chip;
        chip->pci = pci;
        chip->irq = -1;
 
        /* (1) PCI resource allocation */
-       err = pci_request_regions(pci, card->driver);
+       err = pcim_iomap_regions(pci, 1 << 0, card->driver);
        if (err < 0)
-               goto free_and_ret;
+               return err;
 
        chip->bar = pci_resource_start(pci, 0);
-       chip->iobase = pci_ioremap_bar(pci, 0);
-       if (chip->iobase == NULL) {
-               dev_err(card->dev, "unable to reserve region.\n");
-               err = -EBUSY;
-               goto free_and_ret;
-       }
+       chip->iobase = pcim_iomap_table(pci)[0];
        
        pci_set_master(pci);
 
        spin_lock_init(&chip->lock);    /* only now can we call ad1889_free */
 
-       if (request_irq(pci->irq, snd_ad1889_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_ad1889_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "cannot obtain IRQ %d\n", pci->irq);
-               snd_ad1889_free(chip);
                return -EBUSY;
        }
 
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_ad1889_free;
 
        /* (2) initialization of the chip hardware */
-       err = snd_ad1889_init(chip);
-       if (err < 0) {
-               snd_ad1889_free(chip);
-               return err;
-       }
+       ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
+       ad1889_readw(chip, AD_DS_CCS);  /* flush posted write */
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_ad1889_free(chip);
-               return err;
-       }
+       usleep_range(10000, 11000);
 
-       *rchip = chip;
+       /* enable Master and Target abort interrupts */
+       ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE);
 
        return 0;
-
-free_and_ret:
-       kfree(chip);
-       pci_disable_device(pci);
-
-       return err;
 }
 
 static int
@@ -944,19 +861,19 @@ snd_ad1889_probe(struct pci_dev *pci,
        }
 
        /* (2) */
-       err = snd_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE,
-                          0, &card);
-       /* XXX REVISIT: we can probably allocate chip in this call */
+       err = snd_devm_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        strcpy(card->driver, "AD1889");
        strcpy(card->shortname, "Analog Devices AD1889");
 
        /* (3) */
-       err = snd_ad1889_create(card, pci, &chip);
+       err = snd_ad1889_create(card, pci);
        if (err < 0)
-               goto free_and_ret;
+               return err;
 
        /* (4) */
        sprintf(card->longname, "%s at 0x%lx irq %i",
@@ -966,11 +883,11 @@ snd_ad1889_probe(struct pci_dev *pci,
        /* register AC97 mixer */
        err = snd_ad1889_ac97_init(chip, ac97_quirk[devno]);
        if (err < 0)
-               goto free_and_ret;
+               return err;
        
        err = snd_ad1889_pcm_init(chip, 0);
        if (err < 0)
-               goto free_and_ret;
+               return err;
 
        /* register proc interface */
        snd_ad1889_proc_init(chip);
@@ -978,23 +895,13 @@ snd_ad1889_probe(struct pci_dev *pci,
        /* (6) */
        err = snd_card_register(card);
        if (err < 0)
-               goto free_and_ret;
+               return err;
 
        /* (7) */
        pci_set_drvdata(pci, card);
 
        devno++;
        return 0;
-
-free_and_ret:
-       snd_card_free(card);
-       return err;
-}
-
-static void
-snd_ad1889_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static const struct pci_device_id snd_ad1889_ids[] = {
@@ -1007,7 +914,6 @@ static struct pci_driver ad1889_pci_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ad1889_ids,
        .probe = snd_ad1889_probe,
-       .remove = snd_ad1889_remove,
 };
 
 module_pci_driver(ad1889_pci_driver);
index 0d66b92..92eb59d 100644 (file)
@@ -1914,22 +1914,14 @@ static SIMPLE_DEV_PM_OPS(ali_pm, ali_suspend, ali_resume);
 #define ALI_PM_OPS     NULL
 #endif /* CONFIG_PM_SLEEP */
 
-static int snd_ali_free(struct snd_ali * codec)
+static void snd_ali_free(struct snd_card *card)
 {
+       struct snd_ali *codec = card->private_data;
+
        if (codec->hw_initialized)
                snd_ali_disable_address_interrupt(codec);
-       if (codec->irq >= 0)
-               free_irq(codec->irq, codec);
-       if (codec->port)
-               pci_release_regions(codec->pci);
-       pci_disable_device(codec->pci);
-#ifdef CONFIG_PM_SLEEP
-       kfree(codec->image);
-#endif
        pci_dev_put(codec->pci_m1533);
        pci_dev_put(codec->pci_m7101);
-       kfree(codec);
-       return 0;
 }
 
 static int snd_ali_chip_init(struct snd_ali *codec)
@@ -2017,8 +2009,9 @@ static int snd_ali_resources(struct snd_ali *codec)
                return err;
        codec->port = pci_resource_start(codec->pci, 0);
 
-       if (request_irq(codec->pci->irq, snd_ali_card_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, codec)) {
+       if (devm_request_irq(&codec->pci->dev, codec->pci->irq,
+                            snd_ali_card_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, codec)) {
                dev_err(codec->card->dev, "Unable to request irq.\n");
                return -EBUSY;
        }
@@ -2027,48 +2020,29 @@ static int snd_ali_resources(struct snd_ali *codec)
        dev_dbg(codec->card->dev, "resources allocated.\n");
        return 0;
 }
-static int snd_ali_dev_free(struct snd_device *device)
-{
-       struct snd_ali *codec = device->device_data;
-       snd_ali_free(codec);
-       return 0;
-}
 
 static int snd_ali_create(struct snd_card *card,
                          struct pci_dev *pci,
                          int pcm_streams,
-                         int spdif_support,
-                         struct snd_ali **r_ali)
+                         int spdif_support)
 {
-       struct snd_ali *codec;
+       struct snd_ali *codec = card->private_data;
        int i, err;
        unsigned short cmdw;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_ali_dev_free,
-        };
-
-       *r_ali = NULL;
 
        dev_dbg(card->dev, "creating ...\n");
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 31 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31))) {
                dev_err(card->dev,
                        "architecture does not support 31bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       codec = kzalloc(sizeof(*codec), GFP_KERNEL);
-       if (!codec) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&codec->reg_lock);
        spin_lock_init(&codec->voice_alloc);
 
@@ -2089,12 +2063,10 @@ static int snd_ali_create(struct snd_card *card,
                cmdw |= PCI_COMMAND_IO;
                pci_write_config_word(pci, PCI_COMMAND, cmdw);
        }
-       pci_set_master(pci);
        
-       if (snd_ali_resources(codec)) {
-               snd_ali_free(codec);
+       if (snd_ali_resources(codec))
                return -EBUSY;
-       }
+       card->private_free = snd_ali_free;
 
        codec->synth.chmap = 0;
        codec->synth.chcnt = 0;
@@ -2121,24 +2093,15 @@ static int snd_ali_create(struct snd_card *card,
        codec->pci_m1533 = pci_get_device(0x10b9, 0x1533, NULL);
        if (!codec->pci_m1533) {
                dev_err(card->dev, "cannot find ALi 1533 chip.\n");
-               snd_ali_free(codec);
                return -ENODEV;
        }
        /* M7101: power management */
        codec->pci_m7101 = pci_get_device(0x10b9, 0x7101, NULL);
        if (!codec->pci_m7101 && codec->revision == ALI_5451_V02) {
                dev_err(card->dev, "cannot find ALi 7101 chip.\n");
-               snd_ali_free(codec);
                return -ENODEV;
        }
 
-       dev_dbg(card->dev, "snd_device_new is called.\n");
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops);
-       if (err < 0) {
-               snd_ali_free(codec);
-               return err;
-       }
-
        /* initialise synth voices*/
        for (i = 0; i < ALI_CHANNELS; i++)
                codec->synth.voices[i].number = i;
@@ -2150,16 +2113,14 @@ static int snd_ali_create(struct snd_card *card,
        }
 
 #ifdef CONFIG_PM_SLEEP
-       codec->image = kmalloc(sizeof(*codec->image), GFP_KERNEL);
+       codec->image = devm_kmalloc(&pci->dev, sizeof(*codec->image),
+                                   GFP_KERNEL);
        if (!codec->image)
                dev_warn(card->dev, "can't allocate apm buffer\n");
 #endif
 
        snd_ali_enable_address_interrupt(codec);
        codec->hw_initialized = 1;
-
-       *r_ali = codec;
-       dev_dbg(card->dev, "created.\n");
        return 0;
 }
 
@@ -2172,24 +2133,25 @@ static int snd_ali_probe(struct pci_dev *pci,
 
        dev_dbg(&pci->dev, "probe ...\n");
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*codec), &card);
        if (err < 0)
                return err;
+       codec = card->private_data;
 
-       err = snd_ali_create(card, pci, pcm_channels, spdif, &codec);
+       err = snd_ali_create(card, pci, pcm_channels, spdif);
        if (err < 0)
-               goto error;
-       card->private_data = codec;
+               return err;
 
        dev_dbg(&pci->dev, "mixer building ...\n");
        err = snd_ali_mixer(codec);
        if (err < 0)
-               goto error;
+               return err;
        
        dev_dbg(&pci->dev, "pcm building ...\n");
        err = snd_ali_build_pcms(codec);
        if (err < 0)
-               goto error;
+               return err;
 
        snd_ali_proc_init(codec);
 
@@ -2202,26 +2164,16 @@ static int snd_ali_probe(struct pci_dev *pci,
        dev_dbg(&pci->dev, "register card.\n");
        err = snd_card_register(card);
        if (err < 0)
-               goto error;
+               return err;
 
        pci_set_drvdata(pci, card);
        return 0;
-
- error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_ali_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver ali5451_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ali_ids,
        .probe = snd_ali_probe,
-       .remove = snd_ali_remove,
        .driver = {
                .pm = ALI_PM_OPS,
        },
index 668008f..b86565d 100644 (file)
@@ -163,21 +163,11 @@ static void snd_als300_set_irq_flag(struct snd_als300 *chip, int cmd)
        snd_als300_gcr_write(chip->port, MISC_CONTROL, tmp);
 }
 
-static int snd_als300_free(struct snd_als300 *chip)
+static void snd_als300_free(struct snd_card *card)
 {
-       snd_als300_set_irq_flag(chip, IRQ_DISABLE);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
+       struct snd_als300 *chip = card->private_data;
 
-static int snd_als300_dev_free(struct snd_device *device)
-{
-       struct snd_als300 *chip = device->device_data;
-       return snd_als300_free(chip);
+       snd_als300_set_irq_flag(chip, IRQ_DISABLE);
 }
 
 static irqreturn_t snd_als300_interrupt(int irq, void *dev_id)
@@ -248,11 +238,6 @@ static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static void snd_als300_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static unsigned short snd_als300_ac97_read(struct snd_ac97 *ac97,
                                                        unsigned short reg)
 {
@@ -610,35 +595,22 @@ static void snd_als300_init(struct snd_als300 *chip)
 }
 
 static int snd_als300_create(struct snd_card *card,
-                            struct pci_dev *pci, int chip_type,
-                            struct snd_als300 **rchip)
+                            struct pci_dev *pci, int chip_type)
 {
-       struct snd_als300 *chip;
+       struct snd_als300 *chip = card->private_data;
        void *irq_handler;
        int err;
 
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_als300_dev_free,
-       };
-       *rchip = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
                dev_err(card->dev, "error setting 28bit DMA mask\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
        pci_set_master(pci);
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
@@ -646,11 +618,9 @@ static int snd_als300_create(struct snd_card *card,
        spin_lock_init(&chip->reg_lock);
 
        err = pci_request_regions(pci, "ALS300");
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
+
        chip->port = pci_resource_start(pci, 0);
 
        if (chip->chip_type == DEVICE_ALS300_PLUS)
@@ -658,38 +628,29 @@ static int snd_als300_create(struct snd_card *card,
        else
                irq_handler = snd_als300_interrupt;
 
-       if (request_irq(pci->irq, irq_handler, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, irq_handler, IRQF_SHARED,
+                            KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_als300_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_als300_free;
 
        snd_als300_init(chip);
 
        err = snd_als300_ac97(chip);
        if (err < 0) {
                dev_err(card->dev, "Could not create ac97\n");
-               snd_als300_free(chip);
                return err;
        }
 
        err = snd_als300_new_pcm(chip);
        if (err < 0) {
                dev_err(card->dev, "Could not create PCM\n");
-               snd_als300_free(chip);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_als300_free(chip);
                return err;
        }
 
-       *rchip = chip;
        return 0;
 }
 
@@ -737,20 +698,17 @@ static int snd_als300_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
-
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        chip_type = pci_id->driver_data;
 
-       err = snd_als300_create(card, pci, chip_type, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_als300_create(card, pci, chip_type);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        strcpy(card->driver, "ALS300");
        if (chip->chip_type == DEVICE_ALS300_PLUS)
@@ -764,10 +722,9 @@ static int snd_als300_probe(struct pci_dev *pci,
                                card->shortname, chip->port, chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
+
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
@@ -777,7 +734,6 @@ static struct pci_driver als300_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_als300_ids,
        .probe = snd_als300_probe,
-       .remove = snd_als300_remove,
        .driver = {
                .pm = SND_ALS300_PM_OPS,
        },
index 509f317..535eccd 100644 (file)
@@ -746,13 +746,15 @@ static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
 
        if (joystick_port[dev] == 1) { /* auto-detect */
                for (io_port = 0x200; io_port <= 0x218; io_port += 8) {
-                       r = request_region(io_port, 8, "ALS4000 gameport");
+                       r = devm_request_region(&acard->pci->dev, io_port, 8,
+                                               "ALS4000 gameport");
                        if (r)
                                break;
                }
        } else {
                io_port = joystick_port[dev];
-               r = request_region(io_port, 8, "ALS4000 gameport");
+               r = devm_request_region(&acard->pci->dev, io_port, 8,
+                                       "ALS4000 gameport");
        }
 
        if (!r) {
@@ -763,7 +765,6 @@ static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
        acard->gameport = gp = gameport_allocate_port();
        if (!gp) {
                dev_err(&acard->pci->dev, "cannot allocate memory for gameport\n");
-               release_and_free_resource(r);
                return -ENOMEM;
        }
 
@@ -771,7 +772,6 @@ static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
        gameport_set_phys(gp, "pci%s/gameport0", pci_name(acard->pci));
        gameport_set_dev_parent(gp, &acard->pci->dev);
        gp->io = io_port;
-       gameport_set_port_data(gp, r);
 
        /* Enable legacy joystick port */
        snd_als4000_set_addr(acard->iobase, 0, 0, 0, 1);
@@ -784,15 +784,11 @@ static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
 static void snd_als4000_free_gameport(struct snd_card_als4000 *acard)
 {
        if (acard->gameport) {
-               struct resource *r = gameport_get_port_data(acard->gameport);
-
                gameport_unregister_port(acard->gameport);
                acard->gameport = NULL;
 
                /* disable joystick */
                snd_als4000_set_addr(acard->iobase, 0, 0, 0, 0);
-
-               release_and_free_resource(r);
        }
 }
 #else
@@ -808,8 +804,6 @@ static void snd_card_als4000_free( struct snd_card *card )
        snd_als4k_gcr_write_addr(acard->iobase, ALS4K_GCR8C_MISC_CTRL, 0);
        /* free resources */
        snd_als4000_free_gameport(acard);
-       pci_release_regions(acard->pci);
-       pci_disable_device(acard->pci);
 }
 
 static int snd_card_als4000_probe(struct pci_dev *pci,
@@ -832,36 +826,30 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
        }
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        /* check, if we can restrict PCI DMA transfers to 24 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
                dev_err(&pci->dev, "architecture does not support 24bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
        err = pci_request_regions(pci, "ALS4000");
-       if (err < 0) {
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        iobase = pci_resource_start(pci, 0);
 
        pci_read_config_word(pci, PCI_COMMAND, &word);
        pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO);
        pci_set_master(pci);
        
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(*acard) /* private_data: acard */,
-                          &card);
-       if (err < 0) {
-               pci_release_regions(pci);
-               pci_disable_device(pci);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*acard) /* private_data: acard */,
+                               &card);
+       if (err < 0)
                return err;
-       }
 
        acard = card->private_data;
        acard->pci = pci;
@@ -881,7 +869,7 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
                               SB_HW_ALS4000,
                               &chip);
        if (err < 0)
-               goto out_err;
+               return err;
        acard->chip = chip;
 
        chip->pci = pci;
@@ -902,7 +890,7 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
        if (err < 0) {
                dev_err(&pci->dev, "no MPU-401 device at 0x%lx?\n",
                                iobase + ALS4K_IOB_30_MIDI_DATA);
-               goto out_err;
+               return err;
        }
        /* FIXME: ALS4000 has interesting MPU401 configuration features
         * at ALS4K_CR1A_MPU401_UART_MODE_CONTROL
@@ -912,11 +900,11 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
 
        err = snd_als4000_pcm(chip, 0);
        if (err < 0)
-               goto out_err;
+               return err;
 
        err = snd_sbmixer_new(chip);
        if (err < 0)
-               goto out_err;
+               return err;
 
        if (snd_opl3_create(card,
                                iobase + ALS4K_IOB_10_ADLIB_ADDR0,
@@ -928,30 +916,18 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
        } else {
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                if (err < 0)
-                       goto out_err;
+                       return err;
        }
 
        snd_als4000_create_gameport(acard, dev);
 
        err = snd_card_register(card);
        if (err < 0)
-               goto out_err;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
-       err = 0;
-       goto out;
-
-out_err:
-       snd_card_free(card);
-       
-out:
-       return err;
-}
-
-static void snd_card_als4000_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
+       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -996,7 +972,6 @@ static struct pci_driver als4000_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_als4000_ids,
        .probe = snd_card_als4000_probe,
-       .remove = snd_card_als4000_remove,
        .driver = {
                .pm = SND_ALS4000_PM_OPS,
        },
index 5f8aa35..b8e035d 100644 (file)
@@ -1530,87 +1530,44 @@ static void snd_atiixp_proc_init(struct atiixp *chip)
  * destructor
  */
 
-static int snd_atiixp_free(struct atiixp *chip)
+static void snd_atiixp_free(struct snd_card *card)
 {
-       if (chip->irq < 0)
-               goto __hw_end;
-       snd_atiixp_chip_stop(chip);
-
-      __hw_end:
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       iounmap(chip->remap_addr);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_atiixp_dev_free(struct snd_device *device)
-{
-       struct atiixp *chip = device->device_data;
-       return snd_atiixp_free(chip);
+       snd_atiixp_chip_stop(card->private_data);
 }
 
 /*
  * constructor for chip instance
  */
-static int snd_atiixp_create(struct snd_card *card,
-                            struct pci_dev *pci,
-                            struct atiixp **r_chip)
+static int snd_atiixp_init(struct snd_card *card, struct pci_dev *pci)
 {
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_atiixp_dev_free,
-       };
-       struct atiixp *chip;
+       struct atiixp *chip = card->private_data;
        int err;
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&chip->reg_lock);
        mutex_init(&chip->open_mutex);
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
-       err = pci_request_regions(pci, "ATI IXP AC97");
-       if (err < 0) {
-               pci_disable_device(pci);
-               kfree(chip);
+       err = pcim_iomap_regions(pci, 1 << 0, "ATI IXP AC97");
+       if (err < 0)
                return err;
-       }
        chip->addr = pci_resource_start(pci, 0);
-       chip->remap_addr = pci_ioremap_bar(pci, 0);
-       if (chip->remap_addr == NULL) {
-               dev_err(card->dev, "AC'97 space ioremap problem\n");
-               snd_atiixp_free(chip);
-               return -EIO;
-       }
+       chip->remap_addr = pcim_iomap_table(pci)[0];
 
-       if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_atiixp_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_atiixp_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_atiixp_free;
        pci_set_master(pci);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_atiixp_free(chip);
-               return err;
-       }
-
-       *r_chip = chip;
        return 0;
 }
 
@@ -1622,30 +1579,31 @@ static int snd_atiixp_probe(struct pci_dev *pci,
        struct atiixp *chip;
        int err;
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA");
        strcpy(card->shortname, "ATI IXP");
-       err = snd_atiixp_create(card, pci, &chip);
+       err = snd_atiixp_init(card, pci);
        if (err < 0)
-               goto __error;
-       card->private_data = chip;
+               return err;
 
        err = snd_atiixp_aclink_reset(chip);
        if (err < 0)
-               goto __error;
+               return err;
 
        chip->spdif_over_aclink = spdif_aclink;
 
        err = snd_atiixp_mixer_new(chip, ac97_clock, ac97_quirk);
        if (err < 0)
-               goto __error;
+               return err;
 
        err = snd_atiixp_pcm_new(chip);
        if (err < 0)
-               goto __error;
+               return err;
        
        snd_atiixp_proc_init(chip);
 
@@ -1659,26 +1617,16 @@ static int snd_atiixp_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto __error;
+               return err;
 
        pci_set_drvdata(pci, card);
        return 0;
-
- __error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_atiixp_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver atiixp_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_atiixp_ids,
        .probe = snd_atiixp_probe,
-       .remove = snd_atiixp_remove,
        .driver = {
                .pm = SND_ATIIXP_PM_OPS,
        },
index 9739c3a..178dce8 100644 (file)
@@ -1159,87 +1159,44 @@ static void snd_atiixp_proc_init(struct atiixp_modem *chip)
  * destructor
  */
 
-static int snd_atiixp_free(struct atiixp_modem *chip)
+static void snd_atiixp_free(struct snd_card *card)
 {
-       if (chip->irq < 0)
-               goto __hw_end;
-       snd_atiixp_chip_stop(chip);
-
-      __hw_end:
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       iounmap(chip->remap_addr);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_atiixp_dev_free(struct snd_device *device)
-{
-       struct atiixp_modem *chip = device->device_data;
-       return snd_atiixp_free(chip);
+       snd_atiixp_chip_stop(card->private_data);
 }
 
 /*
  * constructor for chip instance
  */
-static int snd_atiixp_create(struct snd_card *card,
-                            struct pci_dev *pci,
-                            struct atiixp_modem **r_chip)
+static int snd_atiixp_init(struct snd_card *card, struct pci_dev *pci)
 {
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_atiixp_dev_free,
-       };
-       struct atiixp_modem *chip;
+       struct atiixp_modem *chip = card->private_data;
        int err;
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&chip->reg_lock);
        mutex_init(&chip->open_mutex);
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
-       err = pci_request_regions(pci, "ATI IXP MC97");
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       err = pcim_iomap_regions(pci, 1 << 0, "ATI IXP MC97");
+       if (err < 0)
                return err;
-       }
        chip->addr = pci_resource_start(pci, 0);
-       chip->remap_addr = pci_ioremap_bar(pci, 0);
-       if (chip->remap_addr == NULL) {
-               dev_err(card->dev, "AC'97 space ioremap problem\n");
-               snd_atiixp_free(chip);
-               return -EIO;
-       }
+       chip->remap_addr = pcim_iomap_table(pci)[0];
 
-       if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_atiixp_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_atiixp_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_atiixp_free;
        pci_set_master(pci);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_atiixp_free(chip);
-               return err;
-       }
-
-       *r_chip = chip;
        return 0;
 }
 
@@ -1251,28 +1208,29 @@ static int snd_atiixp_probe(struct pci_dev *pci,
        struct atiixp_modem *chip;
        int err;
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        strcpy(card->driver, "ATIIXP-MODEM");
        strcpy(card->shortname, "ATI IXP Modem");
-       err = snd_atiixp_create(card, pci, &chip);
+       err = snd_atiixp_init(card, pci);
        if (err < 0)
-               goto __error;
-       card->private_data = chip;
+               return err;
 
        err = snd_atiixp_aclink_reset(chip);
        if (err < 0)
-               goto __error;
+               return err;
 
        err = snd_atiixp_mixer_new(chip, ac97_clock);
        if (err < 0)
-               goto __error;
+               return err;
 
        err = snd_atiixp_pcm_new(chip);
        if (err < 0)
-               goto __error;
+               return err;
        
        snd_atiixp_proc_init(chip);
 
@@ -1283,26 +1241,16 @@ static int snd_atiixp_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto __error;
+               return err;
 
        pci_set_drvdata(pci, card);
        return 0;
-
- __error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_atiixp_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver atiixp_modem_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_atiixp_ids,
        .probe = snd_atiixp_probe,
-       .remove = snd_atiixp_remove,
        .driver = {
                .pm = SND_ATIIXP_PM_OPS,
        },
index 1f7fee4..342ef2a 100644 (file)
@@ -123,56 +123,35 @@ static void snd_vortex_workaround(struct pci_dev *vortex, int fix)
 
 // component-destructor
 // (see "Management of Cards and Components")
-static int snd_vortex_dev_free(struct snd_device *device)
+static void snd_vortex_free(struct snd_card *card)
 {
-       vortex_t *vortex = device->device_data;
+       vortex_t *vortex = card->private_data;
 
        vortex_gameport_unregister(vortex);
        vortex_core_shutdown(vortex);
-       // Take down PCI interface.
-       free_irq(vortex->irq, vortex);
-       iounmap(vortex->mmio);
-       pci_release_regions(vortex->pci_dev);
-       pci_disable_device(vortex->pci_dev);
-       kfree(vortex);
-
-       return 0;
 }
 
 // chip-specific constructor
 // (see "Management of Cards and Components")
 static int
-snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
+snd_vortex_create(struct snd_card *card, struct pci_dev *pci)
 {
-       vortex_t *chip;
+       vortex_t *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_vortex_dev_free,
-       };
-
-       *rchip = NULL;
 
        // check PCI availability (DMA).
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_err(card->dev, "error to set DMA mask\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
 
        // initialize the stuff
        chip->pci_dev = pci;
-       chip->io = pci_resource_start(pci, 0);
        chip->vendor = pci->vendor;
        chip->device = pci->device;
        chip->card = card;
@@ -181,16 +160,12 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
        // (1) PCI resource allocation
        // Get MMIO area
        //
-       err = pci_request_regions(pci, CARD_NAME_SHORT);
+       err = pcim_iomap_regions(pci, 1 << 0, CARD_NAME_SHORT);
        if (err)
-               goto regions_out;
+               return err;
 
-       chip->mmio = pci_ioremap_bar(pci, 0);
-       if (!chip->mmio) {
-               dev_err(card->dev, "MMIO area remap failed.\n");
-               err = -ENOMEM;
-               goto ioremap_out;
-       }
+       chip->io = pci_resource_start(pci, 0);
+       chip->mmio = pcim_iomap_table(pci)[0];
 
        /* Init audio core.
         * This must be done before we do request_irq otherwise we can get spurious
@@ -198,44 +173,22 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
        err = vortex_core_init(chip);
        if (err) {
                dev_err(card->dev, "hw core init failed\n");
-               goto core_out;
+               return err;
        }
 
-       err = request_irq(pci->irq, vortex_interrupt,
-                         IRQF_SHARED, KBUILD_MODNAME, chip);
+       err = devm_request_irq(&pci->dev, pci->irq, vortex_interrupt,
+                              IRQF_SHARED, KBUILD_MODNAME, chip);
        if (err) {
                dev_err(card->dev, "cannot grab irq\n");
-               goto irq_out;
+               return err;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_vortex_free;
 
        pci_set_master(pci);
        // End of PCI setup.
-
-       // Register alsa root device.
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto alloc_out;
-
-       *rchip = chip;
-
        return 0;
-
-      alloc_out:
-       free_irq(chip->irq, chip);
-      irq_out:
-       vortex_core_shutdown(chip);
-      core_out:
-       iounmap(chip->mmio);
-      ioremap_out:
-       pci_release_regions(chip->pci_dev);
-      regions_out:
-       pci_disable_device(chip->pci_dev);
-       //FIXME: this not the right place to unregister the gameport
-       vortex_gameport_unregister(chip);
-       kfree(chip);
-       return err;
 }
 
 // constructor -- see "Constructor" sub-section
@@ -255,17 +208,16 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                return -ENOENT;
        }
        // (2)
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        // (3)
-       err = snd_vortex_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_vortex_create(card, pci);
+       if (err < 0)
                return err;
-       }
        snd_vortex_workaround(pci, pcifix[dev]);
 
        // Card details needed in snd_vortex_midi
@@ -276,50 +228,37 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 
        // (4) Alloc components.
        err = snd_vortex_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        // ADB pcm.
        err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_PCM);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #ifndef CHIP_AU8820
        // ADB SPDIF
        err = snd_vortex_new_pcm(chip, VORTEX_PCM_SPDIF, 1);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        // A3D
        err = snd_vortex_new_pcm(chip, VORTEX_PCM_A3D, NR_A3D);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #endif
        /*
           // ADB I2S
           if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_I2S, 1)) < 0) {
-          snd_card_free(card);
           return err;
           }
         */
 #ifndef CHIP_AU8810
        // WT pcm.
        err = snd_vortex_new_pcm(chip, VORTEX_PCM_WT, NR_WT);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #endif
        err = snd_vortex_midi(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        vortex_gameport_register(chip);
 
@@ -342,15 +281,11 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 
        // (5)
        err = pci_read_config_word(pci, PCI_DEVICE_ID, &chip->device);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }       
        err = pci_read_config_word(pci, PCI_VENDOR_ID, &chip->vendor);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        chip->rev = pci->revision;
 #ifdef CHIP_AU8830
        if ((chip->rev) != 0xfe && (chip->rev) != 0xfa) {
@@ -359,18 +294,14 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                       chip->rev);
                dev_alert(card->dev,
                          "Please email the results of 'lspci -vv' to openvortex-dev@nongnu.org.\n");
-               snd_card_free(card);
-               err = -ENODEV;
-               return err;
+               return -ENODEV;
        }
 #endif
 
        // (6)
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        // (7)
        pci_set_drvdata(pci, card);
        dev++;
@@ -379,18 +310,11 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        return 0;
 }
 
-// destructor -- see "Destructor" sub-section
-static void snd_vortex_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 // pci_driver definition
 static struct pci_driver vortex_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_vortex_ids,
        .probe = snd_vortex_probe,
-       .remove = snd_vortex_remove,
 };
 
 module_pci_driver(vortex_driver);
index 4339684..d56f126 100644 (file)
@@ -99,12 +99,9 @@ struct aw2 {
 /*********************************
  * FUNCTION DECLARATIONS
  ********************************/
-static int snd_aw2_dev_free(struct snd_device *device);
-static int snd_aw2_create(struct snd_card *card,
-                         struct pci_dev *pci, struct aw2 **rchip);
+static int snd_aw2_create(struct snd_card *card, struct pci_dev *pci);
 static int snd_aw2_probe(struct pci_dev *pci,
                         const struct pci_device_id *pci_id);
-static void snd_aw2_remove(struct pci_dev *pci);
 static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream);
 static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream);
 static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream);
@@ -157,7 +154,6 @@ static struct pci_driver aw2_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_aw2_ids,
        .probe = snd_aw2_probe,
-       .remove = snd_aw2_remove,
 };
 
 module_pci_driver(aw2_driver);
@@ -196,41 +192,23 @@ static const struct snd_kcontrol_new aw2_control = {
  ********************************/
 
 /* component-destructor */
-static int snd_aw2_dev_free(struct snd_device *device)
+static void snd_aw2_free(struct snd_card *card)
 {
-       struct aw2 *chip = device->device_data;
+       struct aw2 *chip = card->private_data;
 
        /* Free hardware */
        snd_aw2_saa7146_free(&chip->saa7146);
-
-       /* release the irq */
-       if (chip->irq >= 0)
-               free_irq(chip->irq, (void *)chip);
-       /* release the i/o ports & memory */
-       iounmap(chip->iobase_virt);
-       pci_release_regions(chip->pci);
-       /* disable the PCI entry */
-       pci_disable_device(chip->pci);
-       /* release the data */
-       kfree(chip);
-
-       return 0;
 }
 
 /* chip-specific constructor */
 static int snd_aw2_create(struct snd_card *card,
-                         struct pci_dev *pci, struct aw2 **rchip)
+                         struct pci_dev *pci)
 {
-       struct aw2 *chip;
+       struct aw2 *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_aw2_dev_free,
-       };
-
-       *rchip = NULL;
 
        /* initialize the PCI entry */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        pci_set_master(pci);
@@ -238,14 +216,8 @@ static int snd_aw2_create(struct snd_card *card,
        /* check PCI availability (32bit DMA) */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_err(card->dev, "Impossible to set 32bit mask DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
 
        /* initialize the stuff */
        chip->card = card;
@@ -253,52 +225,23 @@ static int snd_aw2_create(struct snd_card *card,
        chip->irq = -1;
 
        /* (1) PCI resource allocation */
-       err = pci_request_regions(pci, "Audiowerk2");
-       if (err < 0) {
-               pci_disable_device(pci);
-               kfree(chip);
+       err = pcim_iomap_regions(pci, 1 << 0, "Audiowerk2");
+       if (err < 0)
                return err;
-       }
        chip->iobase_phys = pci_resource_start(pci, 0);
-       chip->iobase_virt =
-               ioremap(chip->iobase_phys,
-                               pci_resource_len(pci, 0));
-
-       if (chip->iobase_virt == NULL) {
-               dev_err(card->dev, "unable to remap memory region");
-               pci_release_regions(pci);
-               pci_disable_device(pci);
-               kfree(chip);
-               return -ENOMEM;
-       }
+       chip->iobase_virt = pcim_iomap_table(pci)[0];
 
        /* (2) initialization of the chip hardware */
        snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt);
 
-       if (request_irq(pci->irq, snd_aw2_saa7146_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_aw2_saa7146_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "Cannot grab irq %d\n", pci->irq);
-
-               iounmap(chip->iobase_virt);
-               pci_release_regions(chip->pci);
-               pci_disable_device(chip->pci);
-               kfree(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               free_irq(chip->irq, (void *)chip);
-               iounmap(chip->iobase_virt);
-               pci_release_regions(chip->pci);
-               pci_disable_device(chip->pci);
-               kfree(chip);
-               return err;
-       }
-
-       *rchip = chip;
+       card->private_free = snd_aw2_free;
 
        dev_info(card->dev,
                 "Audiowerk 2 sound card (saa7146 chipset) detected and managed\n");
@@ -323,17 +266,16 @@ static int snd_aw2_probe(struct pci_dev *pci,
        }
 
        /* (2) Create card instance */
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        /* (3) Create main component */
-       err = snd_aw2_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_aw2_create(card, pci);
+       if (err < 0)
                return err;
-       }
 
        /* initialize mutex */
        mutex_init(&chip->mtx);
@@ -351,10 +293,8 @@ static int snd_aw2_probe(struct pci_dev *pci,
 
        /* (6) Register card instance */
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        /* (7) Set PCI driver data */
        pci_set_drvdata(pci, card);
@@ -363,12 +303,6 @@ static int snd_aw2_probe(struct pci_dev *pci,
        return 0;
 }
 
-/* destructor */
-static void snd_aw2_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 /* open callback */
 static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream)
 {
index 4ee7ab4..0890504 100644 (file)
@@ -2244,32 +2244,15 @@ out:
 
 /******************************************************************/
 
-static int
-snd_azf3328_free(struct snd_azf3328 *chip)
+static void
+snd_azf3328_free(struct snd_card *card)
 {
-       if (chip->irq < 0)
-               goto __end_hw;
+       struct snd_azf3328 *chip = card->private_data;
 
        snd_azf3328_mixer_reset(chip);
 
        snd_azf3328_timer_stop(chip->timer);
        snd_azf3328_gameport_free(chip);
-
-__end_hw:
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-
-       kfree(chip);
-       return 0;
-}
-
-static int
-snd_azf3328_dev_free(struct snd_device *device)
-{
-       struct snd_azf3328 *chip = device->device_data;
-       return snd_azf3328_free(chip);
 }
 
 #if 0
@@ -2350,29 +2333,18 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
 static int
 snd_azf3328_create(struct snd_card *card,
                   struct pci_dev *pci,
-                  unsigned long device_type,
-                  struct snd_azf3328 **rchip)
+                  unsigned long device_type)
 {
-       struct snd_azf3328 *chip;
+       struct snd_azf3328 *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_azf3328_dev_free,
-       };
        u8 dma_init;
        enum snd_azf3328_codec_type codec_type;
        struct snd_azf3328_codec_data *codec_setup;
 
-       *rchip = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               err = -ENOMEM;
-               goto out_err;
-       }
        spin_lock_init(&chip->reg_lock);
        chip->card = card;
        chip->pci = pci;
@@ -2383,13 +2355,12 @@ snd_azf3328_create(struct snd_card *card,
                dev_err(card->dev,
                        "architecture does not support 24bit PCI busmaster DMA\n"
                );
-               err = -ENXIO;
-               goto out_err;
+               return -ENXIO;
        }
 
        err = pci_request_regions(pci, "Aztech AZF3328");
        if (err < 0)
-               goto out_err;
+               return err;
 
        chip->ctrl_io  = pci_resource_start(pci, 0);
        chip->game_io  = pci_resource_start(pci, 1);
@@ -2415,26 +2386,22 @@ snd_azf3328_create(struct snd_card *card,
        codec_setup->type = AZF_CODEC_I2S_OUT;
        codec_setup->name = "I2S_OUT";
 
-       if (request_irq(pci->irq, snd_azf3328_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_azf3328_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               err = -EBUSY;
-               goto out_err;
+               return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_azf3328_free;
        pci_set_master(pci);
 
        snd_azf3328_debug_show_ports(chip);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto out_err;
-
        /* create mixer interface & switches */
        err = snd_azf3328_mixer_new(chip);
        if (err < 0)
-               goto out_err;
+               return err;
 
        /* standard codec init stuff */
                /* default DMA init value */
@@ -2456,18 +2423,7 @@ snd_azf3328_create(struct snd_card *card,
                spin_unlock_irq(codec->lock);
        }
 
-       *rchip = chip;
-
-       err = 0;
-       goto out;
-
-out_err:
-       if (chip)
-               snd_azf3328_free(chip);
-       pci_disable_device(pci);
-
-out:
-       return err;
+       return 0;
 }
 
 static int
@@ -2479,29 +2435,25 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        struct snd_opl3 *opl3;
        int err;
 
-       if (dev >= SNDRV_CARDS) {
-               err = -ENODEV;
-               goto out;
-       }
+       if (dev >= SNDRV_CARDS)
+               return -ENODEV;
        if (!enable[dev]) {
                dev++;
-               err = -ENOENT;
-               goto out;
+               return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
-               goto out;
+               return err;
+       chip = card->private_data;
 
        strcpy(card->driver, "AZF3328");
        strcpy(card->shortname, "Aztech AZF3328 (PCI168)");
 
-       err = snd_azf3328_create(card, pci, pci_id->driver_data, &chip);
+       err = snd_azf3328_create(card, pci, pci_id->driver_data);
        if (err < 0)
-               goto out_err;
-
-       card->private_data = chip;
+               return err;
 
        /* chose to use MPU401_HW_AZT2320 ID instead of MPU401_HW_MPU401,
           since our hardware ought to be similar, thus use same ID. */
@@ -2515,16 +2467,16 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                dev_err(card->dev, "no MPU-401 device at 0x%lx?\n",
                                chip->mpu_io
                );
-               goto out_err;
+               return err;
        }
 
        err = snd_azf3328_timer(chip, 0);
        if (err < 0)
-               goto out_err;
+               return err;
 
        err = snd_azf3328_pcm(chip);
        if (err < 0)
-               goto out_err;
+               return err;
 
        if (snd_opl3_create(card, chip->opl3_io, chip->opl3_io+2,
                            OPL3_HW_AUTO, 1, &opl3) < 0) {
@@ -2535,10 +2487,10 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                /* need to use IDs 1, 2 since ID 0 is snd_azf3328_timer above */
                err = snd_opl3_timer_new(opl3, 1, 2);
                if (err < 0)
-                       goto out_err;
+                       return err;
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                if (err < 0)
-                       goto out_err;
+                       return err;
                opl3->private_data = chip;
        }
 
@@ -2547,7 +2499,7 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto out_err;
+               return err;
 
 #ifdef MODULE
        dev_info(card->dev,
@@ -2565,22 +2517,7 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 
        pci_set_drvdata(pci, card);
        dev++;
-
-       err = 0;
-       goto out;
-
-out_err:
-       dev_err(card->dev, "something failed, exiting\n");
-       snd_card_free(card);
-
-out:
-       return err;
-}
-
-static void
-snd_azf3328_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
+       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -2709,7 +2646,6 @@ static struct pci_driver azf3328_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_azf3328_ids,
        .probe = snd_azf3328_probe,
-       .remove = snd_azf3328_remove,
        .driver = {
                .pm = SND_AZF3328_PM_OPS,
        },
index 39bcfb8..d23f931 100644 (file)
@@ -656,23 +656,11 @@ static const struct snd_kcontrol_new snd_bt87x_capture_source = {
        .put = snd_bt87x_capture_source_put,
 };
 
-static int snd_bt87x_free(struct snd_bt87x *chip)
-{
-       if (chip->mmio)
-               snd_bt87x_stop(chip);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       iounmap(chip->mmio);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_bt87x_dev_free(struct snd_device *device)
+static void snd_bt87x_free(struct snd_card *card)
 {
-       struct snd_bt87x *chip = device->device_data;
-       return snd_bt87x_free(chip);
+       struct snd_bt87x *chip = card->private_data;
+
+       snd_bt87x_stop(chip);
 }
 
 static int snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
@@ -694,43 +682,24 @@ static int snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
 }
 
 static int snd_bt87x_create(struct snd_card *card,
-                           struct pci_dev *pci,
-                           struct snd_bt87x **rchip)
+                           struct pci_dev *pci)
 {
-       struct snd_bt87x *chip;
+       struct snd_bt87x *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_bt87x_dev_free
-       };
-
-       *rchip = NULL;
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (!chip) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
        spin_lock_init(&chip->reg_lock);
 
-       err = pci_request_regions(pci, "Bt87x audio");
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       err = pcim_iomap_regions(pci, 1 << 0, "Bt87x audio");
+       if (err < 0)
                return err;
-       }
-       chip->mmio = pci_ioremap_bar(pci, 0);
-       if (!chip->mmio) {
-               dev_err(card->dev, "cannot remap io memory\n");
-               err = -ENOMEM;
-               goto fail;
-       }
+       chip->mmio = pcim_iomap_table(pci)[0];
 
        chip->reg_control = CTL_A_PWRDN | CTL_DA_ES2 |
                            CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT);
@@ -739,26 +708,18 @@ static int snd_bt87x_create(struct snd_card *card,
        snd_bt87x_writel(chip, REG_INT_MASK, 0);
        snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS);
 
-       err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED,
-                         KBUILD_MODNAME, chip);
+       err = devm_request_irq(&pci->dev, pci->irq, snd_bt87x_interrupt,
+                              IRQF_SHARED, KBUILD_MODNAME, chip);
        if (err < 0) {
                dev_err(card->dev, "cannot grab irq %d\n", pci->irq);
-               goto fail;
+               return err;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_bt87x_free;
        pci_set_master(pci);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto fail;
-
-       *rchip = chip;
        return 0;
-
-fail:
-       snd_bt87x_free(chip);
-       return err;
 }
 
 #define BT_DEVICE(chip, subvend, subdev, id) \
@@ -868,14 +829,15 @@ static int snd_bt87x_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       err = snd_bt87x_create(card, pci, &chip);
+       err = snd_bt87x_create(card, pci);
        if (err < 0)
-               goto _error;
+               return err;
 
        memcpy(&chip->board, &snd_bt87x_boards[boardid], sizeof(chip->board));
 
@@ -887,24 +849,24 @@ static int snd_bt87x_probe(struct pci_dev *pci,
 
                err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital");
                if (err < 0)
-                       goto _error;
+                       return err;
        }
        if (!chip->board.no_analog) {
                err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog");
                if (err < 0)
-                       goto _error;
+                       return err;
                err = snd_ctl_add(card, snd_ctl_new1(
                                  &snd_bt87x_capture_volume, chip));
                if (err < 0)
-                       goto _error;
+                       return err;
                err = snd_ctl_add(card, snd_ctl_new1(
                                  &snd_bt87x_capture_boost, chip));
                if (err < 0)
-                       goto _error;
+                       return err;
                err = snd_ctl_add(card, snd_ctl_new1(
                                  &snd_bt87x_capture_source, chip));
                if (err < 0)
-                       goto _error;
+                       return err;
        }
        dev_info(card->dev, "bt87x%d: Using board %d, %sanalog, %sdigital "
                   "(rate %d Hz)\n", dev, boardid,
@@ -920,20 +882,11 @@ static int snd_bt87x_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto _error;
+               return err;
 
        pci_set_drvdata(pci, card);
        ++dev;
        return 0;
-
-_error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_bt87x_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 /* default entries for all Bt87x cards - it's not exported */
@@ -948,7 +901,6 @@ static struct pci_driver driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_bt87x_ids,
        .probe = snd_bt87x_probe,
-       .remove = snd_bt87x_remove,
 };
 
 static int __init alsa_card_bt87x_init(void)
index 62a22ca..f246e60 100644 (file)
@@ -667,7 +667,6 @@ struct snd_ca0106 {
        struct pci_dev *pci;
 
        unsigned long port;
-       struct resource *res_port;
        int irq;
 
        unsigned int serial;            /* serial number */
@@ -688,7 +687,7 @@ struct snd_ca0106 {
        u8 i2c_capture_volume[4][2];
        int capture_mic_line_in;
 
-       struct snd_dma_buffer buffer;
+       struct snd_dma_buffer *buffer;
 
        struct snd_ca_midi midi;
        struct snd_ca_midi midi2;
index 9977871..36fb150 100644 (file)
@@ -718,7 +718,7 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_ca0106_pcm *epcm = runtime->private_data;
        int channel = epcm->channel_id;
-       u32 *table_base = (u32 *)(emu->buffer.area+(8*16*channel));
+       u32 *table_base = (u32 *)(emu->buffer->area+(8*16*channel));
        u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
        u32 hcfg_mask = HCFG_PLAYBACK_S32_LE;
        u32 hcfg_set = 0x00000000;
@@ -746,7 +746,7 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
                   runtime->dma_addr, runtime->dma_area, table_base);
        dev_dbg(emu->card->dev,
                "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
-                  emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+                  emu->buffer->addr, emu->buffer->area, emu->buffer->bytes);
 #endif /* debug */
        /* Rate can be set per channel. */
        /* reg40 control host to fifo */
@@ -796,13 +796,13 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
        reg71 = (reg71 & ~reg71_mask) | reg71_set;
        snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
 
-       /* FIXME: Check emu->buffer.size before actually writing to it. */
+       /* FIXME: Check emu->buffer->size before actually writing to it. */
         for(i=0; i < runtime->periods; i++) {
                table_base[i*2] = runtime->dma_addr + (i * period_size_bytes);
                table_base[i*2+1] = period_size_bytes << 16;
        }
  
-       snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel));
+       snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer->addr+(8*16*channel));
        snd_ca0106_ptr_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
        snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0);
        snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
@@ -853,7 +853,7 @@ static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream)
                   runtime->dma_addr, runtime->dma_area, table_base);
        dev_dbg(emu->card->dev,
                "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
-                  emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+                  emu->buffer->addr, emu->buffer->area, emu->buffer->bytes);
 #endif /* debug */
        /* reg71 controls ADC rate. */
        switch (runtime->rate) {
@@ -1183,32 +1183,11 @@ static int snd_ca0106_ac97(struct snd_ca0106 *chip)
 
 static void ca0106_stop_chip(struct snd_ca0106 *chip);
 
-static int snd_ca0106_free(struct snd_ca0106 *chip)
+static void snd_ca0106_free(struct snd_card *card)
 {
-       if (chip->res_port != NULL) {
-               /* avoid access to already used hardware */
-               ca0106_stop_chip(chip);
-       }
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       // release the data
-#if 1
-       if (chip->buffer.area)
-               snd_dma_free_pages(&chip->buffer);
-#endif
-
-       // release the i/o port
-       release_and_free_resource(chip->res_port);
-
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
+       struct snd_ca0106 *chip = card->private_data;
 
-static int snd_ca0106_dev_free(struct snd_device *device)
-{
-       struct snd_ca0106 *chip = device->device_data;
-       return snd_ca0106_free(chip);
+       ca0106_stop_chip(chip);
 }
 
 static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id)
@@ -1594,50 +1573,33 @@ static void ca0106_stop_chip(struct snd_ca0106 *chip)
 }
 
 static int snd_ca0106_create(int dev, struct snd_card *card,
-                                        struct pci_dev *pci,
-                                        struct snd_ca0106 **rchip)
+                            struct pci_dev *pci)
 {
-       struct snd_ca0106 *chip;
+       struct snd_ca0106 *chip = card->private_data;
        const struct snd_ca0106_details *c;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_ca0106_dev_free,
-       };
-
-       *rchip = NULL;
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_err(card->dev, "error to set 32bit mask DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
 
        spin_lock_init(&chip->emu_lock);
 
+       err = pci_request_regions(pci, "snd_ca0106");
+       if (err < 0)
+               return err;
        chip->port = pci_resource_start(pci, 0);
-       chip->res_port = request_region(chip->port, 0x20, "snd_ca0106");
-       if (!chip->res_port) {
-               snd_ca0106_free(chip);
-               dev_err(card->dev, "cannot allocate the port\n");
-               return -EBUSY;
-       }
 
-       if (request_irq(pci->irq, snd_ca0106_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, chip)) {
-               snd_ca0106_free(chip);
+       if (devm_request_irq(&pci->dev, pci->irq, snd_ca0106_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "cannot grab irq\n");
                return -EBUSY;
        }
@@ -1645,11 +1607,9 @@ static int snd_ca0106_create(int dev, struct snd_card *card,
        card->sync_irq = chip->irq;
 
        /* This stores the periods table. */
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               1024, &chip->buffer) < 0) {
-               snd_ca0106_free(chip);
+       chip->buffer = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 1024);
+       if (!chip->buffer)
                return -ENOMEM;
-       }
 
        pci_set_master(pci);
        /* read serial */
@@ -1678,13 +1638,6 @@ static int snd_ca0106_create(int dev, struct snd_card *card,
                c->name, chip->port, chip->irq);
 
        ca0106_init_chip(chip, 0);
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_ca0106_free(chip);
-               return err;
-       }
-       *rchip = chip;
        return 0;
 }
 
@@ -1787,36 +1740,37 @@ static int snd_ca0106_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       err = snd_ca0106_create(dev, card, pci, &chip);
+       err = snd_ca0106_create(dev, card, pci);
        if (err < 0)
-               goto error;
-       card->private_data = chip;
+               return err;
+       card->private_free = snd_ca0106_free;
 
        for (i = 0; i < 4; i++) {
                err = snd_ca0106_pcm(chip, i);
                if (err < 0)
-                       goto error;
+                       return err;
        }
 
        if (chip->details->ac97 == 1) {
                /* The SB0410 and SB0413 do not have an AC97 chip. */
                err = snd_ca0106_ac97(chip);
                if (err < 0)
-                       goto error;
+                       return err;
        }
        err = snd_ca0106_mixer(chip);
        if (err < 0)
-               goto error;
+               return err;
 
        dev_dbg(card->dev, "probe for MIDI channel A ...");
        err = snd_ca0106_midi(chip, CA0106_MIDI_CHAN_A);
        if (err < 0)
-               goto error;
+               return err;
        dev_dbg(card->dev, " done.\n");
 
 #ifdef CONFIG_SND_PROC_FS
@@ -1825,20 +1779,11 @@ static int snd_ca0106_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto error;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
- error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_ca0106_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -1894,7 +1839,6 @@ static struct pci_driver ca0106_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ca0106_ids,
        .probe = snd_ca0106_probe,
-       .remove = snd_ca0106_remove,
        .driver = {
                .pm = SND_CA0106_PM_OPS,
        },
index f44f118..ea20236 100644 (file)
@@ -2852,13 +2852,15 @@ static int snd_cmipci_create_gameport(struct cmipci *cm, int dev)
        if (joystick_port[dev] == 1) { /* auto-detect */
                for (i = 0; ports[i]; i++) {
                        io_port = ports[i];
-                       r = request_region(io_port, 1, "CMIPCI gameport");
+                       r = devm_request_region(&cm->pci->dev, io_port, 1,
+                                               "CMIPCI gameport");
                        if (r)
                                break;
                }
        } else {
                io_port = joystick_port[dev];
-               r = request_region(io_port, 1, "CMIPCI gameport");
+               r = devm_request_region(&cm->pci->dev, io_port, 1,
+                                       "CMIPCI gameport");
        }
 
        if (!r) {
@@ -2869,14 +2871,12 @@ static int snd_cmipci_create_gameport(struct cmipci *cm, int dev)
        cm->gameport = gp = gameport_allocate_port();
        if (!gp) {
                dev_err(cm->card->dev, "cannot allocate memory for gameport\n");
-               release_and_free_resource(r);
                return -ENOMEM;
        }
        gameport_set_name(gp, "C-Media Gameport");
        gameport_set_phys(gp, "pci%s/gameport0", pci_name(cm->pci));
        gameport_set_dev_parent(gp, &cm->pci->dev);
        gp->io = io_port;
-       gameport_set_port_data(gp, r);
 
        snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
 
@@ -2888,13 +2888,10 @@ static int snd_cmipci_create_gameport(struct cmipci *cm, int dev)
 static void snd_cmipci_free_gameport(struct cmipci *cm)
 {
        if (cm->gameport) {
-               struct resource *r = gameport_get_port_data(cm->gameport);
-
                gameport_unregister_port(cm->gameport);
                cm->gameport = NULL;
 
                snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
-               release_and_free_resource(r);
        }
 }
 #else
@@ -2902,34 +2899,22 @@ static inline int snd_cmipci_create_gameport(struct cmipci *cm, int dev) { retur
 static inline void snd_cmipci_free_gameport(struct cmipci *cm) { }
 #endif
 
-static int snd_cmipci_free(struct cmipci *cm)
+static void snd_cmipci_free(struct snd_card *card)
 {
-       if (cm->irq >= 0) {
-               snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN);
-               snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT);
-               snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0);  /* disable ints */
-               snd_cmipci_ch_reset(cm, CM_CH_PLAY);
-               snd_cmipci_ch_reset(cm, CM_CH_CAPT);
-               snd_cmipci_write(cm, CM_REG_FUNCTRL0, 0); /* disable channels */
-               snd_cmipci_write(cm, CM_REG_FUNCTRL1, 0);
+       struct cmipci *cm = card->private_data;
 
-               /* reset mixer */
-               snd_cmipci_mixer_write(cm, 0, 0);
+       snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN);
+       snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT);
+       snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0);  /* disable ints */
+       snd_cmipci_ch_reset(cm, CM_CH_PLAY);
+       snd_cmipci_ch_reset(cm, CM_CH_CAPT);
+       snd_cmipci_write(cm, CM_REG_FUNCTRL0, 0); /* disable channels */
+       snd_cmipci_write(cm, CM_REG_FUNCTRL1, 0);
 
-               free_irq(cm->irq, cm);
-       }
+       /* reset mixer */
+       snd_cmipci_mixer_write(cm, 0, 0);
 
        snd_cmipci_free_gameport(cm);
-       pci_release_regions(cm->pci);
-       pci_disable_device(cm->pci);
-       kfree(cm);
-       return 0;
-}
-
-static int snd_cmipci_dev_free(struct snd_device *device)
-{
-       struct cmipci *cm = device->device_data;
-       return snd_cmipci_free(cm);
 }
 
 static int snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
@@ -2988,13 +2973,10 @@ static int snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
 }
 
 static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
-                            int dev, struct cmipci **rcmipci)
+                            int dev)
 {
-       struct cmipci *cm;
+       struct cmipci *cm = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_cmipci_dev_free,
-       };
        unsigned int val;
        long iomidi = 0;
        int integrated_midi = 0;
@@ -3005,18 +2987,10 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
                { },
        };
 
-       *rcmipci = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       cm = kzalloc(sizeof(*cm), GFP_KERNEL);
-       if (cm == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&cm->reg_lock);
        mutex_init(&cm->open_mutex);
        cm->device = pci->device;
@@ -3028,21 +3002,18 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
        cm->channel[0].is_dac = cm->channel[1].is_dac = 1; /* dual DAC mode */
 
        err = pci_request_regions(pci, card->driver);
-       if (err < 0) {
-               kfree(cm);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        cm->iobase = pci_resource_start(pci, 0);
 
-       if (request_irq(pci->irq, snd_cmipci_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, cm)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_cmipci_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, cm)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_cmipci_free(cm);
                return -EBUSY;
        }
        cm->irq = pci->irq;
        card->sync_irq = cm->irq;
+       card->private_free = snd_cmipci_free;
 
        pci_set_master(cm->pci);
 
@@ -3142,12 +3113,6 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
        sprintf(card->longname, "%s%s at %#lx, irq %i",
                card->shortname, modelstr, cm->iobase, cm->irq);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cm, &ops);
-       if (err < 0) {
-               snd_cmipci_free(cm);
-               return err;
-       }
-
        if (cm->chip_version >= 39) {
                val = snd_cmipci_read_b(cm, CM_REG_MPU_PCI + 1);
                if (val != 0x00 && val != 0xff) {
@@ -3240,7 +3205,6 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
        if (snd_cmipci_create_gameport(cm, dev) < 0)
                snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
 
-       *rcmipci = cm;
        return 0;
 }
 
@@ -3264,10 +3228,11 @@ static int snd_cmipci_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*cm), &card);
        if (err < 0)
                return err;
+       cm = card->private_data;
        
        switch (pci->device) {
        case PCI_DEVICE_ID_CMEDIA_CM8738:
@@ -3283,31 +3248,19 @@ static int snd_cmipci_probe(struct pci_dev *pci,
                break;
        }
 
-       err = snd_cmipci_create(card, pci, dev, &cm);
+       err = snd_cmipci_create(card, pci, dev);
        if (err < 0)
-               goto free_card;
-
-       card->private_data = cm;
+               return err;
 
        err = snd_card_register(card);
        if (err < 0)
-               goto free_card;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
-free_card:
-       snd_card_free(card);
-       return err;
 }
 
-static void snd_cmipci_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
-
 #ifdef CONFIG_PM_SLEEP
 /*
  * power management
@@ -3382,7 +3335,6 @@ static struct pci_driver cmipci_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cmipci_ids,
        .probe = snd_cmipci_probe,
-       .remove = snd_cmipci_remove,
        .driver = {
                .pm = SND_CMIPCI_PM_OPS,
        },
index e122a16..e736740 100644 (file)
@@ -1268,8 +1268,10 @@ static inline int snd_cs4281_create_gameport(struct cs4281 *chip) { return -ENOS
 static inline void snd_cs4281_free_gameport(struct cs4281 *chip) { }
 #endif /* IS_REACHABLE(CONFIG_GAMEPORT) */
 
-static int snd_cs4281_free(struct cs4281 *chip)
+static void snd_cs4281_free(struct snd_card *card)
 {
+       struct cs4281 *chip = card->private_data;
+
        snd_cs4281_free_gameport(chip);
 
        /* Mask interrupts */
@@ -1278,49 +1280,20 @@ static int snd_cs4281_free(struct cs4281 *chip)
        snd_cs4281_pokeBA0(chip, BA0_CLKCR1, 0);
        /* Sound System Power Management - Turn Everything OFF */
        snd_cs4281_pokeBA0(chip, BA0_SSPM, 0);
-       /* PCI interface - D3 state */
-       pci_set_power_state(chip->pci, PCI_D3hot);
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       iounmap(chip->ba0);
-       iounmap(chip->ba1);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-
-       kfree(chip);
-       return 0;
-}
-
-static int snd_cs4281_dev_free(struct snd_device *device)
-{
-       struct cs4281 *chip = device->device_data;
-       return snd_cs4281_free(chip);
 }
 
 static int snd_cs4281_chip_init(struct cs4281 *chip); /* defined below */
 
 static int snd_cs4281_create(struct snd_card *card,
                             struct pci_dev *pci,
-                            struct cs4281 **rchip,
                             int dual_codec)
 {
-       struct cs4281 *chip;
-       unsigned int tmp;
+       struct cs4281 *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_cs4281_dev_free,
-       };
 
-       *rchip = NULL;
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&chip->reg_lock);
        chip->card = card;
        chip->pci = pci;
@@ -1332,46 +1305,29 @@ static int snd_cs4281_create(struct snd_card *card,
        }
        chip->dual_codec = dual_codec;
 
-       err = pci_request_regions(pci, "CS4281");
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       err = pcim_iomap_regions(pci, 0x03, "CS4281"); /* 2 BARs */
+       if (err < 0)
                return err;
-       }
        chip->ba0_addr = pci_resource_start(pci, 0);
        chip->ba1_addr = pci_resource_start(pci, 1);
 
-       chip->ba0 = pci_ioremap_bar(pci, 0);
-       chip->ba1 = pci_ioremap_bar(pci, 1);
-       if (!chip->ba0 || !chip->ba1) {
-               snd_cs4281_free(chip);
-               return -ENOMEM;
-       }
+       chip->ba0 = pcim_iomap_table(pci)[0];
+       chip->ba1 = pcim_iomap_table(pci)[1];
        
-       if (request_irq(pci->irq, snd_cs4281_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_cs4281_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_cs4281_free(chip);
                return -ENOMEM;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_cs4281_free;
 
-       tmp = snd_cs4281_chip_init(chip);
-       if (tmp) {
-               snd_cs4281_free(chip);
-               return tmp;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_cs4281_free(chip);
+       err = snd_cs4281_chip_init(chip);
+       if (err)
                return err;
-       }
 
        snd_cs4281_proc_init(chip);
-
-       *rchip = chip;
        return 0;
 }
 
@@ -1887,46 +1843,34 @@ static int snd_cs4281_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       err = snd_cs4281_create(card, pci, &chip, dual_codec[dev]);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_cs4281_create(card, pci, dual_codec[dev]);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        err = snd_cs4281_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_cs4281_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_cs4281_midi(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_opl3_new(card, OPL3_HW_OPL3_CS4281, &opl3);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        opl3->private_data = chip;
        opl3->command = snd_cs4281_opl3_command;
        snd_opl3_init(opl3);
        err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        snd_cs4281_create_gameport(chip);
        strcpy(card->driver, "CS4281");
        strcpy(card->shortname, "Cirrus Logic CS4281");
@@ -1936,21 +1880,14 @@ static int snd_cs4281_probe(struct pci_dev *pci,
                chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_cs4281_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 /*
  * Power Management
  */
@@ -2054,7 +1991,6 @@ static struct pci_driver cs4281_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cs4281_ids,
        .probe = snd_cs4281_probe,
-       .remove = snd_cs4281_remove,
        .driver = {
                .pm = CS4281_PM_OPS,
        },
index 358ca84..bd60308 100644 (file)
@@ -66,61 +66,44 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
        err = snd_cs46xx_create(card, pci,
-                               external_amp[dev], thinkpad[dev],
-                               &chip);
-       if (err < 0) {
-               snd_card_free(card);
+                               external_amp[dev], thinkpad[dev]);
+       if (err < 0)
                return err;
-       }
        card->private_data = chip;
        chip->accept_valid = mmap_valid[dev];
        err = snd_cs46xx_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        err = snd_cs46xx_pcm_rear(chip, 1);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_cs46xx_pcm_iec958(chip, 2);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #endif
        err = snd_cs46xx_mixer(chip, 2);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        if (chip->nr_ac97_codecs ==2) {
                err = snd_cs46xx_pcm_center_lfe(chip, 3);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 #endif
        err = snd_cs46xx_midi(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_cs46xx_start_dsp(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
-
 
        snd_cs46xx_gameport(chip);
 
@@ -133,26 +116,18 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci,
                chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_card_cs46xx_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver cs46xx_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cs46xx_ids,
        .probe = snd_card_cs46xx_probe,
-       .remove = snd_card_cs46xx_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &snd_cs46xx_pm,
index b275df8..c4f0a0b 100644 (file)
@@ -1635,7 +1635,6 @@ struct snd_cs46xx_region {
        unsigned long base;
        void __iomem *remap_addr;
        unsigned long size;
-       struct resource *resource;
 };
 
 struct snd_cs46xx {
@@ -1718,8 +1717,7 @@ struct snd_cs46xx {
 
 int snd_cs46xx_create(struct snd_card *card,
                      struct pci_dev *pci,
-                     int external_amp, int thinkpad,
-                     struct snd_cs46xx **rcodec);
+                     int external_amp, int thinkpad);
 extern const struct dev_pm_ops snd_cs46xx_pm;
 
 int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device);
index 1e1eb17..62f4584 100644 (file)
@@ -1121,9 +1121,7 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream,
        if (params_periods(hw_params) == CS46XX_FRAGS) {
                if (runtime->dma_area != cpcm->hw_buf.area)
                        snd_pcm_lib_free_pages(substream);
-               runtime->dma_area = cpcm->hw_buf.area;
-               runtime->dma_addr = cpcm->hw_buf.addr;
-               runtime->dma_bytes = cpcm->hw_buf.bytes;
+               snd_pcm_set_runtime_buffer(substream, &cpcm->hw_buf);
 
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -1143,11 +1141,8 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream,
 #endif
 
        } else {
-               if (runtime->dma_area == cpcm->hw_buf.area) {
-                       runtime->dma_area = NULL;
-                       runtime->dma_addr = 0;
-                       runtime->dma_bytes = 0;
-               }
+               if (runtime->dma_area == cpcm->hw_buf.area)
+                       snd_pcm_set_runtime_buffer(substream, NULL);
                err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
                if (err < 0) {
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -1196,9 +1191,7 @@ static int snd_cs46xx_playback_hw_free(struct snd_pcm_substream *substream)
        if (runtime->dma_area != cpcm->hw_buf.area)
                snd_pcm_lib_free_pages(substream);
     
-       runtime->dma_area = NULL;
-       runtime->dma_addr = 0;
-       runtime->dma_bytes = 0;
+       snd_pcm_set_runtime_buffer(substream, NULL);
 
        return 0;
 }
@@ -1287,16 +1280,11 @@ static int snd_cs46xx_capture_hw_params(struct snd_pcm_substream *substream,
        if (runtime->periods == CS46XX_FRAGS) {
                if (runtime->dma_area != chip->capt.hw_buf.area)
                        snd_pcm_lib_free_pages(substream);
-               runtime->dma_area = chip->capt.hw_buf.area;
-               runtime->dma_addr = chip->capt.hw_buf.addr;
-               runtime->dma_bytes = chip->capt.hw_buf.bytes;
+               snd_pcm_set_runtime_buffer(substream, &chip->capt.hw_buf);
                substream->ops = &snd_cs46xx_capture_ops;
        } else {
-               if (runtime->dma_area == chip->capt.hw_buf.area) {
-                       runtime->dma_area = NULL;
-                       runtime->dma_addr = 0;
-                       runtime->dma_bytes = 0;
-               }
+               if (runtime->dma_area == chip->capt.hw_buf.area)
+                       snd_pcm_set_runtime_buffer(substream, NULL);
                err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
                if (err < 0)
                        return err;
@@ -1313,9 +1301,7 @@ static int snd_cs46xx_capture_hw_free(struct snd_pcm_substream *substream)
 
        if (runtime->dma_area != chip->capt.hw_buf.area)
                snd_pcm_lib_free_pages(substream);
-       runtime->dma_area = NULL;
-       runtime->dma_addr = 0;
-       runtime->dma_bytes = 0;
+       snd_pcm_set_runtime_buffer(substream, NULL);
 
        return 0;
 }
@@ -1865,13 +1851,6 @@ int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device)
 /*
  *  Mixer routines
  */
-static void snd_cs46xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
-{
-       struct snd_cs46xx *chip = bus->private_data;
-
-       chip->ac97_bus = NULL;
-}
-
 static void snd_cs46xx_mixer_free_ac97(struct snd_ac97 *ac97)
 {
        struct snd_cs46xx *chip = ac97->private_data;
@@ -2487,7 +2466,6 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
        err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus);
        if (err < 0)
                return err;
-       chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;
 
        if (cs46xx_detect_codec(chip, CS46XX_PRIMARY_CODEC_INDEX) < 0)
                return -ENXIO;
@@ -2913,12 +2891,12 @@ static void snd_cs46xx_hw_stop(struct snd_cs46xx *chip)
 }
 
 
-static int snd_cs46xx_free(struct snd_cs46xx *chip)
+static void snd_cs46xx_free(struct snd_card *card)
 {
+       struct snd_cs46xx *chip = card->private_data;
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
        int idx;
-
-       if (snd_BUG_ON(!chip))
-               return -EINVAL;
+#endif
 
        if (chip->active_ctrl)
                chip->active_ctrl(chip, 1);
@@ -2930,22 +2908,11 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
        
        snd_cs46xx_proc_done(chip);
 
-       if (chip->region.idx[0].resource)
-               snd_cs46xx_hw_stop(chip);
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
+       snd_cs46xx_hw_stop(chip);
 
        if (chip->active_ctrl)
                chip->active_ctrl(chip, -chip->amplifier);
 
-       for (idx = 0; idx < 5; idx++) {
-               struct snd_cs46xx_region *region = &chip->region.idx[idx];
-
-               iounmap(region->remap_addr);
-               release_and_free_resource(region->resource);
-       }
-
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        if (chip->dsp_spos_instance) {
                cs46xx_dsp_spos_destroy(chip);
@@ -2956,20 +2923,6 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
 #else
        vfree(chip->ba1);
 #endif
-       
-#ifdef CONFIG_PM_SLEEP
-       kfree(chip->saved_regs);
-#endif
-
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_cs46xx_dev_free(struct snd_device *device)
-{
-       struct snd_cs46xx *chip = device->device_data;
-       return snd_cs46xx_free(chip);
 }
 
 /*
@@ -3868,30 +3821,19 @@ SIMPLE_DEV_PM_OPS(snd_cs46xx_pm, snd_cs46xx_suspend, snd_cs46xx_resume);
 
 int snd_cs46xx_create(struct snd_card *card,
                      struct pci_dev *pci,
-                     int external_amp, int thinkpad,
-                     struct snd_cs46xx **rchip)
+                     int external_amp, int thinkpad)
 {
-       struct snd_cs46xx *chip;
+       struct snd_cs46xx *chip = card->private_data;
        int err, idx;
        struct snd_cs46xx_region *region;
        struct cs_card_type *cp;
        u16 ss_card, ss_vendor;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_cs46xx_dev_free,
-       };
        
-       *rchip = NULL;
-
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&chip->reg_lock);
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        mutex_init(&chip->spos_mutex);
@@ -3899,6 +3841,10 @@ int snd_cs46xx_create(struct snd_card *card,
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
+
+       err = pci_request_regions(pci, "CS46xx");
+       if (err < 0)
+               return err;
        chip->ba0_addr = pci_resource_start(pci, 0);
        chip->ba1_addr = pci_resource_start(pci, 1);
        if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 ||
@@ -3906,7 +3852,6 @@ int snd_cs46xx_create(struct snd_card *card,
                dev_err(chip->card->dev,
                        "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n",
                           chip->ba0_addr, chip->ba1_addr);
-               snd_cs46xx_free(chip);
                return -ENOMEM;
        }
 
@@ -3978,67 +3923,45 @@ int snd_cs46xx_create(struct snd_card *card,
 
        for (idx = 0; idx < 5; idx++) {
                region = &chip->region.idx[idx];
-               region->resource = request_mem_region(region->base, region->size,
-                                                     region->name);
-               if (!region->resource) {
-                       dev_err(chip->card->dev,
-                               "unable to request memory region 0x%lx-0x%lx\n",
-                                  region->base, region->base + region->size - 1);
-                       snd_cs46xx_free(chip);
-                       return -EBUSY;
-               }
-               region->remap_addr = ioremap(region->base, region->size);
+               region->remap_addr = devm_ioremap(&pci->dev, region->base,
+                                                 region->size);
                if (region->remap_addr == NULL) {
                        dev_err(chip->card->dev,
                                "%s ioremap problem\n", region->name);
-                       snd_cs46xx_free(chip);
                        return -ENOMEM;
                }
        }
 
-       if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_cs46xx_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_cs46xx_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_cs46xx_free;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        chip->dsp_spos_instance = cs46xx_dsp_spos_create(chip);
-       if (chip->dsp_spos_instance == NULL) {
-               snd_cs46xx_free(chip);
+       if (!chip->dsp_spos_instance)
                return -ENOMEM;
-       }
 #endif
 
        err = snd_cs46xx_chip_init(chip);
-       if (err < 0) {
-               snd_cs46xx_free(chip);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_cs46xx_free(chip);
+       if (err < 0)
                return err;
-       }
        
        snd_cs46xx_proc_init(card, chip);
 
 #ifdef CONFIG_PM_SLEEP
-       chip->saved_regs = kmalloc_array(ARRAY_SIZE(saved_regs),
-                                        sizeof(*chip->saved_regs),
-                                        GFP_KERNEL);
-       if (!chip->saved_regs) {
-               snd_cs46xx_free(chip);
+       chip->saved_regs = devm_kmalloc_array(&pci->dev,
+                                             ARRAY_SIZE(saved_regs),
+                                             sizeof(*chip->saved_regs),
+                                             GFP_KERNEL);
+       if (!chip->saved_regs)
                return -ENOMEM;
-       }
 #endif
 
        chip->active_ctrl(chip, -1); /* disable CLKRUN */
-
-       *rchip = chip;
        return 0;
 }
index 20b4fae..93ff029 100644 (file)
@@ -65,25 +65,6 @@ static const struct pci_device_id snd_cs5530_ids[] = {
 
 MODULE_DEVICE_TABLE(pci, snd_cs5530_ids);
 
-static int snd_cs5530_free(struct snd_cs5530 *chip)
-{
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_cs5530_dev_free(struct snd_device *device)
-{
-       struct snd_cs5530 *chip = device->device_data;
-       return snd_cs5530_free(chip);
-}
-
-static void snd_cs5530_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static u8 snd_cs5530_mixer_read(unsigned long io, u8 reg)
 {
        outb(reg, io + 4);
@@ -94,50 +75,28 @@ static u8 snd_cs5530_mixer_read(unsigned long io, u8 reg)
 }
 
 static int snd_cs5530_create(struct snd_card *card,
-                            struct pci_dev *pci,
-                            struct snd_cs5530 **rchip)
+                            struct pci_dev *pci)
 {
-       struct snd_cs5530 *chip;
+       struct snd_cs5530 *chip = card->private_data;
        unsigned long sb_base;
        u8 irq, dma8, dma16 = 0;
        u16 map;
        void __iomem *mem;
        int err;
 
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_cs5530_dev_free,
-       };
-       *rchip = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
        chip->pci = pci;
 
-       err = pci_request_regions(pci, "CS5530");
-       if (err < 0) {
-               kfree(chip); 
-               pci_disable_device(pci);
+       err = pcim_iomap_regions(pci, 1 << 0, "CS5530");
+       if (err < 0)
                return err;
-       }
        chip->pci_base = pci_resource_start(pci, 0);
-
-       mem = pci_ioremap_bar(pci, 0);
-       if (mem == NULL) {
-               snd_cs5530_free(chip);
-               return -EBUSY;
-       }
-
+       mem = pcim_iomap_table(pci)[0];
        map = readw(mem + 0x18);
-       iounmap(mem);
 
        /* Map bits
                0:1     * 0x20 + 0x200 = sb base
@@ -154,7 +113,6 @@ static int snd_cs5530_create(struct snd_card *card,
                dev_info(card->dev, "XpressAudio at 0x%lx\n", sb_base);
        else {
                dev_err(card->dev, "Could not find XpressAudio!\n");
-               snd_cs5530_free(chip);
                return -ENODEV;
        }
 
@@ -174,7 +132,6 @@ static int snd_cs5530_create(struct snd_card *card,
                dma16 = 7;
        else {
                dev_err(card->dev, "No 16bit DMA enabled\n");
-               snd_cs5530_free(chip);
                return -ENODEV;
        }
 
@@ -186,7 +143,6 @@ static int snd_cs5530_create(struct snd_card *card,
                dma8 = 3;
        else {
                dev_err(card->dev, "No 8bit DMA enabled\n");
-               snd_cs5530_free(chip);
                return -ENODEV;
        }
 
@@ -200,7 +156,6 @@ static int snd_cs5530_create(struct snd_card *card,
                irq = 10;
        else {
                dev_err(card->dev, "SoundBlaster IRQ not set\n");
-               snd_cs5530_free(chip);
                return -ENODEV;
        }
 
@@ -210,31 +165,21 @@ static int snd_cs5530_create(struct snd_card *card,
                                                dma16, SB_HW_CS5530, &chip->sb);
        if (err < 0) {
                dev_err(card->dev, "Could not create SoundBlaster\n");
-               snd_cs5530_free(chip);
                return err;
        }
 
        err = snd_sb16dsp_pcm(chip->sb, 0);
        if (err < 0) {
                dev_err(card->dev, "Could not create PCM\n");
-               snd_cs5530_free(chip);
                return err;
        }
 
        err = snd_sbmixer_new(chip->sb);
        if (err < 0) {
                dev_err(card->dev, "Could not create Mixer\n");
-               snd_cs5530_free(chip);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_cs5530_free(chip);
                return err;
        }
 
-       *rchip = chip;
        return 0;
 }
 
@@ -243,7 +188,7 @@ static int snd_cs5530_probe(struct pci_dev *pci,
 {
        static int dev;
        struct snd_card *card;
-       struct snd_cs5530 *chip = NULL;
+       struct snd_cs5530 *chip;
        int err;
 
        if (dev >= SNDRV_CARDS)
@@ -253,27 +198,23 @@ static int snd_cs5530_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
-
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       err = snd_cs5530_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_cs5530_create(card, pci);
+       if (err < 0)
                return err;
-       }
 
        strcpy(card->driver, "CS5530");
        strcpy(card->shortname, "CS5530 Audio");
        sprintf(card->longname, "%s at 0x%lx", card->shortname, chip->pci_base);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
@@ -283,7 +224,6 @@ static struct pci_driver cs5530_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cs5530_ids,
        .probe = snd_cs5530_probe,
-       .remove = snd_cs5530_remove,
 };
 
 module_pci_driver(cs5530_driver);
index e048b45..499fa01 100644 (file)
@@ -237,51 +237,24 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int snd_cs5535audio_free(struct cs5535audio *cs5535au)
+static void snd_cs5535audio_free(struct snd_card *card)
 {
-       pci_set_power_state(cs5535au->pci, PCI_D3hot);
-
-       if (cs5535au->irq >= 0)
-               free_irq(cs5535au->irq, cs5535au);
-
-       pci_release_regions(cs5535au->pci);
-       pci_disable_device(cs5535au->pci);
-       kfree(cs5535au);
-       return 0;
-}
-
-static int snd_cs5535audio_dev_free(struct snd_device *device)
-{
-       struct cs5535audio *cs5535au = device->device_data;
-       return snd_cs5535audio_free(cs5535au);
+       olpc_quirks_cleanup();
 }
 
 static int snd_cs5535audio_create(struct snd_card *card,
-                                 struct pci_dev *pci,
-                                 struct cs5535audio **rcs5535au)
+                                 struct pci_dev *pci)
 {
-       struct cs5535audio *cs5535au;
-
+       struct cs5535audio *cs5535au = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_cs5535audio_dev_free,
-       };
 
-       *rcs5535au = NULL;
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_warn(card->dev, "unable to get 32bit dma\n");
-               err = -ENXIO;
-               goto pcifail;
-       }
-
-       cs5535au = kzalloc(sizeof(*cs5535au), GFP_KERNEL);
-       if (cs5535au == NULL) {
-               err = -ENOMEM;
-               goto pcifail;
+               return -ENXIO;
        }
 
        spin_lock_init(&cs5535au->reg_lock);
@@ -290,38 +263,22 @@ static int snd_cs5535audio_create(struct snd_card *card,
        cs5535au->irq = -1;
 
        err = pci_request_regions(pci, "CS5535 Audio");
-       if (err < 0) {
-               kfree(cs5535au);
-               goto pcifail;
-       }
+       if (err < 0)
+               return err;
 
        cs5535au->port = pci_resource_start(pci, 0);
 
-       if (request_irq(pci->irq, snd_cs5535audio_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, cs5535au)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_cs5535audio_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, cs5535au)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               err = -EBUSY;
-               goto sndfail;
+               return -EBUSY;
        }
 
        cs5535au->irq = pci->irq;
        card->sync_irq = cs5535au->irq;
        pci_set_master(pci);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cs5535au, &ops);
-       if (err < 0)
-               goto sndfail;
-
-       *rcs5535au = cs5535au;
        return 0;
-
-sndfail: /* leave the device alive, just kill the snd */
-       snd_cs5535audio_free(cs5535au);
-       return err;
-
-pcifail:
-       pci_disable_device(pci);
-       return err;
 }
 
 static int snd_cs5535audio_probe(struct pci_dev *pci,
@@ -339,24 +296,24 @@ static int snd_cs5535audio_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*cs5535au), &card);
        if (err < 0)
                return err;
+       cs5535au = card->private_data;
+       card->private_free = snd_cs5535audio_free;
 
-       err = snd_cs5535audio_create(card, pci, &cs5535au);
+       err = snd_cs5535audio_create(card, pci);
        if (err < 0)
-               goto probefail_out;
-
-       card->private_data = cs5535au;
+               return err;
 
        err = snd_cs5535audio_mixer(cs5535au);
        if (err < 0)
-               goto probefail_out;
+               return err;
 
        err = snd_cs5535audio_pcm(cs5535au);
        if (err < 0)
-               goto probefail_out;
+               return err;
 
        strcpy(card->driver, DRIVER_NAME);
 
@@ -367,28 +324,17 @@ static int snd_cs5535audio_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto probefail_out;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
-probefail_out:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_cs5535audio_remove(struct pci_dev *pci)
-{
-       olpc_quirks_cleanup();
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver cs5535audio_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cs5535audio_ids,
        .probe = snd_cs5535audio_probe,
-       .remove = snd_cs5535audio_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &snd_cs5535audio_pm,
index 110d320..122170a 100644 (file)
@@ -171,10 +171,8 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
        for (i = 0; i < ARRAY_SIZE(olpc_cs5535audio_ctls); i++) {
                err = snd_ctl_add(card, snd_ctl_new1(&olpc_cs5535audio_ctls[i],
                                ac97->private_data));
-               if (err < 0) {
-                       gpio_free(OLPC_GPIO_MIC_AC);
+               if (err < 0)
                        return err;
-               }
        }
 
        /* turn off the mic by default */
@@ -184,5 +182,6 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
 
 void olpc_quirks_cleanup(void)
 {
-       gpio_free(OLPC_GPIO_MIC_AC);
+       if (machine_is_olpc())
+               gpio_free(OLPC_GPIO_MIC_AC);
 }
index a62e558..25b012e 100644 (file)
@@ -1882,105 +1882,63 @@ static irqreturn_t snd_echo_interrupt(int irq, void *dev_id)
        Module construction / destruction
 ******************************************************************************/
 
-static int snd_echo_free(struct echoaudio *chip)
+static void snd_echo_free(struct snd_card *card)
 {
+       struct echoaudio *chip = card->private_data;
+
        if (chip->comm_page)
                rest_in_peace(chip);
 
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
 
-       if (chip->comm_page)
-               snd_dma_free_pages(&chip->commpage_dma_buf);
-
-       iounmap(chip->dsp_registers);
-       release_and_free_resource(chip->iores);
-       pci_disable_device(chip->pci);
-
        /* release chip data */
        free_firmware_cache(chip);
-       kfree(chip);
-       return 0;
-}
-
-
-
-static int snd_echo_dev_free(struct snd_device *device)
-{
-       struct echoaudio *chip = device->device_data;
-
-       return snd_echo_free(chip);
 }
 
-
-
 /* <--snd_echo_probe() */
 static int snd_echo_create(struct snd_card *card,
-                          struct pci_dev *pci,
-                          struct echoaudio **rchip)
+                          struct pci_dev *pci)
 {
-       struct echoaudio *chip;
+       struct echoaudio *chip = card->private_data;
        int err;
        size_t sz;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_echo_dev_free,
-       };
-
-       *rchip = NULL;
 
        pci_write_config_byte(pci, PCI_LATENCY_TIMER, 0xC0);
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        pci_set_master(pci);
 
        /* Allocate chip if needed */
-       if (!*rchip) {
-               chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-               if (!chip) {
-                       pci_disable_device(pci);
-                       return -ENOMEM;
-               }
-               dev_dbg(card->dev, "chip=%p\n", chip);
-               spin_lock_init(&chip->lock);
-               chip->card = card;
-               chip->pci = pci;
-               chip->irq = -1;
-               chip->opencount = 0;
-               mutex_init(&chip->mode_mutex);
-               chip->can_set_rate = 1;
-       } else {
-               /* If this was called from the resume function, chip is
-                * already allocated and it contains current card settings.
-                */
-               chip = *rchip;
-       }
+       spin_lock_init(&chip->lock);
+       chip->card = card;
+       chip->pci = pci;
+       chip->irq = -1;
+       chip->opencount = 0;
+       mutex_init(&chip->mode_mutex);
+       chip->can_set_rate = 1;
 
        /* PCI resource allocation */
+       err = pci_request_regions(pci, ECHOCARD_NAME);
+       if (err < 0)
+               return err;
+
        chip->dsp_registers_phys = pci_resource_start(pci, 0);
        sz = pci_resource_len(pci, 0);
        if (sz > PAGE_SIZE)
                sz = PAGE_SIZE;         /* We map only the required part */
 
-       chip->iores = request_mem_region(chip->dsp_registers_phys, sz,
-                                        ECHOCARD_NAME);
-       if (!chip->iores) {
-               dev_err(chip->card->dev, "cannot get memory region\n");
-               snd_echo_free(chip);
-               return -EBUSY;
-       }
-       chip->dsp_registers = ioremap(chip->dsp_registers_phys, sz);
+       chip->dsp_registers = devm_ioremap(&pci->dev, chip->dsp_registers_phys, sz);
        if (!chip->dsp_registers) {
                dev_err(chip->card->dev, "ioremap failed\n");
-               snd_echo_free(chip);
                return -ENOMEM;
        }
 
        if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED,
                        KBUILD_MODNAME, chip)) {
                dev_err(chip->card->dev, "cannot grab irq\n");
-               snd_echo_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
@@ -1988,39 +1946,29 @@ static int snd_echo_create(struct snd_card *card,
        dev_dbg(card->dev, "pci=%p irq=%d subdev=%04x Init hardware...\n",
                chip->pci, chip->irq, chip->pci->subsystem_device);
 
+       card->private_free = snd_echo_free;
+
        /* Create the DSP comm page - this is the area of memory used for most
        of the communication with the DSP, which accesses it via bus mastering */
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
-                               sizeof(struct comm_page),
-                               &chip->commpage_dma_buf) < 0) {
-               dev_err(chip->card->dev, "cannot allocate the comm page\n");
-               snd_echo_free(chip);
+       chip->commpage_dma_buf =
+               snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+                                    sizeof(struct comm_page));
+       if (!chip->commpage_dma_buf)
                return -ENOMEM;
-       }
-       chip->comm_page_phys = chip->commpage_dma_buf.addr;
-       chip->comm_page = (struct comm_page *)chip->commpage_dma_buf.area;
+       chip->comm_page_phys = chip->commpage_dma_buf->addr;
+       chip->comm_page = (struct comm_page *)chip->commpage_dma_buf->area;
 
        err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device);
        if (err >= 0)
                err = set_mixer_defaults(chip);
        if (err < 0) {
                dev_err(card->dev, "init_hw err=%d\n", err);
-               snd_echo_free(chip);
                return err;
        }
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_echo_free(chip);
-               return err;
-       }
-       *rchip = chip;
-       /* Init done ! */
        return 0;
 }
 
-
-
 /* constructor */
 static int snd_echo_probe(struct pci_dev *pci,
                          const struct pci_device_id *pci_id)
@@ -2040,17 +1988,15 @@ static int snd_echo_probe(struct pci_dev *pci,
        }
 
        i = 0;
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       chip = NULL;    /* Tells snd_echo_create to allocate chip */
-       err = snd_echo_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_echo_create(card, pci);
+       if (err < 0)
                return err;
-       }
 
        strcpy(card->driver, "Echo_" ECHOCARD_NAME);
        strcpy(card->shortname, chip->card_name);
@@ -2066,7 +2012,6 @@ static int snd_echo_probe(struct pci_dev *pci,
        err = snd_echo_new_pcm(chip);
        if (err < 0) {
                dev_err(chip->card->dev, "new pcm error %d\n", err);
-               snd_card_free(card);
                return err;
        }
 
@@ -2075,7 +2020,6 @@ static int snd_echo_probe(struct pci_dev *pci,
                err = snd_echo_midi_create(card, chip);
                if (err < 0) {
                        dev_err(chip->card->dev, "new midi error %d\n", err);
-                       snd_card_free(card);
                        return err;
                }
        }
@@ -2085,64 +2029,64 @@ static int snd_echo_probe(struct pci_dev *pci,
        snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip);
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #ifdef ECHOCARD_HAS_LINE_OUT_GAIN
        err = snd_ctl_add(chip->card,
                          snd_ctl_new1(&snd_echo_line_output_gain, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif
 #else /* ECHOCARD_HAS_VMIXER */
        err = snd_ctl_add(chip->card,
                          snd_ctl_new1(&snd_echo_pcm_output_gain, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif /* ECHOCARD_HAS_VMIXER */
 
 #ifdef ECHOCARD_HAS_INPUT_GAIN
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_input_gain, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif
 
 #ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
        if (!chip->hasnt_input_nominal_level) {
                err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_intput_nominal_level, chip));
                if (err < 0)
-                       goto ctl_error;
+                       return err;
        }
 #endif
 
 #ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_output_nominal_level, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif
 
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters_switch, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 
 #ifdef ECHOCARD_HAS_MONITOR
        snd_echo_monitor_mixer.count = num_busses_in(chip) * num_busses_out(chip);
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_monitor_mixer, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif
 
 #ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_automute_switch, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif
 
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_channels_info, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 
 #ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH
        /* Creates a list of available digital modes */
@@ -2153,7 +2097,7 @@ static int snd_echo_probe(struct pci_dev *pci,
 
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_digital_mode_switch, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */
 
 #ifdef ECHOCARD_HAS_EXTERNAL_CLOCK
@@ -2167,37 +2111,32 @@ static int snd_echo_probe(struct pci_dev *pci,
                chip->clock_src_ctl = snd_ctl_new1(&snd_echo_clock_source_switch, chip);
                err = snd_ctl_add(chip->card, chip->clock_src_ctl);
                if (err < 0)
-                       goto ctl_error;
+                       return err;
        }
 #endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */
 
 #ifdef ECHOCARD_HAS_DIGITAL_IO
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_spdif_mode_switch, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif
 
 #ifdef ECHOCARD_HAS_PHANTOM_POWER
        if (chip->has_phantom_power) {
                err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_phantom_power_switch, chip));
                if (err < 0)
-                       goto ctl_error;
+                       return err;
        }
 #endif
 
        err = snd_card_register(card);
        if (err < 0)
-               goto ctl_error;
+               return err;
        dev_info(card->dev, "Card registered: %s\n", card->longname);
 
        pci_set_drvdata(pci, chip);
        dev++;
        return 0;
-
-ctl_error:
-       dev_err(card->dev, "new control error %d\n", err);
-       snd_card_free(card);
-       return err;
 }
 
 
@@ -2299,18 +2238,6 @@ static SIMPLE_DEV_PM_OPS(snd_echo_pm, snd_echo_suspend, snd_echo_resume);
 #define SND_ECHO_PM_OPS        NULL
 #endif /* CONFIG_PM_SLEEP */
 
-
-static void snd_echo_remove(struct pci_dev *pci)
-{
-       struct echoaudio *chip;
-
-       chip = pci_get_drvdata(pci);
-       if (chip)
-               snd_card_free(chip->card);
-}
-
-
-
 /******************************************************************************
        Everything starts and ends here
 ******************************************************************************/
@@ -2320,7 +2247,6 @@ static struct pci_driver echo_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_echo_ids,
        .probe = snd_echo_probe,
-       .remove = snd_echo_remove,
        .driver = {
                .pm = SND_ECHO_PM_OPS,
        },
index 0afe13f..d51de3e 100644 (file)
@@ -348,7 +348,7 @@ struct echoaudio {
        struct pci_dev *pci;
        unsigned long dsp_registers_phys;
        struct resource *iores;
-       struct snd_dma_buffer commpage_dma_buf;
+       struct snd_dma_buffer *commpage_dma_buf;
        int irq;
 #ifdef ECHOCARD_HAS_MIDI
        struct snd_rawmidi *rmidi;
index 887bfb3..672af4b 100644 (file)
@@ -99,67 +99,67 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*emu), &card);
        if (err < 0)
                return err;
+       emu = card->private_data;
+
        if (max_buffer_size[dev] < 32)
                max_buffer_size[dev] = 32;
        else if (max_buffer_size[dev] > 1024)
                max_buffer_size[dev] = 1024;
        err = snd_emu10k1_create(card, pci, extin[dev], extout[dev],
                                 (long)max_buffer_size[dev] * 1024 * 1024,
-                                enable_ir[dev], subsystem[dev],
-                                &emu);
+                                enable_ir[dev], subsystem[dev]);
        if (err < 0)
-               goto error;
-       card->private_data = emu;
+               return err;
        emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f;
        err = snd_emu10k1_pcm(emu, 0);
        if (err < 0)
-               goto error;
+               return err;
        err = snd_emu10k1_pcm_mic(emu, 1);
        if (err < 0)
-               goto error;
+               return err;
        err = snd_emu10k1_pcm_efx(emu, 2);
        if (err < 0)
-               goto error;
+               return err;
        /* This stores the periods table. */
        if (emu->card_capabilities->ca0151_chip) { /* P16V */   
-               err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                                         1024, &emu->p16v_buffer);
-               if (err < 0)
-                       goto error;
+               emu->p16v_buffer =
+                       snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 1024);
+               if (!emu->p16v_buffer)
+                       return -ENOMEM;
        }
 
        err = snd_emu10k1_mixer(emu, 0, 3);
        if (err < 0)
-               goto error;
+               return err;
        
        err = snd_emu10k1_timer(emu, 0);
        if (err < 0)
-               goto error;
+               return err;
 
        err = snd_emu10k1_pcm_multi(emu, 3);
        if (err < 0)
-               goto error;
+               return err;
        if (emu->card_capabilities->ca0151_chip) { /* P16V */
                err = snd_p16v_pcm(emu, 4);
                if (err < 0)
-                       goto error;
+                       return err;
        }
        if (emu->audigy) {
                err = snd_emu10k1_audigy_midi(emu);
                if (err < 0)
-                       goto error;
+                       return err;
        } else {
                err = snd_emu10k1_midi(emu);
                if (err < 0)
-                       goto error;
+                       return err;
        }
        err = snd_emu10k1_fx8010_new(emu, 0);
        if (err < 0)
-               goto error;
+               return err;
 #ifdef ENABLE_SYNTH
        if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH,
                               sizeof(struct snd_emu10k1_synth_arg), &wave) < 0 ||
@@ -187,7 +187,7 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto error;
+               return err;
 
        if (emu->card_capabilities->emu_model)
                schedule_delayed_work(&emu->emu1010.firmware_work, 0);
@@ -195,18 +195,8 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
- error:
-       snd_card_free(card);
-       return err;
 }
 
-static void snd_card_emu10k1_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
-
 #ifdef CONFIG_PM_SLEEP
 static int snd_emu10k1_suspend(struct device *dev)
 {
@@ -263,7 +253,6 @@ static struct pci_driver emu10k1_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_emu10k1_ids,
        .probe = snd_card_emu10k1_probe,
-       .remove = snd_card_emu10k1_remove,
        .driver = {
                .pm = SND_EMU10K1_PM_OPS,
        },
index 24a2fd7..86cc1ca 100644 (file)
@@ -1242,8 +1242,10 @@ static int alloc_pm_buffer(struct snd_emu10k1 *emu);
 static void free_pm_buffer(struct snd_emu10k1 *emu);
 #endif
 
-static int snd_emu10k1_free(struct snd_emu10k1 *emu)
+static void snd_emu10k1_free(struct snd_card *card)
 {
+       struct snd_emu10k1 *emu = card->private_data;
+
        if (emu->port) {        /* avoid access to already used hardware */
                snd_emu10k1_fx8010_tram_setup(emu, 0);
                snd_emu10k1_done(emu);
@@ -1256,8 +1258,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
        cancel_delayed_work_sync(&emu->emu1010.firmware_work);
        release_firmware(emu->firmware);
        release_firmware(emu->dock_fw);
-       if (emu->irq >= 0)
-               free_irq(emu->irq, emu);
        snd_util_memhdr_free(emu->memhdr);
        if (emu->silent_page.area)
                snd_dma_free_pages(&emu->silent_page);
@@ -1268,19 +1268,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
 #ifdef CONFIG_PM_SLEEP
        free_pm_buffer(emu);
 #endif
-       if (emu->port)
-               pci_release_regions(emu->pci);
-       if (emu->card_capabilities->ca0151_chip) /* P16V */
-               snd_p16v_free(emu);
-       pci_disable_device(emu->pci);
-       kfree(emu);
-       return 0;
-}
-
-static int snd_emu10k1_dev_free(struct snd_device *device)
-{
-       struct snd_emu10k1 *emu = device->device_data;
-       return snd_emu10k1_free(emu);
 }
 
 static const struct snd_emu_chip_details emu_chip_details[] = {
@@ -1782,32 +1769,22 @@ int snd_emu10k1_create(struct snd_card *card,
                       unsigned short extout_mask,
                       long max_cache_bytes,
                       int enable_ir,
-                      uint subsystem,
-                      struct snd_emu10k1 **remu)
+                      uint subsystem)
 {
-       struct snd_emu10k1 *emu;
+       struct snd_emu10k1 *emu = card->private_data;
        int idx, err;
        int is_audigy;
        size_t page_table_size;
        __le32 *pgtbl;
        unsigned int silent_page;
        const struct snd_emu_chip_details *c;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_emu10k1_dev_free,
-       };
-
-       *remu = NULL;
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       emu = kzalloc(sizeof(*emu), GFP_KERNEL);
-       if (emu == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
+       card->private_free = snd_emu10k1_free;
        emu->card = card;
        spin_lock_init(&emu->reg_lock);
        spin_lock_init(&emu->emu_lock);
@@ -1850,8 +1827,6 @@ int snd_emu10k1_create(struct snd_card *card,
        }
        if (c->vendor == 0) {
                dev_err(card->dev, "emu10k1: Card not recognised\n");
-               kfree(emu);
-               pci_disable_device(pci);
                return -ENOENT;
        }
        emu->card_capabilities = c;
@@ -1883,8 +1858,6 @@ int snd_emu10k1_create(struct snd_card *card,
                dev_err(card->dev,
                        "architecture does not support PCI busmaster DMA with mask 0x%lx\n",
                        emu->dma_mask);
-               kfree(emu);
-               pci_disable_device(pci);
                return -ENXIO;
        }
        if (is_audigy)
@@ -1893,11 +1866,8 @@ int snd_emu10k1_create(struct snd_card *card,
                emu->gpr_base = FXGPREGBASE;
 
        err = pci_request_regions(pci, "EMU10K1");
-       if (err < 0) {
-               kfree(emu);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        emu->port = pci_resource_start(pci, 0);
 
        emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
@@ -1905,10 +1875,8 @@ int snd_emu10k1_create(struct snd_card *card,
        page_table_size = sizeof(u32) * (emu->address_mode ? MAXPAGES1 :
                                         MAXPAGES0);
        if (snd_emu10k1_alloc_pages_maybe_wider(emu, page_table_size,
-                                               &emu->ptb_pages) < 0) {
-               err = -ENOMEM;
-               goto error;
-       }
+                                               &emu->ptb_pages) < 0)
+               return -ENOMEM;
        dev_dbg(card->dev, "page table address range is %.8lx:%.8lx\n",
                (unsigned long)emu->ptb_pages.addr,
                (unsigned long)(emu->ptb_pages.addr + emu->ptb_pages.bytes));
@@ -1917,26 +1885,20 @@ int snd_emu10k1_create(struct snd_card *card,
                                                 emu->max_cache_pages));
        emu->page_addr_table = vmalloc(array_size(sizeof(unsigned long),
                                                  emu->max_cache_pages));
-       if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) {
-               err = -ENOMEM;
-               goto error;
-       }
+       if (!emu->page_ptr_table || !emu->page_addr_table)
+               return -ENOMEM;
 
        if (snd_emu10k1_alloc_pages_maybe_wider(emu, EMUPAGESIZE,
-                                               &emu->silent_page) < 0) {
-               err = -ENOMEM;
-               goto error;
-       }
+                                               &emu->silent_page) < 0)
+               return -ENOMEM;
        dev_dbg(card->dev, "silent page range is %.8lx:%.8lx\n",
                (unsigned long)emu->silent_page.addr,
                (unsigned long)(emu->silent_page.addr +
                                emu->silent_page.bytes));
 
        emu->memhdr = snd_util_memhdr_new(emu->max_cache_pages * PAGE_SIZE);
-       if (emu->memhdr == NULL) {
-               err = -ENOMEM;
-               goto error;
-       }
+       if (!emu->memhdr)
+               return -ENOMEM;
        emu->memhdr->block_extra_size = sizeof(struct snd_emu10k1_memblk) -
                sizeof(struct snd_util_memblk);
 
@@ -1954,18 +1916,16 @@ int snd_emu10k1_create(struct snd_card *card,
        if (emu->card_capabilities->ca_cardbus_chip) {
                err = snd_emu10k1_cardbus_init(emu);
                if (err < 0)
-                       goto error;
+                       return err;
        }
        if (emu->card_capabilities->ecard) {
                err = snd_emu10k1_ecard_init(emu);
                if (err < 0)
-                       goto error;
+                       return err;
        } else if (emu->card_capabilities->emu_model) {
                err = snd_emu10k1_emu1010_init(emu);
-               if (err < 0) {
-                       snd_emu10k1_free(emu);
+               if (err < 0)
                        return err;
-               }
        } else {
                /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
                        does not support this, it shouldn't do any harm */
@@ -1979,11 +1939,9 @@ int snd_emu10k1_create(struct snd_card *card,
        emu->fx8010.etram_pages.bytes = 0;
 
        /* irq handler must be registered after I/O ports are activated */
-       if (request_irq(pci->irq, snd_emu10k1_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, emu)) {
-               err = -EBUSY;
-               goto error;
-       }
+       if (devm_request_irq(&pci->dev, pci->irq, snd_emu10k1_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, emu))
+               return -EBUSY;
        emu->irq = pci->irq;
        card->sync_irq = emu->irq;
 
@@ -2022,33 +1980,23 @@ int snd_emu10k1_create(struct snd_card *card,
 
        err = snd_emu10k1_init(emu, enable_ir, 0);
        if (err < 0)
-               goto error;
+               return err;
 #ifdef CONFIG_PM_SLEEP
        err = alloc_pm_buffer(emu);
        if (err < 0)
-               goto error;
+               return err;
 #endif
 
        /*  Initialize the effect engine */
        err = snd_emu10k1_init_efx(emu);
        if (err < 0)
-               goto error;
+               return err;
        snd_emu10k1_audio_enable(emu);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops);
-       if (err < 0)
-               goto error;
-
 #ifdef CONFIG_SND_PROC_FS
        snd_emu10k1_proc_init(emu);
 #endif
-
-       *remu = emu;
        return 0;
-
- error:
-       snd_emu10k1_free(emu);
-       return err;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 89b0f38..c49c44d 100644 (file)
@@ -216,7 +216,6 @@ struct emu10k1x {
        struct pci_dev *pci;
 
        unsigned long port;
-       struct resource *res_port;
        int irq;
 
        unsigned char revision;         /* chip revision */
@@ -233,7 +232,7 @@ struct emu10k1x {
        struct emu10k1x_voice capture_voice;
        u32 spdif_bits[3]; // SPDIF out setup
 
-       struct snd_dma_buffer dma_buffer;
+       struct snd_dma_buffer *dma_buffer;
 
        struct emu10k1x_midi midi;
 };
@@ -442,7 +441,7 @@ static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct emu10k1x_pcm *epcm = runtime->private_data;
        int voice = epcm->voice->number;
-       u32 *table_base = (u32 *)(emu->dma_buffer.area+1024*voice);
+       u32 *table_base = (u32 *)(emu->dma_buffer->area+1024*voice);
        u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
        int i;
        
@@ -451,7 +450,7 @@ static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream)
                *table_base++=period_size_bytes<<16;
        }
 
-       snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_ADDR, voice, emu->dma_buffer.addr+1024*voice);
+       snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_ADDR, voice, emu->dma_buffer->addr+1024*voice);
        snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_SIZE, voice, (runtime->periods - 1) << 19);
        snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_PTR, voice, 0);
        snd_emu10k1x_ptr_write(emu, PLAYBACK_POINTER, voice, 0);
@@ -737,37 +736,15 @@ static int snd_emu10k1x_ac97(struct emu10k1x *chip)
        return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
 }
 
-static int snd_emu10k1x_free(struct emu10k1x *chip)
+static void snd_emu10k1x_free(struct snd_card *card)
 {
+       struct emu10k1x *chip = card->private_data;
+
        snd_emu10k1x_ptr_write(chip, TRIGGER_CHANNEL, 0, 0);
        // disable interrupts
        outl(0, chip->port + INTE);
        // disable audio
        outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
-
-       /* release the irq */
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-
-       // release the i/o port
-       release_and_free_resource(chip->res_port);
-
-       // release the DMA
-       if (chip->dma_buffer.area) {
-               snd_dma_free_pages(&chip->dma_buffer);
-       }
-
-       pci_disable_device(chip->pci);
-
-       // release the data
-       kfree(chip);
-       return 0;
-}
-
-static int snd_emu10k1x_dev_free(struct snd_device *device)
-{
-       struct emu10k1x *chip = device->device_data;
-       return snd_emu10k1x_free(chip);
 }
 
 static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id)
@@ -885,34 +862,21 @@ static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device)
 }
 
 static int snd_emu10k1x_create(struct snd_card *card,
-                              struct pci_dev *pci,
-                              struct emu10k1x **rchip)
+                              struct pci_dev *pci)
 {
-       struct emu10k1x *chip;
+       struct emu10k1x *chip = card->private_data;
        int err;
        int ch;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_emu10k1x_dev_free,
-       };
-
-       *rchip = NULL;
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28)) < 0) {
                dev_err(card->dev, "error to set 28bit mask DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
@@ -920,29 +884,24 @@ static int snd_emu10k1x_create(struct snd_card *card,
        spin_lock_init(&chip->emu_lock);
        spin_lock_init(&chip->voice_lock);
   
+       err = pci_request_regions(pci, "EMU10K1X");
+       if (err < 0)
+               return err;
        chip->port = pci_resource_start(pci, 0);
-       chip->res_port = request_region(chip->port, 8, "EMU10K1X");
-       if (!chip->res_port) {
-               dev_err(card->dev, "cannot allocate the port 0x%lx\n",
-                       chip->port);
-               snd_emu10k1x_free(chip);
-               return -EBUSY;
-       }
 
-       if (request_irq(pci->irq, snd_emu10k1x_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_emu10k1x_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "cannot grab irq %d\n", pci->irq);
-               snd_emu10k1x_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_emu10k1x_free;
   
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               4 * 1024, &chip->dma_buffer) < 0) {
-               snd_emu10k1x_free(chip);
+       chip->dma_buffer = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+                                               4 * 1024);
+       if (!chip->dma_buffer)
                return -ENOMEM;
-       }
 
        pci_set_master(pci);
        /* read revision & serial */
@@ -998,12 +957,6 @@ static int snd_emu10k1x_create(struct snd_card *card,
 
        outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_emu10k1x_free(chip);
-               return err;
-       }
-       *rchip = chip;
        return 0;
 }
 
@@ -1553,50 +1506,37 @@ static int snd_emu10k1x_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       err = snd_emu10k1x_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_emu10k1x_create(card, pci);
+       if (err < 0)
                return err;
-       }
 
        err = snd_emu10k1x_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_emu10k1x_pcm(chip, 1);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_emu10k1x_pcm(chip, 2);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_emu10k1x_ac97(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_emu10k1x_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        
        err = snd_emu10k1x_midi(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        snd_emu10k1x_proc_init(chip);
 
@@ -1606,21 +1546,14 @@ static int snd_emu10k1x_probe(struct pci_dev *pci,
                card->shortname, chip->port, chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_emu10k1x_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 // PCI IDs
 static const struct pci_device_id snd_emu10k1x_ids[] = {
        { PCI_VDEVICE(CREATIVE, 0x0006), 0 },   /* Dell OEM version (EMU10K1) */
@@ -1633,7 +1566,6 @@ static struct pci_driver emu10k1x_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_emu10k1x_ids,
        .probe = snd_emu10k1x_probe,
-       .remove = snd_emu10k1x_remove,
 };
 
 module_pci_driver(emu10k1x_driver);
index ff2a397..18a1b07 100644 (file)
@@ -290,7 +290,7 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
        struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
        int channel = substream->pcm->device - emu->p16v_device_offset;
-       u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
+       u32 *table_base = (u32 *)(emu->p16v_buffer->area+(8*16*channel));
        u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
        int i;
        u32 tmp;
@@ -308,8 +308,8 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
                   runtime->dma_addr, runtime->dma_area, table_base);
        dev_dbg(emu->card->dev,
                "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
-                  emu->p16v_buffer.addr, emu->p16v_buffer.area,
-                  emu->p16v_buffer.bytes);
+                  emu->p16v_buffer->addr, emu->p16v_buffer->area,
+                  emu->p16v_buffer->bytes);
 #endif /* debug */
        tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
         switch (runtime->rate) {
@@ -333,7 +333,7 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
                table_base[(i*2)+1]=period_size_bytes<<16;
        }
  
-       snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel));
+       snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer->addr+(8*16*channel));
        snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
        snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
        snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
@@ -567,20 +567,6 @@ static const struct snd_pcm_ops snd_p16v_capture_ops = {
        .pointer =     snd_p16v_pcm_pointer_capture,
 };
 
-
-int snd_p16v_free(struct snd_emu10k1 *chip)
-{
-       // release the data
-       if (chip->p16v_buffer.area) {
-               snd_dma_free_pages(&chip->p16v_buffer);
-               /*
-               dev_dbg(chip->card->dev, "period lables free: %p\n",
-                          &chip->p16v_buffer);
-               */
-       }
-       return 0;
-}
-
 int snd_p16v_pcm(struct snd_emu10k1 *emu, int device)
 {
        struct snd_pcm *pcm;
index 728b69d..2651f0c 100644 (file)
@@ -414,7 +414,7 @@ struct ensoniq {
        unsigned int spdif_stream;
 
 #ifdef CHIP1370
-       struct snd_dma_buffer dma_bug;
+       struct snd_dma_buffer *dma_bug;
 #endif
 
 #ifdef SUPPORT_JOYSTICK
@@ -1872,11 +1872,11 @@ static void snd_ensoniq_proc_init(struct ensoniq *ensoniq)
 
  */
 
-static int snd_ensoniq_free(struct ensoniq *ensoniq)
+static void snd_ensoniq_free(struct snd_card *card)
 {
+       struct ensoniq *ensoniq = card->private_data;
+
        snd_ensoniq_free_gameport(ensoniq);
-       if (ensoniq->irq < 0)
-               goto __hw_end;
 #ifdef CHIP1370
        outl(ES_1370_SERR_DISABLE, ES_REG(ensoniq, CONTROL));   /* switch everything off */
        outl(0, ES_REG(ensoniq, SERIAL));       /* clear serial interface */
@@ -1884,24 +1884,6 @@ static int snd_ensoniq_free(struct ensoniq *ensoniq)
        outl(0, ES_REG(ensoniq, CONTROL));      /* switch everything off */
        outl(0, ES_REG(ensoniq, SERIAL));       /* clear serial interface */
 #endif
-       pci_set_power_state(ensoniq->pci, PCI_D3hot);
-      __hw_end:
-#ifdef CHIP1370
-       if (ensoniq->dma_bug.area)
-               snd_dma_free_pages(&ensoniq->dma_bug);
-#endif
-       if (ensoniq->irq >= 0)
-               free_irq(ensoniq->irq, ensoniq);
-       pci_release_regions(ensoniq->pci);
-       pci_disable_device(ensoniq->pci);
-       kfree(ensoniq);
-       return 0;
-}
-
-static int snd_ensoniq_dev_free(struct snd_device *device)
-{
-       struct ensoniq *ensoniq = device->device_data;
-       return snd_ensoniq_free(ensoniq);
 }
 
 #ifdef CHIP1371
@@ -1935,7 +1917,7 @@ static void snd_ensoniq_chip_init(struct ensoniq *ensoniq)
        outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
        outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
        outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE));
-       outl(ensoniq->dma_bug.addr, ES_REG(ensoniq, PHANTOM_FRAME));
+       outl(ensoniq->dma_bug->addr, ES_REG(ensoniq, PHANTOM_FRAME));
        outl(0, ES_REG(ensoniq, PHANTOM_COUNT));
 #else
        outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
@@ -2032,51 +2014,35 @@ static SIMPLE_DEV_PM_OPS(snd_ensoniq_pm, snd_ensoniq_suspend, snd_ensoniq_resume
 #endif /* CONFIG_PM_SLEEP */
 
 static int snd_ensoniq_create(struct snd_card *card,
-                             struct pci_dev *pci,
-                             struct ensoniq **rensoniq)
+                             struct pci_dev *pci)
 {
-       struct ensoniq *ensoniq;
+       struct ensoniq *ensoniq = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_ensoniq_dev_free,
-       };
 
-       *rensoniq = NULL;
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
-       ensoniq = kzalloc(sizeof(*ensoniq), GFP_KERNEL);
-       if (ensoniq == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&ensoniq->reg_lock);
        mutex_init(&ensoniq->src_mutex);
        ensoniq->card = card;
        ensoniq->pci = pci;
        ensoniq->irq = -1;
        err = pci_request_regions(pci, "Ensoniq AudioPCI");
-       if (err < 0) {
-               kfree(ensoniq);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        ensoniq->port = pci_resource_start(pci, 0);
-       if (request_irq(pci->irq, snd_audiopci_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, ensoniq)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_audiopci_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, ensoniq)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_ensoniq_free(ensoniq);
                return -EBUSY;
        }
        ensoniq->irq = pci->irq;
        card->sync_irq = ensoniq->irq;
 #ifdef CHIP1370
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               16, &ensoniq->dma_bug) < 0) {
-               dev_err(card->dev, "unable to allocate space for phantom area - dma_bug\n");
-               snd_ensoniq_free(ensoniq);
-               return -EBUSY;
-       }
+       ensoniq->dma_bug =
+               snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 16);
+       if (!ensoniq->dma_bug)
+               return -ENOMEM;
 #endif
        pci_set_master(pci);
        ensoniq->rev = pci->revision;
@@ -2099,17 +2065,10 @@ static int snd_ensoniq_create(struct snd_card *card,
                ensoniq->cssr |= ES_1371_ST_AC97_RST;
 #endif
 
+       card->private_free = snd_ensoniq_free;
        snd_ensoniq_chip_init(ensoniq);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ensoniq, &ops);
-       if (err < 0) {
-               snd_ensoniq_free(ensoniq);
-               return err;
-       }
-
        snd_ensoniq_proc_init(ensoniq);
-
-       *rensoniq = ensoniq;
        return 0;
 }
 
@@ -2360,47 +2319,35 @@ static int snd_audiopci_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*ensoniq), &card);
        if (err < 0)
                return err;
+       ensoniq = card->private_data;
 
-       err = snd_ensoniq_create(card, pci, &ensoniq);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_ensoniq_create(card, pci);
+       if (err < 0)
                return err;
-       }
-       card->private_data = ensoniq;
 
 #ifdef CHIP1370
        err = snd_ensoniq_1370_mixer(ensoniq);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #endif
 #ifdef CHIP1371
        err = snd_ensoniq_1371_mixer(ensoniq, spdif[dev], lineio[dev]);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #endif
        err = snd_ensoniq_pcm(ensoniq, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_ensoniq_pcm2(ensoniq, 1);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_ensoniq_midi(ensoniq, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        snd_ensoniq_create_gameport(ensoniq, dev);
 
@@ -2414,26 +2361,18 @@ static int snd_audiopci_probe(struct pci_dev *pci,
                ensoniq->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_audiopci_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver ens137x_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_audiopci_ids,
        .probe = snd_audiopci_probe,
-       .remove = snd_audiopci_remove,
        .driver = {
                .pm = SND_ENSONIQ_PM_OPS,
        },
index 33b1eb3..00b976f 100644 (file)
@@ -1521,8 +1521,10 @@ static inline int snd_es1938_create_gameport(struct es1938 *chip) { return -ENOS
 static inline void snd_es1938_free_gameport(struct es1938 *chip) { }
 #endif /* SUPPORT_JOYSTICK */
 
-static int snd_es1938_free(struct es1938 *chip)
+static void snd_es1938_free(struct snd_card *card)
 {
+       struct es1938 *chip = card->private_data;
+
        /* disable irqs */
        outb(0x00, SLIO_REG(chip, IRQCONTROL));
        if (chip->rmidi)
@@ -1532,71 +1534,47 @@ static int snd_es1938_free(struct es1938 *chip)
 
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_es1938_dev_free(struct snd_device *device)
-{
-       struct es1938 *chip = device->device_data;
-       return snd_es1938_free(chip);
 }
 
 static int snd_es1938_create(struct snd_card *card,
-                            struct pci_dev *pci,
-                            struct es1938 **rchip)
+                            struct pci_dev *pci)
 {
-       struct es1938 *chip;
+       struct es1938 *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_es1938_dev_free,
-       };
-
-       *rchip = NULL;
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
         /* check, if we can restrict PCI DMA transfers to 24 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
                dev_err(card->dev,
                        "architecture does not support 24bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                 return -ENXIO;
         }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&chip->reg_lock);
        spin_lock_init(&chip->mixer_lock);
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
        err = pci_request_regions(pci, "ESS Solo-1");
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        chip->io_port = pci_resource_start(pci, 0);
        chip->sb_port = pci_resource_start(pci, 1);
        chip->vc_port = pci_resource_start(pci, 2);
        chip->mpu_port = pci_resource_start(pci, 3);
        chip->game_port = pci_resource_start(pci, 4);
+       /* still use non-managed irq handler as it's re-acquired at PM resume */
        if (request_irq(pci->irq, snd_es1938_interrupt, IRQF_SHARED,
                        KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_es1938_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_es1938_free;
        dev_dbg(card->dev,
                "create: io: 0x%lx, sb: 0x%lx, vc: 0x%lx, mpu: 0x%lx, game: 0x%lx\n",
                   chip->io_port, chip->sb_port, chip->vc_port, chip->mpu_port, chip->game_port);
@@ -1604,14 +1582,6 @@ static int snd_es1938_create(struct snd_card *card,
        chip->ddma_port = chip->vc_port + 0x00;         /* fix from Thomas Sailer */
 
        snd_es1938_chip_init(chip);
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_es1938_free(chip);
-               return err;
-       }
-
-       *rchip = chip;
        return 0;
 }
 
@@ -1762,23 +1732,20 @@ static int snd_es1938_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
-       for (idx = 0; idx < 5; idx++) {
+       chip = card->private_data;
+
+       for (idx = 0; idx < 5; idx++)
                if (pci_resource_start(pci, idx) == 0 ||
-                   !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) {
-                       snd_card_free(card);
-                       return -ENODEV;
-               }
-       }
-       err = snd_es1938_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+                   !(pci_resource_flags(pci, idx) & IORESOURCE_IO))
+                       return -ENODEV;
+
+       err = snd_es1938_create(card, pci);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        strcpy(card->driver, "ES1938");
        strcpy(card->shortname, "ESS ES1938 (Solo-1)");
@@ -1788,15 +1755,11 @@ static int snd_es1938_probe(struct pci_dev *pci,
                chip->irq);
 
        err = snd_es1938_new_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_es1938_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        if (snd_opl3_create(card,
                            SLSB_REG(chip, FMLOWADDR),
                            SLSB_REG(chip, FMHIGHADDR),
@@ -1805,15 +1768,11 @@ static int snd_es1938_probe(struct pci_dev *pci,
                           SLSB_REG(chip, FMLOWADDR));
        } else {
                err = snd_opl3_timer_new(opl3, 0, 1);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
        if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
                                chip->mpu_port,
@@ -1829,26 +1788,18 @@ static int snd_es1938_probe(struct pci_dev *pci,
        snd_es1938_create_gameport(chip);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_es1938_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver es1938_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_es1938_ids,
        .probe = snd_es1938_probe,
-       .remove = snd_es1938_remove,
        .driver = {
                .pm = ES1938_PM_OPS,
        },
index c038c10..6a8a02a 100644 (file)
@@ -2442,7 +2442,8 @@ static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
        if (!joystick[dev])
                return -ENODEV;
 
-       r = request_region(JOYSTICK_ADDR, 8, "ES1968 gameport");
+       r = devm_request_region(&chip->pci->dev, JOYSTICK_ADDR, 8,
+                               "ES1968 gameport");
        if (!r)
                return -EBUSY;
 
@@ -2450,7 +2451,6 @@ static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
        if (!gp) {
                dev_err(chip->card->dev,
                        "cannot allocate memory for gameport\n");
-               release_and_free_resource(r);
                return -ENOMEM;
        }
 
@@ -2461,7 +2461,6 @@ static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
        gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
        gameport_set_dev_parent(gp, &chip->pci->dev);
        gp->io = JOYSTICK_ADDR;
-       gameport_set_port_data(gp, r);
 
        gameport_register_port(gp);
 
@@ -2471,12 +2470,8 @@ static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
 static void snd_es1968_free_gameport(struct es1968 *chip)
 {
        if (chip->gameport) {
-               struct resource *r = gameport_get_port_data(chip->gameport);
-
                gameport_unregister_port(chip->gameport);
                chip->gameport = NULL;
-
-               release_and_free_resource(r);
        }
 }
 #else
@@ -2490,7 +2485,7 @@ static int snd_es1968_input_register(struct es1968 *chip)
        struct input_dev *input_dev;
        int err;
 
-       input_dev = input_allocate_device();
+       input_dev = devm_input_allocate_device(&chip->pci->dev);
        if (!input_dev)
                return -ENOMEM;
 
@@ -2510,10 +2505,8 @@ static int snd_es1968_input_register(struct es1968 *chip)
        __set_bit(KEY_VOLUMEUP, input_dev->keybit);
 
        err = input_register_device(input_dev);
-       if (err) {
-               input_free_device(input_dev);
+       if (err)
                return err;
-       }
 
        chip->input_dev = input_dev;
        return 0;
@@ -2597,13 +2590,11 @@ static const struct snd_tea575x_ops snd_es1968_tea_ops = {
 };
 #endif
 
-static int snd_es1968_free(struct es1968 *chip)
+static void snd_es1968_free(struct snd_card *card)
 {
+       struct es1968 *chip = card->private_data;
+
        cancel_work_sync(&chip->hwvol_work);
-#ifdef CONFIG_SND_ES1968_INPUT
-       if (chip->input_dev)
-               input_unregister_device(chip->input_dev);
-#endif
 
        if (chip->io_port) {
                outw(1, chip->io_port + 0x04); /* clear WP interrupts */
@@ -2615,19 +2606,7 @@ static int snd_es1968_free(struct es1968 *chip)
        v4l2_device_unregister(&chip->v4l2_dev);
 #endif
 
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
        snd_es1968_free_gameport(chip);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_es1968_dev_free(struct snd_device *device)
-{
-       struct es1968 *chip = device->device_data;
-       return snd_es1968_free(chip);
 }
 
 struct ess_device_list {
@@ -2657,35 +2636,22 @@ static int snd_es1968_create(struct snd_card *card,
                             int capt_streams,
                             int chip_type,
                             int do_pm,
-                            int radio_nr,
-                            struct es1968 **chip_ret)
+                            int radio_nr)
 {
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_es1968_dev_free,
-       };
-       struct es1968 *chip;
+       struct es1968 *chip = card->private_data;
        int i, err;
 
-       *chip_ret = NULL;
-
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 28 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
                dev_err(card->dev,
                        "architecture does not support 28bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (! chip) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        /* Set Vars */
        chip->type = chip_type;
        spin_lock_init(&chip->reg_lock);
@@ -2702,20 +2668,17 @@ static int snd_es1968_create(struct snd_card *card,
        chip->capture_streams = capt_streams;
 
        err = pci_request_regions(pci, "ESS Maestro");
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        chip->io_port = pci_resource_start(pci, 0);
-       if (request_irq(pci->irq, snd_es1968_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_es1968_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_es1968_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_es1968_free;
                
        /* Clear Maestro_map */
        for (i = 0; i < 32; i++)
@@ -2749,21 +2712,13 @@ static int snd_es1968_create(struct snd_card *card,
 
        snd_es1968_chip_init(chip);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_es1968_free(chip);
-               return err;
-       }
-
 #ifdef CONFIG_SND_ES1968_RADIO
        /* don't play with GPIOs on laptops */
        if (chip->pci->subsystem_vendor != 0x125d)
-               goto no_radio;
+               return 0;
        err = v4l2_device_register(&pci->dev, &chip->v4l2_dev);
-       if (err < 0) {
-               snd_es1968_free(chip);
+       if (err < 0)
                return err;
-       }
        chip->tea.v4l2_dev = &chip->v4l2_dev;
        chip->tea.private_data = chip;
        chip->tea.radio_nr = radio_nr;
@@ -2779,11 +2734,7 @@ static int snd_es1968_create(struct snd_card *card,
                        break;
                }
        }
-no_radio:
 #endif
-
-       *chip_ret = chip;
-
        return 0;
 }
 
@@ -2806,10 +2757,11 @@ static int snd_es1968_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
                 
        if (total_bufsize[dev] < 128)
                total_bufsize[dev] = 128;
@@ -2821,13 +2773,9 @@ static int snd_es1968_probe(struct pci_dev *pci,
                                pcm_substreams_c[dev],
                                pci_id->driver_data,
                                use_pm[dev],
-                               radio_nr[dev],
-                               &chip);
-       if (err < 0) {
-               snd_card_free(card);
+                               radio_nr[dev]);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        switch (chip->type) {
        case TYPE_MAESTRO2E:
@@ -2845,16 +2793,12 @@ static int snd_es1968_probe(struct pci_dev *pci,
        }
 
        err = snd_es1968_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_es1968_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        if (enable_mpu[dev] == 2) {
                /* check the deny list */
@@ -2897,25 +2841,17 @@ static int snd_es1968_probe(struct pci_dev *pci,
                card->shortname, chip->io_port, chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_es1968_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver es1968_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_es1968_ids,
        .probe = snd_es1968_probe,
-       .remove = snd_es1968_remove,
        .driver = {
                .pm = ES1968_PM_OPS,
        },
index ed9dae8..9c22ff1 100644 (file)
@@ -1028,22 +1028,6 @@ FM801_SINGLE(SNDRV_CTL_NAME_IEC958("Raw Data ",CAPTURE,SWITCH), FM801_I2S_MODE,
 FM801_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), FM801_GEN_CTRL, 2, 1, 0),
 };
 
-static void snd_fm801_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
-{
-       struct fm801 *chip = bus->private_data;
-       chip->ac97_bus = NULL;
-}
-
-static void snd_fm801_mixer_free_ac97(struct snd_ac97 *ac97)
-{
-       struct fm801 *chip = ac97->private_data;
-       if (ac97->num == 0) {
-               chip->ac97 = NULL;
-       } else {
-               chip->ac97_sec = NULL;
-       }
-}
-
 static int snd_fm801_mixer(struct fm801 *chip)
 {
        struct snd_ac97_template ac97;
@@ -1057,11 +1041,9 @@ static int snd_fm801_mixer(struct fm801 *chip)
        err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus);
        if (err < 0)
                return err;
-       chip->ac97_bus->private_free = snd_fm801_mixer_free_ac97_bus;
 
        memset(&ac97, 0, sizeof(ac97));
        ac97.private_data = chip;
-       ac97.private_free = snd_fm801_mixer_free_ac97;
        err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97);
        if (err < 0)
                return err;
@@ -1177,55 +1159,35 @@ static void snd_fm801_chip_init(struct fm801 *chip)
                     FM801_IRQ_PLAYBACK | FM801_IRQ_CAPTURE | FM801_IRQ_MPU);
 }
 
-static int snd_fm801_free(struct fm801 *chip)
+static void snd_fm801_free(struct snd_card *card)
 {
+       struct fm801 *chip = card->private_data;
        unsigned short cmdw;
 
-       if (chip->irq < 0)
-               goto __end_hw;
-
        /* interrupt setup - mask everything */
        cmdw = fm801_readw(chip, IRQ_MASK);
        cmdw |= 0x00c3;
        fm801_writew(chip, IRQ_MASK, cmdw);
 
-       devm_free_irq(chip->dev, chip->irq, chip);
-
-      __end_hw:
 #ifdef CONFIG_SND_FM801_TEA575X_BOOL
        if (!(chip->tea575x_tuner & TUNER_DISABLED)) {
                snd_tea575x_exit(&chip->tea);
                v4l2_device_unregister(&chip->v4l2_dev);
        }
 #endif
-       return 0;
-}
-
-static int snd_fm801_dev_free(struct snd_device *device)
-{
-       struct fm801 *chip = device->device_data;
-       return snd_fm801_free(chip);
 }
 
 static int snd_fm801_create(struct snd_card *card,
                            struct pci_dev *pci,
                            int tea575x_tuner,
-                           int radio_nr,
-                           struct fm801 **rchip)
+                           int radio_nr)
 {
-       struct fm801 *chip;
+       struct fm801 *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_fm801_dev_free,
-       };
 
-       *rchip = NULL;
        err = pcim_enable_device(pci);
        if (err < 0)
                return err;
-       chip = devm_kzalloc(&pci->dev, sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL)
-               return -ENOMEM;
        spin_lock_init(&chip->reg_lock);
        chip->card = card;
        chip->dev = &pci->dev;
@@ -1253,7 +1215,6 @@ static int snd_fm801_create(struct snd_card *card,
                if (devm_request_irq(&pci->dev, pci->irq, snd_fm801_interrupt,
                                IRQF_SHARED, KBUILD_MODNAME, chip)) {
                        dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-                       snd_fm801_free(chip);
                        return -EBUSY;
                }
                chip->irq = pci->irq;
@@ -1261,20 +1222,13 @@ static int snd_fm801_create(struct snd_card *card,
                pci_set_master(pci);
        }
 
+       card->private_free = snd_fm801_free;
        snd_fm801_chip_init(chip);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_fm801_free(chip);
-               return err;
-       }
-
 #ifdef CONFIG_SND_FM801_TEA575X_BOOL
        err = v4l2_device_register(&pci->dev, &chip->v4l2_dev);
-       if (err < 0) {
-               snd_fm801_free(chip);
+       if (err < 0)
                return err;
-       }
        chip->tea.v4l2_dev = &chip->v4l2_dev;
        chip->tea.radio_nr = radio_nr;
        chip->tea.private_data = chip;
@@ -1284,7 +1238,6 @@ static int snd_fm801_create(struct snd_card *card,
            (chip->tea575x_tuner & TUNER_TYPE_MASK) < 4) {
                if (snd_tea575x_init(&chip->tea, THIS_MODULE)) {
                        dev_err(card->dev, "TEA575x radio not found\n");
-                       snd_fm801_free(chip);
                        return -ENODEV;
                }
        } else if ((chip->tea575x_tuner & TUNER_TYPE_MASK) == 0) {
@@ -1312,8 +1265,6 @@ static int snd_fm801_create(struct snd_card *card,
                        sizeof(chip->tea.card));
        }
 #endif
-
-       *rchip = chip;
        return 0;
 }
 
@@ -1333,16 +1284,14 @@ static int snd_card_fm801_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
-       err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev], &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       chip = card->private_data;
+       err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev]);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        strcpy(card->driver, "FM801");
        strcpy(card->shortname, "ForteMedia FM801-");
@@ -1354,53 +1303,36 @@ static int snd_card_fm801_probe(struct pci_dev *pci,
                goto __fm801_tuner_only;
 
        err = snd_fm801_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_fm801_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801,
                                  chip->port + FM801_MPU401_DATA,
                                  MPU401_INFO_INTEGRATED |
                                  MPU401_INFO_IRQ_HOOK,
                                  -1, &chip->rmidi);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_opl3_create(card, chip->port + FM801_OPL3_BANK0,
                              chip->port + FM801_OPL3_BANK1,
                              OPL3_HW_OPL3_FM801, 1, &opl3);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
       __fm801_tuner_only:
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_card_fm801_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 #ifdef CONFIG_PM_SLEEP
 static const unsigned char saved_regs[] = {
        FM801_PCM_VOL, FM801_I2S_VOL, FM801_FM_VOL, FM801_REC_SRC,
@@ -1468,7 +1400,6 @@ static struct pci_driver fm801_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_fm801_ids,
        .probe = snd_card_fm801_probe,
-       .remove = snd_card_fm801_remove,
        .driver = {
                .pm = SND_FM801_PM_OPS,
        },
index c4360cd..ab9d274 100644 (file)
@@ -157,6 +157,16 @@ config SND_HDA_CODEC_CIRRUS
 comment "Set to Y if you want auto-loading the codec driver"
        depends on SND_HDA=y && SND_HDA_CODEC_CIRRUS=m
 
+config SND_HDA_CODEC_CS8409
+       tristate "Build Cirrus Logic HDA bridge support"
+       select SND_HDA_GENERIC
+       help
+         Say Y or M here to include Cirrus Logic HDA bridge support in
+         snd-hda-intel driver, such as CS8409.
+
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA=y && SND_HDA_CODEC_CS8409=m
+
 config SND_HDA_CODEC_CONEXANT
        tristate "Build Conexant HD-audio codec support"
        select SND_HDA_GENERIC
index b57432f..b8fa682 100644 (file)
@@ -20,6 +20,7 @@ snd-hda-codec-analog-objs :=  patch_analog.o
 snd-hda-codec-idt-objs :=      patch_sigmatel.o
 snd-hda-codec-si3054-objs :=   patch_si3054.o
 snd-hda-codec-cirrus-objs :=   patch_cirrus.o
+snd-hda-codec-cs8409-objs :=   patch_cs8409.o patch_cs8409-tables.o
 snd-hda-codec-ca0110-objs :=   patch_ca0110.o
 snd-hda-codec-ca0132-objs :=   patch_ca0132.o
 snd-hda-codec-conexant-objs := patch_conexant.o
@@ -37,6 +38,7 @@ obj-$(CONFIG_SND_HDA_CODEC_ANALOG) += snd-hda-codec-analog.o
 obj-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += snd-hda-codec-idt.o
 obj-$(CONFIG_SND_HDA_CODEC_SI3054) += snd-hda-codec-si3054.o
 obj-$(CONFIG_SND_HDA_CODEC_CIRRUS) += snd-hda-codec-cirrus.o
+obj-$(CONFIG_SND_HDA_CODEC_CS8409) += snd-hda-codec-cs8409.o
 obj-$(CONFIG_SND_HDA_CODEC_CA0110) += snd-hda-codec-ca0110.o
 obj-$(CONFIG_SND_HDA_CODEC_CA0132) += snd-hda-codec-ca0132.o
 obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o
index 1a001ec..4a85447 100644 (file)
@@ -971,6 +971,8 @@ EXPORT_SYMBOL_GPL(snd_hda_pick_pin_fixup);
  * When a special model string "nofixup" is given, also no fixup is applied.
  *
  * The function tries to find the matching model name at first, if given.
+ * If the model string contains the SSID alias, try to look up with the given
+ * alias ID.
  * If nothing matched, try to look up the PCI SSID.
  * If still nothing matched, try to look up the codec SSID.
  */
@@ -982,65 +984,77 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
        const struct snd_pci_quirk *q;
        int id = HDA_FIXUP_ID_NOT_SET;
        const char *name = NULL;
+       const char *type = NULL;
+       int vendor, device;
 
        if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
                return;
 
        /* when model=nofixup is given, don't pick up any fixups */
        if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
-               codec->fixup_list = NULL;
-               codec->fixup_name = NULL;
-               codec->fixup_id = HDA_FIXUP_ID_NO_FIXUP;
+               id = HDA_FIXUP_ID_NO_FIXUP;
+               fixlist = NULL;
                codec_dbg(codec, "%s: picked no fixup (nofixup specified)\n",
                          codec->core.chip_name);
-               return;
+               goto found;
        }
 
+       /* match with the model name string */
        if (codec->modelname && models) {
                while (models->name) {
                        if (!strcmp(codec->modelname, models->name)) {
-                               codec->fixup_id = models->id;
-                               codec->fixup_name = models->name;
-                               codec->fixup_list = fixlist;
+                               id = models->id;
+                               name = models->name;
                                codec_dbg(codec, "%s: picked fixup %s (model specified)\n",
                                          codec->core.chip_name, codec->fixup_name);
-                               return;
+                               goto found;
                        }
                        models++;
                }
        }
-       if (quirk) {
-               q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
+
+       if (!quirk)
+               return;
+
+       /* match with the SSID alias given by the model string "XXXX:YYYY" */
+       if (codec->modelname &&
+           sscanf(codec->modelname, "%04x:%04x", &vendor, &device) == 2) {
+               q = snd_pci_quirk_lookup_id(vendor, device, quirk);
                if (q) {
-                       id = q->value;
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-                       name = q->name;
-                       codec_dbg(codec, "%s: picked fixup %s (PCI SSID%s)\n",
-                                 codec->core.chip_name, name, q->subdevice_mask ? "" : " - vendor generic");
-#endif
+                       type = "alias SSID";
+                       goto found_device;
                }
        }
-       if (id < 0 && quirk) {
-               for (q = quirk; q->subvendor || q->subdevice; q++) {
-                       unsigned int vendorid =
-                               q->subdevice | (q->subvendor << 16);
-                       unsigned int mask = 0xffff0000 | q->subdevice_mask;
-                       if ((codec->core.subsystem_id & mask) == (vendorid & mask)) {
-                               id = q->value;
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-                               name = q->name;
-                               codec_dbg(codec, "%s: picked fixup %s (codec SSID)\n",
-                                         codec->core.chip_name, name);
-#endif
-                               break;
-                       }
-               }
+
+       /* match with the PCI SSID */
+       q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
+       if (q) {
+               type = "PCI SSID";
+               goto found_device;
        }
 
-       codec->fixup_id = id;
-       if (id >= 0) {
-               codec->fixup_list = fixlist;
-               codec->fixup_name = name;
+       /* match with the codec SSID */
+       q = snd_pci_quirk_lookup_id(codec->core.subsystem_id >> 16,
+                                   codec->core.subsystem_id & 0xffff,
+                                   quirk);
+       if (q) {
+               type = "codec SSID";
+               goto found_device;
        }
+
+       return; /* no matching */
+
+ found_device:
+       id = q->value;
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+       name = q->name;
+#endif
+       codec_dbg(codec, "%s: picked fixup %s for %s %04x:%04x\n",
+                 codec->core.chip_name, name ? name : "",
+                 type, q->subvendor, q->subdevice);
+ found:
+       codec->fixup_id = id;
+       codec->fixup_list = fixlist;
+       codec->fixup_name = name;
 }
 EXPORT_SYMBOL_GPL(snd_hda_pick_fixup);
index e8dee24..2523b23 100644 (file)
@@ -165,13 +165,7 @@ static int hda_codec_driver_remove(struct device *dev)
 
 static void hda_codec_driver_shutdown(struct device *dev)
 {
-       struct hda_codec *codec = dev_to_hda_codec(dev);
-
-       if (!pm_runtime_suspended(dev)) {
-               if (codec->patch_ops.reboot_notify)
-                       codec->patch_ops.reboot_notify(codec);
-               snd_hda_codec_display_power(codec, false);
-       }
+       snd_hda_codec_shutdown(dev_to_hda_codec(dev));
 }
 
 int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name,
index 7a717e1..a9ebefd 100644 (file)
@@ -2981,6 +2981,18 @@ const struct dev_pm_ops hda_codec_driver_pm = {
                           NULL)
 };
 
+/* suspend the codec at shutdown; called from driver's shutdown callback */
+void snd_hda_codec_shutdown(struct hda_codec *codec)
+{
+       struct hda_pcm *cpcm;
+
+       list_for_each_entry(cpcm, &codec->pcm_list_head, list)
+               snd_pcm_suspend_all(cpcm->pcm);
+
+       pm_runtime_force_suspend(hda_codec_dev(codec));
+       pm_runtime_disable(hda_codec_dev(codec));
+}
+
 /*
  * add standard channel maps if not specified
  */
index ca2f2ec..7cd4528 100644 (file)
@@ -669,16 +669,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        return err;
 }
 
-static int azx_pcm_mmap(struct snd_pcm_substream *substream,
-                       struct vm_area_struct *area)
-{
-       struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
-       struct azx *chip = apcm->chip;
-       if (chip->ops->pcm_mmap_prepare)
-               chip->ops->pcm_mmap_prepare(substream, area);
-       return snd_pcm_lib_default_mmap(substream, area);
-}
-
 static const struct snd_pcm_ops azx_pcm_ops = {
        .open = azx_pcm_open,
        .close = azx_pcm_close,
@@ -688,7 +678,6 @@ static const struct snd_pcm_ops azx_pcm_ops = {
        .trigger = azx_pcm_trigger,
        .pointer = azx_pcm_pointer,
        .get_time_info =  azx_get_time_info,
-       .mmap = azx_pcm_mmap,
 };
 
 static void azx_pcm_free(struct snd_pcm *pcm)
@@ -753,7 +742,7 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec,
        if (size > MAX_PREALLOC_SIZE)
                size = MAX_PREALLOC_SIZE;
        if (chip->uc_buffer)
-               type = SNDRV_DMA_TYPE_DEV_UC_SG;
+               type = SNDRV_DMA_TYPE_DEV_WC_SG;
        snd_pcm_set_managed_buffer_all(pcm, type, chip->card->dev,
                                       size, MAX_PREALLOC_SIZE);
        return 0;
index 68f9668..3062f87 100644 (file)
@@ -74,8 +74,6 @@ struct azx;
 struct hda_controller_ops {
        /* Disable msi if supported, PCI only */
        int (*disable_msi_reset_irq)(struct azx *);
-       void (*pcm_mmap_prepare)(struct snd_pcm_substream *substream,
-                                struct vm_area_struct *area);
        /* Check if current position is acceptable */
        int (*position_check)(struct azx *chip, struct azx_dev *azx_dev);
        /* enable/disable the link power */
@@ -141,7 +139,6 @@ struct azx {
        unsigned int snoop:1;
        unsigned int uc_buffer:1; /* non-cached pages for stream buffers */
        unsigned int align_buffer_size:1;
-       unsigned int region_requested:1;
        unsigned int disabled:1; /* disabled by vga_switcheroo */
        unsigned int pm_prepared:1;
 
index 481d8f8..3bf5e34 100644 (file)
@@ -6004,24 +6004,6 @@ void snd_hda_gen_free(struct hda_codec *codec)
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_free);
 
-/**
- * snd_hda_gen_reboot_notify - Make codec enter D3 before rebooting
- * @codec: the HDA codec
- *
- * This can be put as patch_ops reboot_notify function.
- */
-void snd_hda_gen_reboot_notify(struct hda_codec *codec)
-{
-       /* Make the codec enter D3 to avoid spurious noises from the internal
-        * speaker during (and after) reboot
-        */
-       snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
-       snd_hda_codec_write(codec, codec->core.afg, 0,
-                           AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-       msleep(10);
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_reboot_notify);
-
 #ifdef CONFIG_PM
 /**
  * snd_hda_gen_check_power_status - check the loopback power save state
@@ -6049,7 +6031,6 @@ static const struct hda_codec_ops generic_patch_ops = {
        .init = snd_hda_gen_init,
        .free = snd_hda_gen_free,
        .unsol_event = snd_hda_jack_unsol_event,
-       .reboot_notify = snd_hda_gen_reboot_notify,
 #ifdef CONFIG_PM
        .check_power_status = snd_hda_gen_check_power_status,
 #endif
index d4dd1b8..c43bd0f 100644 (file)
@@ -324,7 +324,6 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
                                  struct auto_pin_cfg *cfg);
 int snd_hda_gen_build_controls(struct hda_codec *codec);
 int snd_hda_gen_build_pcms(struct hda_codec *codec);
-void snd_hda_gen_reboot_notify(struct hda_codec *codec);
 
 /* standard jack event callbacks */
 void snd_hda_gen_hp_automute(struct hda_codec *codec,
index 0062c18..3aa432d 100644 (file)
@@ -883,11 +883,10 @@ static unsigned int azx_get_pos_skl(struct azx *chip, struct azx_dev *azx_dev)
        return azx_get_pos_posbuf(chip, azx_dev);
 }
 
-static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset)
+static void azx_shutdown_chip(struct azx *chip)
 {
        azx_stop_chip(chip);
-       if (!skip_link_reset)
-               azx_enter_link_reset(chip);
+       azx_enter_link_reset(chip);
        azx_clear_irq_pending(chip);
        display_power(chip, false);
 }
@@ -896,11 +895,6 @@ static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset)
 static DEFINE_MUTEX(card_list_lock);
 static LIST_HEAD(card_list);
 
-static void azx_shutdown_chip(struct azx *chip)
-{
-       __azx_shutdown_chip(chip, false);
-}
-
 static void azx_add_card_list(struct azx *chip)
 {
        struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
@@ -1373,18 +1367,11 @@ static void azx_free(struct azx *chip)
 
        if (bus->irq >= 0)
                free_irq(bus->irq, (void*)chip);
-       if (chip->msi)
-               pci_disable_msi(chip->pci);
-       iounmap(bus->remap_addr);
 
        azx_free_stream_pages(chip);
        azx_free_streams(chip);
        snd_hdac_bus_exit(bus);
 
-       if (chip->region_requested)
-               pci_release_regions(chip->pci);
-
-       pci_disable_device(chip->pci);
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
        release_firmware(chip->fw);
 #endif
@@ -1773,15 +1760,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
 
        *rchip = NULL;
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        hda = devm_kzalloc(&pci->dev, sizeof(*hda), GFP_KERNEL);
-       if (!hda) {
-               pci_disable_device(pci);
+       if (!hda)
                return -ENOMEM;
-       }
 
        chip = &hda->chip;
        mutex_init(&chip->open_mutex);
@@ -1817,14 +1802,12 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
                chip->bdl_pos_adj = bdl_pos_adj[dev];
 
        err = azx_bus_init(chip, model[dev]);
-       if (err < 0) {
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
 
        /* use the non-cached pages in non-snoop mode */
        if (!azx_snoop(chip))
-               azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_UC;
+               azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_WC;
 
        if (chip->driver_type == AZX_DRIVER_NVIDIA) {
                dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
@@ -1866,17 +1849,12 @@ static int azx_first_init(struct azx *chip)
        }
 #endif
 
-       err = pci_request_regions(pci, "ICH HD audio");
+       err = pcim_iomap_regions(pci, 1 << 0, "ICH HD audio");
        if (err < 0)
                return err;
-       chip->region_requested = 1;
 
        bus->addr = pci_resource_start(pci, 0);
-       bus->remap_addr = pci_ioremap_bar(pci, 0);
-       if (bus->remap_addr == NULL) {
-               dev_err(card->dev, "ioremap error\n");
-               return -ENXIO;
-       }
+       bus->remap_addr = pcim_iomap_table(pci)[0];
 
        if (chip->driver_type == AZX_DRIVER_SKL)
                snd_hdac_bus_parse_capabilities(bus);
@@ -2059,17 +2037,6 @@ static int disable_msi_reset_irq(struct azx *chip)
        return 0;
 }
 
-static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
-                            struct vm_area_struct *area)
-{
-#ifdef CONFIG_X86
-       struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
-       struct azx *chip = apcm->chip;
-       if (chip->uc_buffer)
-               area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
-#endif
-}
-
 /* Denylist for skipping the whole probe:
  * some HD-audio PCI entries are exposed without any codecs, and such devices
  * should be ignored from the beginning.
@@ -2083,7 +2050,6 @@ static const struct pci_device_id driver_denylist[] = {
 
 static const struct hda_controller_ops pci_hda_ops = {
        .disable_msi_reset_irq = disable_msi_reset_irq,
-       .pcm_mmap_prepare = pcm_mmap_prepare,
        .position_check = azx_position_check,
 };
 
@@ -2391,7 +2357,7 @@ static void azx_shutdown(struct pci_dev *pci)
                return;
        chip = card->private_data;
        if (chip && chip->running)
-               __azx_shutdown_chip(chip, true);
+               azx_shutdown_chip(chip);
 }
 
 /* PCI IDs */
index 8d2503e..ea8ab8b 100644 (file)
@@ -615,6 +615,8 @@ unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
                                             hda_nid_t nid,
                                             unsigned int power_state);
 
+void snd_hda_codec_shutdown(struct hda_codec *codec);
+
 /*
  * AMP control callbacks
  */
index 2132b2a..8afe600 100644 (file)
@@ -72,7 +72,7 @@ static int create_beep_ctls(struct hda_codec *codec)
 #define create_beep_ctls(codec)                0
 #endif
 
-
+#ifdef CONFIG_PM
 static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
                                hda_nid_t hp)
 {
@@ -112,16 +112,10 @@ static void ad198x_power_eapd(struct hda_codec *codec)
        }
 }
 
-static void ad198x_shutup(struct hda_codec *codec)
+static int ad198x_suspend(struct hda_codec *codec)
 {
        snd_hda_shutup_pins(codec);
        ad198x_power_eapd(codec);
-}
-
-#ifdef CONFIG_PM
-static int ad198x_suspend(struct hda_codec *codec)
-{
-       ad198x_shutup(codec);
        return 0;
 }
 #endif
@@ -168,7 +162,6 @@ static const struct hda_codec_ops ad198x_auto_patch_ops = {
        .check_power_status = snd_hda_gen_check_power_status,
        .suspend = ad198x_suspend,
 #endif
-       .reboot_notify = ad198x_shutup,
 };
 
 
index b66e7bd..2089337 100644 (file)
@@ -2270,7 +2270,7 @@ static int dspio_send_scp_message(struct hda_codec *codec,
                                  unsigned int *bytes_returned)
 {
        struct ca0132_spec *spec = codec->spec;
-       int status = -1;
+       int status;
        unsigned int scp_send_size = 0;
        unsigned int total_size;
        bool waiting_for_resp = false;
@@ -9682,11 +9682,6 @@ static void dbpro_free(struct hda_codec *codec)
        kfree(codec->spec);
 }
 
-static void ca0132_reboot_notify(struct hda_codec *codec)
-{
-       codec->patch_ops.free(codec);
-}
-
 #ifdef CONFIG_PM
 static int ca0132_suspend(struct hda_codec *codec)
 {
@@ -9706,7 +9701,6 @@ static const struct hda_codec_ops ca0132_patch_ops = {
 #ifdef CONFIG_PM
        .suspend = ca0132_suspend,
 #endif
-       .reboot_notify = ca0132_reboot_notify,
 };
 
 static const struct hda_codec_ops dbpro_patch_ops = {
index 8629e84..678fbca 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <sound/core.h>
-#include <linux/mutex.h>
 #include <linux/pci.h>
 #include <sound/tlv.h>
 #include <sound/hda_codec.h>
@@ -21,9 +20,6 @@
 /*
  */
 
-#define CS42L42_HP_CH     (2U)
-#define CS42L42_HS_MIC_CH (1U)
-
 struct cs_spec {
        struct hda_gen_spec gen;
 
@@ -42,18 +38,6 @@ struct cs_spec {
        /* for MBP SPDIF control */
        int (*spdif_sw_put)(struct snd_kcontrol *kcontrol,
                            struct snd_ctl_elem_value *ucontrol);
-
-       unsigned int cs42l42_hp_jack_in:1;
-       unsigned int cs42l42_mic_jack_in:1;
-       unsigned int cs42l42_volume_init:1;
-       char cs42l42_hp_volume[CS42L42_HP_CH];
-       char cs42l42_hs_mic_volume[CS42L42_HS_MIC_CH];
-
-       struct mutex cs8409_i2c_mux;
-
-       /* verb exec op override */
-       int (*exec_verb)(struct hdac_device *dev, unsigned int cmd,
-                                unsigned int flags, unsigned int *res);
 };
 
 /* available models with CS420x */
@@ -1239,1063 +1223,6 @@ static int patch_cs4213(struct hda_codec *codec)
        return err;
 }
 
-/* Cirrus Logic CS8409 HDA bridge with
- * companion codec CS42L42
- */
-#define CS8409_VENDOR_NID 0x47
-
-#define CS8409_CS42L42_HP_PIN_NID      0x24
-#define CS8409_CS42L42_SPK_PIN_NID     0x2c
-#define CS8409_CS42L42_AMIC_PIN_NID    0x34
-#define CS8409_CS42L42_DMIC_PIN_NID    0x44
-#define CS8409_CS42L42_DMIC_ADC_PIN_NID        0x22
-
-#define CS42L42_HSDET_AUTO_DONE        0x02
-#define CS42L42_HSTYPE_MASK            0x03
-
-#define CS42L42_JACK_INSERTED  0x0C
-#define CS42L42_JACK_REMOVED   0x00
-
-#define GPIO3_INT (1 << 3)
-#define GPIO4_INT (1 << 4)
-#define GPIO5_INT (1 << 5)
-
-#define CS42L42_I2C_ADDR       (0x48 << 1)
-
-#define CIR_I2C_ADDR   0x0059
-#define CIR_I2C_DATA   0x005A
-#define CIR_I2C_CTRL   0x005B
-#define CIR_I2C_STATUS 0x005C
-#define CIR_I2C_QWRITE 0x005D
-#define CIR_I2C_QREAD  0x005E
-
-#define CS8409_CS42L42_HP_VOL_REAL_MIN   (-63)
-#define CS8409_CS42L42_HP_VOL_REAL_MAX   (0)
-#define CS8409_CS42L42_AMIC_VOL_REAL_MIN (-97)
-#define CS8409_CS42L42_AMIC_VOL_REAL_MAX (12)
-#define CS8409_CS42L42_REG_HS_VOLUME_CHA (0x2301)
-#define CS8409_CS42L42_REG_HS_VOLUME_CHB (0x2303)
-#define CS8409_CS42L42_REG_AMIC_VOLUME   (0x1D03)
-
-struct cs8409_i2c_param {
-       unsigned int addr;
-       unsigned int reg;
-};
-
-struct cs8409_cir_param {
-       unsigned int nid;
-       unsigned int cir;
-       unsigned int coeff;
-};
-
-enum {
-       CS8409_BULLSEYE,
-       CS8409_WARLOCK,
-       CS8409_CYBORG,
-       CS8409_FIXUPS,
-};
-
-static void cs8409_cs42l42_fixups(struct hda_codec *codec,
-                                   const struct hda_fixup *fix, int action);
-static int cs8409_cs42l42_exec_verb(struct hdac_device *dev,
-               unsigned int cmd, unsigned int flags, unsigned int *res);
-
-/* Dell Inspiron models with cs8409/cs42l42 */
-static const struct hda_model_fixup cs8409_models[] = {
-       { .id = CS8409_BULLSEYE, .name = "bullseye" },
-       { .id = CS8409_WARLOCK, .name = "warlock" },
-       { .id = CS8409_CYBORG, .name = "cyborg" },
-       {}
-};
-
-/* Dell Inspiron platforms
- * with cs8409 bridge and cs42l42 codec
- */
-static const struct snd_pci_quirk cs8409_fixup_tbl[] = {
-       SND_PCI_QUIRK(0x1028, 0x0A11, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A12, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A23, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A24, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A25, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A29, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A2A, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A2B, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0AB0, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AB2, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AB1, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AB3, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AB4, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AB5, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AD9, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0ADA, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0ADB, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0ADC, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AF4, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AF5, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0A77, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A78, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A79, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A7A, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A7D, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A7E, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A7F, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A80, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0ADF, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AE0, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AE1, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AE2, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AE9, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AEA, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AEB, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AEC, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AED, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AEE, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AEF, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AF0, "Cyborg", CS8409_CYBORG),
-       {} /* terminator */
-};
-
-static const struct hda_verb cs8409_cs42l42_init_verbs[] = {
-       { 0x01, AC_VERB_SET_GPIO_WAKE_MASK, 0x0018 }, /* WAKE from GPIO 3,4 */
-       { 0x47, AC_VERB_SET_PROC_STATE, 0x0001 },     /* Enable VPW processing  */
-       { 0x47, AC_VERB_SET_COEF_INDEX, 0x0002 },     /* Configure GPIO 6,7 */
-       { 0x47, AC_VERB_SET_PROC_COEF,  0x0080 },     /* I2C mode */
-       { 0x47, AC_VERB_SET_COEF_INDEX, 0x005b },     /* Set I2C bus speed */
-       { 0x47, AC_VERB_SET_PROC_COEF,  0x0200 },     /* 100kHz I2C_STO = 2 */
-       {} /* terminator */
-};
-
-static const struct hda_pintbl cs8409_cs42l42_pincfgs[] = {
-       { 0x24, 0x042120f0 }, /* ASP-1-TX */
-       { 0x34, 0x04a12050 }, /* ASP-1-RX */
-       { 0x2c, 0x901000f0 }, /* ASP-2-TX */
-       { 0x44, 0x90a00090 }, /* DMIC-1 */
-       {} /* terminator */
-};
-
-static const struct hda_fixup cs8409_fixups[] = {
-       [CS8409_BULLSEYE] = {
-               .type = HDA_FIXUP_PINS,
-               .v.pins = cs8409_cs42l42_pincfgs,
-               .chained = true,
-               .chain_id = CS8409_FIXUPS,
-       },
-       [CS8409_WARLOCK] = {
-               .type = HDA_FIXUP_PINS,
-               .v.pins = cs8409_cs42l42_pincfgs,
-               .chained = true,
-               .chain_id = CS8409_FIXUPS,
-       },
-       [CS8409_CYBORG] = {
-               .type = HDA_FIXUP_PINS,
-               .v.pins = cs8409_cs42l42_pincfgs,
-               .chained = true,
-               .chain_id = CS8409_FIXUPS,
-       },
-       [CS8409_FIXUPS] = {
-               .type = HDA_FIXUP_FUNC,
-               .v.func = cs8409_cs42l42_fixups,
-       },
-};
-
-/* Vendor specific HW configuration for CS42L42 */
-static const struct cs8409_i2c_param cs42l42_init_reg_seq[] = {
-       { 0x1010, 0xB0 },
-       { 0x1D01, 0x00 },
-       { 0x1D02, 0x06 },
-       { 0x1D03, 0x00 },
-       { 0x1107, 0x01 },
-       { 0x1009, 0x02 },
-       { 0x1007, 0x03 },
-       { 0x1201, 0x00 },
-       { 0x1208, 0x13 },
-       { 0x1205, 0xFF },
-       { 0x1206, 0x00 },
-       { 0x1207, 0x20 },
-       { 0x1202, 0x0D },
-       { 0x2A02, 0x02 },
-       { 0x2A03, 0x00 },
-       { 0x2A04, 0x00 },
-       { 0x2A05, 0x02 },
-       { 0x2A06, 0x00 },
-       { 0x2A07, 0x20 },
-       { 0x2A08, 0x02 },
-       { 0x2A09, 0x00 },
-       { 0x2A0A, 0x80 },
-       { 0x2A0B, 0x02 },
-       { 0x2A0C, 0x00 },
-       { 0x2A0D, 0xA0 },
-       { 0x2A01, 0x0C },
-       { 0x2902, 0x01 },
-       { 0x2903, 0x02 },
-       { 0x2904, 0x00 },
-       { 0x2905, 0x00 },
-       { 0x2901, 0x01 },
-       { 0x1101, 0x0A },
-       { 0x1102, 0x84 },
-       { 0x2301, 0x00 },
-       { 0x2303, 0x00 },
-       { 0x2302, 0x3f },
-       { 0x2001, 0x03 },
-       { 0x1B75, 0xB6 },
-       { 0x1B73, 0xC2 },
-       { 0x1129, 0x01 },
-       { 0x1121, 0xF3 },
-       { 0x1103, 0x20 },
-       { 0x1105, 0x00 },
-       { 0x1112, 0xC0 },
-       { 0x1113, 0x80 },
-       { 0x1C03, 0xC0 },
-       { 0x1105, 0x00 },
-       { 0x1112, 0xC0 },
-       { 0x1101, 0x02 },
-       {} /* Terminator */
-};
-
-/* Vendor specific hw configuration for CS8409 */
-static const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[] = {
-       { 0x47, 0x00, 0xb008 }, /* +PLL1/2_EN, +I2C_EN */
-       { 0x47, 0x01, 0x0002 }, /* ASP1/2_EN=0, ASP1_STP=1 */
-       { 0x47, 0x02, 0x0a80 }, /* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
-       { 0x47, 0x19, 0x0800 }, /* ASP1.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
-       { 0x47, 0x1a, 0x0820 }, /* ASP1.A: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=32 */
-       { 0x47, 0x29, 0x0800 }, /* ASP2.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
-       { 0x47, 0x2a, 0x2800 }, /* ASP2.A: TX.RAP=1, TX.RSZ=24 bits, TX.RCS=0 */
-       { 0x47, 0x39, 0x0800 }, /* ASP1.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
-       { 0x47, 0x3a, 0x0800 }, /* ASP1.A: RX.RAP=0, RX.RSZ=24 bits, RX.RCS=0 */
-       { 0x47, 0x03, 0x8000 }, /* ASP1: LCHI = 00h */
-       { 0x47, 0x04, 0x28ff }, /* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
-       { 0x47, 0x05, 0x0062 }, /* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
-       { 0x47, 0x06, 0x801f }, /* ASP2: LCHI=1Fh */
-       { 0x47, 0x07, 0x283f }, /* ASP2: MC/SC_SRCSEL=PLL1, LCPR=3Fh */
-       { 0x47, 0x08, 0x805c }, /* ASP2: 5050=1, MCEN=0, FSD=010, SCPOL_IN/OUT=1, SCDIV=1:16 */
-       { 0x47, 0x09, 0x0023 }, /* DMIC1_MO=10b, DMIC1/2_SR=1 */
-       { 0x47, 0x0a, 0x0000 }, /* ASP1/2_BEEP=0 */
-       { 0x47, 0x01, 0x0062 }, /* ASP1/2_EN=1, ASP1_STP=1 */
-       { 0x47, 0x00, 0x9008 }, /* -PLL2_EN */
-       { 0x47, 0x68, 0x0000 }, /* TX2.A: pre-scale att.=0 dB */
-       { 0x47, 0x82, 0xfc03 }, /* ASP1/2_xxx_EN=1, ASP1/2_MCLK_EN=0, DMIC1_SCL_EN=1 */
-       { 0x47, 0xc0, 0x9999 }, /* test mode on */
-       { 0x47, 0xc5, 0x0000 }, /* GPIO hysteresis = 30 us */
-       { 0x47, 0xc0, 0x0000 }, /* test mode off */
-       {} /* Terminator */
-};
-
-static const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[] = {
-       { 0x47, 0x65, 0x4000 }, /* EQ_SEL=1, EQ1/2_EN=0 */
-       { 0x47, 0x64, 0x4000 }, /* +EQ_ACC */
-       { 0x47, 0x65, 0x4010 }, /* +EQ2_EN */
-       { 0x47, 0x63, 0x0647 }, /* EQ_DATA_HI=0x0647 */
-       { 0x47, 0x64, 0xc0c7 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=0, EQ_DATA_LO=0x67 */
-       { 0x47, 0x63, 0x0647 }, /* EQ_DATA_HI=0x0647 */
-       { 0x47, 0x64, 0xc1c7 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=1, EQ_DATA_LO=0x67 */
-       { 0x47, 0x63, 0xf370 }, /* EQ_DATA_HI=0xf370 */
-       { 0x47, 0x64, 0xc271 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=2, EQ_DATA_LO=0x71 */
-       { 0x47, 0x63, 0x1ef8 }, /* EQ_DATA_HI=0x1ef8 */
-       { 0x47, 0x64, 0xc348 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=3, EQ_DATA_LO=0x48 */
-       { 0x47, 0x63, 0xc110 }, /* EQ_DATA_HI=0xc110 */
-       { 0x47, 0x64, 0xc45a }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=4, EQ_DATA_LO=0x5a */
-       { 0x47, 0x63, 0x1f29 }, /* EQ_DATA_HI=0x1f29 */
-       { 0x47, 0x64, 0xc574 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=5, EQ_DATA_LO=0x74 */
-       { 0x47, 0x63, 0x1d7a }, /* EQ_DATA_HI=0x1d7a */
-       { 0x47, 0x64, 0xc653 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=6, EQ_DATA_LO=0x53 */
-       { 0x47, 0x63, 0xc38c }, /* EQ_DATA_HI=0xc38c */
-       { 0x47, 0x64, 0xc714 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=7, EQ_DATA_LO=0x14 */
-       { 0x47, 0x63, 0x1ca3 }, /* EQ_DATA_HI=0x1ca3 */
-       { 0x47, 0x64, 0xc8c7 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=8, EQ_DATA_LO=0xc7 */
-       { 0x47, 0x63, 0xc38c }, /* EQ_DATA_HI=0xc38c */
-       { 0x47, 0x64, 0xc914 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=9, EQ_DATA_LO=0x14 */
-       { 0x47, 0x64, 0x0000 }, /* -EQ_ACC, -EQ_WRT */
-       {} /* Terminator */
-};
-
-/**
- * cs8409_enable_i2c_clock - Enable I2C clocks
- * @codec: the codec instance
- * @enable: Enable or disable I2C clocks
- *
- * Enable or Disable I2C clocks.
- */
-static void cs8409_enable_i2c_clock(struct hda_codec *codec, unsigned int enable)
-{
-       unsigned int retval;
-       unsigned int newval;
-
-       retval = cs_vendor_coef_get(codec, 0x0);
-       newval = (enable) ? (retval | 0x8) : (retval & 0xfffffff7);
-       cs_vendor_coef_set(codec, 0x0, newval);
-}
-
-/**
- * cs8409_i2c_wait_complete - Wait for I2C transaction
- * @codec: the codec instance
- *
- * Wait for I2C transaction to complete.
- * Return -1 if transaction wait times out.
- */
-static int cs8409_i2c_wait_complete(struct hda_codec *codec)
-{
-       int repeat = 5;
-       unsigned int retval;
-
-       do {
-               retval = cs_vendor_coef_get(codec, CIR_I2C_STATUS);
-               if ((retval & 0x18) != 0x18) {
-                       usleep_range(2000, 4000);
-                       --repeat;
-               } else
-                       return 0;
-
-       } while (repeat);
-
-       return -1;
-}
-
-/**
- * cs8409_i2c_read - CS8409 I2C Read.
- * @codec: the codec instance
- * @i2c_address: I2C Address
- * @i2c_reg: Register to read
- * @paged: Is a paged transaction
- *
- * CS8409 I2C Read.
- * Returns negative on error, otherwise returns read value in bits 0-7.
- */
-static int cs8409_i2c_read(struct hda_codec *codec,
-               unsigned int i2c_address,
-               unsigned int i2c_reg,
-               unsigned int paged)
-{
-       unsigned int i2c_reg_data;
-       unsigned int read_data;
-
-       cs8409_enable_i2c_clock(codec, 1);
-       cs_vendor_coef_set(codec, CIR_I2C_ADDR, i2c_address);
-
-       if (paged) {
-               cs_vendor_coef_set(codec, CIR_I2C_QWRITE, i2c_reg >> 8);
-               if (cs8409_i2c_wait_complete(codec) < 0) {
-                       codec_err(codec,
-                               "%s() Paged Transaction Failed 0x%02x : 0x%04x\n",
-                               __func__, i2c_address, i2c_reg);
-                       return -EIO;
-               }
-       }
-
-       i2c_reg_data = (i2c_reg << 8) & 0x0ffff;
-       cs_vendor_coef_set(codec, CIR_I2C_QREAD, i2c_reg_data);
-       if (cs8409_i2c_wait_complete(codec) < 0) {
-               codec_err(codec, "%s() Transaction Failed 0x%02x : 0x%04x\n",
-                       __func__, i2c_address, i2c_reg);
-               return -EIO;
-       }
-
-       /* Register in bits 15-8 and the data in 7-0 */
-       read_data = cs_vendor_coef_get(codec, CIR_I2C_QREAD);
-
-       cs8409_enable_i2c_clock(codec, 0);
-
-       return read_data & 0x0ff;
-}
-
-/**
- * cs8409_i2c_write - CS8409 I2C Write.
- * @codec: the codec instance
- * @i2c_address: I2C Address
- * @i2c_reg: Register to write to
- * @i2c_data: Data to write
- * @paged: Is a paged transaction
- *
- * CS8409 I2C Write.
- * Returns negative on error, otherwise returns 0.
- */
-static int cs8409_i2c_write(struct hda_codec *codec,
-               unsigned int i2c_address, unsigned int i2c_reg,
-               unsigned int i2c_data,
-               unsigned int paged)
-{
-       unsigned int i2c_reg_data;
-
-       cs8409_enable_i2c_clock(codec, 1);
-       cs_vendor_coef_set(codec, CIR_I2C_ADDR, i2c_address);
-
-       if (paged) {
-               cs_vendor_coef_set(codec, CIR_I2C_QWRITE, i2c_reg >> 8);
-               if (cs8409_i2c_wait_complete(codec) < 0) {
-                       codec_err(codec,
-                               "%s() Paged Transaction Failed 0x%02x : 0x%04x\n",
-                               __func__, i2c_address, i2c_reg);
-                       return -EIO;
-               }
-       }
-
-       i2c_reg_data = ((i2c_reg << 8) & 0x0ff00) | (i2c_data & 0x0ff);
-       cs_vendor_coef_set(codec, CIR_I2C_QWRITE, i2c_reg_data);
-
-       if (cs8409_i2c_wait_complete(codec) < 0) {
-               codec_err(codec, "%s() Transaction Failed 0x%02x : 0x%04x\n",
-                       __func__, i2c_address, i2c_reg);
-               return -EIO;
-       }
-
-       cs8409_enable_i2c_clock(codec, 0);
-
-       return 0;
-}
-
-static int cs8409_cs42l42_volume_info(struct snd_kcontrol *kcontrol,
-                                 struct snd_ctl_elem_info *uinfo)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       u16 nid = get_amp_nid(kcontrol);
-       u8 chs = get_amp_channels(kcontrol);
-
-       codec_dbg(codec, "%s() nid: %d\n", __func__, nid);
-       switch (nid) {
-       case CS8409_CS42L42_HP_PIN_NID:
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-               uinfo->count = chs == 3 ? 2 : 1;
-               uinfo->value.integer.min = CS8409_CS42L42_HP_VOL_REAL_MIN;
-               uinfo->value.integer.max = CS8409_CS42L42_HP_VOL_REAL_MAX;
-               break;
-       case CS8409_CS42L42_AMIC_PIN_NID:
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-               uinfo->count = chs == 3 ? 2 : 1;
-               uinfo->value.integer.min = CS8409_CS42L42_AMIC_VOL_REAL_MIN;
-               uinfo->value.integer.max = CS8409_CS42L42_AMIC_VOL_REAL_MAX;
-               break;
-       default:
-               break;
-       }
-       return 0;
-}
-
-static void cs8409_cs42l42_update_volume(struct hda_codec *codec)
-{
-       struct cs_spec *spec = codec->spec;
-       int data;
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-       data = cs8409_i2c_read(codec, CS42L42_I2C_ADDR,
-                               CS8409_CS42L42_REG_HS_VOLUME_CHA, 1);
-       if (data >= 0)
-               spec->cs42l42_hp_volume[0] = -data;
-       else
-               spec->cs42l42_hp_volume[0] = CS8409_CS42L42_HP_VOL_REAL_MIN;
-       data = cs8409_i2c_read(codec, CS42L42_I2C_ADDR,
-                               CS8409_CS42L42_REG_HS_VOLUME_CHB, 1);
-       if (data >= 0)
-               spec->cs42l42_hp_volume[1] = -data;
-       else
-               spec->cs42l42_hp_volume[1] = CS8409_CS42L42_HP_VOL_REAL_MIN;
-       data = cs8409_i2c_read(codec, CS42L42_I2C_ADDR,
-                               CS8409_CS42L42_REG_AMIC_VOLUME, 1);
-       if (data >= 0)
-               spec->cs42l42_hs_mic_volume[0] = -data;
-       else
-               spec->cs42l42_hs_mic_volume[0] = CS8409_CS42L42_AMIC_VOL_REAL_MIN;
-       mutex_unlock(&spec->cs8409_i2c_mux);
-       spec->cs42l42_volume_init = 1;
-}
-
-static int cs8409_cs42l42_volume_get(struct snd_kcontrol *kcontrol,
-                                struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct cs_spec *spec = codec->spec;
-       hda_nid_t nid = get_amp_nid(kcontrol);
-       int chs = get_amp_channels(kcontrol);
-       long *valp = ucontrol->value.integer.value;
-
-       if (!spec->cs42l42_volume_init) {
-               snd_hda_power_up(codec);
-               cs8409_cs42l42_update_volume(codec);
-               snd_hda_power_down(codec);
-       }
-       switch (nid) {
-       case CS8409_CS42L42_HP_PIN_NID:
-               if (chs & BIT(0))
-                       *valp++ = spec->cs42l42_hp_volume[0];
-               if (chs & BIT(1))
-                       *valp++ = spec->cs42l42_hp_volume[1];
-               break;
-       case CS8409_CS42L42_AMIC_PIN_NID:
-               if (chs & BIT(0))
-                       *valp++ = spec->cs42l42_hs_mic_volume[0];
-               break;
-       default:
-               break;
-       }
-       return 0;
-}
-
-static int cs8409_cs42l42_volume_put(struct snd_kcontrol *kcontrol,
-                                struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct cs_spec *spec = codec->spec;
-       hda_nid_t nid = get_amp_nid(kcontrol);
-       int chs = get_amp_channels(kcontrol);
-       long *valp = ucontrol->value.integer.value;
-       int change = 0;
-       char vol;
-
-       snd_hda_power_up(codec);
-       switch (nid) {
-       case CS8409_CS42L42_HP_PIN_NID:
-               mutex_lock(&spec->cs8409_i2c_mux);
-               if (chs & BIT(0)) {
-                       vol = -(*valp);
-                       change = cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
-                               CS8409_CS42L42_REG_HS_VOLUME_CHA, vol, 1);
-                       valp++;
-               }
-               if (chs & BIT(1)) {
-                       vol = -(*valp);
-                       change |= cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
-                               CS8409_CS42L42_REG_HS_VOLUME_CHB, vol, 1);
-               }
-               mutex_unlock(&spec->cs8409_i2c_mux);
-               break;
-       case CS8409_CS42L42_AMIC_PIN_NID:
-               mutex_lock(&spec->cs8409_i2c_mux);
-               if (chs & BIT(0)) {
-                       change = cs8409_i2c_write(
-                               codec, CS42L42_I2C_ADDR,
-                               CS8409_CS42L42_REG_AMIC_VOLUME, (char)*valp, 1);
-                       valp++;
-               }
-               mutex_unlock(&spec->cs8409_i2c_mux);
-               break;
-       default:
-               break;
-       }
-       cs8409_cs42l42_update_volume(codec);
-       snd_hda_power_down(codec);
-       return change;
-}
-
-static const DECLARE_TLV_DB_SCALE(
-       cs8409_cs42l42_hp_db_scale,
-       CS8409_CS42L42_HP_VOL_REAL_MIN * 100, 100, 1);
-
-static const DECLARE_TLV_DB_SCALE(
-       cs8409_cs42l42_amic_db_scale,
-       CS8409_CS42L42_AMIC_VOL_REAL_MIN * 100, 100, 1);
-
-static const struct snd_kcontrol_new cs8409_cs42l42_hp_volume_mixer = {
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .index = 0,
-       .name = "Headphone Playback Volume",
-       .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
-       .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE
-                        | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
-       .info = cs8409_cs42l42_volume_info,
-       .get = cs8409_cs42l42_volume_get,
-       .put = cs8409_cs42l42_volume_put,
-       .tlv = { .p = cs8409_cs42l42_hp_db_scale },
-       .private_value = HDA_COMPOSE_AMP_VAL(
-               CS8409_CS42L42_HP_PIN_NID, 3, 0, HDA_OUTPUT)
-               | HDA_AMP_VAL_MIN_MUTE
-};
-
-static const struct snd_kcontrol_new cs8409_cs42l42_amic_volume_mixer = {
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .index = 0,
-       .name = "Mic Capture Volume",
-       .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
-       .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE
-                        | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
-       .info = cs8409_cs42l42_volume_info,
-       .get = cs8409_cs42l42_volume_get,
-       .put = cs8409_cs42l42_volume_put,
-       .tlv = { .p = cs8409_cs42l42_amic_db_scale },
-       .private_value = HDA_COMPOSE_AMP_VAL(
-               CS8409_CS42L42_AMIC_PIN_NID, 1, 0, HDA_INPUT)
-               | HDA_AMP_VAL_MIN_MUTE
-};
-
-/* Assert/release RTS# line to CS42L42 */
-static void cs8409_cs42l42_reset(struct hda_codec *codec)
-{
-       struct cs_spec *spec = codec->spec;
-
-       /* Assert RTS# line */
-       snd_hda_codec_write(codec,
-                       codec->core.afg, 0, AC_VERB_SET_GPIO_DATA, 0);
-       /* wait ~10ms */
-       usleep_range(10000, 15000);
-       /* Release RTS# line */
-       snd_hda_codec_write(codec,
-                       codec->core.afg, 0, AC_VERB_SET_GPIO_DATA, GPIO5_INT);
-       /* wait ~10ms */
-       usleep_range(10000, 15000);
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-
-       /* Clear interrupts, by reading interrupt status registers */
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308, 1);
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1309, 1);
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130A, 1);
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130F, 1);
-
-       mutex_unlock(&spec->cs8409_i2c_mux);
-
-}
-
-/* Configure CS42L42 slave codec for jack autodetect */
-static void cs8409_cs42l42_enable_jack_detect(struct hda_codec *codec)
-{
-       struct cs_spec *spec = codec->spec;
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-
-       /* Set TIP_SENSE_EN for analog front-end of tip sense. */
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b70, 0x0020, 1);
-       /* Clear WAKE# */
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b71, 0x0001, 1);
-       /* Wait ~2.5ms */
-       usleep_range(2500, 3000);
-       /* Set mode WAKE# output follows the combination logic directly */
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b71, 0x0020, 1);
-       /* Clear interrupts status */
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f, 1);
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1b7b, 1);
-       /* Enable interrupt */
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0x03, 1);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b79, 0x00, 1);
-
-       mutex_unlock(&spec->cs8409_i2c_mux);
-}
-
-/* Enable and run CS42L42 slave codec jack auto detect */
-static void cs8409_cs42l42_run_jack_detect(struct hda_codec *codec)
-{
-       struct cs_spec *spec = codec->spec;
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-
-       /* Clear interrupts */
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308, 1);
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1b77, 1);
-
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1102, 0x87, 1);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1f06, 0x86, 1);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b74, 0x07, 1);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x131b, 0x01, 1);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1120, 0x80, 1);
-       /* Wait ~110ms*/
-       usleep_range(110000, 200000);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x111f, 0x77, 1);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1120, 0xc0, 1);
-       /* Wait ~10ms */
-       usleep_range(10000, 25000);
-
-       mutex_unlock(&spec->cs8409_i2c_mux);
-
-}
-
-static void cs8409_cs42l42_reg_setup(struct hda_codec *codec)
-{
-       const struct cs8409_i2c_param *seq = cs42l42_init_reg_seq;
-       struct cs_spec *spec = codec->spec;
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-
-       for (; seq->addr; seq++)
-               cs8409_i2c_write(codec, CS42L42_I2C_ADDR, seq->addr, seq->reg, 1);
-
-       mutex_unlock(&spec->cs8409_i2c_mux);
-
-}
-
-/*
- * In the case of CS8409 we do not have unsolicited events from NID's 0x24
- * and 0x34 where hs mic and hp are connected. Companion codec CS42L42 will
- * generate interrupt via gpio 4 to notify jack events. We have to overwrite
- * generic snd_hda_jack_unsol_event(), read CS42L42 jack detect status registers
- * and then notify status via generic snd_hda_jack_unsol_event() call.
- */
-static void cs8409_jack_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-       struct cs_spec *spec = codec->spec;
-       int status_changed = 0;
-       int reg_cdc_status;
-       int reg_hs_status;
-       int reg_ts_status;
-       int type;
-       struct hda_jack_tbl *jk;
-
-       /* jack_unsol_event() will be called every time gpio line changing state.
-        * In this case gpio4 line goes up as a result of reading interrupt status
-        * registers in previous cs8409_jack_unsol_event() call.
-        * We don't need to handle this event, ignoring...
-        */
-       if ((res & (1 << 4)))
-               return;
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-
-       /* Read jack detect status registers */
-       reg_cdc_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308, 1);
-       reg_hs_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1124, 1);
-       reg_ts_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f, 1);
-
-       /* Clear interrupts, by reading interrupt status registers */
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1b7b, 1);
-
-       mutex_unlock(&spec->cs8409_i2c_mux);
-
-       /* If status values are < 0, read error has occurred. */
-       if (reg_cdc_status < 0 || reg_hs_status < 0 || reg_ts_status < 0)
-               return;
-
-       /* HSDET_AUTO_DONE */
-       if (reg_cdc_status & CS42L42_HSDET_AUTO_DONE) {
-
-               type = ((reg_hs_status & CS42L42_HSTYPE_MASK) + 1);
-               /* CS42L42 reports optical jack as type 4
-                * We don't handle optical jack
-                */
-               if (type != 4) {
-                       if (!spec->cs42l42_hp_jack_in) {
-                               status_changed = 1;
-                               spec->cs42l42_hp_jack_in = 1;
-                       }
-                       /* type = 3 has no mic */
-                       if ((!spec->cs42l42_mic_jack_in) && (type != 3)) {
-                               status_changed = 1;
-                               spec->cs42l42_mic_jack_in = 1;
-                       }
-               } else {
-                       if (spec->cs42l42_hp_jack_in || spec->cs42l42_mic_jack_in) {
-                               status_changed = 1;
-                               spec->cs42l42_hp_jack_in = 0;
-                               spec->cs42l42_mic_jack_in = 0;
-                       }
-               }
-
-       } else {
-               /* TIP_SENSE INSERT/REMOVE */
-               switch (reg_ts_status) {
-               case CS42L42_JACK_INSERTED:
-                       cs8409_cs42l42_run_jack_detect(codec);
-                       break;
-
-               case CS42L42_JACK_REMOVED:
-                       if (spec->cs42l42_hp_jack_in || spec->cs42l42_mic_jack_in) {
-                               status_changed = 1;
-                               spec->cs42l42_hp_jack_in = 0;
-                               spec->cs42l42_mic_jack_in = 0;
-                       }
-                       break;
-
-               default:
-                       /* jack in transition */
-                       status_changed = 0;
-                       break;
-               }
-       }
-
-       if (status_changed) {
-
-               snd_hda_set_pin_ctl(codec, CS8409_CS42L42_SPK_PIN_NID,
-                               spec->cs42l42_hp_jack_in ? 0 : PIN_OUT);
-
-               /* Report jack*/
-               jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_HP_PIN_NID, 0);
-               if (jk) {
-                       snd_hda_jack_unsol_event(codec,
-                               (jk->tag << AC_UNSOL_RES_TAG_SHIFT) & AC_UNSOL_RES_TAG);
-               }
-               /* Report jack*/
-               jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_AMIC_PIN_NID, 0);
-               if (jk) {
-                       snd_hda_jack_unsol_event(codec,
-                               (jk->tag << AC_UNSOL_RES_TAG_SHIFT) & AC_UNSOL_RES_TAG);
-               }
-       }
-}
-
-#ifdef CONFIG_PM
-/* Manage PDREF, when transition to D3hot */
-static int cs8409_suspend(struct hda_codec *codec)
-{
-       struct cs_spec *spec = codec->spec;
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-       /* Power down CS42L42 ASP/EQ/MIX/HP */
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1101, 0xfe, 1);
-       mutex_unlock(&spec->cs8409_i2c_mux);
-       /* Assert CS42L42 RTS# line */
-       snd_hda_codec_write(codec,
-                       codec->core.afg, 0, AC_VERB_SET_GPIO_DATA, 0);
-
-       snd_hda_shutup_pins(codec);
-
-       return 0;
-}
-#endif
-
-/* Enable/Disable Unsolicited Response for gpio(s) 3,4 */
-static void cs8409_enable_ur(struct hda_codec *codec, int flag)
-{
-       /* GPIO4 INT# and GPIO3 WAKE# */
-       snd_hda_codec_write(codec, codec->core.afg,
-                       0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK,
-                       flag ? (GPIO3_INT | GPIO4_INT) : 0);
-
-       snd_hda_codec_write(codec, codec->core.afg,
-                       0, AC_VERB_SET_UNSOLICITED_ENABLE,
-                       flag ? AC_UNSOL_ENABLED : 0);
-
-}
-
-/* Vendor specific HW configuration
- * PLL, ASP, I2C, SPI, GPIOs, DMIC etc...
- */
-static void cs8409_cs42l42_hw_init(struct hda_codec *codec)
-{
-       const struct cs8409_cir_param *seq = cs8409_cs42l42_hw_cfg;
-       const struct cs8409_cir_param *seq_bullseye = cs8409_cs42l42_bullseye_atn;
-       struct cs_spec *spec = codec->spec;
-
-       if (spec->gpio_mask) {
-               snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
-                                   spec->gpio_mask);
-               snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
-                                   spec->gpio_dir);
-               snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
-                                   spec->gpio_data);
-       }
-
-       for (; seq->nid; seq++)
-               cs_vendor_coef_set(codec, seq->cir, seq->coeff);
-
-       if (codec->fixup_id == CS8409_BULLSEYE)
-               for (; seq_bullseye->nid; seq_bullseye++)
-                       cs_vendor_coef_set(codec, seq_bullseye->cir, seq_bullseye->coeff);
-
-       /* Disable Unsolicited Response during boot */
-       cs8409_enable_ur(codec, 0);
-
-       /* Reset CS42L42 */
-       cs8409_cs42l42_reset(codec);
-
-       /* Initialise CS42L42 companion codec */
-       cs8409_cs42l42_reg_setup(codec);
-
-       if (codec->fixup_id == CS8409_WARLOCK ||
-                       codec->fixup_id == CS8409_CYBORG) {
-               /* FULL_SCALE_VOL = 0 for Warlock / Cyborg */
-               mutex_lock(&spec->cs8409_i2c_mux);
-               cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x2001, 0x01, 1);
-               mutex_unlock(&spec->cs8409_i2c_mux);
-               /* DMIC1_MO=00b, DMIC1/2_SR=1 */
-               cs_vendor_coef_set(codec, 0x09, 0x0003);
-       }
-
-       /* Restore Volumes after Resume */
-       if (spec->cs42l42_volume_init) {
-               mutex_lock(&spec->cs8409_i2c_mux);
-               cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
-                                       CS8409_CS42L42_REG_HS_VOLUME_CHA,
-                                       -spec->cs42l42_hp_volume[0],
-                                       1);
-               cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
-                                       CS8409_CS42L42_REG_HS_VOLUME_CHB,
-                                       -spec->cs42l42_hp_volume[1],
-                                       1);
-               cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
-                                       CS8409_CS42L42_REG_AMIC_VOLUME,
-                                       spec->cs42l42_hs_mic_volume[0],
-                                       1);
-               mutex_unlock(&spec->cs8409_i2c_mux);
-       }
-
-       cs8409_cs42l42_update_volume(codec);
-
-       cs8409_cs42l42_enable_jack_detect(codec);
-
-       /* Enable Unsolicited Response */
-       cs8409_enable_ur(codec, 1);
-}
-
-static int cs8409_cs42l42_init(struct hda_codec *codec)
-{
-       int ret = snd_hda_gen_init(codec);
-
-       if (!ret)
-               snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
-
-       return ret;
-}
-
-static const struct hda_codec_ops cs8409_cs42l42_patch_ops = {
-       .build_controls = cs_build_controls,
-       .build_pcms = snd_hda_gen_build_pcms,
-       .init = cs8409_cs42l42_init,
-       .free = cs_free,
-       .unsol_event = cs8409_jack_unsol_event,
-#ifdef CONFIG_PM
-       .suspend = cs8409_suspend,
-#endif
-};
-
-static void cs8409_cs42l42_fixups(struct hda_codec *codec,
-                                   const struct hda_fixup *fix, int action)
-{
-       struct cs_spec *spec = codec->spec;
-       int caps;
-
-       switch (action) {
-       case HDA_FIXUP_ACT_PRE_PROBE:
-               snd_hda_add_verbs(codec, cs8409_cs42l42_init_verbs);
-               /* verb exec op override */
-               spec->exec_verb = codec->core.exec_verb;
-               codec->core.exec_verb = cs8409_cs42l42_exec_verb;
-
-               mutex_init(&spec->cs8409_i2c_mux);
-
-               codec->patch_ops = cs8409_cs42l42_patch_ops;
-
-               spec->gen.suppress_auto_mute = 1;
-               spec->gen.no_primary_hp = 1;
-               spec->gen.suppress_vmaster = 1;
-
-               /* GPIO 5 out, 3,4 in */
-               spec->gpio_dir = GPIO5_INT;
-               spec->gpio_data = 0;
-               spec->gpio_mask = 0x03f;
-
-               spec->cs42l42_hp_jack_in = 0;
-               spec->cs42l42_mic_jack_in = 0;
-
-               /* Basic initial sequence for specific hw configuration */
-               snd_hda_sequence_write(codec, cs8409_cs42l42_init_verbs);
-
-               /* CS8409 is simple HDA bridge and intended to be used with a remote
-                * companion codec. Most of input/output PIN(s) have only basic
-                * capabilities. NID(s) 0x24 and 0x34 have only OUTC and INC
-                * capabilities and no presence detect capable (PDC) and call to
-                * snd_hda_gen_build_controls() will mark them as non detectable
-                * phantom jacks. However, in this configuration companion codec
-                * CS42L42 is connected to these pins and it has jack detect
-                * capabilities. We have to override pin capabilities,
-                * otherwise they will not be created as input devices.
-                */
-               caps = snd_hdac_read_parm(&codec->core, CS8409_CS42L42_HP_PIN_NID,
-                               AC_PAR_PIN_CAP);
-               if (caps >= 0)
-                       snd_hdac_override_parm(&codec->core,
-                               CS8409_CS42L42_HP_PIN_NID, AC_PAR_PIN_CAP,
-                               (caps | (AC_PINCAP_IMP_SENSE | AC_PINCAP_PRES_DETECT)));
-
-               caps = snd_hdac_read_parm(&codec->core, CS8409_CS42L42_AMIC_PIN_NID,
-                               AC_PAR_PIN_CAP);
-               if (caps >= 0)
-                       snd_hdac_override_parm(&codec->core,
-                               CS8409_CS42L42_AMIC_PIN_NID, AC_PAR_PIN_CAP,
-                               (caps | (AC_PINCAP_IMP_SENSE | AC_PINCAP_PRES_DETECT)));
-
-               snd_hda_override_wcaps(codec, CS8409_CS42L42_HP_PIN_NID,
-                       (get_wcaps(codec, CS8409_CS42L42_HP_PIN_NID) | AC_WCAP_UNSOL_CAP));
-
-               snd_hda_override_wcaps(codec, CS8409_CS42L42_AMIC_PIN_NID,
-                       (get_wcaps(codec, CS8409_CS42L42_AMIC_PIN_NID) | AC_WCAP_UNSOL_CAP));
-               break;
-       case HDA_FIXUP_ACT_PROBE:
-
-               /* Set initial DMIC volume to -26 dB */
-               snd_hda_codec_amp_init_stereo(codec, CS8409_CS42L42_DMIC_ADC_PIN_NID,
-                               HDA_INPUT, 0, 0xff, 0x19);
-               snd_hda_gen_add_kctl(&spec->gen,
-                       NULL, &cs8409_cs42l42_hp_volume_mixer);
-               snd_hda_gen_add_kctl(&spec->gen,
-                       NULL, &cs8409_cs42l42_amic_volume_mixer);
-               cs8409_cs42l42_hw_init(codec);
-               snd_hda_codec_set_name(codec, "CS8409/CS42L42");
-               break;
-       case HDA_FIXUP_ACT_INIT:
-               cs8409_cs42l42_hw_init(codec);
-               fallthrough;
-       case HDA_FIXUP_ACT_BUILD:
-               /* Run jack auto detect first time on boot
-                * after controls have been added, to check if jack has
-                * been already plugged in.
-                * Run immediately after init.
-                */
-               cs8409_cs42l42_run_jack_detect(codec);
-               usleep_range(100000, 150000);
-               break;
-       default:
-               break;
-       }
-}
-
-static int cs8409_cs42l42_exec_verb(struct hdac_device *dev,
-               unsigned int cmd, unsigned int flags, unsigned int *res)
-{
-       struct hda_codec *codec = container_of(dev, struct hda_codec, core);
-       struct cs_spec *spec = codec->spec;
-
-       unsigned int nid = ((cmd >> 20) & 0x07f);
-       unsigned int verb = ((cmd >> 8) & 0x0fff);
-
-       /* CS8409 pins have no AC_PINSENSE_PRESENCE
-        * capabilities. We have to intercept 2 calls for pins 0x24 and 0x34
-        * and return correct pin sense values for read_pin_sense() call from
-        * hda_jack based on CS42L42 jack detect status.
-        */
-       switch (nid) {
-       case CS8409_CS42L42_HP_PIN_NID:
-               if (verb == AC_VERB_GET_PIN_SENSE) {
-                       *res = (spec->cs42l42_hp_jack_in) ? AC_PINSENSE_PRESENCE : 0;
-                       return 0;
-               }
-               break;
-
-       case CS8409_CS42L42_AMIC_PIN_NID:
-               if (verb == AC_VERB_GET_PIN_SENSE) {
-                       *res = (spec->cs42l42_mic_jack_in) ? AC_PINSENSE_PRESENCE : 0;
-                       return 0;
-               }
-               break;
-
-       default:
-               break;
-       }
-
-       return spec->exec_verb(dev, cmd, flags, res);
-}
-
-static int patch_cs8409(struct hda_codec *codec)
-{
-       int err;
-
-       if (!cs_alloc_spec(codec, CS8409_VENDOR_NID))
-               return -ENOMEM;
-
-       snd_hda_pick_fixup(codec,
-                       cs8409_models, cs8409_fixup_tbl, cs8409_fixups);
-
-       codec_dbg(codec, "Picked ID=%d, VID=%08x, DEV=%08x\n",
-                       codec->fixup_id,
-                       codec->bus->pci->subsystem_vendor,
-                       codec->bus->pci->subsystem_device);
-
-       snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
-       err = cs_parse_auto_config(codec);
-       if (err < 0) {
-               cs_free(codec);
-               return err;
-       }
-
-       snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-       return 0;
-}
-
 /*
  * patch entries
  */
@@ -2305,7 +1232,6 @@ static const struct hda_device_id snd_hda_id_cirrus[] = {
        HDA_CODEC_ENTRY(0x10134208, "CS4208", patch_cs4208),
        HDA_CODEC_ENTRY(0x10134210, "CS4210", patch_cs4210),
        HDA_CODEC_ENTRY(0x10134213, "CS4213", patch_cs4213),
-       HDA_CODEC_ENTRY(0x10138409, "CS8409", patch_cs8409),
        {} /* terminator */
 };
 MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cirrus);
index d111258..0515137 100644 (file)
@@ -177,30 +177,37 @@ static int cx_auto_init(struct hda_codec *codec)
        return 0;
 }
 
-static void cx_auto_reboot_notify(struct hda_codec *codec)
+static void cx_auto_shutdown(struct hda_codec *codec)
 {
        struct conexant_spec *spec = codec->spec;
 
        /* Turn the problematic codec into D3 to avoid spurious noises
           from the internal speaker during (and after) reboot */
        cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false);
-       snd_hda_gen_reboot_notify(codec);
 }
 
 static void cx_auto_free(struct hda_codec *codec)
 {
-       cx_auto_reboot_notify(codec);
+       cx_auto_shutdown(codec);
        snd_hda_gen_free(codec);
 }
 
+#ifdef CONFIG_PM
+static int cx_auto_suspend(struct hda_codec *codec)
+{
+       cx_auto_shutdown(codec);
+       return 0;
+}
+#endif
+
 static const struct hda_codec_ops cx_auto_patch_ops = {
        .build_controls = snd_hda_gen_build_controls,
        .build_pcms = snd_hda_gen_build_pcms,
        .init = cx_auto_init,
-       .reboot_notify = cx_auto_reboot_notify,
        .free = cx_auto_free,
        .unsol_event = snd_hda_jack_unsol_event,
 #ifdef CONFIG_PM
+       .suspend = cx_auto_suspend,
        .check_power_status = snd_hda_gen_check_power_status,
 #endif
 };
diff --git a/sound/pci/hda/patch_cs8409-tables.c b/sound/pci/hda/patch_cs8409-tables.c
new file mode 100644 (file)
index 0000000..0fb0a42
--- /dev/null
@@ -0,0 +1,560 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * patch_cs8409-tables.c  --  HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
+ *
+ * Copyright (C) 2021 Cirrus Logic, Inc. and
+ *                    Cirrus Logic International Semiconductor Ltd.
+ *
+ * Author: Lucas Tanure <tanureal@opensource.cirrus.com>
+ */
+
+#include "patch_cs8409.h"
+
+/******************************************************************************
+ *                          CS42L42 Specific Data
+ *
+ ******************************************************************************/
+
+static const DECLARE_TLV_DB_SCALE(cs42l42_dac_db_scale, CS42L42_HP_VOL_REAL_MIN * 100, 100, 1);
+
+static const DECLARE_TLV_DB_SCALE(cs42l42_adc_db_scale, CS42L42_AMIC_VOL_REAL_MIN * 100, 100, 1);
+
+const struct snd_kcontrol_new cs42l42_dac_volume_mixer = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .index = 0,
+       .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
+       .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+       .info = cs42l42_volume_info,
+       .get = cs42l42_volume_get,
+       .put = cs42l42_volume_put,
+       .tlv = { .p = cs42l42_dac_db_scale },
+       .private_value = HDA_COMPOSE_AMP_VAL_OFS(CS8409_PIN_ASP1_TRANSMITTER_A, 3, CS8409_CODEC0,
+                        HDA_OUTPUT, CS42L42_VOL_DAC) | HDA_AMP_VAL_MIN_MUTE
+};
+
+const struct snd_kcontrol_new cs42l42_adc_volume_mixer = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .index = 0,
+       .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
+       .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+       .info = cs42l42_volume_info,
+       .get = cs42l42_volume_get,
+       .put = cs42l42_volume_put,
+       .tlv = { .p = cs42l42_adc_db_scale },
+       .private_value = HDA_COMPOSE_AMP_VAL_OFS(CS8409_PIN_ASP1_RECEIVER_A, 1, CS8409_CODEC0,
+                        HDA_INPUT, CS42L42_VOL_ADC) | HDA_AMP_VAL_MIN_MUTE
+};
+
+const struct hda_pcm_stream cs42l42_48k_pcm_analog_playback = {
+       .rates = SNDRV_PCM_RATE_48000, /* fixed rate */
+};
+
+const struct hda_pcm_stream cs42l42_48k_pcm_analog_capture = {
+       .rates = SNDRV_PCM_RATE_48000, /* fixed rate */
+};
+
+/******************************************************************************
+ *                   BULLSEYE / WARLOCK / CYBORG Specific Arrays
+ *                               CS8409/CS42L42
+ ******************************************************************************/
+
+const struct hda_verb cs8409_cs42l42_init_verbs[] = {
+       { CS8409_PIN_AFG, AC_VERB_SET_GPIO_WAKE_MASK, 0x0018 },         /* WAKE from GPIO 3,4 */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_STATE, 0x0001 },   /* Enable VPW processing */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x0002 },   /* Configure GPIO 6,7 */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF,  0x0080 },   /* I2C mode */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x005b },   /* Set I2C bus speed */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF,  0x0200 },   /* 100kHz I2C_STO = 2 */
+       {} /* terminator */
+};
+
+const struct hda_pintbl cs8409_cs42l42_pincfgs[] = {
+       { CS8409_PIN_ASP1_TRANSMITTER_A, 0x042120f0 },  /* ASP-1-TX */
+       { CS8409_PIN_ASP1_RECEIVER_A, 0x04a12050 },     /* ASP-1-RX */
+       { CS8409_PIN_ASP2_TRANSMITTER_A, 0x901000f0 },  /* ASP-2-TX */
+       { CS8409_PIN_DMIC1_IN, 0x90a00090 },            /* DMIC-1 */
+       {} /* terminator */
+};
+
+/* Vendor specific HW configuration for CS42L42 */
+static const struct cs8409_i2c_param cs42l42_init_reg_seq[] = {
+       { 0x1010, 0xB0 },
+       { 0x1D01, 0x00 },
+       { 0x1D02, 0x06 },
+       { 0x1D03, 0x9F },
+       { 0x1107, 0x01 },
+       { 0x1009, 0x02 },
+       { 0x1007, 0x03 },
+       { 0x1201, 0x00 },
+       { 0x1208, 0x13 },
+       { 0x1205, 0xFF },
+       { 0x1206, 0x00 },
+       { 0x1207, 0x20 },
+       { 0x1202, 0x0D },
+       { 0x2A02, 0x02 },
+       { 0x2A03, 0x00 },
+       { 0x2A04, 0x00 },
+       { 0x2A05, 0x02 },
+       { 0x2A06, 0x00 },
+       { 0x2A07, 0x20 },
+       { 0x2A08, 0x02 },
+       { 0x2A09, 0x00 },
+       { 0x2A0A, 0x80 },
+       { 0x2A0B, 0x02 },
+       { 0x2A0C, 0x00 },
+       { 0x2A0D, 0xA0 },
+       { 0x2A01, 0x0C },
+       { 0x2902, 0x01 },
+       { 0x2903, 0x02 },
+       { 0x2904, 0x00 },
+       { 0x2905, 0x00 },
+       { 0x2901, 0x01 },
+       { 0x1101, 0x0A },
+       { 0x1102, 0x84 },
+       { 0x2301, 0x3F },
+       { 0x2303, 0x3F },
+       { 0x2302, 0x3f },
+       { 0x2001, 0x03 },
+       { 0x1B75, 0xB6 },
+       { 0x1B73, 0xC2 },
+       { 0x1129, 0x01 },
+       { 0x1121, 0xF3 },
+       { 0x1103, 0x20 },
+       { 0x1105, 0x00 },
+       { 0x1112, 0x00 },
+       { 0x1113, 0x80 },
+       { 0x1C03, 0xC0 },
+       { 0x1101, 0x02 },
+       { 0x1316, 0xff },
+       { 0x1317, 0xff },
+       { 0x1318, 0xff },
+       { 0x1319, 0xff },
+       { 0x131a, 0xff },
+       { 0x131b, 0xff },
+       { 0x131c, 0xff },
+       { 0x131e, 0xff },
+       { 0x131f, 0xff },
+       { 0x1320, 0xff },
+       { 0x1b79, 0xff },
+       { 0x1b7a, 0xff },
+};
+
+/* Vendor specific hw configuration for CS8409 */
+const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[] = {
+       /* +PLL1/2_EN, +I2C_EN */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0xb008 },
+       /* ASP1/2_EN=0, ASP1_STP=1 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0002 },
+       /* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG3, 0x0a80 },
+       /* ASP1.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL1, 0x0800 },
+       /* ASP1.A: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=32 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL2, 0x0820 },
+       /* ASP2.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP2_A_TX_CTRL1, 0x0800 },
+       /* ASP2.A: TX.RAP=1, TX.RSZ=24 bits, TX.RCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP2_A_TX_CTRL2, 0x2800 },
+       /* ASP1.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL1, 0x0800 },
+       /* ASP1.A: RX.RAP=0, RX.RSZ=24 bits, RX.RCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL2, 0x0800 },
+       /* ASP1: LCHI = 00h */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL1, 0x8000 },
+       /* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL2, 0x28ff },
+       /* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL3, 0x0062 },
+       /* ASP2: LCHI=1Fh */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL1, 0x801f },
+       /* ASP2: MC/SC_SRCSEL=PLL1, LCPR=3Fh */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL2, 0x283f },
+       /* ASP2: 5050=1, MCEN=0, FSD=010, SCPOL_IN/OUT=1, SCDIV=1:16 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL3, 0x805c },
+       /* DMIC1_MO=10b, DMIC1/2_SR=1 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DMIC_CFG, 0x0023 },
+       /* ASP1/2_BEEP=0 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_BEEP_CFG, 0x0000 },
+       /* ASP1/2_EN=1, ASP1_STP=1 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0062 },
+       /* -PLL2_EN */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0x9008 },
+       /* TX2.A: pre-scale att.=0 dB */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PRE_SCALE_ATTN2, 0x0000 },
+       /* ASP1/2_xxx_EN=1, ASP1/2_MCLK_EN=0, DMIC1_SCL_EN=1 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PAD_CFG_SLW_RATE_CTRL, 0xfc03 },
+       /* test mode on */
+       { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x9999 },
+       /* GPIO hysteresis = 30 us */
+       { CS8409_PIN_VENDOR_WIDGET, 0xc5, 0x0000 },
+       /* test mode off */
+       { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x0000 },
+       {} /* Terminator */
+};
+
+const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[] = {
+       /* EQ_SEL=1, EQ1/2_EN=0 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_CTRL1, 0x4000 },
+       /* +EQ_ACC */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0x4000 },
+       /* +EQ2_EN */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_CTRL1, 0x4010 },
+       /* EQ_DATA_HI=0x0647 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x0647 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=0, EQ_DATA_LO=0x67 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc0c7 },
+       /* EQ_DATA_HI=0x0647 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x0647 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=1, EQ_DATA_LO=0x67 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc1c7 },
+       /* EQ_DATA_HI=0xf370 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xf370 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=2, EQ_DATA_LO=0x71 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc271 },
+       /* EQ_DATA_HI=0x1ef8 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1ef8 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=3, EQ_DATA_LO=0x48 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc348 },
+       /* EQ_DATA_HI=0xc110 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc110 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=4, EQ_DATA_LO=0x5a */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc45a },
+       /* EQ_DATA_HI=0x1f29 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1f29 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=5, EQ_DATA_LO=0x74 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc574 },
+       /* EQ_DATA_HI=0x1d7a */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1d7a },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=6, EQ_DATA_LO=0x53 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc653 },
+       /* EQ_DATA_HI=0xc38c */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc38c },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=7, EQ_DATA_LO=0x14 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc714 },
+       /* EQ_DATA_HI=0x1ca3 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1ca3 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=8, EQ_DATA_LO=0xc7 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc8c7 },
+       /* EQ_DATA_HI=0xc38c */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc38c },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=9, EQ_DATA_LO=0x14 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc914 },
+       /* -EQ_ACC, -EQ_WRT */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0x0000 },
+       {} /* Terminator */
+};
+
+struct sub_codec cs8409_cs42l42_codec = {
+       .addr = CS42L42_I2C_ADDR,
+       .reset_gpio = CS8409_CS42L42_RESET,
+       .irq_mask = CS8409_CS42L42_INT,
+       .init_seq = cs42l42_init_reg_seq,
+       .init_seq_num = ARRAY_SIZE(cs42l42_init_reg_seq),
+       .hp_jack_in = 0,
+       .mic_jack_in = 0,
+       .paged = 1,
+       .suspended = 1,
+       .no_type_dect = 0,
+};
+
+/******************************************************************************
+ *                          Dolphin Specific Arrays
+ *                            CS8409/ 2 X CS42L42
+ ******************************************************************************/
+
+const struct hda_verb dolphin_init_verbs[] = {
+       { 0x01, AC_VERB_SET_GPIO_WAKE_MASK, DOLPHIN_WAKE }, /* WAKE from GPIO 0,4 */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_STATE, 0x0001 }, /* Enable VPW processing  */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x0002 }, /* Configure GPIO 6,7 */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF,  0x0080 }, /* I2C mode */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x005b }, /* Set I2C bus speed */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF,  0x0200 }, /* 100kHz I2C_STO = 2 */
+       {} /* terminator */
+};
+
+const struct hda_pintbl dolphin_pincfgs[] = {
+       { 0x24, 0x022210f0 }, /* ASP-1-TX-A */
+       { 0x25, 0x010240f0 }, /* ASP-1-TX-B */
+       { 0x34, 0x02a21050 }, /* ASP-1-RX */
+       {} /* terminator */
+};
+
+/* Vendor specific HW configuration for CS42L42 */
+static const struct cs8409_i2c_param dolphin_c0_init_reg_seq[] = {
+       { 0x1010, 0xB0 },
+       { 0x1D01, 0x00 },
+       { 0x1D02, 0x06 },
+       { 0x1D03, 0x9F },
+       { 0x1107, 0x01 },
+       { 0x1009, 0x02 },
+       { 0x1007, 0x03 },
+       { 0x1201, 0x00 },
+       { 0x1208, 0x13 },
+       { 0x1205, 0xFF },
+       { 0x1206, 0x00 },
+       { 0x1207, 0x20 },
+       { 0x1202, 0x0D },
+       { 0x2A02, 0x02 },
+       { 0x2A03, 0x00 },
+       { 0x2A04, 0x00 },
+       { 0x2A05, 0x02 },
+       { 0x2A06, 0x00 },
+       { 0x2A07, 0x20 },
+       { 0x2A01, 0x0C },
+       { 0x2902, 0x01 },
+       { 0x2903, 0x02 },
+       { 0x2904, 0x00 },
+       { 0x2905, 0x00 },
+       { 0x2901, 0x01 },
+       { 0x1101, 0x0A },
+       { 0x1102, 0x84 },
+       { 0x2001, 0x03 },
+       { 0x2301, 0x3F },
+       { 0x2303, 0x3F },
+       { 0x2302, 0x3f },
+       { 0x1B75, 0xB6 },
+       { 0x1B73, 0xC2 },
+       { 0x1129, 0x01 },
+       { 0x1121, 0xF3 },
+       { 0x1103, 0x20 },
+       { 0x1105, 0x00 },
+       { 0x1112, 0x00 },
+       { 0x1113, 0x80 },
+       { 0x1C03, 0xC0 },
+       { 0x1101, 0x02 },
+       { 0x1316, 0xff },
+       { 0x1317, 0xff },
+       { 0x1318, 0xff },
+       { 0x1319, 0xff },
+       { 0x131a, 0xff },
+       { 0x131b, 0xff },
+       { 0x131c, 0xff },
+       { 0x131e, 0xff },
+       { 0x131f, 0xff },
+       { 0x1320, 0xff },
+       { 0x1b79, 0xff },
+       { 0x1b7a, 0xff }
+};
+
+static const struct cs8409_i2c_param dolphin_c1_init_reg_seq[] = {
+       { 0x1010, 0xB0 },
+       { 0x1D01, 0x00 },
+       { 0x1D02, 0x06 },
+       { 0x1D03, 0x9F },
+       { 0x1107, 0x01 },
+       { 0x1009, 0x02 },
+       { 0x1007, 0x03 },
+       { 0x1201, 0x00 },
+       { 0x1208, 0x13 },
+       { 0x1205, 0xFF },
+       { 0x1206, 0x00 },
+       { 0x1207, 0x20 },
+       { 0x1202, 0x0D },
+       { 0x2A02, 0x02 },
+       { 0x2A03, 0x00 },
+       { 0x2A04, 0x80 },
+       { 0x2A05, 0x02 },
+       { 0x2A06, 0x00 },
+       { 0x2A07, 0xA0 },
+       { 0x2A01, 0x0C },
+       { 0x2902, 0x00 },
+       { 0x2903, 0x02 },
+       { 0x2904, 0x00 },
+       { 0x2905, 0x00 },
+       { 0x2901, 0x00 },
+       { 0x1101, 0x0E },
+       { 0x1102, 0x84 },
+       { 0x2001, 0x01 },
+       { 0x2301, 0x3F },
+       { 0x2303, 0x3F },
+       { 0x2302, 0x3f },
+       { 0x1B75, 0xB6 },
+       { 0x1B73, 0xC2 },
+       { 0x1129, 0x01 },
+       { 0x1121, 0xF3 },
+       { 0x1103, 0x20 },
+       { 0x1105, 0x00 },
+       { 0x1112, 0x00 },
+       { 0x1113, 0x80 },
+       { 0x1C03, 0xC0 },
+       { 0x1101, 0x06 },
+       { 0x1316, 0xff },
+       { 0x1317, 0xff },
+       { 0x1318, 0xff },
+       { 0x1319, 0xff },
+       { 0x131a, 0xff },
+       { 0x131b, 0xff },
+       { 0x131c, 0xff },
+       { 0x131e, 0xff },
+       { 0x131f, 0xff },
+       { 0x1320, 0xff },
+       { 0x1b79, 0xff },
+       { 0x1b7a, 0xff }
+};
+
+/* Vendor specific hw configuration for CS8409 */
+const struct cs8409_cir_param dolphin_hw_cfg[] = {
+       /* +PLL1/2_EN, +I2C_EN */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0xb008 },
+       /* ASP1_EN=0, ASP1_STP=1 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0002 },
+       /* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG3, 0x0a80 },
+       /* ASP1.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL1, 0x0800 },
+       /* ASP1.A: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=32 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL2, 0x0820 },
+       /* ASP1.B: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=128 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_B_TX_CTRL1, 0x0880 },
+       /* ASP1.B: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=160 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_B_TX_CTRL2, 0x08a0 },
+       /* ASP1.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL1, 0x0800 },
+       /* ASP1.A: RX.RAP=0, RX.RSZ=24 bits, RX.RCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL2, 0x0800 },
+       /* ASP1: LCHI = 00h */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL1, 0x8000 },
+       /* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL2, 0x28ff },
+       /* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL3, 0x0062 },
+       /* ASP1/2_BEEP=0 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_BEEP_CFG, 0x0000 },
+       /* ASP1_EN=1, ASP1_STP=1 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0022 },
+       /* -PLL2_EN */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0x9008 },
+       /* ASP1_xxx_EN=1, ASP1_MCLK_EN=0 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PAD_CFG_SLW_RATE_CTRL, 0x5400 },
+       /* test mode on */
+       { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x9999 },
+       /* GPIO hysteresis = 30 us */
+       { CS8409_PIN_VENDOR_WIDGET, 0xc5, 0x0000 },
+       /* test mode off */
+       { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x0000 },
+       {} /* Terminator */
+};
+
+struct sub_codec dolphin_cs42l42_0 = {
+       .addr = DOLPHIN_C0_I2C_ADDR,
+       .reset_gpio = DOLPHIN_C0_RESET,
+       .irq_mask = DOLPHIN_C0_INT,
+       .init_seq = dolphin_c0_init_reg_seq,
+       .init_seq_num = ARRAY_SIZE(dolphin_c0_init_reg_seq),
+       .hp_jack_in = 0,
+       .mic_jack_in = 0,
+       .paged = 1,
+       .suspended = 1,
+       .no_type_dect = 0,
+};
+
+struct sub_codec dolphin_cs42l42_1 = {
+       .addr = DOLPHIN_C1_I2C_ADDR,
+       .reset_gpio = DOLPHIN_C1_RESET,
+       .irq_mask = DOLPHIN_C1_INT,
+       .init_seq = dolphin_c1_init_reg_seq,
+       .init_seq_num = ARRAY_SIZE(dolphin_c1_init_reg_seq),
+       .hp_jack_in = 0,
+       .mic_jack_in = 0,
+       .paged = 1,
+       .suspended = 1,
+       .no_type_dect = 1,
+};
+
+/******************************************************************************
+ *                         CS8409 Patch Driver Structs
+ *                    Arrays Used for all projects using CS8409
+ ******************************************************************************/
+
+const struct snd_pci_quirk cs8409_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x1028, 0x0A11, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A12, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A23, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A24, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A25, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A29, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A2A, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A2B, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0AB0, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AB2, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AB1, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AB3, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AB4, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AB5, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AD9, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0ADA, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0ADB, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0ADC, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AF4, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AF5, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0A77, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A78, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A79, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A7A, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A7D, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A7E, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A7F, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A80, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0ADF, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AE0, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AE1, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AE2, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AE9, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AEA, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AEB, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AEC, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AED, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AEE, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AEF, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AF0, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AD0, "Dolphin", CS8409_DOLPHIN),
+       SND_PCI_QUIRK(0x1028, 0x0AD1, "Dolphin", CS8409_DOLPHIN),
+       SND_PCI_QUIRK(0x1028, 0x0AD2, "Dolphin", CS8409_DOLPHIN),
+       SND_PCI_QUIRK(0x1028, 0x0AD3, "Dolphin", CS8409_DOLPHIN),
+       SND_PCI_QUIRK(0x1028, 0x0ACF, "Dolphin", CS8409_DOLPHIN),
+       {} /* terminator */
+};
+
+/* Dell Inspiron models with cs8409/cs42l42 */
+const struct hda_model_fixup cs8409_models[] = {
+       { .id = CS8409_BULLSEYE, .name = "bullseye" },
+       { .id = CS8409_WARLOCK, .name = "warlock" },
+       { .id = CS8409_CYBORG, .name = "cyborg" },
+       { .id = CS8409_DOLPHIN, .name = "dolphin" },
+       {}
+};
+
+const struct hda_fixup cs8409_fixups[] = {
+       [CS8409_BULLSEYE] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = cs8409_cs42l42_pincfgs,
+               .chained = true,
+               .chain_id = CS8409_FIXUPS,
+       },
+       [CS8409_WARLOCK] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = cs8409_cs42l42_pincfgs,
+               .chained = true,
+               .chain_id = CS8409_FIXUPS,
+       },
+       [CS8409_CYBORG] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = cs8409_cs42l42_pincfgs,
+               .chained = true,
+               .chain_id = CS8409_FIXUPS,
+       },
+       [CS8409_FIXUPS] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = cs8409_cs42l42_fixups,
+       },
+       [CS8409_DOLPHIN] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = dolphin_pincfgs,
+               .chained = true,
+               .chain_id = CS8409_DOLPHIN_FIXUPS,
+       },
+       [CS8409_DOLPHIN_FIXUPS] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = dolphin_fixups,
+       },
+};
diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c
new file mode 100644 (file)
index 0000000..3c7ef55
--- /dev/null
@@ -0,0 +1,1299 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
+ *
+ * Copyright (C) 2021 Cirrus Logic, Inc. and
+ *                    Cirrus Logic International Semiconductor Ltd.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <linux/mutex.h>
+#include <linux/iopoll.h>
+
+#include "patch_cs8409.h"
+
+/******************************************************************************
+ *                        CS8409 Specific Functions
+ ******************************************************************************/
+
+static int cs8409_parse_auto_config(struct hda_codec *codec)
+{
+       struct cs8409_spec *spec = codec->spec;
+       int err;
+       int i;
+
+       err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
+       if (err < 0)
+               return err;
+
+       err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
+       if (err < 0)
+               return err;
+
+       /* keep the ADCs powered up when it's dynamically switchable */
+       if (spec->gen.dyn_adc_switch) {
+               unsigned int done = 0;
+
+               for (i = 0; i < spec->gen.input_mux.num_items; i++) {
+                       int idx = spec->gen.dyn_adc_idx[i];
+
+                       if (done & (1 << idx))
+                               continue;
+                       snd_hda_gen_fix_pin_power(codec, spec->gen.adc_nids[idx]);
+                       done |= 1 << idx;
+               }
+       }
+
+       return 0;
+}
+
+static void cs8409_disable_i2c_clock_worker(struct work_struct *work);
+
+static struct cs8409_spec *cs8409_alloc_spec(struct hda_codec *codec)
+{
+       struct cs8409_spec *spec;
+
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return NULL;
+       codec->spec = spec;
+       spec->codec = codec;
+       codec->power_save_node = 1;
+       mutex_init(&spec->i2c_mux);
+       INIT_DELAYED_WORK(&spec->i2c_clk_work, cs8409_disable_i2c_clock_worker);
+       snd_hda_gen_spec_init(&spec->gen);
+
+       return spec;
+}
+
+static inline int cs8409_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
+{
+       snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_COEF_INDEX, idx);
+       return snd_hda_codec_read(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_GET_PROC_COEF, 0);
+}
+
+static inline void cs8409_vendor_coef_set(struct hda_codec *codec, unsigned int idx,
+                                         unsigned int coef)
+{
+       snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_COEF_INDEX, idx);
+       snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_PROC_COEF, coef);
+}
+
+/*
+ * cs8409_enable_i2c_clock - Disable I2C clocks
+ * @codec: the codec instance
+ * Disable I2C clocks.
+ * This must be called when the i2c mutex is unlocked.
+ */
+static void cs8409_disable_i2c_clock(struct hda_codec *codec)
+{
+       struct cs8409_spec *spec = codec->spec;
+
+       mutex_lock(&spec->i2c_mux);
+       if (spec->i2c_clck_enabled) {
+               cs8409_vendor_coef_set(spec->codec, 0x0,
+                              cs8409_vendor_coef_get(spec->codec, 0x0) & 0xfffffff7);
+               spec->i2c_clck_enabled = 0;
+       }
+       mutex_unlock(&spec->i2c_mux);
+}
+
+/*
+ * cs8409_disable_i2c_clock_worker - Worker that disable the I2C Clock after 25ms without use
+ */
+static void cs8409_disable_i2c_clock_worker(struct work_struct *work)
+{
+       struct cs8409_spec *spec = container_of(work, struct cs8409_spec, i2c_clk_work.work);
+
+       cs8409_disable_i2c_clock(spec->codec);
+}
+
+/*
+ * cs8409_enable_i2c_clock - Enable I2C clocks
+ * @codec: the codec instance
+ * Enable I2C clocks.
+ * This must be called when the i2c mutex is locked.
+ */
+static void cs8409_enable_i2c_clock(struct hda_codec *codec)
+{
+       struct cs8409_spec *spec = codec->spec;
+
+       /* Cancel the disable timer, but do not wait for any running disable functions to finish.
+        * If the disable timer runs out before cancel, the delayed work thread will be blocked,
+        * waiting for the mutex to become unlocked. This mutex will be locked for the duration of
+        * any i2c transaction, so the disable function will run to completion immediately
+        * afterwards in the scenario. The next enable call will re-enable the clock, regardless.
+        */
+       cancel_delayed_work(&spec->i2c_clk_work);
+
+       if (!spec->i2c_clck_enabled) {
+               cs8409_vendor_coef_set(codec, 0x0, cs8409_vendor_coef_get(codec, 0x0) | 0x8);
+               spec->i2c_clck_enabled = 1;
+       }
+       queue_delayed_work(system_power_efficient_wq, &spec->i2c_clk_work, msecs_to_jiffies(25));
+}
+
+/**
+ * cs8409_i2c_wait_complete - Wait for I2C transaction
+ * @codec: the codec instance
+ *
+ * Wait for I2C transaction to complete.
+ * Return -ETIMEDOUT if transaction wait times out.
+ */
+static int cs8409_i2c_wait_complete(struct hda_codec *codec)
+{
+       unsigned int retval;
+
+       return read_poll_timeout(cs8409_vendor_coef_get, retval, retval & 0x18,
+               CS42L42_I2C_SLEEP_US, CS42L42_I2C_TIMEOUT_US, false, codec, CS8409_I2C_STS);
+}
+
+/**
+ * cs8409_set_i2c_dev_addr - Set i2c address for transaction
+ * @codec: the codec instance
+ * @addr: I2C Address
+ */
+static void cs8409_set_i2c_dev_addr(struct hda_codec *codec, unsigned int addr)
+{
+       struct cs8409_spec *spec = codec->spec;
+
+       if (spec->dev_addr != addr) {
+               cs8409_vendor_coef_set(codec, CS8409_I2C_ADDR, addr);
+               spec->dev_addr = addr;
+       }
+}
+
+/**
+ * cs8409_i2c_set_page - CS8409 I2C set page register.
+ * @scodec: the codec instance
+ * @i2c_reg: Page register
+ *
+ * Returns negative on error.
+ */
+static int cs8409_i2c_set_page(struct sub_codec *scodec, unsigned int i2c_reg)
+{
+       struct hda_codec *codec = scodec->codec;
+
+       if (scodec->paged && (scodec->last_page != (i2c_reg >> 8))) {
+               cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg >> 8);
+               if (cs8409_i2c_wait_complete(codec) < 0)
+                       return -EIO;
+               scodec->last_page = i2c_reg >> 8;
+       }
+
+       return 0;
+}
+
+/**
+ * cs8409_i2c_read - CS8409 I2C Read.
+ * @scodec: the codec instance
+ * @addr: Register to read
+ *
+ * Returns negative on error, otherwise returns read value in bits 0-7.
+ */
+static int cs8409_i2c_read(struct sub_codec *scodec, unsigned int addr)
+{
+       struct hda_codec *codec = scodec->codec;
+       struct cs8409_spec *spec = codec->spec;
+       unsigned int i2c_reg_data;
+       unsigned int read_data;
+
+       if (scodec->suspended)
+               return -EPERM;
+
+       mutex_lock(&spec->i2c_mux);
+       cs8409_enable_i2c_clock(codec);
+       cs8409_set_i2c_dev_addr(codec, scodec->addr);
+
+       if (cs8409_i2c_set_page(scodec, addr))
+               goto error;
+
+       i2c_reg_data = (addr << 8) & 0x0ffff;
+       cs8409_vendor_coef_set(codec, CS8409_I2C_QREAD, i2c_reg_data);
+       if (cs8409_i2c_wait_complete(codec) < 0)
+               goto error;
+
+       /* Register in bits 15-8 and the data in 7-0 */
+       read_data = cs8409_vendor_coef_get(codec, CS8409_I2C_QREAD);
+
+       mutex_unlock(&spec->i2c_mux);
+
+       return read_data & 0x0ff;
+
+error:
+       mutex_unlock(&spec->i2c_mux);
+       codec_err(codec, "%s() Failed 0x%02x : 0x%04x\n", __func__, scodec->addr, addr);
+       return -EIO;
+}
+
+/**
+ * cs8409_i2c_bulk_read - CS8409 I2C Read Sequence.
+ * @scodec: the codec instance
+ * @seq: Register Sequence to read
+ * @count: Number of registeres to read
+ *
+ * Returns negative on error, values are read into value element of cs8409_i2c_param sequence.
+ */
+static int cs8409_i2c_bulk_read(struct sub_codec *scodec, struct cs8409_i2c_param *seq, int count)
+{
+       struct hda_codec *codec = scodec->codec;
+       struct cs8409_spec *spec = codec->spec;
+       unsigned int i2c_reg_data;
+       int i;
+
+       if (scodec->suspended)
+               return -EPERM;
+
+       mutex_lock(&spec->i2c_mux);
+       cs8409_set_i2c_dev_addr(codec, scodec->addr);
+
+       for (i = 0; i < count; i++) {
+               cs8409_enable_i2c_clock(codec);
+               if (cs8409_i2c_set_page(scodec, seq[i].addr))
+                       goto error;
+
+               i2c_reg_data = (seq[i].addr << 8) & 0x0ffff;
+               cs8409_vendor_coef_set(codec, CS8409_I2C_QREAD, i2c_reg_data);
+
+               if (cs8409_i2c_wait_complete(codec) < 0)
+                       goto error;
+
+               seq[i].value = cs8409_vendor_coef_get(codec, CS8409_I2C_QREAD) & 0xff;
+       }
+
+       mutex_unlock(&spec->i2c_mux);
+
+       return 0;
+
+error:
+       mutex_unlock(&spec->i2c_mux);
+       codec_err(codec, "I2C Bulk Write Failed 0x%02x\n", scodec->addr);
+       return -EIO;
+}
+
+/**
+ * cs8409_i2c_write - CS8409 I2C Write.
+ * @scodec: the codec instance
+ * @addr: Register to write to
+ * @value: Data to write
+ *
+ * Returns negative on error, otherwise returns 0.
+ */
+static int cs8409_i2c_write(struct sub_codec *scodec, unsigned int addr, unsigned int value)
+{
+       struct hda_codec *codec = scodec->codec;
+       struct cs8409_spec *spec = codec->spec;
+       unsigned int i2c_reg_data;
+
+       if (scodec->suspended)
+               return -EPERM;
+
+       mutex_lock(&spec->i2c_mux);
+
+       cs8409_enable_i2c_clock(codec);
+       cs8409_set_i2c_dev_addr(codec, scodec->addr);
+
+       if (cs8409_i2c_set_page(scodec, addr))
+               goto error;
+
+       i2c_reg_data = ((addr << 8) & 0x0ff00) | (value & 0x0ff);
+       cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg_data);
+
+       if (cs8409_i2c_wait_complete(codec) < 0)
+               goto error;
+
+       mutex_unlock(&spec->i2c_mux);
+       return 0;
+
+error:
+       mutex_unlock(&spec->i2c_mux);
+       codec_err(codec, "%s() Failed 0x%02x : 0x%04x\n", __func__, scodec->addr, addr);
+       return -EIO;
+}
+
+/**
+ * cs8409_i2c_bulk_write - CS8409 I2C Write Sequence.
+ * @scodec: the codec instance
+ * @seq: Register Sequence to write
+ * @count: Number of registeres to write
+ *
+ * Returns negative on error.
+ */
+static int cs8409_i2c_bulk_write(struct sub_codec *scodec, const struct cs8409_i2c_param *seq,
+                                int count)
+{
+       struct hda_codec *codec = scodec->codec;
+       struct cs8409_spec *spec = codec->spec;
+       unsigned int i2c_reg_data;
+       int i;
+
+       if (scodec->suspended)
+               return -EPERM;
+
+       mutex_lock(&spec->i2c_mux);
+       cs8409_set_i2c_dev_addr(codec, scodec->addr);
+
+       for (i = 0; i < count; i++) {
+               cs8409_enable_i2c_clock(codec);
+               if (cs8409_i2c_set_page(scodec, seq[i].addr))
+                       goto error;
+
+               i2c_reg_data = ((seq[i].addr << 8) & 0x0ff00) | (seq[i].value & 0x0ff);
+               cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg_data);
+
+               if (cs8409_i2c_wait_complete(codec) < 0)
+                       goto error;
+       }
+
+       mutex_unlock(&spec->i2c_mux);
+
+       return 0;
+
+error:
+       mutex_unlock(&spec->i2c_mux);
+       codec_err(codec, "I2C Bulk Write Failed 0x%02x\n", scodec->addr);
+       return -EIO;
+}
+
+static int cs8409_init(struct hda_codec *codec)
+{
+       int ret = snd_hda_gen_init(codec);
+
+       if (!ret)
+               snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
+
+       return ret;
+}
+
+static int cs8409_build_controls(struct hda_codec *codec)
+{
+       int err;
+
+       err = snd_hda_gen_build_controls(codec);
+       if (err < 0)
+               return err;
+       snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
+
+       return 0;
+}
+
+/* Enable/Disable Unsolicited Response */
+static void cs8409_enable_ur(struct hda_codec *codec, int flag)
+{
+       struct cs8409_spec *spec = codec->spec;
+       unsigned int ur_gpios = 0;
+       int i;
+
+       for (i = 0; i < spec->num_scodecs; i++)
+               ur_gpios |= spec->scodecs[i]->irq_mask;
+
+       snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK,
+                           flag ? ur_gpios : 0);
+
+       snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_UNSOLICITED_ENABLE,
+                           flag ? AC_UNSOL_ENABLED : 0);
+}
+
+static void cs8409_fix_caps(struct hda_codec *codec, unsigned int nid)
+{
+       int caps;
+
+       /* CS8409 is simple HDA bridge and intended to be used with a remote
+        * companion codec. Most of input/output PIN(s) have only basic
+        * capabilities. Receive and Transmit NID(s) have only OUTC and INC
+        * capabilities and no presence detect capable (PDC) and call to
+        * snd_hda_gen_build_controls() will mark them as non detectable
+        * phantom jacks. However, a companion codec may be
+        * connected to these pins which supports jack detect
+        * capabilities. We have to override pin capabilities,
+        * otherwise they will not be created as input devices.
+        */
+       caps = snd_hdac_read_parm(&codec->core, nid, AC_PAR_PIN_CAP);
+       if (caps >= 0)
+               snd_hdac_override_parm(&codec->core, nid, AC_PAR_PIN_CAP,
+                                      (caps | (AC_PINCAP_IMP_SENSE | AC_PINCAP_PRES_DETECT)));
+
+       snd_hda_override_wcaps(codec, nid, (get_wcaps(codec, nid) | AC_WCAP_UNSOL_CAP));
+}
+
+/******************************************************************************
+ *                        CS42L42 Specific Functions
+ ******************************************************************************/
+
+int cs42l42_volume_info(struct snd_kcontrol *kctrl, struct snd_ctl_elem_info *uinfo)
+{
+       unsigned int ofs = get_amp_offset(kctrl);
+       u8 chs = get_amp_channels(kctrl);
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->value.integer.step = 1;
+       uinfo->count = chs == 3 ? 2 : 1;
+
+       switch (ofs) {
+       case CS42L42_VOL_DAC:
+               uinfo->value.integer.min = CS42L42_HP_VOL_REAL_MIN;
+               uinfo->value.integer.max = CS42L42_HP_VOL_REAL_MAX;
+               break;
+       case CS42L42_VOL_ADC:
+               uinfo->value.integer.min = CS42L42_AMIC_VOL_REAL_MIN;
+               uinfo->value.integer.max = CS42L42_AMIC_VOL_REAL_MAX;
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+int cs42l42_volume_get(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kctrl);
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42 = spec->scodecs[get_amp_index(kctrl)];
+       int chs = get_amp_channels(kctrl);
+       unsigned int ofs = get_amp_offset(kctrl);
+       long *valp = uctrl->value.integer.value;
+
+       switch (ofs) {
+       case CS42L42_VOL_DAC:
+               if (chs & BIT(0))
+                       *valp++ = cs42l42->vol[ofs];
+               if (chs & BIT(1))
+                       *valp = cs42l42->vol[ofs+1];
+               break;
+       case CS42L42_VOL_ADC:
+               if (chs & BIT(0))
+                       *valp = cs42l42->vol[ofs];
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static void cs42l42_mute(struct sub_codec *cs42l42, int vol_type,
+       unsigned int chs, bool mute)
+{
+       if (mute) {
+               if (vol_type == CS42L42_VOL_DAC) {
+                       if (chs & BIT(0))
+                               cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHA, 0x3f);
+                       if (chs & BIT(1))
+                               cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHB, 0x3f);
+               } else if (vol_type == CS42L42_VOL_ADC) {
+                       if (chs & BIT(0))
+                               cs8409_i2c_write(cs42l42, CS42L42_REG_AMIC_VOL, 0x9f);
+               }
+       } else {
+               if (vol_type == CS42L42_VOL_DAC) {
+                       if (chs & BIT(0))
+                               cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHA,
+                                       -(cs42l42->vol[CS42L42_DAC_CH0_VOL_OFFSET])
+                                       & CS42L42_REG_HS_VOL_MASK);
+                       if (chs & BIT(1))
+                               cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHB,
+                                       -(cs42l42->vol[CS42L42_DAC_CH1_VOL_OFFSET])
+                                       & CS42L42_REG_HS_VOL_MASK);
+               } else if (vol_type == CS42L42_VOL_ADC) {
+                       if (chs & BIT(0))
+                               cs8409_i2c_write(cs42l42, CS42L42_REG_AMIC_VOL,
+                                       cs42l42->vol[CS42L42_ADC_VOL_OFFSET]
+                                       & CS42L42_REG_AMIC_VOL_MASK);
+               }
+       }
+}
+
+int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kctrl);
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42 = spec->scodecs[get_amp_index(kctrl)];
+       int chs = get_amp_channels(kctrl);
+       unsigned int ofs = get_amp_offset(kctrl);
+       long *valp = uctrl->value.integer.value;
+
+       switch (ofs) {
+       case CS42L42_VOL_DAC:
+               if (chs & BIT(0))
+                       cs42l42->vol[ofs] = *valp;
+               if (chs & BIT(1)) {
+                       valp++;
+                       cs42l42->vol[ofs + 1] = *valp;
+               }
+               if (spec->playback_started)
+                       cs42l42_mute(cs42l42, CS42L42_VOL_DAC, chs, false);
+               break;
+       case CS42L42_VOL_ADC:
+               if (chs & BIT(0))
+                       cs42l42->vol[ofs] = *valp;
+               if (spec->capture_started)
+                       cs42l42_mute(cs42l42, CS42L42_VOL_ADC, chs, false);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static void cs42l42_playback_pcm_hook(struct hda_pcm_stream *hinfo,
+                                  struct hda_codec *codec,
+                                  struct snd_pcm_substream *substream,
+                                  int action)
+{
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42;
+       int i;
+       bool mute;
+
+       switch (action) {
+       case HDA_GEN_PCM_ACT_PREPARE:
+               mute = false;
+               spec->playback_started = 1;
+               break;
+       case HDA_GEN_PCM_ACT_CLEANUP:
+               mute = true;
+               spec->playback_started = 0;
+               break;
+       default:
+               return;
+       }
+
+       for (i = 0; i < spec->num_scodecs; i++) {
+               cs42l42 = spec->scodecs[i];
+               cs42l42_mute(cs42l42, CS42L42_VOL_DAC, 0x3, mute);
+       }
+}
+
+static void cs42l42_capture_pcm_hook(struct hda_pcm_stream *hinfo,
+                                  struct hda_codec *codec,
+                                  struct snd_pcm_substream *substream,
+                                  int action)
+{
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42;
+       int i;
+       bool mute;
+
+       switch (action) {
+       case HDA_GEN_PCM_ACT_PREPARE:
+               mute = false;
+               spec->capture_started = 1;
+               break;
+       case HDA_GEN_PCM_ACT_CLEANUP:
+               mute = true;
+               spec->capture_started = 0;
+               break;
+       default:
+               return;
+       }
+
+       for (i = 0; i < spec->num_scodecs; i++) {
+               cs42l42 = spec->scodecs[i];
+               cs42l42_mute(cs42l42, CS42L42_VOL_ADC, 0x3, mute);
+       }
+}
+
+/* Configure CS42L42 slave codec for jack autodetect */
+static void cs42l42_enable_jack_detect(struct sub_codec *cs42l42)
+{
+       cs8409_i2c_write(cs42l42, 0x1b70, cs42l42->hsbias_hiz);
+       /* Clear WAKE# */
+       cs8409_i2c_write(cs42l42, 0x1b71, 0x00C1);
+       /* Wait ~2.5ms */
+       usleep_range(2500, 3000);
+       /* Set mode WAKE# output follows the combination logic directly */
+       cs8409_i2c_write(cs42l42, 0x1b71, 0x00C0);
+       /* Clear interrupts status */
+       cs8409_i2c_read(cs42l42, 0x130f);
+       /* Enable interrupt */
+       cs8409_i2c_write(cs42l42, 0x1320, 0xF3);
+}
+
+/* Enable and run CS42L42 slave codec jack auto detect */
+static void cs42l42_run_jack_detect(struct sub_codec *cs42l42)
+{
+       /* Clear interrupts */
+       cs8409_i2c_read(cs42l42, 0x1308);
+       cs8409_i2c_read(cs42l42, 0x1b77);
+       cs8409_i2c_write(cs42l42, 0x1320, 0xFF);
+       cs8409_i2c_read(cs42l42, 0x130f);
+
+       cs8409_i2c_write(cs42l42, 0x1102, 0x87);
+       cs8409_i2c_write(cs42l42, 0x1f06, 0x86);
+       cs8409_i2c_write(cs42l42, 0x1b74, 0x07);
+       cs8409_i2c_write(cs42l42, 0x131b, 0xFD);
+       cs8409_i2c_write(cs42l42, 0x1120, 0x80);
+       /* Wait ~100us*/
+       usleep_range(100, 200);
+       cs8409_i2c_write(cs42l42, 0x111f, 0x77);
+       cs8409_i2c_write(cs42l42, 0x1120, 0xc0);
+}
+
+static int cs42l42_handle_tip_sense(struct sub_codec *cs42l42, unsigned int reg_ts_status)
+{
+       int status_changed = 0;
+
+       /* TIP_SENSE INSERT/REMOVE */
+       switch (reg_ts_status) {
+       case CS42L42_JACK_INSERTED:
+               if (!cs42l42->hp_jack_in) {
+                       if (cs42l42->no_type_dect) {
+                               status_changed = 1;
+                               cs42l42->hp_jack_in = 1;
+                               cs42l42->mic_jack_in = 0;
+                       } else {
+                               cs42l42_run_jack_detect(cs42l42);
+                       }
+               }
+               break;
+
+       case CS42L42_JACK_REMOVED:
+               if (cs42l42->hp_jack_in || cs42l42->mic_jack_in) {
+                       status_changed = 1;
+                       cs42l42->hp_jack_in = 0;
+                       cs42l42->mic_jack_in = 0;
+               }
+               break;
+       default:
+               /* jack in transition */
+               break;
+       }
+
+       return status_changed;
+}
+
+static int cs42l42_jack_unsol_event(struct sub_codec *cs42l42)
+{
+       int status_changed = 0;
+       int reg_cdc_status;
+       int reg_hs_status;
+       int reg_ts_status;
+       int type;
+
+       /* Read jack detect status registers */
+       reg_cdc_status = cs8409_i2c_read(cs42l42, 0x1308);
+       reg_hs_status = cs8409_i2c_read(cs42l42, 0x1124);
+       reg_ts_status = cs8409_i2c_read(cs42l42, 0x130f);
+
+       /* If status values are < 0, read error has occurred. */
+       if (reg_cdc_status < 0 || reg_hs_status < 0 || reg_ts_status < 0)
+               return -EIO;
+
+       /* HSDET_AUTO_DONE */
+       if (reg_cdc_status & CS42L42_HSDET_AUTO_DONE) {
+
+               /* Disable HSDET_AUTO_DONE */
+               cs8409_i2c_write(cs42l42, 0x131b, 0xFF);
+
+               type = ((reg_hs_status & CS42L42_HSTYPE_MASK) + 1);
+
+               if (cs42l42->no_type_dect) {
+                       status_changed = cs42l42_handle_tip_sense(cs42l42, reg_ts_status);
+               } else if (type == 4) {
+                       /* Type 4 not supported */
+                       status_changed = cs42l42_handle_tip_sense(cs42l42, CS42L42_JACK_REMOVED);
+               } else {
+                       if (!cs42l42->hp_jack_in) {
+                               status_changed = 1;
+                               cs42l42->hp_jack_in = 1;
+                       }
+                       /* type = 3 has no mic */
+                       if ((!cs42l42->mic_jack_in) && (type != 3)) {
+                               status_changed = 1;
+                               cs42l42->mic_jack_in = 1;
+                       }
+               }
+               /* Configure the HSDET mode. */
+               cs8409_i2c_write(cs42l42, 0x1120, 0x80);
+               /* Enable the HPOUT ground clamp and configure the HP pull-down */
+               cs8409_i2c_write(cs42l42, 0x1F06, 0x02);
+               /* Re-Enable Tip Sense Interrupt */
+               cs8409_i2c_write(cs42l42, 0x1320, 0xF3);
+       } else {
+               status_changed = cs42l42_handle_tip_sense(cs42l42, reg_ts_status);
+       }
+
+       return status_changed;
+}
+
+static void cs42l42_resume(struct sub_codec *cs42l42)
+{
+       struct hda_codec *codec = cs42l42->codec;
+       unsigned int gpio_data;
+       struct cs8409_i2c_param irq_regs[] = {
+               { 0x1308, 0x00 },
+               { 0x1309, 0x00 },
+               { 0x130A, 0x00 },
+               { 0x130F, 0x00 },
+       };
+
+       /* Bring CS42L42 out of Reset */
+       gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
+       gpio_data |= cs42l42->reset_gpio;
+       snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
+       usleep_range(10000, 15000);
+
+       cs42l42->suspended = 0;
+
+       /* Initialize CS42L42 companion codec */
+       cs8409_i2c_bulk_write(cs42l42, cs42l42->init_seq, cs42l42->init_seq_num);
+       usleep_range(20000, 25000);
+
+       /* Clear interrupts, by reading interrupt status registers */
+       cs8409_i2c_bulk_read(cs42l42, irq_regs, ARRAY_SIZE(irq_regs));
+
+       if (cs42l42->full_scale_vol)
+               cs8409_i2c_write(cs42l42, 0x2001, 0x01);
+
+       cs42l42_enable_jack_detect(cs42l42);
+}
+
+#ifdef CONFIG_PM
+static void cs42l42_suspend(struct sub_codec *cs42l42)
+{
+       struct hda_codec *codec = cs42l42->codec;
+       unsigned int gpio_data;
+       int reg_cdc_status = 0;
+       const struct cs8409_i2c_param cs42l42_pwr_down_seq[] = {
+               { 0x1F06, 0x02 },
+               { 0x1129, 0x00 },
+               { 0x2301, 0x3F },
+               { 0x2302, 0x3F },
+               { 0x2303, 0x3F },
+               { 0x2001, 0x0F },
+               { 0x2A01, 0x00 },
+               { 0x1207, 0x00 },
+               { 0x1101, 0xFE },
+               { 0x1102, 0x8C },
+               { 0x1101, 0xFF },
+       };
+
+       cs8409_i2c_bulk_write(cs42l42, cs42l42_pwr_down_seq, ARRAY_SIZE(cs42l42_pwr_down_seq));
+
+       if (read_poll_timeout(cs8409_i2c_read, reg_cdc_status,
+                       (reg_cdc_status & 0x1), CS42L42_PDN_SLEEP_US, CS42L42_PDN_TIMEOUT_US,
+                       true, cs42l42, 0x1308) < 0)
+               codec_warn(codec, "Timeout waiting for PDN_DONE for CS42L42\n");
+
+       /* Power down CS42L42 ASP/EQ/MIX/HP */
+       cs8409_i2c_write(cs42l42, 0x1102, 0x9C);
+       cs42l42->suspended = 1;
+       cs42l42->last_page = 0;
+       cs42l42->hp_jack_in = 0;
+       cs42l42->mic_jack_in = 0;
+
+       /* Put CS42L42 into Reset */
+       gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
+       gpio_data &= ~cs42l42->reset_gpio;
+       snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
+}
+#endif
+
+static void cs8409_free(struct hda_codec *codec)
+{
+       struct cs8409_spec *spec = codec->spec;
+
+       /* Cancel i2c clock disable timer, and disable clock if left enabled */
+       cancel_delayed_work_sync(&spec->i2c_clk_work);
+       cs8409_disable_i2c_clock(codec);
+
+       snd_hda_gen_free(codec);
+}
+
+/******************************************************************************
+ *                   BULLSEYE / WARLOCK / CYBORG Specific Functions
+ *                               CS8409/CS42L42
+ ******************************************************************************/
+
+/*
+ * In the case of CS8409 we do not have unsolicited events from NID's 0x24
+ * and 0x34 where hs mic and hp are connected. Companion codec CS42L42 will
+ * generate interrupt via gpio 4 to notify jack events. We have to overwrite
+ * generic snd_hda_jack_unsol_event(), read CS42L42 jack detect status registers
+ * and then notify status via generic snd_hda_jack_unsol_event() call.
+ */
+static void cs8409_cs42l42_jack_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
+       struct hda_jack_tbl *jk;
+
+       /* jack_unsol_event() will be called every time gpio line changing state.
+        * In this case gpio4 line goes up as a result of reading interrupt status
+        * registers in previous cs8409_jack_unsol_event() call.
+        * We don't need to handle this event, ignoring...
+        */
+       if (res & cs42l42->irq_mask)
+               return;
+
+       if (cs42l42_jack_unsol_event(cs42l42)) {
+               snd_hda_set_pin_ctl(codec, CS8409_CS42L42_SPK_PIN_NID,
+                                   cs42l42->hp_jack_in ? 0 : PIN_OUT);
+               /* Report jack*/
+               jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_HP_PIN_NID, 0);
+               if (jk)
+                       snd_hda_jack_unsol_event(codec, (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+                                                       AC_UNSOL_RES_TAG);
+               /* Report jack*/
+               jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_AMIC_PIN_NID, 0);
+               if (jk)
+                       snd_hda_jack_unsol_event(codec, (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+                                                        AC_UNSOL_RES_TAG);
+       }
+}
+
+#ifdef CONFIG_PM
+/* Manage PDREF, when transition to D3hot */
+static int cs8409_cs42l42_suspend(struct hda_codec *codec)
+{
+       struct cs8409_spec *spec = codec->spec;
+       int i;
+
+       spec->init_done = 0;
+
+       cs8409_enable_ur(codec, 0);
+
+       for (i = 0; i < spec->num_scodecs; i++)
+               cs42l42_suspend(spec->scodecs[i]);
+
+       /* Cancel i2c clock disable timer, and disable clock if left enabled */
+       cancel_delayed_work_sync(&spec->i2c_clk_work);
+       cs8409_disable_i2c_clock(codec);
+
+       snd_hda_shutup_pins(codec);
+
+       return 0;
+}
+#endif
+
+/* Vendor specific HW configuration
+ * PLL, ASP, I2C, SPI, GPIOs, DMIC etc...
+ */
+static void cs8409_cs42l42_hw_init(struct hda_codec *codec)
+{
+       const struct cs8409_cir_param *seq = cs8409_cs42l42_hw_cfg;
+       const struct cs8409_cir_param *seq_bullseye = cs8409_cs42l42_bullseye_atn;
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
+
+       if (spec->gpio_mask) {
+               snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_MASK,
+                       spec->gpio_mask);
+               snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DIRECTION,
+                       spec->gpio_dir);
+               snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA,
+                       spec->gpio_data);
+       }
+
+       for (; seq->nid; seq++)
+               cs8409_vendor_coef_set(codec, seq->cir, seq->coeff);
+
+       if (codec->fixup_id == CS8409_BULLSEYE) {
+               for (; seq_bullseye->nid; seq_bullseye++)
+                       cs8409_vendor_coef_set(codec, seq_bullseye->cir, seq_bullseye->coeff);
+       }
+
+       /* DMIC1_MO=00b, DMIC1/2_SR=1 */
+       if (codec->fixup_id == CS8409_WARLOCK || codec->fixup_id == CS8409_CYBORG)
+               cs8409_vendor_coef_set(codec, 0x09, 0x0003);
+
+       cs42l42_resume(cs42l42);
+
+       /* Enable Unsolicited Response */
+       cs8409_enable_ur(codec, 1);
+}
+
+static const struct hda_codec_ops cs8409_cs42l42_patch_ops = {
+       .build_controls = cs8409_build_controls,
+       .build_pcms = snd_hda_gen_build_pcms,
+       .init = cs8409_init,
+       .free = cs8409_free,
+       .unsol_event = cs8409_cs42l42_jack_unsol_event,
+#ifdef CONFIG_PM
+       .suspend = cs8409_cs42l42_suspend,
+#endif
+};
+
+static int cs8409_cs42l42_exec_verb(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
+                                   unsigned int *res)
+{
+       struct hda_codec *codec = container_of(dev, struct hda_codec, core);
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
+
+       unsigned int nid = ((cmd >> 20) & 0x07f);
+       unsigned int verb = ((cmd >> 8) & 0x0fff);
+
+       /* CS8409 pins have no AC_PINSENSE_PRESENCE
+        * capabilities. We have to intercept 2 calls for pins 0x24 and 0x34
+        * and return correct pin sense values for read_pin_sense() call from
+        * hda_jack based on CS42L42 jack detect status.
+        */
+       switch (nid) {
+       case CS8409_CS42L42_HP_PIN_NID:
+               if (verb == AC_VERB_GET_PIN_SENSE) {
+                       *res = (cs42l42->hp_jack_in) ? AC_PINSENSE_PRESENCE : 0;
+                       return 0;
+               }
+               break;
+       case CS8409_CS42L42_AMIC_PIN_NID:
+               if (verb == AC_VERB_GET_PIN_SENSE) {
+                       *res = (cs42l42->mic_jack_in) ? AC_PINSENSE_PRESENCE : 0;
+                       return 0;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return spec->exec_verb(dev, cmd, flags, res);
+}
+
+void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action)
+{
+       struct cs8409_spec *spec = codec->spec;
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
+               snd_hda_add_verbs(codec, cs8409_cs42l42_init_verbs);
+               /* verb exec op override */
+               spec->exec_verb = codec->core.exec_verb;
+               codec->core.exec_verb = cs8409_cs42l42_exec_verb;
+
+               spec->scodecs[CS8409_CODEC0] = &cs8409_cs42l42_codec;
+               spec->num_scodecs = 1;
+               spec->scodecs[CS8409_CODEC0]->codec = codec;
+               codec->patch_ops = cs8409_cs42l42_patch_ops;
+
+               spec->gen.suppress_auto_mute = 1;
+               spec->gen.no_primary_hp = 1;
+               spec->gen.suppress_vmaster = 1;
+
+               /* GPIO 5 out, 3,4 in */
+               spec->gpio_dir = spec->scodecs[CS8409_CODEC0]->reset_gpio;
+               spec->gpio_data = 0;
+               spec->gpio_mask = 0x03f;
+
+               /* Basic initial sequence for specific hw configuration */
+               snd_hda_sequence_write(codec, cs8409_cs42l42_init_verbs);
+
+               cs8409_fix_caps(codec, CS8409_CS42L42_HP_PIN_NID);
+               cs8409_fix_caps(codec, CS8409_CS42L42_AMIC_PIN_NID);
+
+               /* Set TIP_SENSE_EN for analog front-end of tip sense.
+                * Additionally set HSBIAS_SENSE_EN and Full Scale volume for some variants.
+                */
+               switch (codec->fixup_id) {
+               case CS8409_WARLOCK:
+                       spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x0020;
+                       spec->scodecs[CS8409_CODEC0]->full_scale_vol = 1;
+                       break;
+               case CS8409_BULLSEYE:
+                       spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x0020;
+                       spec->scodecs[CS8409_CODEC0]->full_scale_vol = 0;
+                       break;
+               case CS8409_CYBORG:
+                       spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x00a0;
+                       spec->scodecs[CS8409_CODEC0]->full_scale_vol = 1;
+                       break;
+               default:
+                       spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x0003;
+                       spec->scodecs[CS8409_CODEC0]->full_scale_vol = 1;
+                       break;
+               }
+
+               break;
+       case HDA_FIXUP_ACT_PROBE:
+               /* Fix Sample Rate to 48kHz */
+               spec->gen.stream_analog_playback = &cs42l42_48k_pcm_analog_playback;
+               spec->gen.stream_analog_capture = &cs42l42_48k_pcm_analog_capture;
+               /* add hooks */
+               spec->gen.pcm_playback_hook = cs42l42_playback_pcm_hook;
+               spec->gen.pcm_capture_hook = cs42l42_capture_pcm_hook;
+               /* Set initial DMIC volume to -26 dB */
+               snd_hda_codec_amp_init_stereo(codec, CS8409_CS42L42_DMIC_ADC_PIN_NID,
+                                             HDA_INPUT, 0, 0xff, 0x19);
+               snd_hda_gen_add_kctl(&spec->gen, "Headphone Playback Volume",
+                               &cs42l42_dac_volume_mixer);
+               snd_hda_gen_add_kctl(&spec->gen, "Mic Capture Volume",
+                               &cs42l42_adc_volume_mixer);
+               /* Disable Unsolicited Response during boot */
+               cs8409_enable_ur(codec, 0);
+               snd_hda_codec_set_name(codec, "CS8409/CS42L42");
+               break;
+       case HDA_FIXUP_ACT_INIT:
+               cs8409_cs42l42_hw_init(codec);
+               spec->init_done = 1;
+               if (spec->init_done && spec->build_ctrl_done
+                       && !spec->scodecs[CS8409_CODEC0]->hp_jack_in)
+                       cs42l42_run_jack_detect(spec->scodecs[CS8409_CODEC0]);
+               break;
+       case HDA_FIXUP_ACT_BUILD:
+               spec->build_ctrl_done = 1;
+               /* Run jack auto detect first time on boot
+                * after controls have been added, to check if jack has
+                * been already plugged in.
+                * Run immediately after init.
+                */
+               if (spec->init_done && spec->build_ctrl_done
+                       && !spec->scodecs[CS8409_CODEC0]->hp_jack_in)
+                       cs42l42_run_jack_detect(spec->scodecs[CS8409_CODEC0]);
+               break;
+       default:
+               break;
+       }
+}
+
+/******************************************************************************
+ *                          Dolphin Specific Functions
+ *                               CS8409/ 2 X CS42L42
+ ******************************************************************************/
+
+/*
+ * In the case of CS8409 we do not have unsolicited events when
+ * hs mic and hp are connected. Companion codec CS42L42 will
+ * generate interrupt via irq_mask to notify jack events. We have to overwrite
+ * generic snd_hda_jack_unsol_event(), read CS42L42 jack detect status registers
+ * and then notify status via generic snd_hda_jack_unsol_event() call.
+ */
+static void dolphin_jack_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42;
+       struct hda_jack_tbl *jk;
+
+       cs42l42 = spec->scodecs[CS8409_CODEC0];
+       if (!cs42l42->suspended && (~res & cs42l42->irq_mask) &&
+           cs42l42_jack_unsol_event(cs42l42)) {
+               jk = snd_hda_jack_tbl_get_mst(codec, DOLPHIN_HP_PIN_NID, 0);
+               if (jk)
+                       snd_hda_jack_unsol_event(codec,
+                                                (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+                                                 AC_UNSOL_RES_TAG);
+
+               jk = snd_hda_jack_tbl_get_mst(codec, DOLPHIN_AMIC_PIN_NID, 0);
+               if (jk)
+                       snd_hda_jack_unsol_event(codec,
+                                                (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+                                                 AC_UNSOL_RES_TAG);
+       }
+
+       cs42l42 = spec->scodecs[CS8409_CODEC1];
+       if (!cs42l42->suspended && (~res & cs42l42->irq_mask) &&
+           cs42l42_jack_unsol_event(cs42l42)) {
+               jk = snd_hda_jack_tbl_get_mst(codec, DOLPHIN_LO_PIN_NID, 0);
+               if (jk)
+                       snd_hda_jack_unsol_event(codec,
+                                                (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+                                                 AC_UNSOL_RES_TAG);
+       }
+}
+
+/* Vendor specific HW configuration
+ * PLL, ASP, I2C, SPI, GPIOs, DMIC etc...
+ */
+static void dolphin_hw_init(struct hda_codec *codec)
+{
+       const struct cs8409_cir_param *seq = dolphin_hw_cfg;
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42;
+       int i;
+
+       if (spec->gpio_mask) {
+               snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_MASK,
+                                   spec->gpio_mask);
+               snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DIRECTION,
+                                   spec->gpio_dir);
+               snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA,
+                                   spec->gpio_data);
+       }
+
+       for (; seq->nid; seq++)
+               cs8409_vendor_coef_set(codec, seq->cir, seq->coeff);
+
+       for (i = 0; i < spec->num_scodecs; i++) {
+               cs42l42 = spec->scodecs[i];
+               cs42l42_resume(cs42l42);
+       }
+
+       /* Enable Unsolicited Response */
+       cs8409_enable_ur(codec, 1);
+}
+
+static const struct hda_codec_ops cs8409_dolphin_patch_ops = {
+       .build_controls = cs8409_build_controls,
+       .build_pcms = snd_hda_gen_build_pcms,
+       .init = cs8409_init,
+       .free = cs8409_free,
+       .unsol_event = dolphin_jack_unsol_event,
+#ifdef CONFIG_PM
+       .suspend = cs8409_cs42l42_suspend,
+#endif
+};
+
+static int dolphin_exec_verb(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
+                            unsigned int *res)
+{
+       struct hda_codec *codec = container_of(dev, struct hda_codec, core);
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
+
+       unsigned int nid = ((cmd >> 20) & 0x07f);
+       unsigned int verb = ((cmd >> 8) & 0x0fff);
+
+       /* CS8409 pins have no AC_PINSENSE_PRESENCE
+        * capabilities. We have to intercept calls for CS42L42 pins
+        * and return correct pin sense values for read_pin_sense() call from
+        * hda_jack based on CS42L42 jack detect status.
+        */
+       switch (nid) {
+       case DOLPHIN_HP_PIN_NID:
+       case DOLPHIN_LO_PIN_NID:
+               if (nid == DOLPHIN_LO_PIN_NID)
+                       cs42l42 = spec->scodecs[CS8409_CODEC1];
+               if (verb == AC_VERB_GET_PIN_SENSE) {
+                       *res = (cs42l42->hp_jack_in) ? AC_PINSENSE_PRESENCE : 0;
+                       return 0;
+               }
+               break;
+       case DOLPHIN_AMIC_PIN_NID:
+               if (verb == AC_VERB_GET_PIN_SENSE) {
+                       *res = (cs42l42->mic_jack_in) ? AC_PINSENSE_PRESENCE : 0;
+                       return 0;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return spec->exec_verb(dev, cmd, flags, res);
+}
+
+void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action)
+{
+       struct cs8409_spec *spec = codec->spec;
+       struct snd_kcontrol_new *kctrl;
+       int i;
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
+               snd_hda_add_verbs(codec, dolphin_init_verbs);
+               /* verb exec op override */
+               spec->exec_verb = codec->core.exec_verb;
+               codec->core.exec_verb = dolphin_exec_verb;
+
+               spec->scodecs[CS8409_CODEC0] = &dolphin_cs42l42_0;
+               spec->scodecs[CS8409_CODEC0]->codec = codec;
+               spec->scodecs[CS8409_CODEC1] = &dolphin_cs42l42_1;
+               spec->scodecs[CS8409_CODEC1]->codec = codec;
+               spec->num_scodecs = 2;
+
+               codec->patch_ops = cs8409_dolphin_patch_ops;
+
+               /* GPIO 1,5 out, 0,4 in */
+               spec->gpio_dir = spec->scodecs[CS8409_CODEC0]->reset_gpio |
+                                spec->scodecs[CS8409_CODEC1]->reset_gpio;
+               spec->gpio_data = 0;
+               spec->gpio_mask = 0x03f;
+
+               /* Basic initial sequence for specific hw configuration */
+               snd_hda_sequence_write(codec, dolphin_init_verbs);
+
+               snd_hda_jack_add_kctl(codec, DOLPHIN_LO_PIN_NID, "Line Out", true,
+                                     SND_JACK_HEADPHONE, NULL);
+
+               cs8409_fix_caps(codec, DOLPHIN_HP_PIN_NID);
+               cs8409_fix_caps(codec, DOLPHIN_LO_PIN_NID);
+               cs8409_fix_caps(codec, DOLPHIN_AMIC_PIN_NID);
+
+               break;
+       case HDA_FIXUP_ACT_PROBE:
+               /* Fix Sample Rate to 48kHz */
+               spec->gen.stream_analog_playback = &cs42l42_48k_pcm_analog_playback;
+               spec->gen.stream_analog_capture = &cs42l42_48k_pcm_analog_capture;
+               /* add hooks */
+               spec->gen.pcm_playback_hook = cs42l42_playback_pcm_hook;
+               spec->gen.pcm_capture_hook = cs42l42_capture_pcm_hook;
+               snd_hda_gen_add_kctl(&spec->gen, "Headphone Playback Volume",
+                                    &cs42l42_dac_volume_mixer);
+               snd_hda_gen_add_kctl(&spec->gen, "Mic Capture Volume", &cs42l42_adc_volume_mixer);
+               kctrl = snd_hda_gen_add_kctl(&spec->gen, "Line Out Playback Volume",
+                                            &cs42l42_dac_volume_mixer);
+               /* Update Line Out kcontrol template */
+               kctrl->private_value = HDA_COMPOSE_AMP_VAL_OFS(DOLPHIN_HP_PIN_NID, 3, CS8409_CODEC1,
+                                      HDA_OUTPUT, CS42L42_VOL_DAC) | HDA_AMP_VAL_MIN_MUTE;
+               cs8409_enable_ur(codec, 0);
+               snd_hda_codec_set_name(codec, "CS8409/CS42L42");
+               break;
+       case HDA_FIXUP_ACT_INIT:
+               dolphin_hw_init(codec);
+               spec->init_done = 1;
+               if (spec->init_done && spec->build_ctrl_done) {
+                       for (i = 0; i < spec->num_scodecs; i++) {
+                               if (!spec->scodecs[i]->hp_jack_in)
+                                       cs42l42_run_jack_detect(spec->scodecs[i]);
+                       }
+               }
+               break;
+       case HDA_FIXUP_ACT_BUILD:
+               spec->build_ctrl_done = 1;
+               /* Run jack auto detect first time on boot
+                * after controls have been added, to check if jack has
+                * been already plugged in.
+                * Run immediately after init.
+                */
+               if (spec->init_done && spec->build_ctrl_done) {
+                       for (i = 0; i < spec->num_scodecs; i++) {
+                               if (!spec->scodecs[i]->hp_jack_in)
+                                       cs42l42_run_jack_detect(spec->scodecs[i]);
+                       }
+               }
+               break;
+       default:
+               break;
+       }
+}
+
+static int patch_cs8409(struct hda_codec *codec)
+{
+       int err;
+
+       if (!cs8409_alloc_spec(codec))
+               return -ENOMEM;
+
+       snd_hda_pick_fixup(codec, cs8409_models, cs8409_fixup_tbl, cs8409_fixups);
+
+       codec_dbg(codec, "Picked ID=%d, VID=%08x, DEV=%08x\n", codec->fixup_id,
+                        codec->bus->pci->subsystem_vendor,
+                        codec->bus->pci->subsystem_device);
+
+       snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
+
+       err = cs8409_parse_auto_config(codec);
+       if (err < 0) {
+               cs8409_free(codec);
+               return err;
+       }
+
+       snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
+       return 0;
+}
+
+static const struct hda_device_id snd_hda_id_cs8409[] = {
+       HDA_CODEC_ENTRY(0x10138409, "CS8409", patch_cs8409),
+       {} /* terminator */
+};
+MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cs8409);
+
+static struct hda_codec_driver cs8409_driver = {
+       .id = snd_hda_id_cs8409,
+};
+module_hda_codec_driver(cs8409_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cirrus Logic HDA bridge");
diff --git a/sound/pci/hda/patch_cs8409.h b/sound/pci/hda/patch_cs8409.h
new file mode 100644 (file)
index 0000000..ade2b83
--- /dev/null
@@ -0,0 +1,371 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
+ *
+ * Copyright (C) 2021 Cirrus Logic, Inc. and
+ *                    Cirrus Logic International Semiconductor Ltd.
+ */
+
+#ifndef __CS8409_PATCH_H
+#define __CS8409_PATCH_H
+
+#include <linux/pci.h>
+#include <sound/tlv.h>
+#include <linux/workqueue.h>
+#include <sound/hda_codec.h>
+#include "hda_local.h"
+#include "hda_auto_parser.h"
+#include "hda_jack.h"
+#include "hda_generic.h"
+
+/* CS8409 Specific Definitions */
+
+enum cs8409_pins {
+       CS8409_PIN_ROOT,
+       CS8409_PIN_AFG,
+       CS8409_PIN_ASP1_OUT_A,
+       CS8409_PIN_ASP1_OUT_B,
+       CS8409_PIN_ASP1_OUT_C,
+       CS8409_PIN_ASP1_OUT_D,
+       CS8409_PIN_ASP1_OUT_E,
+       CS8409_PIN_ASP1_OUT_F,
+       CS8409_PIN_ASP1_OUT_G,
+       CS8409_PIN_ASP1_OUT_H,
+       CS8409_PIN_ASP2_OUT_A,
+       CS8409_PIN_ASP2_OUT_B,
+       CS8409_PIN_ASP2_OUT_C,
+       CS8409_PIN_ASP2_OUT_D,
+       CS8409_PIN_ASP2_OUT_E,
+       CS8409_PIN_ASP2_OUT_F,
+       CS8409_PIN_ASP2_OUT_G,
+       CS8409_PIN_ASP2_OUT_H,
+       CS8409_PIN_ASP1_IN_A,
+       CS8409_PIN_ASP1_IN_B,
+       CS8409_PIN_ASP1_IN_C,
+       CS8409_PIN_ASP1_IN_D,
+       CS8409_PIN_ASP1_IN_E,
+       CS8409_PIN_ASP1_IN_F,
+       CS8409_PIN_ASP1_IN_G,
+       CS8409_PIN_ASP1_IN_H,
+       CS8409_PIN_ASP2_IN_A,
+       CS8409_PIN_ASP2_IN_B,
+       CS8409_PIN_ASP2_IN_C,
+       CS8409_PIN_ASP2_IN_D,
+       CS8409_PIN_ASP2_IN_E,
+       CS8409_PIN_ASP2_IN_F,
+       CS8409_PIN_ASP2_IN_G,
+       CS8409_PIN_ASP2_IN_H,
+       CS8409_PIN_DMIC1,
+       CS8409_PIN_DMIC2,
+       CS8409_PIN_ASP1_TRANSMITTER_A,
+       CS8409_PIN_ASP1_TRANSMITTER_B,
+       CS8409_PIN_ASP1_TRANSMITTER_C,
+       CS8409_PIN_ASP1_TRANSMITTER_D,
+       CS8409_PIN_ASP1_TRANSMITTER_E,
+       CS8409_PIN_ASP1_TRANSMITTER_F,
+       CS8409_PIN_ASP1_TRANSMITTER_G,
+       CS8409_PIN_ASP1_TRANSMITTER_H,
+       CS8409_PIN_ASP2_TRANSMITTER_A,
+       CS8409_PIN_ASP2_TRANSMITTER_B,
+       CS8409_PIN_ASP2_TRANSMITTER_C,
+       CS8409_PIN_ASP2_TRANSMITTER_D,
+       CS8409_PIN_ASP2_TRANSMITTER_E,
+       CS8409_PIN_ASP2_TRANSMITTER_F,
+       CS8409_PIN_ASP2_TRANSMITTER_G,
+       CS8409_PIN_ASP2_TRANSMITTER_H,
+       CS8409_PIN_ASP1_RECEIVER_A,
+       CS8409_PIN_ASP1_RECEIVER_B,
+       CS8409_PIN_ASP1_RECEIVER_C,
+       CS8409_PIN_ASP1_RECEIVER_D,
+       CS8409_PIN_ASP1_RECEIVER_E,
+       CS8409_PIN_ASP1_RECEIVER_F,
+       CS8409_PIN_ASP1_RECEIVER_G,
+       CS8409_PIN_ASP1_RECEIVER_H,
+       CS8409_PIN_ASP2_RECEIVER_A,
+       CS8409_PIN_ASP2_RECEIVER_B,
+       CS8409_PIN_ASP2_RECEIVER_C,
+       CS8409_PIN_ASP2_RECEIVER_D,
+       CS8409_PIN_ASP2_RECEIVER_E,
+       CS8409_PIN_ASP2_RECEIVER_F,
+       CS8409_PIN_ASP2_RECEIVER_G,
+       CS8409_PIN_ASP2_RECEIVER_H,
+       CS8409_PIN_DMIC1_IN,
+       CS8409_PIN_DMIC2_IN,
+       CS8409_PIN_BEEP_GEN,
+       CS8409_PIN_VENDOR_WIDGET
+};
+
+enum cs8409_coefficient_index_registers {
+       CS8409_DEV_CFG1,
+       CS8409_DEV_CFG2,
+       CS8409_DEV_CFG3,
+       CS8409_ASP1_CLK_CTRL1,
+       CS8409_ASP1_CLK_CTRL2,
+       CS8409_ASP1_CLK_CTRL3,
+       CS8409_ASP2_CLK_CTRL1,
+       CS8409_ASP2_CLK_CTRL2,
+       CS8409_ASP2_CLK_CTRL3,
+       CS8409_DMIC_CFG,
+       CS8409_BEEP_CFG,
+       ASP1_RX_NULL_INS_RMV,
+       ASP1_Rx_RATE1,
+       ASP1_Rx_RATE2,
+       ASP1_Tx_NULL_INS_RMV,
+       ASP1_Tx_RATE1,
+       ASP1_Tx_RATE2,
+       ASP2_Rx_NULL_INS_RMV,
+       ASP2_Rx_RATE1,
+       ASP2_Rx_RATE2,
+       ASP2_Tx_NULL_INS_RMV,
+       ASP2_Tx_RATE1,
+       ASP2_Tx_RATE2,
+       ASP1_SYNC_CTRL,
+       ASP2_SYNC_CTRL,
+       ASP1_A_TX_CTRL1,
+       ASP1_A_TX_CTRL2,
+       ASP1_B_TX_CTRL1,
+       ASP1_B_TX_CTRL2,
+       ASP1_C_TX_CTRL1,
+       ASP1_C_TX_CTRL2,
+       ASP1_D_TX_CTRL1,
+       ASP1_D_TX_CTRL2,
+       ASP1_E_TX_CTRL1,
+       ASP1_E_TX_CTRL2,
+       ASP1_F_TX_CTRL1,
+       ASP1_F_TX_CTRL2,
+       ASP1_G_TX_CTRL1,
+       ASP1_G_TX_CTRL2,
+       ASP1_H_TX_CTRL1,
+       ASP1_H_TX_CTRL2,
+       ASP2_A_TX_CTRL1,
+       ASP2_A_TX_CTRL2,
+       ASP2_B_TX_CTRL1,
+       ASP2_B_TX_CTRL2,
+       ASP2_C_TX_CTRL1,
+       ASP2_C_TX_CTRL2,
+       ASP2_D_TX_CTRL1,
+       ASP2_D_TX_CTRL2,
+       ASP2_E_TX_CTRL1,
+       ASP2_E_TX_CTRL2,
+       ASP2_F_TX_CTRL1,
+       ASP2_F_TX_CTRL2,
+       ASP2_G_TX_CTRL1,
+       ASP2_G_TX_CTRL2,
+       ASP2_H_TX_CTRL1,
+       ASP2_H_TX_CTRL2,
+       ASP1_A_RX_CTRL1,
+       ASP1_A_RX_CTRL2,
+       ASP1_B_RX_CTRL1,
+       ASP1_B_RX_CTRL2,
+       ASP1_C_RX_CTRL1,
+       ASP1_C_RX_CTRL2,
+       ASP1_D_RX_CTRL1,
+       ASP1_D_RX_CTRL2,
+       ASP1_E_RX_CTRL1,
+       ASP1_E_RX_CTRL2,
+       ASP1_F_RX_CTRL1,
+       ASP1_F_RX_CTRL2,
+       ASP1_G_RX_CTRL1,
+       ASP1_G_RX_CTRL2,
+       ASP1_H_RX_CTRL1,
+       ASP1_H_RX_CTRL2,
+       ASP2_A_RX_CTRL1,
+       ASP2_A_RX_CTRL2,
+       ASP2_B_RX_CTRL1,
+       ASP2_B_RX_CTRL2,
+       ASP2_C_RX_CTRL1,
+       ASP2_C_RX_CTRL2,
+       ASP2_D_RX_CTRL1,
+       ASP2_D_RX_CTRL2,
+       ASP2_E_RX_CTRL1,
+       ASP2_E_RX_CTRL2,
+       ASP2_F_RX_CTRL1,
+       ASP2_F_RX_CTRL2,
+       ASP2_G_RX_CTRL1,
+       ASP2_G_RX_CTRL2,
+       ASP2_H_RX_CTRL1,
+       ASP2_H_RX_CTRL2,
+       CS8409_I2C_ADDR,
+       CS8409_I2C_DATA,
+       CS8409_I2C_CTRL,
+       CS8409_I2C_STS,
+       CS8409_I2C_QWRITE,
+       CS8409_I2C_QREAD,
+       CS8409_SPI_CTRL,
+       CS8409_SPI_TX_DATA,
+       CS8409_SPI_RX_DATA,
+       CS8409_SPI_STS,
+       CS8409_PFE_COEF_W1, /* Parametric filter engine coefficient write 1*/
+       CS8409_PFE_COEF_W2,
+       CS8409_PFE_CTRL1,
+       CS8409_PFE_CTRL2,
+       CS8409_PRE_SCALE_ATTN1,
+       CS8409_PRE_SCALE_ATTN2,
+       CS8409_PFE_COEF_MON1, /* Parametric filter engine coefficient monitor 1*/
+       CS8409_PFE_COEF_MON2,
+       CS8409_ASP1_INTRN_STS,
+       CS8409_ASP2_INTRN_STS,
+       CS8409_ASP1_RX_SCLK_COUNT,
+       CS8409_ASP1_TX_SCLK_COUNT,
+       CS8409_ASP2_RX_SCLK_COUNT,
+       CS8409_ASP2_TX_SCLK_COUNT,
+       CS8409_ASP_UNS_RESP_MASK,
+       CS8409_LOOPBACK_CTRL = 0x80,
+       CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */
+};
+
+/* CS42L42 Specific Definitions */
+
+#define CS8409_MAX_CODECS                      8
+#define CS42L42_VOLUMES                                (4U)
+#define CS42L42_HP_VOL_REAL_MIN                        (-63)
+#define CS42L42_HP_VOL_REAL_MAX                        (0)
+#define CS42L42_AMIC_VOL_REAL_MIN              (-97)
+#define CS42L42_AMIC_VOL_REAL_MAX              (12)
+#define CS42L42_REG_HS_VOL_CHA                 (0x2301)
+#define CS42L42_REG_HS_VOL_CHB                 (0x2303)
+#define CS42L42_REG_HS_VOL_MASK                        (0x003F)
+#define CS42L42_REG_AMIC_VOL                   (0x1D03)
+#define CS42L42_REG_AMIC_VOL_MASK              (0x00FF)
+#define CS42L42_HSDET_AUTO_DONE                        (0x02)
+#define CS42L42_HSTYPE_MASK                    (0x03)
+#define CS42L42_JACK_INSERTED                  (0x0C)
+#define CS42L42_JACK_REMOVED                   (0x00)
+#define CS42L42_I2C_TIMEOUT_US                 (20000)
+#define CS42L42_I2C_SLEEP_US                   (2000)
+#define CS42L42_PDN_TIMEOUT_US                 (250000)
+#define CS42L42_PDN_SLEEP_US                   (2000)
+
+/* Dell BULLSEYE / WARLOCK / CYBORG Specific Definitions */
+
+#define CS42L42_I2C_ADDR                       (0x48 << 1)
+#define CS8409_CS42L42_RESET                   GENMASK(5, 5) /* CS8409_GPIO5 */
+#define CS8409_CS42L42_INT                     GENMASK(4, 4) /* CS8409_GPIO4 */
+#define CS8409_CS42L42_HP_PIN_NID              CS8409_PIN_ASP1_TRANSMITTER_A
+#define CS8409_CS42L42_SPK_PIN_NID             CS8409_PIN_ASP2_TRANSMITTER_A
+#define CS8409_CS42L42_AMIC_PIN_NID            CS8409_PIN_ASP1_RECEIVER_A
+#define CS8409_CS42L42_DMIC_PIN_NID            CS8409_PIN_DMIC1_IN
+#define CS8409_CS42L42_DMIC_ADC_PIN_NID                CS8409_PIN_DMIC1
+
+/* Dolphin */
+
+#define DOLPHIN_C0_I2C_ADDR                    (0x48 << 1)
+#define DOLPHIN_C1_I2C_ADDR                    (0x49 << 1)
+#define DOLPHIN_HP_PIN_NID                     CS8409_PIN_ASP1_TRANSMITTER_A
+#define DOLPHIN_LO_PIN_NID                     CS8409_PIN_ASP1_TRANSMITTER_B
+#define DOLPHIN_AMIC_PIN_NID                   CS8409_PIN_ASP1_RECEIVER_A
+
+#define DOLPHIN_C0_INT                         GENMASK(4, 4)
+#define DOLPHIN_C1_INT                         GENMASK(0, 0)
+#define DOLPHIN_C0_RESET                       GENMASK(5, 5)
+#define DOLPHIN_C1_RESET                       GENMASK(1, 1)
+#define DOLPHIN_WAKE                           (DOLPHIN_C0_INT | DOLPHIN_C1_INT)
+
+enum {
+       CS8409_BULLSEYE,
+       CS8409_WARLOCK,
+       CS8409_CYBORG,
+       CS8409_FIXUPS,
+       CS8409_DOLPHIN,
+       CS8409_DOLPHIN_FIXUPS,
+};
+
+enum {
+       CS8409_CODEC0,
+       CS8409_CODEC1
+};
+
+enum {
+       CS42L42_VOL_ADC,
+       CS42L42_VOL_DAC,
+};
+
+#define CS42L42_ADC_VOL_OFFSET                 (CS42L42_VOL_ADC)
+#define CS42L42_DAC_CH0_VOL_OFFSET             (CS42L42_VOL_DAC)
+#define CS42L42_DAC_CH1_VOL_OFFSET             (CS42L42_VOL_DAC + 1)
+
+struct cs8409_i2c_param {
+       unsigned int addr;
+       unsigned int value;
+};
+
+struct cs8409_cir_param {
+       unsigned int nid;
+       unsigned int cir;
+       unsigned int coeff;
+};
+
+struct sub_codec {
+       struct hda_codec *codec;
+       unsigned int addr;
+       unsigned int reset_gpio;
+       unsigned int irq_mask;
+       const struct cs8409_i2c_param *init_seq;
+       unsigned int init_seq_num;
+
+       unsigned int hp_jack_in:1;
+       unsigned int mic_jack_in:1;
+       unsigned int suspended:1;
+       unsigned int paged:1;
+       unsigned int last_page;
+       unsigned int hsbias_hiz;
+       unsigned int full_scale_vol:1;
+       unsigned int no_type_dect:1;
+
+       s8 vol[CS42L42_VOLUMES];
+};
+
+struct cs8409_spec {
+       struct hda_gen_spec gen;
+       struct hda_codec *codec;
+
+       struct sub_codec *scodecs[CS8409_MAX_CODECS];
+       unsigned int num_scodecs;
+
+       unsigned int gpio_mask;
+       unsigned int gpio_dir;
+       unsigned int gpio_data;
+
+       struct mutex i2c_mux;
+       unsigned int i2c_clck_enabled;
+       unsigned int dev_addr;
+       struct delayed_work i2c_clk_work;
+
+       unsigned int playback_started:1;
+       unsigned int capture_started:1;
+       unsigned int init_done:1;
+       unsigned int build_ctrl_done:1;
+
+       /* verb exec op override */
+       int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
+                        unsigned int *res);
+};
+
+extern const struct snd_kcontrol_new cs42l42_dac_volume_mixer;
+extern const struct snd_kcontrol_new cs42l42_adc_volume_mixer;
+
+int cs42l42_volume_info(struct snd_kcontrol *kctrl, struct snd_ctl_elem_info *uinfo);
+int cs42l42_volume_get(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl);
+int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl);
+
+extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_playback;
+extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_capture;
+extern const struct snd_pci_quirk cs8409_fixup_tbl[];
+extern const struct hda_model_fixup cs8409_models[];
+extern const struct hda_fixup cs8409_fixups[];
+extern const struct hda_verb cs8409_cs42l42_init_verbs[];
+extern const struct hda_pintbl cs8409_cs42l42_pincfgs[];
+extern const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[];
+extern const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[];
+extern struct sub_codec cs8409_cs42l42_codec;
+
+extern const struct hda_verb dolphin_init_verbs[];
+extern const struct hda_pintbl dolphin_pincfgs[];
+extern const struct cs8409_cir_param dolphin_hw_cfg[];
+extern struct sub_codec dolphin_cs42l42_0;
+extern struct sub_codec dolphin_cs42l42_1;
+
+void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action);
+void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action);
+
+#endif
index e143e69..65d2c55 100644 (file)
@@ -47,6 +47,10 @@ IS_ENABLED(CONFIG_SND_HDA_INTEL_HDMI_SILENT_STREAM);
 module_param(enable_silent_stream, bool, 0644);
 MODULE_PARM_DESC(enable_silent_stream, "Enable Silent Stream for HDMI devices");
 
+static bool enable_all_pins;
+module_param(enable_all_pins, bool, 0444);
+MODULE_PARM_DESC(enable_all_pins, "Forcibly enable all pins");
+
 struct hdmi_spec_per_cvt {
        hda_nid_t cvt_nid;
        int assigned;
@@ -1959,6 +1963,9 @@ static int hdmi_parse_codec(struct hda_codec *codec)
                return -EINVAL;
        }
 
+       if (enable_all_pins)
+               spec->force_connect = true;
+
        q = snd_pci_quirk_lookup(codec->bus->pci, force_connect_list);
 
        if (q && q->value)
index 7ad689f..8b7a389 100644 (file)
@@ -109,7 +109,6 @@ struct alc_spec {
        void (*power_hook)(struct hda_codec *codec);
 #endif
        void (*shutup)(struct hda_codec *codec);
-       void (*reboot_notify)(struct hda_codec *codec);
 
        int init_amp;
        int codec_variant;      /* flag for other variants */
@@ -897,16 +896,6 @@ static inline void alc_shutup(struct hda_codec *codec)
                alc_shutup_pins(codec);
 }
 
-static void alc_reboot_notify(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-
-       if (spec && spec->reboot_notify)
-               spec->reboot_notify(codec);
-       else
-               alc_shutup(codec);
-}
-
 #define alc_free       snd_hda_gen_free
 
 #ifdef CONFIG_PM
@@ -952,7 +941,6 @@ static const struct hda_codec_ops alc_patch_ops = {
        .suspend = alc_suspend,
        .check_power_status = snd_hda_gen_check_power_status,
 #endif
-       .reboot_notify = alc_reboot_notify,
 };
 
 
@@ -5773,7 +5761,6 @@ static void alc_fixup_tpt440_dock(struct hda_codec *codec,
        struct alc_spec *spec = codec->spec;
 
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
-               spec->reboot_notify = snd_hda_gen_reboot_notify; /* reduce noise */
                spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
                codec->power_save_node = 0; /* avoid click noises */
                snd_hda_apply_pincfgs(codec, pincfgs);
@@ -8438,6 +8425,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x87f2, "HP ProBook 640 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x87f6, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
        SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
        SND_PCI_QUIRK(0x103c, 0x8805, "HP ProBook 650 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x880d, "HP EliteBook 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
@@ -9521,6 +9509,16 @@ static int patch_alc269(struct hda_codec *codec)
 
        snd_hda_pick_fixup(codec, alc269_fixup_models,
                       alc269_fixup_tbl, alc269_fixups);
+       /* FIXME: both TX300 and ROG Strix G17 have the same SSID, and
+        * the quirk breaks the latter (bko#214101).
+        * Clear the wrong entry.
+        */
+       if (codec->fixup_id == ALC282_FIXUP_ASUS_TX300 &&
+           codec->core.vendor_id == 0x10ec0294) {
+               codec_dbg(codec, "Clear wrong fixup for ASUS ROG Strix G17\n");
+               codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
+       }
+
        snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups, true);
        snd_hda_pick_pin_fixup(codec, alc269_fallback_pin_fixup_tbl, alc269_fixups, false);
        snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl,
index 3bd592e..61df4d3 100644 (file)
@@ -4380,18 +4380,6 @@ static int stac_init(struct hda_codec *codec)
        return 0;
 }
 
-static void stac_shutup(struct hda_codec *codec)
-{
-       struct sigmatel_spec *spec = codec->spec;
-
-       snd_hda_shutup_pins(codec);
-
-       if (spec->eapd_mask)
-               stac_gpio_set(codec, spec->gpio_mask,
-                               spec->gpio_dir, spec->gpio_data &
-                               ~spec->eapd_mask);
-}
-
 #define stac_free      snd_hda_gen_free
 
 #ifdef CONFIG_SND_PROC_FS
@@ -4444,7 +4432,15 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer,
 #ifdef CONFIG_PM
 static int stac_suspend(struct hda_codec *codec)
 {
-       stac_shutup(codec);
+       struct sigmatel_spec *spec = codec->spec;
+
+       snd_hda_shutup_pins(codec);
+
+       if (spec->eapd_mask)
+               stac_gpio_set(codec, spec->gpio_mask,
+                               spec->gpio_dir, spec->gpio_data &
+                               ~spec->eapd_mask);
+
        return 0;
 }
 #else
@@ -4460,7 +4456,6 @@ static const struct hda_codec_ops stac_patch_ops = {
 #ifdef CONFIG_PM
        .suspend = stac_suspend,
 #endif
-       .reboot_notify = stac_shutup,
 };
 
 static int alloc_stac_spec(struct hda_codec *codec)
index d54cd51..a5241a2 100644 (file)
@@ -2432,31 +2432,18 @@ static int snd_ice1712_build_controls(struct snd_ice1712 *ice)
                           snd_ctl_new1(&snd_ice1712_mixer_pro_peak, ice));
 }
 
-static int snd_ice1712_free(struct snd_ice1712 *ice)
+static void snd_ice1712_free(struct snd_card *card)
 {
-       if (!ice->port)
-               goto __hw_end;
+       struct snd_ice1712 *ice = card->private_data;
+
+       if (ice->card_info && ice->card_info->chip_exit)
+               ice->card_info->chip_exit(ice);
+
        /* mask all interrupts */
        outb(ICE1712_MULTI_CAPTURE | ICE1712_MULTI_PLAYBACK, ICEMT(ice, IRQ));
        outb(0xff, ICEREG(ice, IRQMASK));
-       /* --- */
-__hw_end:
-       if (ice->irq >= 0)
-               free_irq(ice->irq, ice);
 
-       if (ice->port)
-               pci_release_regions(ice->pci);
        snd_ice1712_akm4xxx_free(ice);
-       pci_disable_device(ice->pci);
-       kfree(ice->spec);
-       kfree(ice);
-       return 0;
-}
-
-static int snd_ice1712_dev_free(struct snd_device *device)
-{
-       struct snd_ice1712 *ice = device->device_data;
-       return snd_ice1712_free(ice);
 }
 
 static int snd_ice1712_create(struct snd_card *card,
@@ -2464,34 +2451,22 @@ static int snd_ice1712_create(struct snd_card *card,
                              const char *modelname,
                              int omni,
                              int cs8427_timeout,
-                             int dxr_enable,
-                             struct snd_ice1712 **r_ice1712)
+                             int dxr_enable)
 {
-       struct snd_ice1712 *ice;
+       struct snd_ice1712 *ice = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_ice1712_dev_free,
-       };
-
-       *r_ice1712 = NULL;
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 28 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
                dev_err(card->dev,
                        "architecture does not support 28bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       ice = kzalloc(sizeof(*ice), GFP_KERNEL);
-       if (ice == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        ice->omni = omni ? 1 : 0;
        if (cs8427_timeout < 1)
                cs8427_timeout = 1;
@@ -2523,45 +2498,29 @@ static int snd_ice1712_create(struct snd_card *card,
        pci_write_config_word(ice->pci, 0x42, 0x0006);
        snd_ice1712_proc_init(ice);
 
-       card->private_data = ice;
-
        err = pci_request_regions(pci, "ICE1712");
-       if (err < 0) {
-               kfree(ice);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        ice->port = pci_resource_start(pci, 0);
        ice->ddma_port = pci_resource_start(pci, 1);
        ice->dmapath_port = pci_resource_start(pci, 2);
        ice->profi_port = pci_resource_start(pci, 3);
 
-       if (request_irq(pci->irq, snd_ice1712_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, ice)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_ice1712_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, ice)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_ice1712_free(ice);
                return -EIO;
        }
 
        ice->irq = pci->irq;
        card->sync_irq = ice->irq;
+       card->private_free = snd_ice1712_free;
 
-       if (snd_ice1712_read_eeprom(ice, modelname) < 0) {
-               snd_ice1712_free(ice);
+       if (snd_ice1712_read_eeprom(ice, modelname) < 0)
                return -EIO;
-       }
-       if (snd_ice1712_chip_init(ice) < 0) {
-               snd_ice1712_free(ice);
+       if (snd_ice1712_chip_init(ice) < 0)
                return -EIO;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops);
-       if (err < 0) {
-               snd_ice1712_free(ice);
-               return err;
-       }
 
-       *r_ice1712 = ice;
        return 0;
 }
 
@@ -2591,34 +2550,31 @@ static int snd_ice1712_probe(struct pci_dev *pci,
        }
 
        err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+                          sizeof(*ice), &card);
        if (err < 0)
                return err;
+       ice = card->private_data;
 
        strcpy(card->driver, "ICE1712");
        strcpy(card->shortname, "ICEnsemble ICE1712");
 
        err = snd_ice1712_create(card, pci, model[dev], omni[dev],
-               cs8427_timeout[dev], dxr_enable[dev], &ice);
-       if (err < 0) {
-               snd_card_free(card);
+                                cs8427_timeout[dev], dxr_enable[dev]);
+       if (err < 0)
                return err;
-       }
 
        for (tbl = card_tables; *tbl; tbl++) {
                for (c = *tbl; c->subvendor; c++) {
                        if (c->subvendor == ice->eeprom.subvendor) {
-                               ice->card_info = c;
                                strcpy(card->shortname, c->name);
                                if (c->driver) /* specific driver? */
                                        strcpy(card->driver, c->driver);
                                if (c->chip_init) {
                                        err = c->chip_init(ice);
-                                       if (err < 0) {
-                                               snd_card_free(card);
+                                       if (err < 0)
                                                return err;
-                                       }
                                }
+                               ice->card_info = c;
                                goto __found;
                        }
                }
@@ -2627,45 +2583,33 @@ static int snd_ice1712_probe(struct pci_dev *pci,
  __found:
 
        err = snd_ice1712_pcm_profi(ice, pcm_dev++);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        if (ice_has_con_ac97(ice)) {
                err = snd_ice1712_pcm(ice, pcm_dev++);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 
        err = snd_ice1712_ac97_mixer(ice);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_ice1712_build_controls(ice);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        if (c->build_controls) {
                err = c->build_controls(ice);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 
        if (ice_has_con_ac97(ice)) {
                err = snd_ice1712_pcm_ds(ice, pcm_dev++);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 
        if (!c->no_mpu401) {
@@ -2674,10 +2618,8 @@ static int snd_ice1712_probe(struct pci_dev *pci,
                        c->mpu401_1_info_flags |
                        MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
                        -1, &ice->rmidi[0]);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
                if (c->mpu401_1_name)
                        /*  Preferred name available in card_info */
                        snprintf(ice->rmidi[0]->name,
@@ -2692,10 +2634,8 @@ static int snd_ice1712_probe(struct pci_dev *pci,
                                MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
                                -1, &ice->rmidi[1]);
 
-                       if (err < 0) {
-                               snd_card_free(card);
+                       if (err < 0)
                                return err;
-                       }
                        if (c->mpu401_2_name)
                                /*  Preferred name available in card_info */
                                snprintf(ice->rmidi[1]->name,
@@ -2711,25 +2651,13 @@ static int snd_ice1712_probe(struct pci_dev *pci,
                card->shortname, ice->port, ice->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_ice1712_remove(struct pci_dev *pci)
-{
-       struct snd_card *card = pci_get_drvdata(pci);
-       struct snd_ice1712 *ice = card->private_data;
-
-       if (ice->card_info && ice->card_info->chip_exit)
-               ice->card_info->chip_exit(ice);
-       snd_card_free(card);
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int snd_ice1712_suspend(struct device *dev)
 {
@@ -2810,7 +2738,6 @@ static struct pci_driver ice1712_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ice1712_ids,
        .probe = snd_ice1712_probe,
-       .remove = snd_ice1712_remove,
        .driver = {
                .pm = SND_VT1712_PM_OPS,
        },
index ef2367d..f627586 100644 (file)
@@ -2150,13 +2150,6 @@ static const struct snd_kcontrol_new snd_vt1724_mixer_pro_peak = {
        .get = snd_vt1724_pro_peak_get
 };
 
-/*
- *
- */
-
-static const struct snd_ice1712_card_info no_matched;
-
-
 /*
   ooAoo cards with no controls
 */
@@ -2454,54 +2447,29 @@ static int snd_vt1724_build_controls(struct snd_ice1712 *ice)
                           snd_ctl_new1(&snd_vt1724_mixer_pro_peak, ice));
 }
 
-static int snd_vt1724_free(struct snd_ice1712 *ice)
+static void snd_vt1724_free(struct snd_card *card)
 {
-       if (!ice->port)
-               goto __hw_end;
+       struct snd_ice1712 *ice = card->private_data;
+
        /* mask all interrupts */
        outb(0xff, ICEMT1724(ice, DMA_INT_MASK));
        outb(0xff, ICEREG1724(ice, IRQMASK));
-       /* --- */
-__hw_end:
-       if (ice->irq >= 0)
-               free_irq(ice->irq, ice);
-       pci_release_regions(ice->pci);
-       snd_ice1712_akm4xxx_free(ice);
-       pci_disable_device(ice->pci);
-       kfree(ice->spec);
-       kfree(ice);
-       return 0;
-}
 
-static int snd_vt1724_dev_free(struct snd_device *device)
-{
-       struct snd_ice1712 *ice = device->device_data;
-       return snd_vt1724_free(ice);
+       snd_ice1712_akm4xxx_free(ice);
 }
 
 static int snd_vt1724_create(struct snd_card *card,
                             struct pci_dev *pci,
-                            const char *modelname,
-                            struct snd_ice1712 **r_ice1712)
+                            const char *modelname)
 {
-       struct snd_ice1712 *ice;
+       struct snd_ice1712 *ice = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_vt1724_dev_free,
-       };
-
-       *r_ice1712 = NULL;
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       ice = kzalloc(sizeof(*ice), GFP_KERNEL);
-       if (ice == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        ice->vt1724 = 1;
        spin_lock_init(&ice->reg_lock);
        mutex_init(&ice->gpio_mutex);
@@ -2519,44 +2487,28 @@ static int snd_vt1724_create(struct snd_card *card,
        pci_set_master(pci);
        snd_vt1724_proc_init(ice);
 
-       card->private_data = ice;
-
        err = pci_request_regions(pci, "ICE1724");
-       if (err < 0) {
-               kfree(ice);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        ice->port = pci_resource_start(pci, 0);
        ice->profi_port = pci_resource_start(pci, 1);
 
-       if (request_irq(pci->irq, snd_vt1724_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, ice)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_vt1724_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, ice)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_vt1724_free(ice);
                return -EIO;
        }
 
        ice->irq = pci->irq;
        card->sync_irq = ice->irq;
+       card->private_free = snd_vt1724_free;
 
        snd_vt1724_chip_reset(ice);
-       if (snd_vt1724_read_eeprom(ice, modelname) < 0) {
-               snd_vt1724_free(ice);
+       if (snd_vt1724_read_eeprom(ice, modelname) < 0)
                return -EIO;
-       }
-       if (snd_vt1724_chip_init(ice) < 0) {
-               snd_vt1724_free(ice);
+       if (snd_vt1724_chip_init(ice) < 0)
                return -EIO;
-       }
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops);
-       if (err < 0) {
-               snd_vt1724_free(ice);
-               return err;
-       }
-
-       *r_ice1712 = ice;
        return 0;
 }
 
@@ -2574,7 +2526,7 @@ static int snd_vt1724_probe(struct pci_dev *pci,
        struct snd_card *card;
        struct snd_ice1712 *ice;
        int pcm_dev = 0, err;
-       const struct snd_ice1712_card_info * const *tbl, *c;
+       const struct snd_ice1712_card_info *c;
 
        if (dev >= SNDRV_CARDS)
                return -ENODEV;
@@ -2583,44 +2535,34 @@ static int snd_vt1724_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*ice), &card);
        if (err < 0)
                return err;
+       ice = card->private_data;
 
        strcpy(card->driver, "ICE1724");
        strcpy(card->shortname, "ICEnsemble ICE1724");
 
-       err = snd_vt1724_create(card, pci, model[dev], &ice);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_vt1724_create(card, pci, model[dev]);
+       if (err < 0)
                return err;
-       }
 
        /* field init before calling chip_init */
        ice->ext_clock_count = 0;
 
-       for (tbl = card_tables; *tbl; tbl++) {
-               for (c = *tbl; c->name; c++) {
-                       if ((model[dev] && c->model &&
-                            !strcmp(model[dev], c->model)) ||
-                           (c->subvendor == ice->eeprom.subvendor)) {
-                               strcpy(card->shortname, c->name);
-                               if (c->driver) /* specific driver? */
-                                       strcpy(card->driver, c->driver);
-                               if (c->chip_init) {
-                                       err = c->chip_init(ice);
-                                       if (err < 0) {
-                                               snd_card_free(card);
-                                               return err;
-                                       }
-                               }
-                               goto __found;
-                       }
+       c = ice->card_info;
+       if (c) {
+               strcpy(card->shortname, c->name);
+               if (c->driver) /* specific driver? */
+                       strcpy(card->driver, c->driver);
+               if (c->chip_init) {
+                       err = c->chip_init(ice);
+                       if (err < 0)
+                               return err;
                }
        }
-       c = &no_matched;
-__found:
+
        /*
        * VT1724 has separate DMAs for the analog and the SPDIF streams while
        * ICE1712 has only one for both (mixed up).
@@ -2651,60 +2593,44 @@ __found:
                set_std_hw_rates(ice);
 
        err = snd_vt1724_pcm_profi(ice, pcm_dev++);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_vt1724_pcm_spdif(ice, pcm_dev++);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_vt1724_pcm_indep(ice, pcm_dev++);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_vt1724_ac97_mixer(ice);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_vt1724_build_controls(ice);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        if (ice->pcm && ice->has_spdif) { /* has SPDIF I/O */
                err = snd_vt1724_spdif_build_controls(ice);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 
-       if (c->build_controls) {
+       if (c && c->build_controls) {
                err = c->build_controls(ice);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 
-       if (!c->no_mpu401) {
+       if (!c || !c->no_mpu401) {
                if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {
                        struct snd_rawmidi *rmidi;
 
                        err = snd_rawmidi_new(card, "MIDI", 0, 1, 1, &rmidi);
-                       if (err < 0) {
-                               snd_card_free(card);
+                       if (err < 0)
                                return err;
-                       }
                        ice->rmidi[0] = rmidi;
                        rmidi->private_data = ice;
                        strcpy(rmidi->name, "ICE1724 MIDI");
@@ -2729,25 +2655,13 @@ __found:
                card->shortname, ice->port, ice->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_vt1724_remove(struct pci_dev *pci)
-{
-       struct snd_card *card = pci_get_drvdata(pci);
-       struct snd_ice1712 *ice = card->private_data;
-
-       if (ice->card_info && ice->card_info->chip_exit)
-               ice->card_info->chip_exit(ice);
-       snd_card_free(card);
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int snd_vt1724_suspend(struct device *dev)
 {
@@ -2825,7 +2739,6 @@ static struct pci_driver vt1724_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_vt1724_ids,
        .probe = snd_vt1724_probe,
-       .remove = snd_vt1724_remove,
        .driver = {
                .pm = SND_VT1724_PM_OPS,
        },
index df3ba5c..a51032b 100644 (file)
@@ -378,7 +378,7 @@ struct intel8x0 {
        spinlock_t reg_lock;
        
        u32 bdbars_count;
-       struct snd_dma_buffer bdbars;
+       struct snd_dma_buffer *bdbars;
        u32 int_sta_reg;                /* interrupt status register */
        u32 int_sta_mask;               /* interrupt status mask */
 };
@@ -1427,7 +1427,7 @@ struct ich_pcm_table {
 };
 
 #define intel8x0_dma_type(chip) \
-       ((chip)->fix_nocache ? SNDRV_DMA_TYPE_DEV_UC : SNDRV_DMA_TYPE_DEV)
+       ((chip)->fix_nocache ? SNDRV_DMA_TYPE_DEV_WC : SNDRV_DMA_TYPE_DEV)
 
 static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
                             const struct ich_pcm_table *rec)
@@ -2528,8 +2528,9 @@ static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing)
        return 0;
 }
 
-static int snd_intel8x0_free(struct intel8x0 *chip)
+static void snd_intel8x0_free(struct snd_card *card)
 {
+       struct intel8x0 *chip = card->private_data;
        unsigned int i;
 
        if (chip->irq < 0)
@@ -2552,16 +2553,6 @@ static int snd_intel8x0_free(struct intel8x0 *chip)
       __hw_end:
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
-       if (chip->bdbars.area)
-               snd_dma_free_pages(&chip->bdbars);
-       if (chip->addr)
-               pci_iounmap(chip->pci, chip->addr);
-       if (chip->bmaddr)
-               pci_iounmap(chip->pci, chip->bmaddr);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -2656,6 +2647,8 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip)
 
        if (chip->ac97_bus->clock != 48000)
                return; /* specified in module option */
+       if (chip->inside_vm && !ac97_clock)
+               return; /* no measurement on VM */
 
       __again:
        subs = chip->pcm[0]->streams[0].substream;
@@ -2829,12 +2822,6 @@ static void snd_intel8x0_proc_init(struct intel8x0 *chip)
                             snd_intel8x0_proc_read);
 }
 
-static int snd_intel8x0_dev_free(struct snd_device *device)
-{
-       struct intel8x0 *chip = device->device_data;
-       return snd_intel8x0_free(chip);
-}
-
 struct ich_reg_info {
        unsigned int int_sta_mask;
        unsigned int offset;
@@ -2878,19 +2865,15 @@ fini:
        return result;
 }
 
-static int snd_intel8x0_create(struct snd_card *card,
-                              struct pci_dev *pci,
-                              unsigned long device_type,
-                              struct intel8x0 **r_intel8x0)
+static int snd_intel8x0_init(struct snd_card *card,
+                            struct pci_dev *pci,
+                            unsigned long device_type)
 {
-       struct intel8x0 *chip;
+       struct intel8x0 *chip = card->private_data;
        int err;
        unsigned int i;
        unsigned int int_sta_masks;
        struct ichdev *ichdev;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_intel8x0_dev_free,
-       };
 
        static const unsigned int bdbars[] = {
                3, /* DEVICE_INTEL */
@@ -2923,17 +2906,10 @@ static int snd_intel8x0_create(struct snd_card *card,
        };
        const struct ich_reg_info *tbl;
 
-       *r_intel8x0 = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&chip->reg_lock);
        chip->device_type = device_type;
        chip->card = card;
@@ -2959,38 +2935,23 @@ static int snd_intel8x0_create(struct snd_card *card,
                chip->fix_nocache = 1; /* enable workaround */
 
        err = pci_request_regions(pci, card->shortname);
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
 
        if (device_type == DEVICE_ALI) {
                /* ALI5455 has no ac97 region */
-               chip->bmaddr = pci_iomap(pci, 0, 0);
-               goto port_inited;
-       }
-
-       if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
-               chip->addr = pci_iomap(pci, 2, 0);
-       else
-               chip->addr = pci_iomap(pci, 0, 0);
-       if (!chip->addr) {
-               dev_err(card->dev, "AC'97 space ioremap problem\n");
-               snd_intel8x0_free(chip);
-               return -EIO;
+               chip->bmaddr = pcim_iomap(pci, 0, 0);
+       } else {
+               if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
+                       chip->addr = pcim_iomap(pci, 2, 0);
+               else
+                       chip->addr = pcim_iomap(pci, 0, 0);
+               if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
+                       chip->bmaddr = pcim_iomap(pci, 3, 0);
+               else
+                       chip->bmaddr = pcim_iomap(pci, 1, 0);
        }
-       if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
-               chip->bmaddr = pci_iomap(pci, 3, 0);
-       else
-               chip->bmaddr = pci_iomap(pci, 1, 0);
 
- port_inited:
-       if (!chip->bmaddr) {
-               dev_err(card->dev, "Controller space ioremap problem\n");
-               snd_intel8x0_free(chip);
-               return -EIO;
-       }
        chip->bdbars_count = bdbars[device_type];
 
        /* initialize offsets */
@@ -3026,21 +2987,20 @@ static int snd_intel8x0_create(struct snd_card *card,
 
        /* allocate buffer descriptor lists */
        /* the start of each lists must be aligned to 8 bytes */
-       if (snd_dma_alloc_pages(intel8x0_dma_type(chip), &pci->dev,
-                               chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
-                               &chip->bdbars) < 0) {
-               snd_intel8x0_free(chip);
-               dev_err(card->dev, "cannot allocate buffer descriptors\n");
+       chip->bdbars = snd_devm_alloc_pages(&pci->dev, intel8x0_dma_type(chip),
+                                           chip->bdbars_count * sizeof(u32) *
+                                           ICH_MAX_FRAGS * 2);
+       if (!chip->bdbars)
                return -ENOMEM;
-       }
+
        /* tables must be aligned to 8 bytes here, but the kernel pages
           are much bigger, so we don't care (on i386) */
        int_sta_masks = 0;
        for (i = 0; i < chip->bdbars_count; i++) {
                ichdev = &chip->ichd[i];
-               ichdev->bdbar = ((__le32 *)chip->bdbars.area) +
+               ichdev->bdbar = ((__le32 *)chip->bdbars->area) +
                        (i * ICH_MAX_FRAGS * 2);
-               ichdev->bdbar_addr = chip->bdbars.addr +
+               ichdev->bdbar_addr = chip->bdbars->addr +
                        (i * sizeof(u32) * ICH_MAX_FRAGS * 2);
                int_sta_masks |= ichdev->int_sta_mask;
        }
@@ -3074,28 +3034,24 @@ static int snd_intel8x0_create(struct snd_card *card,
                chip->codec_isr_bits |= chip->codec_bit[i];
 
        err = snd_intel8x0_chip_init(chip, 1);
-       if (err < 0) {
-               snd_intel8x0_free(chip);
+       if (err < 0)
                return err;
-       }
 
        /* request irq after initializaing int_sta_mask, etc */
+       /* NOTE: we don't use devm version here since it's released /
+        * re-acquired in PM callbacks.
+        * It's released explicitly in snd_intel8x0_free(), too.
+        */
        if (request_irq(pci->irq, snd_intel8x0_interrupt,
                        IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_intel8x0_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_intel8x0_free(chip);
-               return err;
-       }
+       card->private_free = snd_intel8x0_free;
 
-       *r_intel8x0 = chip;
        return 0;
 }
 
@@ -3161,9 +3117,11 @@ static int snd_intel8x0_probe(struct pci_dev *pci,
        int err;
        struct shortname_table *name;
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        if (spdif_aclink < 0)
                spdif_aclink = check_default_spdif_aclink(pci);
@@ -3197,23 +3155,16 @@ static int snd_intel8x0_probe(struct pci_dev *pci,
                        buggy_irq = 0;
        }
 
-       err = snd_intel8x0_create(card, pci, pci_id->driver_data, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_intel8x0_init(card, pci, pci_id->driver_data);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        err = snd_intel8x0_mixer(chip, ac97_clock, ac97_quirk);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_intel8x0_pcm(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        
        snd_intel8x0_proc_init(chip);
 
@@ -3231,24 +3182,17 @@ static int snd_intel8x0_probe(struct pci_dev *pci,
        }
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
+
        pci_set_drvdata(pci, card);
        return 0;
 }
 
-static void snd_intel8x0_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver intel8x0_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_intel8x0_ids,
        .probe = snd_intel8x0_probe,
-       .remove = snd_intel8x0_remove,
        .driver = {
                .pm = INTEL8X0_PM_OPS,
        },
index b96fce6..7de3cb2 100644 (file)
@@ -182,7 +182,7 @@ struct intel8x0m {
 
        spinlock_t reg_lock;
        
-       struct snd_dma_buffer bdbars;
+       struct snd_dma_buffer *bdbars;
        u32 bdbars_count;
        u32 int_sta_reg;                /* interrupt status register */
        u32 int_sta_mask;               /* interrupt status mask */
@@ -947,8 +947,9 @@ static int snd_intel8x0m_chip_init(struct intel8x0m *chip, int probing)
        return 0;
 }
 
-static int snd_intel8x0m_free(struct intel8x0m *chip)
+static void snd_intel8x0m_free(struct snd_card *card)
 {
+       struct intel8x0m *chip = card->private_data;
        unsigned int i;
 
        if (chip->irq < 0)
@@ -962,16 +963,6 @@ static int snd_intel8x0m_free(struct intel8x0m *chip)
  __hw_end:
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
-       if (chip->bdbars.area)
-               snd_dma_free_pages(&chip->bdbars);
-       if (chip->addr)
-               pci_iounmap(chip->pci, chip->addr);
-       if (chip->bmaddr)
-               pci_iounmap(chip->pci, chip->bmaddr);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -1047,47 +1038,30 @@ static void snd_intel8x0m_proc_init(struct intel8x0m *chip)
                             snd_intel8x0m_proc_read);
 }
 
-static int snd_intel8x0m_dev_free(struct snd_device *device)
-{
-       struct intel8x0m *chip = device->device_data;
-       return snd_intel8x0m_free(chip);
-}
-
 struct ich_reg_info {
        unsigned int int_sta_mask;
        unsigned int offset;
 };
 
-static int snd_intel8x0m_create(struct snd_card *card,
-                               struct pci_dev *pci,
-                               unsigned long device_type,
-                               struct intel8x0m **r_intel8x0m)
+static int snd_intel8x0m_init(struct snd_card *card,
+                             struct pci_dev *pci,
+                             unsigned long device_type)
 {
-       struct intel8x0m *chip;
+       struct intel8x0m *chip = card->private_data;
        int err;
        unsigned int i;
        unsigned int int_sta_masks;
        struct ichdev *ichdev;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_intel8x0m_dev_free,
-       };
        static const struct ich_reg_info intel_regs[2] = {
                { ICH_MIINT, 0 },
                { ICH_MOINT, 0x10 },
        };
        const struct ich_reg_info *tbl;
 
-       *r_intel8x0m = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&chip->reg_lock);
        chip->device_type = device_type;
        chip->card = card;
@@ -1095,37 +1069,21 @@ static int snd_intel8x0m_create(struct snd_card *card,
        chip->irq = -1;
 
        err = pci_request_regions(pci, card->shortname);
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
 
        if (device_type == DEVICE_ALI) {
                /* ALI5455 has no ac97 region */
-               chip->bmaddr = pci_iomap(pci, 0, 0);
-               goto port_inited;
-       }
-
-       if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
-               chip->addr = pci_iomap(pci, 2, 0);
-       else
-               chip->addr = pci_iomap(pci, 0, 0);
-       if (!chip->addr) {
-               dev_err(card->dev, "AC'97 space ioremap problem\n");
-               snd_intel8x0m_free(chip);
-               return -EIO;
-       }
-       if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
-               chip->bmaddr = pci_iomap(pci, 3, 0);
-       else
-               chip->bmaddr = pci_iomap(pci, 1, 0);
-
-port_inited:
-       if (!chip->bmaddr) {
-               dev_err(card->dev, "Controller space ioremap problem\n");
-               snd_intel8x0m_free(chip);
-               return -EIO;
+               chip->bmaddr = pcim_iomap(pci, 0, 0);
+       } else {
+               if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
+                       chip->addr = pcim_iomap(pci, 2, 0);
+               else
+                       chip->addr = pcim_iomap(pci, 0, 0);
+               if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
+                       chip->bmaddr = pcim_iomap(pci, 3, 0);
+               else
+                       chip->bmaddr = pcim_iomap(pci, 1, 0);
        }
 
        /* initialize offsets */
@@ -1153,19 +1111,19 @@ port_inited:
 
        /* allocate buffer descriptor lists */
        /* the start of each lists must be aligned to 8 bytes */
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
-                               &chip->bdbars) < 0) {
-               snd_intel8x0m_free(chip);
+       chip->bdbars = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+                                           chip->bdbars_count * sizeof(u32) *
+                                           ICH_MAX_FRAGS * 2);
+       if (!chip->bdbars)
                return -ENOMEM;
-       }
+
        /* tables must be aligned to 8 bytes here, but the kernel pages
           are much bigger, so we don't care (on i386) */
        int_sta_masks = 0;
        for (i = 0; i < chip->bdbars_count; i++) {
                ichdev = &chip->ichd[i];
-               ichdev->bdbar = ((__le32 *)chip->bdbars.area) + (i * ICH_MAX_FRAGS * 2);
-               ichdev->bdbar_addr = chip->bdbars.addr + (i * sizeof(u32) * ICH_MAX_FRAGS * 2);
+               ichdev->bdbar = ((__le32 *)chip->bdbars->area) + (i * ICH_MAX_FRAGS * 2);
+               ichdev->bdbar_addr = chip->bdbars->addr + (i * sizeof(u32) * ICH_MAX_FRAGS * 2);
                int_sta_masks |= ichdev->int_sta_mask;
        }
        chip->int_sta_reg = ICH_REG_GLOB_STA;
@@ -1174,27 +1132,23 @@ port_inited:
        pci_set_master(pci);
 
        err = snd_intel8x0m_chip_init(chip, 1);
-       if (err < 0) {
-               snd_intel8x0m_free(chip);
+       if (err < 0)
                return err;
-       }
 
+       /* NOTE: we don't use devm version here since it's released /
+        * re-acquired in PM callbacks.
+        * It's released explicitly in snd_intel8x0m_free(), too.
+        */
        if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED,
                        KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_intel8x0m_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_intel8x0m_free(chip);
-               return err;
-       }
+       card->private_free = snd_intel8x0m_free;
 
-       *r_intel8x0m = chip;
        return 0;
 }
 
@@ -1232,9 +1186,11 @@ static int snd_intel8x0m_probe(struct pci_dev *pci,
        int err;
        struct shortname_table *name;
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        strcpy(card->driver, "ICH-MODEM");
        strcpy(card->shortname, "Intel ICH");
@@ -1246,23 +1202,16 @@ static int snd_intel8x0m_probe(struct pci_dev *pci,
        }
        strcat(card->shortname," Modem");
 
-       err = snd_intel8x0m_create(card, pci, pci_id->driver_data, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_intel8x0m_init(card, pci, pci_id->driver_data);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        err = snd_intel8x0m_mixer(chip, ac97_clock);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_intel8x0m_pcm(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        
        snd_intel8x0m_proc_init(chip);
 
@@ -1270,24 +1219,16 @@ static int snd_intel8x0m_probe(struct pci_dev *pci,
                card->shortname, chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        return 0;
 }
 
-static void snd_intel8x0m_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver intel8x0m_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_intel8x0m_ids,
        .probe = snd_intel8x0m_probe,
-       .remove = snd_intel8x0m_remove,
        .driver = {
                .pm = INTEL8X0M_PM_OPS,
        },
index 030e01b..5c9e240 100644 (file)
@@ -320,10 +320,10 @@ struct snd_korg1212 {
         unsigned long inIRQ;
         void __iomem *iobase;
 
-       struct snd_dma_buffer dma_dsp;
-        struct snd_dma_buffer dma_play;
-        struct snd_dma_buffer dma_rec;
-       struct snd_dma_buffer dma_shared;
+       struct snd_dma_buffer *dma_dsp;
+       struct snd_dma_buffer *dma_play;
+       struct snd_dma_buffer *dma_rec;
+       struct snd_dma_buffer *dma_shared;
 
        u32 DataBufsSize;
 
@@ -1200,8 +1200,8 @@ static int snd_korg1212_downloadDSPCode(struct snd_korg1212 *korg1212)
         snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_IN_PROCESS);
 
         rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_StartDSPDownload,
-                                     UpperWordSwap(korg1212->dma_dsp.addr),
-                                     0, 0, 0);
+                                         UpperWordSwap(korg1212->dma_dsp->addr),
+                                         0, 0, 0);
        if (rc)
                K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n",
                                   rc, stateName[korg1212->cardState]);
@@ -1382,7 +1382,7 @@ static int snd_korg1212_playback_open(struct snd_pcm_substream *substream)
        snd_korg1212_OpenCard(korg1212);
 
         runtime->hw = snd_korg1212_playback_info;
-       snd_pcm_set_runtime_buffer(substream, &korg1212->dma_play);
+       snd_pcm_set_runtime_buffer(substream, korg1212->dma_play);
 
         spin_lock_irqsave(&korg1212->lock, flags);
 
@@ -1413,7 +1413,7 @@ static int snd_korg1212_capture_open(struct snd_pcm_substream *substream)
        snd_korg1212_OpenCard(korg1212);
 
         runtime->hw = snd_korg1212_capture_info;
-       snd_pcm_set_runtime_buffer(substream, &korg1212->dma_rec);
+       snd_pcm_set_runtime_buffer(substream, korg1212->dma_rec);
 
         spin_lock_irqsave(&korg1212->lock, flags);
 
@@ -2080,96 +2080,30 @@ static void snd_korg1212_proc_init(struct snd_korg1212 *korg1212)
                             snd_korg1212_proc_read);
 }
 
-static int
-snd_korg1212_free(struct snd_korg1212 *korg1212)
+static void
+snd_korg1212_free(struct snd_card *card)
 {
-        snd_korg1212_TurnOffIdleMonitor(korg1212);
-
-        if (korg1212->irq >= 0) {
-                snd_korg1212_DisableCardInterrupts(korg1212);
-                free_irq(korg1212->irq, korg1212);
-                korg1212->irq = -1;
-        }
-        
-        if (korg1212->iobase != NULL) {
-                iounmap(korg1212->iobase);
-                korg1212->iobase = NULL;
-        }
-        
-       pci_release_regions(korg1212->pci);
-
-        // ----------------------------------------------------
-        // free up memory resources used for the DSP download.
-        // ----------------------------------------------------
-        if (korg1212->dma_dsp.area) {
-               snd_dma_free_pages(&korg1212->dma_dsp);
-               korg1212->dma_dsp.area = NULL;
-        }
-
-#ifndef K1212_LARGEALLOC
-
-        // ------------------------------------------------------
-        // free up memory resources used for the Play/Rec Buffers
-        // ------------------------------------------------------
-       if (korg1212->dma_play.area) {
-               snd_dma_free_pages(&korg1212->dma_play);
-               korg1212->dma_play.area = NULL;
-        }
+       struct snd_korg1212 *korg1212 = card->private_data;
 
-       if (korg1212->dma_rec.area) {
-               snd_dma_free_pages(&korg1212->dma_rec);
-               korg1212->dma_rec.area = NULL;
-        }
-
-#endif
-
-        // ----------------------------------------------------
-        // free up memory resources used for the Shared Buffers
-        // ----------------------------------------------------
-       if (korg1212->dma_shared.area) {
-               snd_dma_free_pages(&korg1212->dma_shared);
-               korg1212->dma_shared.area = NULL;
-        }
-        
-       pci_disable_device(korg1212->pci);
-        kfree(korg1212);
-        return 0;
+       snd_korg1212_TurnOffIdleMonitor(korg1212);
+       snd_korg1212_DisableCardInterrupts(korg1212);
 }
 
-static int snd_korg1212_dev_free(struct snd_device *device)
-{
-        struct snd_korg1212 *korg1212 = device->device_data;
-        K1212_DEBUG_PRINTK("K1212_DEBUG: Freeing device\n");
-       return snd_korg1212_free(korg1212);
-}
-
-static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
-                              struct snd_korg1212 **rchip)
+static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci)
 
 {
         int err, rc;
         unsigned int i;
-       unsigned iomem_size;
+       __maybe_unused unsigned iomem_size;
        __maybe_unused unsigned ioport_size;
        __maybe_unused unsigned iomem2_size;
-        struct snd_korg1212 * korg1212;
+       struct snd_korg1212 *korg1212 = card->private_data;
        const struct firmware *dsp_code;
 
-       static const struct snd_device_ops ops = {
-                .dev_free = snd_korg1212_dev_free,
-        };
-
-        * rchip = NULL;
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                 return err;
 
-        korg1212 = kzalloc(sizeof(*korg1212), GFP_KERNEL);
-        if (korg1212 == NULL) {
-               pci_disable_device(pci);
-                return -ENOMEM;
-       }
-
        korg1212->card = card;
        korg1212->pci = pci;
 
@@ -2198,12 +2132,9 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
         for (i=0; i<kAudioChannels; i++)
                 korg1212->volumePhase[i] = 0;
 
-       err = pci_request_regions(pci, "korg1212");
-       if (err < 0) {
-               kfree(korg1212);
-               pci_disable_device(pci);
+       err = pcim_iomap_regions_request_all(pci, 1 << 0, "korg1212");
+       if (err < 0)
                return err;
-       }
 
         korg1212->iomem = pci_resource_start(korg1212->pci, 0);
         korg1212->ioport = pci_resource_start(korg1212->pci, 1);
@@ -2223,26 +2154,20 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
                   korg1212->iomem2, iomem2_size,
                   stateName[korg1212->cardState]);
 
-       korg1212->iobase = ioremap(korg1212->iomem, iomem_size);
-       if (!korg1212->iobase) {
-               snd_printk(KERN_ERR "korg1212: unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem,
-                           korg1212->iomem + iomem_size - 1);
-                snd_korg1212_free(korg1212);
-                return -EBUSY;
-        }
+       korg1212->iobase = pcim_iomap_table(pci)[0];
 
-        err = request_irq(pci->irq, snd_korg1212_interrupt,
+       err = devm_request_irq(&pci->dev, pci->irq, snd_korg1212_interrupt,
                           IRQF_SHARED,
                           KBUILD_MODNAME, korg1212);
 
         if (err) {
                snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq);
-                snd_korg1212_free(korg1212);
                 return -EBUSY;
         }
 
         korg1212->irq = pci->irq;
        card->sync_irq = korg1212->irq;
+       card->private_free = snd_korg1212_free;
 
        pci_set_master(korg1212->pci);
 
@@ -2281,41 +2206,36 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
                    korg1212->idRegPtr,
                   stateName[korg1212->cardState]);
 
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               sizeof(struct KorgSharedBuffer), &korg1212->dma_shared) < 0) {
-               snd_printk(KERN_ERR "korg1212: can not allocate shared buffer memory (%zd bytes)\n", sizeof(struct KorgSharedBuffer));
-                snd_korg1212_free(korg1212);
-                return -ENOMEM;
-        }
-        korg1212->sharedBufferPtr = (struct KorgSharedBuffer *)korg1212->dma_shared.area;
-        korg1212->sharedBufferPhy = korg1212->dma_shared.addr;
+       korg1212->dma_shared = snd_devm_alloc_pages(&pci->dev,
+                                                   SNDRV_DMA_TYPE_DEV,
+                                                   sizeof(struct KorgSharedBuffer));
+       if (!korg1212->dma_shared)
+               return -ENOMEM;
+       korg1212->sharedBufferPtr = (struct KorgSharedBuffer *)korg1212->dma_shared->area;
+       korg1212->sharedBufferPhy = korg1212->dma_shared->addr;
 
         K1212_DEBUG_PRINTK("K1212_DEBUG: Shared Buffer Area = 0x%p (0x%08lx), %d bytes\n", korg1212->sharedBufferPtr, korg1212->sharedBufferPhy, sizeof(struct KorgSharedBuffer));
 
 #ifndef K1212_LARGEALLOC
-
         korg1212->DataBufsSize = sizeof(struct KorgAudioBuffer) * kNumBuffers;
+       korg1212->dma_play = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+                                                 korg1212->DataBufsSize);
+       if (!korg1212->dma_play)
+               return -ENOMEM;
 
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               korg1212->DataBufsSize, &korg1212->dma_play) < 0) {
-               snd_printk(KERN_ERR "korg1212: can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
-                snd_korg1212_free(korg1212);
-                return -ENOMEM;
-        }
-       korg1212->playDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_play.area;
-       korg1212->PlayDataPhy = korg1212->dma_play.addr;
+       korg1212->playDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_play->area;
+       korg1212->PlayDataPhy = korg1212->dma_play->addr;
 
         K1212_DEBUG_PRINTK("K1212_DEBUG: Play Data Area = 0x%p (0x%08x), %d bytes\n",
                korg1212->playDataBufsPtr, korg1212->PlayDataPhy, korg1212->DataBufsSize);
 
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               korg1212->DataBufsSize, &korg1212->dma_rec) < 0) {
-               snd_printk(KERN_ERR "korg1212: can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
-                snd_korg1212_free(korg1212);
-                return -ENOMEM;
-        }
-        korg1212->recordDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_rec.area;
-        korg1212->RecDataPhy = korg1212->dma_rec.addr;
+       korg1212->dma_rec = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+                                                korg1212->DataBufsSize);
+       if (!korg1212->dma_rec)
+               return -ENOMEM;
+
+       korg1212->recordDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_rec->area;
+       korg1212->RecDataPhy = korg1212->dma_rec->addr;
 
         K1212_DEBUG_PRINTK("K1212_DEBUG: Record Data Area = 0x%p (0x%08x), %d bytes\n",
                korg1212->recordDataBufsPtr, korg1212->RecDataPhy, korg1212->DataBufsSize);
@@ -2339,23 +2259,21 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
        err = request_firmware(&dsp_code, "korg/k1212.dsp", &pci->dev);
        if (err < 0) {
                snd_printk(KERN_ERR "firmware not available\n");
-               snd_korg1212_free(korg1212);
                return err;
        }
 
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               dsp_code->size, &korg1212->dma_dsp) < 0) {
-               snd_printk(KERN_ERR "korg1212: cannot allocate dsp code memory (%zd bytes)\n", dsp_code->size);
-                snd_korg1212_free(korg1212);
+       korg1212->dma_dsp = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+                                                dsp_code->size);
+       if (!korg1212->dma_dsp) {
                release_firmware(dsp_code);
-                return -ENOMEM;
-        }
+               return -ENOMEM;
+       }
 
         K1212_DEBUG_PRINTK("K1212_DEBUG: DSP Code area = 0x%p (0x%08x) %d bytes [%s]\n",
-                  korg1212->dma_dsp.area, korg1212->dma_dsp.addr, dsp_code->size,
+                  korg1212->dma_dsp->area, korg1212->dma_dsp->addr, dsp_code->size,
                   stateName[korg1212->cardState]);
 
-       memcpy(korg1212->dma_dsp.area, dsp_code->data, dsp_code->size);
+       memcpy(korg1212->dma_dsp->area, dsp_code->data, dsp_code->size);
 
        release_firmware(dsp_code);
 
@@ -2364,12 +2282,6 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
        if (rc)
                K1212_DEBUG_PRINTK("K1212_DEBUG: Reboot Card - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, korg1212, &ops);
-       if (err < 0) {
-                snd_korg1212_free(korg1212);
-                return err;
-        }
-        
        snd_korg1212_EnableCardInterrupts(korg1212);
 
        mdelay(CARD_BOOT_DELAY_IN_MS);
@@ -2411,10 +2323,8 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
         }
 
         snd_korg1212_proc_init(korg1212);
-        
-        * rchip = korg1212;
-       return 0;
 
+       return 0;
 }
 
 /*
@@ -2437,16 +2347,15 @@ snd_korg1212_probe(struct pci_dev *pci,
                dev++;
                return -ENOENT;
        }
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*korg1212), &card);
        if (err < 0)
                return err;
+       korg1212 = card->private_data;
 
-       err = snd_korg1212_create(card, pci, &korg1212);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_korg1212_create(card, pci);
+       if (err < 0)
                return err;
-       }
 
        strcpy(card->driver, "korg1212");
        strcpy(card->shortname, "korg1212");
@@ -2456,25 +2365,17 @@ snd_korg1212_probe(struct pci_dev *pci,
         K1212_DEBUG_PRINTK("K1212_DEBUG: %s\n", card->longname);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_korg1212_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver korg1212_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_korg1212_ids,
        .probe = snd_korg1212_probe,
-       .remove = snd_korg1212_remove,
 };
 
 module_pci_driver(korg1212_driver);
index 03b4be4..5269a1d 100644 (file)
@@ -344,20 +344,18 @@ static void lola_irq_disable(struct lola *chip)
 
 static int setup_corb_rirb(struct lola *chip)
 {
-       int err;
        unsigned char tmp;
        unsigned long end_time;
 
-       err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-                                 &chip->pci->dev,
-                                 PAGE_SIZE, &chip->rb);
-       if (err < 0)
-               return err;
+       chip->rb = snd_devm_alloc_pages(&chip->pci->dev, SNDRV_DMA_TYPE_DEV,
+                                       PAGE_SIZE);
+       if (!chip->rb)
+               return -ENOMEM;
 
-       chip->corb.addr = chip->rb.addr;
-       chip->corb.buf = (__le32 *)chip->rb.area;
-       chip->rirb.addr = chip->rb.addr + 2048;
-       chip->rirb.buf = (__le32 *)(chip->rb.area + 2048);
+       chip->corb.addr = chip->rb->addr;
+       chip->corb.buf = (__le32 *)chip->rb->area;
+       chip->rirb.addr = chip->rb->addr + 2048;
+       chip->rirb.buf = (__le32 *)(chip->rb->area + 2048);
 
        /* disable ringbuffer DMAs */
        lola_writeb(chip, BAR0, RIRBCTL, 0);
@@ -529,56 +527,31 @@ static void lola_stop_hw(struct lola *chip)
        lola_irq_disable(chip);
 }
 
-static void lola_free(struct lola *chip)
+static void lola_free(struct snd_card *card)
 {
+       struct lola *chip = card->private_data;
+
        if (chip->initialized)
                lola_stop_hw(chip);
-       lola_free_pcm(chip);
        lola_free_mixer(chip);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, (void *)chip);
-       iounmap(chip->bar[0].remap_addr);
-       iounmap(chip->bar[1].remap_addr);
-       if (chip->rb.area)
-               snd_dma_free_pages(&chip->rb);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
 }
 
-static int lola_dev_free(struct snd_device *device)
+static int lola_create(struct snd_card *card, struct pci_dev *pci, int dev)
 {
-       lola_free(device->device_data);
-       return 0;
-}
-
-static int lola_create(struct snd_card *card, struct pci_dev *pci,
-                      int dev, struct lola **rchip)
-{
-       struct lola *chip;
+       struct lola *chip = card->private_data;
        int err;
        unsigned int dever;
-       static const struct snd_device_ops ops = {
-               .dev_free = lola_dev_free,
-       };
 
-       *rchip = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (!chip) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&chip->reg_lock);
        mutex_init(&chip->open_mutex);
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
+       card->private_free = lola_free;
 
        chip->granularity = granularity[dev];
        switch (chip->granularity) {
@@ -607,34 +580,25 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
                chip->sample_rate_min = 16000;
        }
 
-       err = pci_request_regions(pci, DRVNAME);
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       err = pcim_iomap_regions(pci, (1 << 0) | (1 << 2), DRVNAME);
+       if (err < 0)
                return err;
-       }
 
        chip->bar[0].addr = pci_resource_start(pci, 0);
-       chip->bar[0].remap_addr = pci_ioremap_bar(pci, 0);
+       chip->bar[0].remap_addr = pcim_iomap_table(pci)[0];
        chip->bar[1].addr = pci_resource_start(pci, 2);
-       chip->bar[1].remap_addr = pci_ioremap_bar(pci, 2);
-       if (!chip->bar[0].remap_addr || !chip->bar[1].remap_addr) {
-               dev_err(chip->card->dev, "ioremap error\n");
-               err = -ENXIO;
-               goto errout;
-       }
+       chip->bar[1].remap_addr = pcim_iomap_table(pci)[2];
 
        pci_set_master(pci);
 
        err = reset_controller(chip);
        if (err < 0)
-               goto errout;
+               return err;
 
-       if (request_irq(pci->irq, lola_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, lola_interrupt, IRQF_SHARED,
+                            KBUILD_MODNAME, chip)) {
                dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq);
-               err = -EBUSY;
-               goto errout;
+               return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
@@ -653,19 +617,12 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
            (!chip->pcm[CAPT].num_streams &&
             !chip->pcm[PLAY].num_streams)) {
                dev_err(chip->card->dev, "invalid DEVER = %x\n", dever);
-               err = -EINVAL;
-               goto errout;
+               return -EINVAL;
        }
 
        err = setup_corb_rirb(chip);
        if (err < 0)
-               goto errout;
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               dev_err(chip->card->dev, "Error creating device [card]!\n");
-               goto errout;
-       }
+               return err;
 
        strcpy(card->driver, "Lola");
        strscpy(card->shortname, "Digigram Lola", sizeof(card->shortname));
@@ -677,12 +634,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
        lola_irq_enable(chip);
 
        chip->initialized = 1;
-       *rchip = chip;
        return 0;
-
- errout:
-       lola_free(chip);
-       return err;
 }
 
 static int lola_probe(struct pci_dev *pci,
@@ -700,47 +652,39 @@ static int lola_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0) {
                dev_err(&pci->dev, "Error creating card!\n");
                return err;
        }
+       chip = card->private_data;
 
-       err = lola_create(card, pci, dev, &chip);
+       err = lola_create(card, pci, dev);
        if (err < 0)
-               goto out_free;
-       card->private_data = chip;
+               return err;
 
        err = lola_parse_tree(chip);
        if (err < 0)
-               goto out_free;
+               return err;
 
        err = lola_create_pcm(chip);
        if (err < 0)
-               goto out_free;
+               return err;
 
        err = lola_create_mixer(chip);
        if (err < 0)
-               goto out_free;
+               return err;
 
        lola_proc_debug_new(chip);
 
        err = snd_card_register(card);
        if (err < 0)
-               goto out_free;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
-       return err;
-out_free:
-       snd_card_free(card);
-       return err;
-}
-
-static void lola_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
+       return 0;
 }
 
 /* PCI IDs */
@@ -755,7 +699,6 @@ static struct pci_driver lola_driver = {
        .name = KBUILD_MODNAME,
        .id_table = lola_ids,
        .probe = lola_probe,
-       .remove = lola_remove,
 };
 
 module_pci_driver(lola_driver);
index 8a598aa..0ff772c 100644 (file)
@@ -303,7 +303,7 @@ struct lola_stream {
 
 struct lola_pcm {
        unsigned int num_streams;
-       struct snd_dma_buffer bdl; /* BDL buffer */
+       struct snd_dma_buffer *bdl; /* BDL buffer */
        struct lola_stream streams[MAX_STREAM_COUNT];
 };
 
@@ -328,7 +328,7 @@ struct lola {
        unsigned int last_cmd_nid, last_verb, last_data, last_extdata;
 
        /* CORB/RIRB buffers */
-       struct snd_dma_buffer rb;
+       struct snd_dma_buffer *rb;
 
        /* unsolicited events */
        unsigned int last_unsol_res;
@@ -480,7 +480,6 @@ int lola_codec_flush(struct lola *chip);
 
 /* PCM */
 int lola_create_pcm(struct lola *chip);
-void lola_free_pcm(struct lola *chip);
 int lola_init_pcm(struct lola *chip, int dir, int *nidp);
 void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits);
 
index 684faaf..738ec98 100644 (file)
@@ -348,7 +348,7 @@ static int lola_setup_periods(struct lola *chip, struct lola_pcm *pcm,
        periods = str->bufsize / period_bytes;
 
        /* program the initial BDL entries */
-       bdl = (__le32 *)(pcm->bdl.area + LOLA_BDL_ENTRY_SIZE * str->index);
+       bdl = (__le32 *)(pcm->bdl->area + LOLA_BDL_ENTRY_SIZE * str->index);
        ofs = 0;
        str->frags = 0;
        for (i = 0; i < periods; i++) {
@@ -433,7 +433,7 @@ static int lola_setup_controller(struct lola *chip, struct lola_pcm *pcm,
                return -EINVAL;
 
        /* set up BDL */
-       bdl = pcm->bdl.addr + LOLA_BDL_ENTRY_SIZE * str->index;
+       bdl = pcm->bdl->addr + LOLA_BDL_ENTRY_SIZE * str->index;
        lola_dsd_write(chip, str->dsd, BDPL, (u32)bdl);
        lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(bdl));
        /* program the stream LVI (last valid index) of the BDL */
@@ -588,11 +588,11 @@ int lola_create_pcm(struct lola *chip)
        int i, err;
 
        for (i = 0; i < 2; i++) {
-               err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-                                         &chip->pci->dev,
-                                         PAGE_SIZE, &chip->pcm[i].bdl);
-               if (err < 0)
-                       return err;
+               chip->pcm[i].bdl =
+                       snd_devm_alloc_pages(&chip->pci->dev, SNDRV_DMA_TYPE_DEV,
+                                            PAGE_SIZE);
+               if (!chip->pcm[i].bdl)
+                       return -ENOMEM;
        }
 
        err = snd_pcm_new(chip->card, "Digigram Lola", 0,
@@ -614,12 +614,6 @@ int lola_create_pcm(struct lola *chip)
        return 0;
 }
 
-void lola_free_pcm(struct lola *chip)
-{
-       snd_dma_free_pages(&chip->pcm[0].bdl);
-       snd_dma_free_pages(&chip->pcm[1].bdl);
-}
-
 /*
  */
 
index 1be97c3..168a108 100644 (file)
@@ -524,29 +524,11 @@ static int lx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        return lx_pcm_trigger_dispatch(chip, stream, cmd);
 }
 
-static int snd_lx6464es_free(struct lx6464es *chip)
+static void snd_lx6464es_free(struct snd_card *card)
 {
-       dev_dbg(chip->card->dev, "->snd_lx6464es_free\n");
+       struct lx6464es *chip = card->private_data;
 
        lx_irq_disable(chip);
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-
-       iounmap(chip->port_dsp_bar);
-       ioport_unmap(chip->port_plx_remapped);
-
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-
-       kfree(chip);
-
-       return 0;
-}
-
-static int snd_lx6464es_dev_free(struct snd_device *device)
-{
-       return snd_lx6464es_free(device->device_data);
 }
 
 /* reset the dsp during initialization */
@@ -930,22 +912,15 @@ static int lx_proc_create(struct snd_card *card, struct lx6464es *chip)
 
 
 static int snd_lx6464es_create(struct snd_card *card,
-                              struct pci_dev *pci,
-                              struct lx6464es **rchip)
+                              struct pci_dev *pci)
 {
-       struct lx6464es *chip;
+       struct lx6464es *chip = card->private_data;
        int err;
 
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_lx6464es_dev_free,
-       };
-
        dev_dbg(card->dev, "->snd_lx6464es_create\n");
 
-       *rchip = NULL;
-
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
@@ -956,16 +931,9 @@ static int snd_lx6464es_create(struct snd_card *card,
        if (err < 0) {
                dev_err(card->dev,
                        "architecture does not support 32bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               err = -ENOMEM;
-               goto alloc_failed;
-       }
-
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
@@ -978,33 +946,30 @@ static int snd_lx6464es_create(struct snd_card *card,
        /* request resources */
        err = pci_request_regions(pci, card_name);
        if (err < 0)
-               goto request_regions_failed;
+               return err;
 
        /* plx port */
        chip->port_plx = pci_resource_start(pci, 1);
-       chip->port_plx_remapped = ioport_map(chip->port_plx,
-                                            pci_resource_len(pci, 1));
+       chip->port_plx_remapped = devm_ioport_map(&pci->dev, chip->port_plx,
+                                                 pci_resource_len(pci, 1));
+       if (!chip->port_plx_remapped)
+               return -ENOMEM;
 
        /* dsp port */
-       chip->port_dsp_bar = pci_ioremap_bar(pci, 2);
-       if (!chip->port_dsp_bar) {
-               dev_err(card->dev, "cannot remap PCI memory region\n");
-               err = -ENOMEM;
-               goto remap_pci_failed;
-       }
+       chip->port_dsp_bar = pcim_iomap(pci, 2, 0);
+       if (!chip->port_dsp_bar)
+               return -ENOMEM;
 
-       err = request_threaded_irq(pci->irq, lx_interrupt, lx_threaded_irq,
-                                  IRQF_SHARED, KBUILD_MODNAME, chip);
+       err = devm_request_threaded_irq(&pci->dev, pci->irq, lx_interrupt,
+                                       lx_threaded_irq, IRQF_SHARED,
+                                       KBUILD_MODNAME, chip);
        if (err) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               goto request_irq_failed;
+               return err;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto device_new_failed;
+       card->private_free = snd_lx6464es_free;
 
        err = lx_init_dsp(chip);
        if (err < 0) {
@@ -1025,25 +990,7 @@ static int snd_lx6464es_create(struct snd_card *card,
        if (err < 0)
                return err;
 
-       *rchip = chip;
        return 0;
-
-device_new_failed:
-       free_irq(pci->irq, chip);
-
-request_irq_failed:
-       iounmap(chip->port_dsp_bar);
-
-remap_pci_failed:
-       pci_release_regions(pci);
-
-request_regions_failed:
-       kfree(chip);
-
-alloc_failed:
-       pci_disable_device(pci);
-
-       return err;
 }
 
 static int snd_lx6464es_probe(struct pci_dev *pci,
@@ -1063,15 +1010,16 @@ static int snd_lx6464es_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       err = snd_lx6464es_create(card, pci, &chip);
+       err = snd_lx6464es_create(card, pci);
        if (err < 0) {
                dev_err(card->dev, "error during snd_lx6464es_create\n");
-               goto out_free;
+               return err;
        }
 
        strcpy(card->driver, "LX6464ES");
@@ -1088,30 +1036,18 @@ static int snd_lx6464es_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto out_free;
+               return err;
 
        dev_dbg(chip->card->dev, "initialization successful\n");
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
-out_free:
-       snd_card_free(card);
-       return err;
-
 }
 
-static void snd_lx6464es_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
-
 static struct pci_driver lx6464es_driver = {
        .name =     KBUILD_MODNAME,
        .id_table = snd_lx6464es_ids,
        .probe =    snd_lx6464es_probe,
-       .remove = snd_lx6464es_remove,
 };
 
 module_pci_driver(lx6464es_driver);
index 77a484b..056838e 100644 (file)
@@ -2339,16 +2339,13 @@ snd_m3_enable_ints(struct snd_m3 *chip)
 /*
  */
 
-static int snd_m3_free(struct snd_m3 *chip)
+static void snd_m3_free(struct snd_card *card)
 {
+       struct snd_m3 *chip = card->private_data;
        struct m3_dma *s;
        int i;
 
        cancel_work_sync(&chip->hwvol_work);
-#ifdef CONFIG_SND_MAESTRO3_INPUT
-       if (chip->input_dev)
-               input_unregister_device(chip->input_dev);
-#endif
 
        if (chip->substreams) {
                spin_lock_irq(&chip->reg_lock);
@@ -2359,7 +2356,6 @@ static int snd_m3_free(struct snd_m3 *chip)
                                snd_m3_pcm_stop(chip, s, s->substream);
                }
                spin_unlock_irq(&chip->reg_lock);
-               kfree(chip->substreams);
        }
        if (chip->iobase) {
                outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */
@@ -2368,19 +2364,8 @@ static int snd_m3_free(struct snd_m3 *chip)
 #ifdef CONFIG_PM_SLEEP
        vfree(chip->suspend_mem);
 #endif
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-
-       if (chip->iobase)
-               pci_release_regions(chip->pci);
-
        release_firmware(chip->assp_kernel_image);
        release_firmware(chip->assp_minisrc_image);
-
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
 }
 
 
@@ -2473,7 +2458,7 @@ static int snd_m3_input_register(struct snd_m3 *chip)
        struct input_dev *input_dev;
        int err;
 
-       input_dev = input_allocate_device();
+       input_dev = devm_input_allocate_device(&chip->pci->dev);
        if (!input_dev)
                return -ENOMEM;
 
@@ -2493,10 +2478,8 @@ static int snd_m3_input_register(struct snd_m3 *chip)
        __set_bit(KEY_VOLUMEUP, input_dev->keybit);
 
        err = input_register_device(input_dev);
-       if (err) {
-               input_free_device(input_dev);
+       if (err)
                return err;
-       }
 
        chip->input_dev = input_dev;
        return 0;
@@ -2506,44 +2489,25 @@ static int snd_m3_input_register(struct snd_m3 *chip)
 /*
  */
 
-static int snd_m3_dev_free(struct snd_device *device)
-{
-       struct snd_m3 *chip = device->device_data;
-       return snd_m3_free(chip);
-}
-
 static int
 snd_m3_create(struct snd_card *card, struct pci_dev *pci,
              int enable_amp,
-             int amp_gpio,
-             struct snd_m3 **chip_ret)
+             int amp_gpio)
 {
-       struct snd_m3 *chip;
+       struct snd_m3 *chip = card->private_data;
        int i, err;
        const struct snd_pci_quirk *quirk;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_m3_dev_free,
-       };
 
-       *chip_ret = NULL;
-
-       if (pci_enable_device(pci))
+       if (pcim_enable_device(pci))
                return -EIO;
 
        /* check, if we can restrict PCI DMA transfers to 28 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
                dev_err(card->dev,
                        "architecture does not support 28bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&chip->reg_lock);
 
        switch (pci->device) {
@@ -2559,6 +2523,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
        chip->pci = pci;
        chip->irq = -1;
        INIT_WORK(&chip->hwvol_work, snd_m3_update_hw_volume);
+       card->private_free = snd_m3_free;
 
        chip->external_amp = enable_amp;
        if (amp_gpio >= 0 && amp_gpio <= 0x0f)
@@ -2588,27 +2553,24 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
                chip->is_omnibook = 1;
 
        chip->num_substreams = NR_DSPS;
-       chip->substreams = kcalloc(chip->num_substreams, sizeof(struct m3_dma),
-                                  GFP_KERNEL);
-       if (chip->substreams == NULL) {
-               kfree(chip);
-               pci_disable_device(pci);
+       chip->substreams = devm_kcalloc(&pci->dev, chip->num_substreams,
+                                       sizeof(struct m3_dma), GFP_KERNEL);
+       if (!chip->substreams)
                return -ENOMEM;
-       }
 
        err = request_firmware(&chip->assp_kernel_image,
                               "ess/maestro3_assp_kernel.fw", &pci->dev);
        if (err < 0)
-               goto free_chip;
+               return err;
 
        err = request_firmware(&chip->assp_minisrc_image,
                               "ess/maestro3_assp_minisrc.fw", &pci->dev);
        if (err < 0)
-               goto free_chip;
+               return err;
 
        err = pci_request_regions(pci, card->driver);
        if (err < 0)
-               goto free_chip;
+               return err;
 
        chip->iobase = pci_resource_start(pci, 0);
        
@@ -2624,11 +2586,10 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
 
        snd_m3_hv_init(chip);
 
-       if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_m3_interrupt, IRQF_SHARED,
+                            KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               err = -ENOMEM;
-               goto free_chip;
+               return -ENOMEM;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
@@ -2642,10 +2603,6 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
                dev_warn(card->dev, "can't allocate apm buffer\n");
 #endif
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto free_chip;
-
        err = snd_m3_mixer(chip);
        if (err < 0)
                return err;
@@ -2674,13 +2631,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
        snd_m3_enable_ints(chip);
        snd_m3_assp_continue(chip);
 
-       *chip_ret = chip;
-
        return 0; 
-
-free_chip:
-       snd_m3_free(chip);
-       return err;
 }
 
 /*
@@ -2704,10 +2655,11 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        switch (pci->device) {
        case PCI_DEVICE_ID_ESS_ALLEGRO:
@@ -2723,11 +2675,9 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                break;
        }
 
-       err = snd_m3_create(card, pci, external_amp[dev], amp_gpio[dev], &chip);
+       err = snd_m3_create(card, pci, external_amp[dev], amp_gpio[dev]);
        if (err < 0)
-               goto free_card;
-
-       card->private_data = chip;
+               return err;
 
        sprintf(card->shortname, "ESS %s PCI", card->driver);
        sprintf(card->longname, "%s at 0x%lx, irq %d",
@@ -2735,7 +2685,7 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto free_card;
+               return err;
 
 #if 0 /* TODO: not supported yet */
        /* TODO enable MIDI IRQ and I/O */
@@ -2750,22 +2700,12 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
-free_card:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_m3_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver m3_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_m3_ids,
        .probe = snd_m3_probe,
-       .remove = snd_m3_remove,
        .driver = {
                .pm = M3_PM_OPS,
        },
index 12d02d7..c9c1785 100644 (file)
@@ -193,11 +193,9 @@ struct nm256 {
        struct snd_card *card;
 
        void __iomem *cport;            /* control port */
-       struct resource *res_cport;     /* its resource */
        unsigned long cport_addr;       /* physical address */
 
        void __iomem *buffer;           /* buffer */
-       struct resource *res_buffer;    /* its resource */
        unsigned long buffer_addr;      /* buffer phyiscal address */
 
        u32 buffer_start;               /* start offset from pci resource 0 */
@@ -1313,8 +1311,9 @@ snd_nm256_mixer(struct nm256 *chip)
                .read = snd_nm256_ac97_read,
        };
 
-       chip->ac97_regs = kcalloc(ARRAY_SIZE(nm256_ac97_init_val),
-                                 sizeof(short), GFP_KERNEL);
+       chip->ac97_regs = devm_kcalloc(chip->card->dev,
+                                      ARRAY_SIZE(nm256_ac97_init_val),
+                                      sizeof(short), GFP_KERNEL);
        if (! chip->ac97_regs)
                return -ENOMEM;
 
@@ -1437,56 +1436,27 @@ static SIMPLE_DEV_PM_OPS(nm256_pm, nm256_suspend, nm256_resume);
 #define NM256_PM_OPS   NULL
 #endif /* CONFIG_PM_SLEEP */
 
-static int snd_nm256_free(struct nm256 *chip)
+static void snd_nm256_free(struct snd_card *card)
 {
+       struct nm256 *chip = card->private_data;
+
        if (chip->streams[SNDRV_PCM_STREAM_PLAYBACK].running)
                snd_nm256_playback_stop(chip);
        if (chip->streams[SNDRV_PCM_STREAM_CAPTURE].running)
                snd_nm256_capture_stop(chip);
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-
-       iounmap(chip->cport);
-       iounmap(chip->buffer);
-       release_and_free_resource(chip->res_cport);
-       release_and_free_resource(chip->res_buffer);
-
-       pci_disable_device(chip->pci);
-       kfree(chip->ac97_regs);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_nm256_dev_free(struct snd_device *device)
-{
-       struct nm256 *chip = device->device_data;
-       return snd_nm256_free(chip);
 }
 
 static int
-snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
-                struct nm256 **chip_ret)
+snd_nm256_create(struct snd_card *card, struct pci_dev *pci)
 {
-       struct nm256 *chip;
+       struct nm256 *chip = card->private_data;
        int err, pval;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_nm256_dev_free,
-       };
        u32 addr;
 
-       *chip_ret = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
        chip->pci = pci;
        chip->use_cache = use_cache;
@@ -1508,22 +1478,17 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
        chip->buffer_addr = pci_resource_start(pci, 0);
        chip->cport_addr = pci_resource_start(pci, 1);
 
+       err = pci_request_regions(pci, card->driver);
+       if (err < 0)
+               return err;
+
        /* Init the memory port info.  */
        /* remap control port (#2) */
-       chip->res_cport = request_mem_region(chip->cport_addr, NM_PORT2_SIZE,
-                                            card->driver);
-       if (chip->res_cport == NULL) {
-               dev_err(card->dev, "memory region 0x%lx (size 0x%x) busy\n",
-                          chip->cport_addr, NM_PORT2_SIZE);
-               err = -EBUSY;
-               goto __error;
-       }
-       chip->cport = ioremap(chip->cport_addr, NM_PORT2_SIZE);
-       if (chip->cport == NULL) {
+       chip->cport = devm_ioremap(&pci->dev, chip->cport_addr, NM_PORT2_SIZE);
+       if (!chip->cport) {
                dev_err(card->dev, "unable to map control port %lx\n",
                        chip->cport_addr);
-               err = -ENOMEM;
-               goto __error;
+               return -ENOMEM;
        }
 
        if (!strcmp(card->driver, "NM256AV")) {
@@ -1539,8 +1504,7 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
                                        " force_ac97=1\n");
                                dev_err(card->dev,
                                        "or try sb16, opl3sa2, or cs423x drivers instead.\n");
-                               err = -ENXIO;
-                               goto __error;
+                               return -ENXIO;
                        }
                }
                chip->buffer_end = 2560 * 1024;
@@ -1572,7 +1536,7 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
                /* get buffer end pointer from signature */
                err = snd_nm256_peek_for_sig(chip);
                if (err < 0)
-                       goto __error;
+                       return err;
        }
 
        chip->buffer_start = chip->buffer_end - chip->buffer_size;
@@ -1581,21 +1545,12 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
        dev_info(card->dev, "Mapping port 1 from 0x%x - 0x%x\n",
               chip->buffer_start, chip->buffer_end);
 
-       chip->res_buffer = request_mem_region(chip->buffer_addr,
-                                             chip->buffer_size,
-                                             card->driver);
-       if (chip->res_buffer == NULL) {
-               dev_err(card->dev, "buffer 0x%lx (size 0x%x) busy\n",
-                          chip->buffer_addr, chip->buffer_size);
-               err = -EBUSY;
-               goto __error;
-       }
-       chip->buffer = ioremap(chip->buffer_addr, chip->buffer_size);
-       if (chip->buffer == NULL) {
-               err = -ENOMEM;
+       chip->buffer = devm_ioremap(&pci->dev, chip->buffer_addr,
+                                   chip->buffer_size);
+       if (!chip->buffer) {
                dev_err(card->dev, "unable to map ring buffer at %lx\n",
                        chip->buffer_addr);
-               goto __error;
+               return -ENOMEM;
        }
 
        /* set offsets */
@@ -1618,19 +1573,10 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
        chip->coeffs_current = 0;
 
        snd_nm256_init_chip(chip);
+       card->private_free = snd_nm256_free;
 
        // pci_set_master(pci); /* needed? */
-       
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto __error;
-
-       *chip_ret = chip;
        return 0;
-
-__error:
-       snd_nm256_free(chip);
-       return err;
 }
 
 
@@ -1673,9 +1619,11 @@ static int snd_nm256_probe(struct pci_dev *pci,
                }
        }
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        switch (pci->device) {
        case PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO:
@@ -1689,7 +1637,6 @@ static int snd_nm256_probe(struct pci_dev *pci,
                break;
        default:
                dev_err(&pci->dev, "invalid device id 0x%x\n", pci->device);
-               snd_card_free(card);
                return -EINVAL;
        }
 
@@ -1704,12 +1651,9 @@ static int snd_nm256_probe(struct pci_dev *pci,
                capture_bufsize = 4;
        if (capture_bufsize > 128)
                capture_bufsize = 128;
-       err = snd_nm256_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_nm256_create(card, pci);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        if (reset_workaround) {
                dev_dbg(&pci->dev, "reset_workaround activated\n");
@@ -1722,15 +1666,11 @@ static int snd_nm256_probe(struct pci_dev *pci,
        }
 
        err = snd_nm256_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_nm256_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        sprintf(card->shortname, "NeoMagic %s", card->driver);
        sprintf(card->longname, "%s at 0x%lx & 0x%lx, irq %d",
@@ -1738,26 +1678,17 @@ static int snd_nm256_probe(struct pci_dev *pci,
                chip->buffer_addr, chip->cport_addr, chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        return 0;
 }
 
-static void snd_nm256_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
-
 static struct pci_driver nm256_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_nm256_ids,
        .probe = snd_nm256_probe,
-       .remove = snd_nm256_remove,
        .driver = {
                .pm = NM256_PM_OPS,
        },
index e335c4b..c346f42 100644 (file)
@@ -854,7 +854,6 @@ static struct pci_driver oxygen_driver = {
        .name = KBUILD_MODNAME,
        .id_table = oxygen_ids,
        .probe = generic_oxygen_probe,
-       .remove = oxygen_pci_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &oxygen_pci_pm,
index 06bf7e5..0cae640 100644 (file)
@@ -161,7 +161,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
                                      const struct pci_device_id *id
                                     )
                    );
-void oxygen_pci_remove(struct pci_dev *pci);
 #ifdef CONFIG_PM_SLEEP
 extern const struct dev_pm_ops oxygen_pci_pm;
 #endif
index afc6dd3..4fb3f24 100644 (file)
@@ -570,15 +570,10 @@ static void oxygen_card_free(struct snd_card *card)
        struct oxygen *chip = card->private_data;
 
        oxygen_shutdown(chip);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
        flush_work(&chip->spdif_input_bits_work);
        flush_work(&chip->gpio_work);
        chip->model.cleanup(chip);
-       kfree(chip->model_data);
        mutex_destroy(&chip->mutex);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
 }
 
 int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
@@ -594,8 +589,8 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
        const struct pci_device_id *pci_id;
        int err;
 
-       err = snd_card_new(&pci->dev, index, id, owner,
-                          sizeof(*chip), &card);
+       err = snd_devm_card_new(&pci->dev, index, id, owner,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
 
@@ -610,41 +605,38 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
        INIT_WORK(&chip->gpio_work, oxygen_gpio_changed);
        init_waitqueue_head(&chip->ac97_waitqueue);
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
-               goto err_card;
+               return err;
 
        err = pci_request_regions(pci, DRIVER);
        if (err < 0) {
                dev_err(card->dev, "cannot reserve PCI resources\n");
-               goto err_pci_enable;
+               return err;
        }
 
        if (!(pci_resource_flags(pci, 0) & IORESOURCE_IO) ||
            pci_resource_len(pci, 0) < OXYGEN_IO_SIZE) {
                dev_err(card->dev, "invalid PCI I/O range\n");
-               err = -ENXIO;
-               goto err_pci_regions;
+               return -ENXIO;
        }
        chip->addr = pci_resource_start(pci, 0);
 
        pci_id = oxygen_search_pci_id(chip, ids);
-       if (!pci_id) {
-               err = -ENODEV;
-               goto err_pci_regions;
-       }
+       if (!pci_id)
+               return -ENODEV;
+
        oxygen_restore_eeprom(chip, pci_id);
        err = get_model(chip, pci_id);
        if (err < 0)
-               goto err_pci_regions;
+               return err;
 
        if (chip->model.model_data_size) {
-               chip->model_data = kzalloc(chip->model.model_data_size,
-                                          GFP_KERNEL);
-               if (!chip->model_data) {
-                       err = -ENOMEM;
-                       goto err_pci_regions;
-               }
+               chip->model_data = devm_kzalloc(&pci->dev,
+                                               chip->model.model_data_size,
+                                               GFP_KERNEL);
+               if (!chip->model_data)
+                       return -ENOMEM;
        }
 
        pci_set_master(pci);
@@ -654,11 +646,11 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
        oxygen_init(chip);
        chip->model.init(chip);
 
-       err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED,
-                         KBUILD_MODNAME, chip);
+       err = devm_request_irq(&pci->dev, pci->irq, oxygen_interrupt,
+                              IRQF_SHARED, KBUILD_MODNAME, chip);
        if (err < 0) {
                dev_err(card->dev, "cannot grab interrupt %d\n", pci->irq);
-               goto err_card;
+               return err;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
@@ -672,11 +664,11 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
 
        err = oxygen_pcm_init(chip);
        if (err < 0)
-               goto err_card;
+               return err;
 
        err = oxygen_mixer_init(chip);
        if (err < 0)
-               goto err_card;
+               return err;
 
        if (chip->model.device_config & (MIDI_OUTPUT | MIDI_INPUT)) {
                unsigned int info_flags =
@@ -689,7 +681,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
                                          chip->addr + OXYGEN_MPU401,
                                          info_flags, -1, &chip->midi);
                if (err < 0)
-                       goto err_card;
+                       return err;
        }
 
        oxygen_proc_init(chip);
@@ -704,27 +696,13 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto err_card;
+               return err;
 
        pci_set_drvdata(pci, card);
        return 0;
-
-err_pci_regions:
-       pci_release_regions(pci);
-err_pci_enable:
-       pci_disable_device(pci);
-err_card:
-       snd_card_free(card);
-       return err;
 }
 EXPORT_SYMBOL(oxygen_pci_probe);
 
-void oxygen_pci_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-EXPORT_SYMBOL(oxygen_pci_remove);
-
 #ifdef CONFIG_PM_SLEEP
 static int oxygen_pci_suspend(struct device *dev)
 {
index 434f885..17650a5 100644 (file)
@@ -137,7 +137,6 @@ static struct pci_driver se6x_driver = {
        .name = KBUILD_MODNAME,
        .id_table = se6x_ids,
        .probe = se6x_probe,
-       .remove = oxygen_pci_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &oxygen_pci_pm,
index baa3244..2e40513 100644 (file)
@@ -82,7 +82,6 @@ static struct pci_driver xonar_driver = {
        .name = KBUILD_MODNAME,
        .id_table = xonar_ids,
        .probe = xonar_probe,
-       .remove = oxygen_pci_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &oxygen_pci_pm,
index 96b9371..242bd7e 100644 (file)
@@ -366,7 +366,7 @@ static int pcxhr_sub_set_clock(struct pcxhr_mgr *mgr,
                mgr->codec_speed = speed;       /* save new codec speed */
        }
 
-       dev_dbg(&mgr->pci->dev, "pcxhr_sub_set_clock to %dHz (realfreq=%d)\n",
+       dev_dbg(&mgr->pci->dev, "%s to %dHz (realfreq=%d)\n", __func__,
                    rate, realfreq);
        return 0;
 }
@@ -499,7 +499,7 @@ static int pcxhr_set_stream_state(struct snd_pcxhr *chip,
        else {
                if (stream->status != PCXHR_STREAM_STATUS_SCHEDULE_STOP) {
                        dev_err(chip->card->dev,
-                               "pcxhr_set_stream_state CANNOT be stopped\n");
+                               "%s CANNOT be stopped\n", __func__);
                        return -EINVAL;
                }
                start = 0;
@@ -524,7 +524,7 @@ static int pcxhr_set_stream_state(struct snd_pcxhr *chip,
        err = pcxhr_send_msg(chip->mgr, &rmh);
        if (err)
                dev_err(chip->card->dev,
-                       "ERROR pcxhr_set_stream_state err=%x;\n", err);
+                       "ERROR %s err=%x;\n", __func__, err);
        stream->status =
          start ? PCXHR_STREAM_STATUS_STARTED : PCXHR_STREAM_STATUS_STOPPED;
        return err;
@@ -570,7 +570,7 @@ static int pcxhr_set_format(struct pcxhr_stream *stream)
                break;
        default:
                dev_err(chip->card->dev,
-                       "error pcxhr_set_format() : unknown format\n");
+                       "error %s() : unknown format\n", __func__);
                return -EINVAL;
        }
 
@@ -615,7 +615,7 @@ static int pcxhr_set_format(struct pcxhr_stream *stream)
        err = pcxhr_send_msg(chip->mgr, &rmh);
        if (err)
                dev_err(chip->card->dev,
-                       "ERROR pcxhr_set_format err=%x;\n", err);
+                       "ERROR %s err=%x;\n", __func__, err);
        return err;
 }
 
@@ -630,7 +630,7 @@ static int pcxhr_update_r_buffer(struct pcxhr_stream *stream)
        stream_num = is_capture ? 0 : subs->number;
 
        dev_dbg(chip->card->dev,
-               "pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n",
+               "%s(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n", __func__,
                is_capture ? 'c' : 'p',
                chip->chip_idx, (void *)(long)subs->runtime->dma_addr,
                subs->runtime->dma_bytes, subs->number);
@@ -721,21 +721,20 @@ static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr)
        }
        if (capture_mask == 0 && playback_mask == 0) {
                mutex_unlock(&mgr->setup_mutex);
-               dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : no pipes\n");
+               dev_err(&mgr->pci->dev, "%s : no pipes\n", __func__);
                return;
        }
 
-       dev_dbg(&mgr->pci->dev, "pcxhr_start_linked_stream : "
-                   "playback_mask=%x capture_mask=%x\n",
-                   playback_mask, capture_mask);
+       dev_dbg(&mgr->pci->dev, "%s : playback_mask=%x capture_mask=%x\n",
+                   __func__, playback_mask, capture_mask);
 
        /* synchronous stop of all the pipes concerned */
        err = pcxhr_set_pipe_state(mgr,  playback_mask, capture_mask, 0);
        if (err) {
                mutex_unlock(&mgr->setup_mutex);
-               dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
+               dev_err(&mgr->pci->dev, "%s : "
                           "error stop pipes (P%x C%x)\n",
-                          playback_mask, capture_mask);
+                          __func__, playback_mask, capture_mask);
                return;
        }
 
@@ -778,9 +777,9 @@ static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr)
        err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
        if (err) {
                mutex_unlock(&mgr->setup_mutex);
-               dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
+               dev_err(&mgr->pci->dev, "%s : "
                           "error start pipes (P%x C%x)\n",
-                          playback_mask, capture_mask);
+                          __func__, playback_mask, capture_mask);
                return;
        }
 
@@ -889,7 +888,7 @@ static int pcxhr_hardware_timer(struct pcxhr_mgr *mgr, int start)
        }
        err = pcxhr_send_msg(mgr, &rmh);
        if (err < 0)
-               dev_err(&mgr->pci->dev, "error pcxhr_hardware_timer err(%x)\n",
+               dev_err(&mgr->pci->dev, "error %s err(%x)\n", __func__,
                           err);
        return err;
 }
@@ -904,7 +903,7 @@ static int pcxhr_prepare(struct snd_pcm_substream *subs)
        int err = 0;
 
        dev_dbg(chip->card->dev,
-               "pcxhr_prepare : period_size(%lx) periods(%x) buffer_size(%lx)\n",
+               "%s : period_size(%lx) periods(%x) buffer_size(%lx)\n", __func__,
                    subs->runtime->period_size, subs->runtime->periods,
                    subs->runtime->buffer_size);
 
@@ -997,12 +996,12 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
        runtime->hw = pcxhr_caps;
 
        if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK ) {
-               dev_dbg(chip->card->dev, "pcxhr_open playback chip%d subs%d\n",
-                           chip->chip_idx, subs->number);
+               dev_dbg(chip->card->dev, "%s playback chip%d subs%d\n",
+                           __func__, chip->chip_idx, subs->number);
                stream = &chip->playback_stream[subs->number];
        } else {
-               dev_dbg(chip->card->dev, "pcxhr_open capture chip%d subs%d\n",
-                           chip->chip_idx, subs->number);
+               dev_dbg(chip->card->dev, "%s capture chip%d subs%d\n",
+                           __func__, chip->chip_idx, subs->number);
                if (mgr->mono_capture)
                        runtime->hw.channels_max = 1;
                else
@@ -1011,8 +1010,8 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
        }
        if (stream->status != PCXHR_STREAM_STATUS_FREE){
                /* streams in use */
-               dev_err(chip->card->dev, "pcxhr_open chip%d subs%d in use\n",
-                          chip->chip_idx, subs->number);
+               dev_err(chip->card->dev, "%s chip%d subs%d in use\n",
+                          __func__, chip->chip_idx, subs->number);
                mutex_unlock(&mgr->setup_mutex);
                return -EBUSY;
        }
@@ -1077,7 +1076,7 @@ static int pcxhr_close(struct snd_pcm_substream *subs)
 
        mutex_lock(&mgr->setup_mutex);
 
-       dev_dbg(chip->card->dev, "pcxhr_close chip%d subs%d\n",
+       dev_dbg(chip->card->dev, "%s chip%d subs%d\n", __func__,
                    chip->chip_idx, subs->number);
 
        /* sample rate released */
@@ -1572,7 +1571,7 @@ static int pcxhr_probe(struct pci_dev *pci,
        /* init setup mutex*/
        mutex_init(&mgr->setup_mutex);
 
-       mgr->prmh = kmalloc(sizeof(*mgr->prmh) + 
+       mgr->prmh = kmalloc(sizeof(*mgr->prmh) +
                            sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS -
                                           PCXHR_SIZE_MAX_STATUS),
                            GFP_KERNEL);
index 709a1a2..5a987c6 100644 (file)
@@ -1798,13 +1798,11 @@ static int snd_riptide_initialize(struct snd_riptide *chip)
        return err;
 }
 
-static int snd_riptide_free(struct snd_riptide *chip)
+static void snd_riptide_free(struct snd_card *card)
 {
+       struct snd_riptide *chip = card->private_data;
        struct cmdif *cif;
 
-       if (!chip)
-               return 0;
-
        cif = chip->cif;
        if (cif) {
                SET_GRESET(cif->hwport);
@@ -1812,39 +1810,19 @@ static int snd_riptide_free(struct snd_riptide *chip)
                UNSET_GRESET(cif->hwport);
                kfree(chip->cif);
        }
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
        release_firmware(chip->fw_entry);
-       release_and_free_resource(chip->res_port);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_riptide_dev_free(struct snd_device *device)
-{
-       struct snd_riptide *chip = device->device_data;
-
-       return snd_riptide_free(chip);
 }
 
 static int
-snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
-                  struct snd_riptide **rchip)
+snd_riptide_create(struct snd_card *card, struct pci_dev *pci)
 {
-       struct snd_riptide *chip;
+       struct snd_riptide *chip = card->private_data;
        struct riptideport *hwport;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_riptide_dev_free,
-       };
 
-       *rchip = NULL;
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
-       chip = kzalloc(sizeof(struct snd_riptide), GFP_KERNEL);
-       if (!chip)
-               return -ENOMEM;
 
        spin_lock_init(&chip->lock);
        chip->card = card;
@@ -1855,24 +1833,20 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
        chip->received_irqs = 0;
        chip->handled_irqs = 0;
        chip->cif = NULL;
+       card->private_free = snd_riptide_free;
 
-       chip->res_port = request_region(chip->port, 64, "RIPTIDE");
-       if (!chip->res_port) {
-               snd_printk(KERN_ERR
-                          "Riptide: unable to grab region 0x%lx-0x%lx\n",
-                          chip->port, chip->port + 64 - 1);
-               snd_riptide_free(chip);
-               return -EBUSY;
-       }
+       err = pci_request_regions(pci, "RIPTIDE");
+       if (err < 0)
+               return err;
        hwport = (struct riptideport *)chip->port;
        UNSET_AIE(hwport);
 
-       if (request_threaded_irq(pci->irq, snd_riptide_interrupt,
-                                riptide_handleirq, IRQF_SHARED,
-                                KBUILD_MODNAME, chip)) {
+       if (devm_request_threaded_irq(&pci->dev, pci->irq,
+                                     snd_riptide_interrupt,
+                                     riptide_handleirq, IRQF_SHARED,
+                                     KBUILD_MODNAME, chip)) {
                snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n",
                           pci->irq);
-               snd_riptide_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
@@ -1880,18 +1854,9 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
        chip->device_id = pci->device;
        pci_set_master(pci);
        err = snd_riptide_initialize(chip);
-       if (err < 0) {
-               snd_riptide_free(chip);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_riptide_free(chip);
+       if (err < 0)
                return err;
-       }
 
-       *rchip = chip;
        return 0;
 }
 
@@ -2073,20 +2038,20 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
-       err = snd_riptide_create(card, pci, &chip);
+       chip = card->private_data;
+       err = snd_riptide_create(card, pci);
        if (err < 0)
-               goto error;
-       card->private_data = chip;
+               return err;
        err = snd_riptide_pcm(chip, 0);
        if (err < 0)
-               goto error;
+               return err;
        err = snd_riptide_mixer(chip);
        if (err < 0)
-               goto error;
+               return err;
 
        val = LEGACY_ENABLE_ALL;
        if (opl3_port[dev])
@@ -2153,26 +2118,16 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        snd_riptide_proc_init(chip);
        err = snd_card_register(card);
        if (err < 0)
-               goto error;
+               return err;
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
- error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_card_riptide_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_riptide_ids,
        .probe = snd_card_riptide_probe,
-       .remove = snd_card_riptide_remove,
        .driver = {
                .pm = RIPTIDE_PM_OPS,
        },
index b5b3578..5b6bd9f 100644 (file)
@@ -1278,27 +1278,10 @@ static const struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = {
        .ack =          snd_rme32_capture_fd_ack,
 };
 
-static void snd_rme32_free(void *private_data)
+static void snd_rme32_free(struct rme32 *rme32)
 {
-       struct rme32 *rme32 = (struct rme32 *) private_data;
-
-       if (rme32 == NULL) {
-               return;
-       }
-       if (rme32->irq >= 0) {
+       if (rme32->irq >= 0)
                snd_rme32_pcm_stop(rme32, 0);
-               free_irq(rme32->irq, (void *) rme32);
-               rme32->irq = -1;
-       }
-       if (rme32->iobase) {
-               iounmap(rme32->iobase);
-               rme32->iobase = NULL;
-       }
-       if (rme32->port) {
-               pci_release_regions(rme32->pci);
-               rme32->port = 0;
-       }
-       pci_disable_device(rme32->pci);
 }
 
 static void snd_rme32_free_spdif_pcm(struct snd_pcm *pcm)
@@ -1322,7 +1305,7 @@ static int snd_rme32_create(struct rme32 *rme32)
        rme32->irq = -1;
        spin_lock_init(&rme32->lock);
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
@@ -1331,16 +1314,16 @@ static int snd_rme32_create(struct rme32 *rme32)
                return err;
        rme32->port = pci_resource_start(rme32->pci, 0);
 
-       rme32->iobase = ioremap(rme32->port, RME32_IO_SIZE);
+       rme32->iobase = devm_ioremap(&pci->dev, rme32->port, RME32_IO_SIZE);
        if (!rme32->iobase) {
                dev_err(rme32->card->dev,
                        "unable to remap memory region 0x%lx-0x%lx\n",
-                          rme32->port, rme32->port + RME32_IO_SIZE - 1);
+                       rme32->port, rme32->port + RME32_IO_SIZE - 1);
                return -ENOMEM;
        }
 
-       if (request_irq(pci->irq, snd_rme32_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, rme32)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_rme32_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, rme32)) {
                dev_err(rme32->card->dev, "unable to grab IRQ %d\n", pci->irq);
                return -EBUSY;
        }
@@ -1907,8 +1890,8 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct rme32), &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*rme32), &card);
        if (err < 0)
                return err;
        card->private_free = snd_rme32_card_free;
@@ -1918,10 +1901,8 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
         if (fullduplex[dev])
                rme32->fullduplex_mode = 1;
        err = snd_rme32_create(rme32);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        strcpy(card->driver, "Digi32");
        switch (rme32->pci->device) {
@@ -1939,25 +1920,17 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                card->shortname, rme32->rev, rme32->port, rme32->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_rme32_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver rme32_driver = {
        .name =         KBUILD_MODNAME,
        .id_table =     snd_rme32_ids,
        .probe =        snd_rme32_probe,
-       .remove =       snd_rme32_remove,
 };
 
 module_pci_driver(rme32_driver);
index fc7ac07..8fc8115 100644 (file)
@@ -1562,33 +1562,17 @@ static const struct snd_pcm_ops snd_rme96_capture_adat_ops = {
 };
 
 static void
-snd_rme96_free(void *private_data)
+snd_rme96_free(struct rme96 *rme96)
 {
-       struct rme96 *rme96 = (struct rme96 *)private_data;
-
-       if (!rme96)
-               return;
-
        if (rme96->irq >= 0) {
                snd_rme96_trigger(rme96, RME96_STOP_BOTH);
                rme96->areg &= ~RME96_AR_DAC_EN;
                writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);
-               free_irq(rme96->irq, (void *)rme96);
-               rme96->irq = -1;
-       }
-       if (rme96->iobase) {
-               iounmap(rme96->iobase);
-               rme96->iobase = NULL;
-       }
-       if (rme96->port) {
-               pci_release_regions(rme96->pci);
-               rme96->port = 0;
        }
 #ifdef CONFIG_PM_SLEEP
        vfree(rme96->playback_suspend_buffer);
        vfree(rme96->capture_suspend_buffer);
 #endif
-       pci_disable_device(rme96->pci);
 }
 
 static void
@@ -1614,7 +1598,7 @@ snd_rme96_create(struct rme96 *rme96)
        rme96->irq = -1;
        spin_lock_init(&rme96->lock);
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
@@ -1623,16 +1607,16 @@ snd_rme96_create(struct rme96 *rme96)
                return err;
        rme96->port = pci_resource_start(rme96->pci, 0);
 
-       rme96->iobase = ioremap(rme96->port, RME96_IO_SIZE);
+       rme96->iobase = devm_ioremap(&pci->dev, rme96->port, RME96_IO_SIZE);
        if (!rme96->iobase) {
                dev_err(rme96->card->dev,
                        "unable to remap memory region 0x%lx-0x%lx\n",
                        rme96->port, rme96->port + RME96_IO_SIZE - 1);
-               return -ENOMEM;
+               return -EBUSY;
        }
 
-       if (request_irq(pci->irq, snd_rme96_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, rme96)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_rme96_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, rme96)) {
                dev_err(rme96->card->dev, "unable to grab IRQ %d\n", pci->irq);
                return -EBUSY;
        }
@@ -2462,8 +2446,8 @@ snd_rme96_probe(struct pci_dev *pci,
                dev++;
                return -ENOENT;
        }
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct rme96), &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*rme96), &card);
        if (err < 0)
                return err;
        card->private_free = snd_rme96_card_free;
@@ -2472,19 +2456,15 @@ snd_rme96_probe(struct pci_dev *pci,
        rme96->pci = pci;
        err = snd_rme96_create(rme96);
        if (err)
-               goto free_card;
+               return err;
        
 #ifdef CONFIG_PM_SLEEP
        rme96->playback_suspend_buffer = vmalloc(RME96_BUFFER_SIZE);
-       if (!rme96->playback_suspend_buffer) {
-               err = -ENOMEM;
-               goto free_card;
-       }
+       if (!rme96->playback_suspend_buffer)
+               return -ENOMEM;
        rme96->capture_suspend_buffer = vmalloc(RME96_BUFFER_SIZE);
-       if (!rme96->capture_suspend_buffer) {
-               err = -ENOMEM;
-               goto free_card;
-       }
+       if (!rme96->capture_suspend_buffer)
+               return -ENOMEM;
 #endif
 
        strcpy(card->driver, "Digi96");
@@ -2511,26 +2491,17 @@ snd_rme96_probe(struct pci_dev *pci,
                rme96->port, rme96->irq);
        err = snd_card_register(card);
        if (err)
-               goto free_card;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-free_card:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_rme96_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver rme96_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_rme96_ids,
        .probe = snd_rme96_probe,
-       .remove = snd_rme96_remove,
        .driver = {
                .pm = RME96_PM_OPS,
        },
index 8457a4b..75aa2ea 100644 (file)
@@ -468,8 +468,8 @@ struct hdsp {
        unsigned char         ss_out_channels;
        u32                   io_loopback;          /* output loopback channel states*/
 
-       struct snd_dma_buffer capture_dma_buf;
-       struct snd_dma_buffer playback_dma_buf;
+       struct snd_dma_buffer *capture_dma_buf;
+       struct snd_dma_buffer *playback_dma_buf;
        unsigned char        *capture_buffer;       /* suitably aligned address */
        unsigned char        *playback_buffer;      /* suitably aligned address */
 
@@ -565,18 +565,12 @@ static const char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = {
        -1, -1
 };
 
-static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
+static struct snd_dma_buffer *
+snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size)
 {
-       return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, size, dmab);
+       return snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, size);
 }
 
-static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
-{
-       if (dmab->area)
-               snd_dma_free_pages(dmab);
-}
-
-
 static const struct pci_device_id snd_hdsp_ids[] = {
        {
                .vendor = PCI_VENDOR_ID_XILINX,
@@ -3768,20 +3762,15 @@ static void snd_hdsp_proc_init(struct hdsp *hdsp)
        snd_card_ro_proc_new(hdsp->card, "hdsp", hdsp, snd_hdsp_proc_read);
 }
 
-static void snd_hdsp_free_buffers(struct hdsp *hdsp)
-{
-       snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
-       snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
-}
-
 static int snd_hdsp_initialize_memory(struct hdsp *hdsp)
 {
        unsigned long pb_bus, cb_bus;
 
-       if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 ||
-           snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) {
-               if (hdsp->capture_dma_buf.area)
-                       snd_dma_free_pages(&hdsp->capture_dma_buf);
+       hdsp->capture_dma_buf =
+               snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES);
+       hdsp->playback_dma_buf =
+               snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES);
+       if (!hdsp->capture_dma_buf || !hdsp->playback_dma_buf) {
                dev_err(hdsp->card->dev,
                        "%s: no buffers available\n", hdsp->card_name);
                return -ENOMEM;
@@ -3789,16 +3778,16 @@ static int snd_hdsp_initialize_memory(struct hdsp *hdsp)
 
        /* Align to bus-space 64K boundary */
 
-       cb_bus = ALIGN(hdsp->capture_dma_buf.addr, 0x10000ul);
-       pb_bus = ALIGN(hdsp->playback_dma_buf.addr, 0x10000ul);
+       cb_bus = ALIGN(hdsp->capture_dma_buf->addr, 0x10000ul);
+       pb_bus = ALIGN(hdsp->playback_dma_buf->addr, 0x10000ul);
 
        /* Tell the card where it is */
 
        hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus);
        hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus);
 
-       hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr);
-       hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr);
+       hdsp->capture_buffer = hdsp->capture_dma_buf->area + (cb_bus - hdsp->capture_dma_buf->addr);
+       hdsp->playback_buffer = hdsp->playback_dma_buf->area + (pb_bus - hdsp->playback_dma_buf->addr);
 
        return 0;
 }
@@ -4518,8 +4507,7 @@ static int snd_hdsp_playback_open(struct snd_pcm_substream *substream)
        snd_pcm_set_sync(substream);
 
         runtime->hw = snd_hdsp_playback_subinfo;
-       runtime->dma_area = hdsp->playback_buffer;
-       runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
+       snd_pcm_set_runtime_buffer(substream, hdsp->playback_dma_buf);
 
        hdsp->playback_pid = current->pid;
        hdsp->playback_substream = substream;
@@ -4595,8 +4583,7 @@ static int snd_hdsp_capture_open(struct snd_pcm_substream *substream)
        snd_pcm_set_sync(substream);
 
        runtime->hw = snd_hdsp_capture_subinfo;
-       runtime->dma_area = hdsp->capture_buffer;
-       runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
+       snd_pcm_set_runtime_buffer(substream, hdsp->capture_dma_buf);
 
        hdsp->capture_pid = current->pid;
        hdsp->capture_substream = substream;
@@ -5313,7 +5300,7 @@ static int snd_hdsp_create(struct snd_card *card,
                is_9632 = 1;
        }
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
@@ -5323,15 +5310,15 @@ static int snd_hdsp_create(struct snd_card *card,
        if (err < 0)
                return err;
        hdsp->port = pci_resource_start(pci, 0);
-       hdsp->iobase = ioremap(hdsp->port, HDSP_IO_EXTENT);
+       hdsp->iobase = devm_ioremap(&pci->dev, hdsp->port, HDSP_IO_EXTENT);
        if (!hdsp->iobase) {
                dev_err(hdsp->card->dev, "unable to remap region 0x%lx-0x%lx\n",
                        hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
                return -EBUSY;
        }
 
-       if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, hdsp)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_hdsp_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, hdsp)) {
                dev_err(hdsp->card->dev, "unable to use IRQ %d\n", pci->irq);
                return -EBUSY;
        }
@@ -5411,8 +5398,10 @@ static int snd_hdsp_create(struct snd_card *card,
        return 0;
 }
 
-static int snd_hdsp_free(struct hdsp *hdsp)
+static void snd_hdsp_card_free(struct snd_card *card)
 {
+       struct hdsp *hdsp = card->private_data;
+
        if (hdsp->port) {
                /* stop the audio, and cancel all interrupts */
                cancel_work_sync(&hdsp->midi_work);
@@ -5420,29 +5409,8 @@ static int snd_hdsp_free(struct hdsp *hdsp)
                hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
        }
 
-       if (hdsp->irq >= 0)
-               free_irq(hdsp->irq, (void *)hdsp);
-
-       snd_hdsp_free_buffers(hdsp);
-
        release_firmware(hdsp->firmware);
        vfree(hdsp->fw_uploaded);
-       iounmap(hdsp->iobase);
-
-       if (hdsp->port)
-               pci_release_regions(hdsp->pci);
-
-       if (pci_is_enabled(hdsp->pci))
-               pci_disable_device(hdsp->pci);
-       return 0;
-}
-
-static void snd_hdsp_card_free(struct snd_card *card)
-{
-       struct hdsp *hdsp = card->private_data;
-
-       if (hdsp)
-               snd_hdsp_free(hdsp);
 }
 
 static int snd_hdsp_probe(struct pci_dev *pci,
@@ -5460,8 +5428,8 @@ static int snd_hdsp_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct hdsp), &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct hdsp), &card);
        if (err < 0)
                return err;
 
@@ -5471,32 +5439,23 @@ static int snd_hdsp_probe(struct pci_dev *pci,
        hdsp->pci = pci;
        err = snd_hdsp_create(card, hdsp);
        if (err)
-               goto free_card;
+               return err;
 
        strcpy(card->shortname, "Hammerfall DSP");
        sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
                hdsp->port, hdsp->irq);
        err = snd_card_register(card);
-       if (err) {
-free_card:
-               snd_card_free(card);
+       if (err)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_hdsp_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver hdsp_driver = {
        .name =     KBUILD_MODNAME,
        .id_table = snd_hdsp_ids,
        .probe =    snd_hdsp_probe,
-       .remove = snd_hdsp_remove,
 };
 
 module_pci_driver(hdsp_driver);
index 97a0bff..ff06ee8 100644 (file)
@@ -6575,34 +6575,25 @@ static int snd_hdspm_create(struct snd_card *card,
                }
        }
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        pci_set_master(hdspm->pci);
 
-       err = pci_request_regions(pci, "hdspm");
+       err = pcim_iomap_regions(pci, 1 << 0, "hdspm");
        if (err < 0)
                return err;
 
        hdspm->port = pci_resource_start(pci, 0);
        io_extent = pci_resource_len(pci, 0);
-
-       dev_dbg(card->dev, "grabbed memory region 0x%lx-0x%lx\n",
-                       hdspm->port, hdspm->port + io_extent - 1);
-
-       hdspm->iobase = ioremap(hdspm->port, io_extent);
-       if (!hdspm->iobase) {
-               dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n",
-                               hdspm->port, hdspm->port + io_extent - 1);
-               return -EBUSY;
-       }
+       hdspm->iobase = pcim_iomap_table(pci)[0];
        dev_dbg(card->dev, "remapped region (0x%lx) 0x%lx-0x%lx\n",
                        (unsigned long)hdspm->iobase, hdspm->port,
                        hdspm->port + io_extent - 1);
 
-       if (request_irq(pci->irq, snd_hdspm_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_hdspm_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
                dev_err(card->dev, "unable to use IRQ %d\n", pci->irq);
                return -EBUSY;
        }
@@ -6614,7 +6605,7 @@ static int snd_hdspm_create(struct snd_card *card,
 
        dev_dbg(card->dev, "kmalloc Mixer memory of %zd Bytes\n",
                sizeof(*hdspm->mixer));
-       hdspm->mixer = kzalloc(sizeof(*hdspm->mixer), GFP_KERNEL);
+       hdspm->mixer = devm_kzalloc(&pci->dev, sizeof(*hdspm->mixer), GFP_KERNEL);
        if (!hdspm->mixer)
                return -ENOMEM;
 
@@ -6859,8 +6850,9 @@ static int snd_hdspm_create(struct snd_card *card,
 }
 
 
-static int snd_hdspm_free(struct hdspm * hdspm)
+static void snd_hdspm_card_free(struct snd_card *card)
 {
+       struct hdspm *hdspm = card->private_data;
 
        if (hdspm->port) {
                cancel_work_sync(&hdspm->midi_work);
@@ -6873,28 +6865,6 @@ static int snd_hdspm_free(struct hdspm * hdspm)
                hdspm_write(hdspm, HDSPM_controlRegister,
                            hdspm->control_register);
        }
-
-       if (hdspm->irq >= 0)
-               free_irq(hdspm->irq, (void *) hdspm);
-
-       kfree(hdspm->mixer);
-       iounmap(hdspm->iobase);
-
-       if (hdspm->port)
-               pci_release_regions(hdspm->pci);
-
-       if (pci_is_enabled(hdspm->pci))
-               pci_disable_device(hdspm->pci);
-       return 0;
-}
-
-
-static void snd_hdspm_card_free(struct snd_card *card)
-{
-       struct hdspm *hdspm = card->private_data;
-
-       if (hdspm)
-               snd_hdspm_free(hdspm);
 }
 
 
@@ -6913,8 +6883,8 @@ static int snd_hdspm_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev],
-                          THIS_MODULE, sizeof(*hdspm), &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev],
+                               THIS_MODULE, sizeof(*hdspm), &card);
        if (err < 0)
                return err;
 
@@ -6925,7 +6895,7 @@ static int snd_hdspm_probe(struct pci_dev *pci,
 
        err = snd_hdspm_create(card, hdspm);
        if (err < 0)
-               goto free_card;
+               return err;
 
        if (hdspm->io_type != MADIface) {
                snprintf(card->shortname, sizeof(card->shortname), "%s_%x",
@@ -6944,28 +6914,18 @@ static int snd_hdspm_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto free_card;
+               return err;
 
        pci_set_drvdata(pci, card);
 
        dev++;
        return 0;
-
-free_card:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_hdspm_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver hdspm_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_hdspm_ids,
        .probe = snd_hdspm_probe,
-       .remove = snd_hdspm_remove,
 };
 
 module_pci_driver(hdspm_driver);
index f1aad38..e76f737 100644 (file)
@@ -208,8 +208,8 @@ struct snd_rme9652 {
        unsigned char ds_channels;
        unsigned char ss_channels;      /* different for hammerfall/hammerfall-light */
 
-       struct snd_dma_buffer playback_dma_buf;
-       struct snd_dma_buffer capture_dma_buf;
+       struct snd_dma_buffer *playback_dma_buf;
+       struct snd_dma_buffer *capture_dma_buf;
 
        unsigned char *capture_buffer;  /* suitably aligned address */
        unsigned char *playback_buffer; /* suitably aligned address */
@@ -275,18 +275,12 @@ static const char channel_map_9636_ds[26] = {
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 };
 
-static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
+static struct snd_dma_buffer *
+snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size)
 {
-       return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, size, dmab);
+       return snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, size);
 }
 
-static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
-{
-       if (dmab->area)
-               snd_dma_free_pages(dmab);
-}
-
-
 static const struct pci_device_id snd_rme9652_ids[] = {
        {
                .vendor    = 0x10ee,
@@ -1715,37 +1709,23 @@ static void snd_rme9652_proc_init(struct snd_rme9652 *rme9652)
                             snd_rme9652_proc_read);
 }
 
-static void snd_rme9652_free_buffers(struct snd_rme9652 *rme9652)
+static void snd_rme9652_card_free(struct snd_card *card)
 {
-       snd_hammerfall_free_buffer(&rme9652->capture_dma_buf, rme9652->pci);
-       snd_hammerfall_free_buffer(&rme9652->playback_dma_buf, rme9652->pci);
-}
+       struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) card->private_data;
 
-static int snd_rme9652_free(struct snd_rme9652 *rme9652)
-{
        if (rme9652->irq >= 0)
                rme9652_stop(rme9652);
-       snd_rme9652_free_buffers(rme9652);
-
-       if (rme9652->irq >= 0)
-               free_irq(rme9652->irq, (void *)rme9652);
-       iounmap(rme9652->iobase);
-       if (rme9652->port)
-               pci_release_regions(rme9652->pci);
-
-       if (pci_is_enabled(rme9652->pci))
-               pci_disable_device(rme9652->pci);
-       return 0;
 }
 
 static int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
 {
        unsigned long pb_bus, cb_bus;
 
-       if (snd_hammerfall_get_buffer(rme9652->pci, &rme9652->capture_dma_buf, RME9652_DMA_AREA_BYTES) < 0 ||
-           snd_hammerfall_get_buffer(rme9652->pci, &rme9652->playback_dma_buf, RME9652_DMA_AREA_BYTES) < 0) {
-               if (rme9652->capture_dma_buf.area)
-                       snd_dma_free_pages(&rme9652->capture_dma_buf);
+       rme9652->capture_dma_buf =
+               snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES);
+       rme9652->playback_dma_buf =
+               snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES);
+       if (!rme9652->capture_dma_buf || !rme9652->playback_dma_buf) {
                dev_err(rme9652->card->dev,
                        "%s: no buffers available\n", rme9652->card_name);
                return -ENOMEM;
@@ -1753,16 +1733,16 @@ static int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
 
        /* Align to bus-space 64K boundary */
 
-       cb_bus = ALIGN(rme9652->capture_dma_buf.addr, 0x10000ul);
-       pb_bus = ALIGN(rme9652->playback_dma_buf.addr, 0x10000ul);
+       cb_bus = ALIGN(rme9652->capture_dma_buf->addr, 0x10000ul);
+       pb_bus = ALIGN(rme9652->playback_dma_buf->addr, 0x10000ul);
 
        /* Tell the card where it is */
 
        rme9652_write(rme9652, RME9652_rec_buffer, cb_bus);
        rme9652_write(rme9652, RME9652_play_buffer, pb_bus);
 
-       rme9652->capture_buffer = rme9652->capture_dma_buf.area + (cb_bus - rme9652->capture_dma_buf.addr);
-       rme9652->playback_buffer = rme9652->playback_dma_buf.area + (pb_bus - rme9652->playback_dma_buf.addr);
+       rme9652->capture_buffer = rme9652->capture_dma_buf->area + (cb_bus - rme9652->capture_dma_buf->addr);
+       rme9652->playback_buffer = rme9652->playback_dma_buf->area + (pb_bus - rme9652->playback_dma_buf->addr);
 
        return 0;
 }
@@ -2279,8 +2259,7 @@ static int snd_rme9652_playback_open(struct snd_pcm_substream *substream)
        snd_pcm_set_sync(substream);
 
         runtime->hw = snd_rme9652_playback_subinfo;
-       runtime->dma_area = rme9652->playback_buffer;
-       runtime->dma_bytes = RME9652_DMA_AREA_BYTES;
+       snd_pcm_set_runtime_buffer(substream, rme9652->playback_dma_buf);
 
        if (rme9652->capture_substream == NULL) {
                rme9652_stop(rme9652);
@@ -2339,8 +2318,7 @@ static int snd_rme9652_capture_open(struct snd_pcm_substream *substream)
        snd_pcm_set_sync(substream);
 
        runtime->hw = snd_rme9652_capture_subinfo;
-       runtime->dma_area = rme9652->capture_buffer;
-       runtime->dma_bytes = RME9652_DMA_AREA_BYTES;
+       snd_pcm_set_runtime_buffer(substream, rme9652->capture_dma_buf);
 
        if (rme9652->playback_substream == NULL) {
                rme9652_stop(rme9652);
@@ -2452,7 +2430,7 @@ static int snd_rme9652_create(struct snd_card *card,
                return -ENODEV;
        }
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
@@ -2462,15 +2440,15 @@ static int snd_rme9652_create(struct snd_card *card,
        if (err < 0)
                return err;
        rme9652->port = pci_resource_start(pci, 0);
-       rme9652->iobase = ioremap(rme9652->port, RME9652_IO_EXTENT);
+       rme9652->iobase = devm_ioremap(&pci->dev, rme9652->port, RME9652_IO_EXTENT);
        if (rme9652->iobase == NULL) {
                dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n",
                        rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1);
                return -EBUSY;
        }
        
-       if (request_irq(pci->irq, snd_rme9652_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, rme9652)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_rme9652_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, rme9652)) {
                dev_err(card->dev, "unable to request IRQ %d\n", pci->irq);
                return -EBUSY;
        }
@@ -2562,14 +2540,6 @@ static int snd_rme9652_create(struct snd_card *card,
        return 0;
 }
 
-static void snd_rme9652_card_free(struct snd_card *card)
-{
-       struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) card->private_data;
-
-       if (rme9652)
-               snd_rme9652_free(rme9652);
-}
-
 static int snd_rme9652_probe(struct pci_dev *pci,
                             const struct pci_device_id *pci_id)
 {
@@ -2585,8 +2555,8 @@ static int snd_rme9652_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_rme9652), &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_rme9652), &card);
 
        if (err < 0)
                return err;
@@ -2597,33 +2567,24 @@ static int snd_rme9652_probe(struct pci_dev *pci,
        rme9652->pci = pci;
        err = snd_rme9652_create(card, rme9652, precise_ptr[dev]);
        if (err)
-               goto free_card;
+               return err;
 
        strcpy(card->shortname, rme9652->card_name);
 
        sprintf(card->longname, "%s at 0x%lx, irq %d",
                card->shortname, rme9652->port, rme9652->irq);
        err = snd_card_register(card);
-       if (err) {
-free_card:
-               snd_card_free(card);
+       if (err)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_rme9652_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver rme9652_driver = {
        .name     = KBUILD_MODNAME,
        .id_table = snd_rme9652_ids,
        .probe    = snd_rme9652_probe,
-       .remove   = snd_rme9652_remove,
 };
 
 module_pci_driver(rme9652_driver);
index 00ab51c..0b722b0 100644 (file)
@@ -1007,16 +1007,10 @@ static int sis_mixer_create(struct sis7019 *sis)
        return rc;
 }
 
-static void sis_free_suspend(struct sis7019 *sis)
+static void sis_chip_free(struct snd_card *card)
 {
-       int i;
-
-       for (i = 0; i < SIS_SUSPEND_PAGES; i++)
-               kfree(sis->suspend_state[i]);
-}
+       struct sis7019 *sis = card->private_data;
 
-static int sis_chip_free(struct sis7019 *sis)
-{
        /* Reset the chip, and disable all interrputs.
         */
        outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR);
@@ -1028,18 +1022,6 @@ static int sis_chip_free(struct sis7019 *sis)
         */
        if (sis->irq >= 0)
                free_irq(sis->irq, sis);
-
-       iounmap(sis->ioaddr);
-       pci_release_regions(sis->pci);
-       pci_disable_device(sis->pci);
-       sis_free_suspend(sis);
-       return 0;
-}
-
-static int sis_dev_free(struct snd_device *dev)
-{
-       struct sis7019 *sis = dev->device_data;
-       return sis_chip_free(sis);
 }
 
 static int sis_chip_init(struct sis7019 *sis)
@@ -1265,7 +1247,8 @@ static int sis_alloc_suspend(struct sis7019 *sis)
         * buffer.
         */
        for (i = 0; i < SIS_SUSPEND_PAGES; i++) {
-               sis->suspend_state[i] = kmalloc(4096, GFP_KERNEL);
+               sis->suspend_state[i] = devm_kmalloc(&sis->pci->dev, 4096,
+                                                    GFP_KERNEL);
                if (!sis->suspend_state[i])
                        return -ENOMEM;
        }
@@ -1279,23 +1262,19 @@ static int sis_chip_create(struct snd_card *card,
 {
        struct sis7019 *sis = card->private_data;
        struct voice *voice;
-       static const struct snd_device_ops ops = {
-               .dev_free = sis_dev_free,
-       };
        int rc;
        int i;
 
-       rc = pci_enable_device(pci);
+       rc = pcim_enable_device(pci);
        if (rc)
-               goto error_out;
+               return rc;
 
        rc = dma_set_mask(&pci->dev, DMA_BIT_MASK(30));
        if (rc < 0) {
                dev_err(&pci->dev, "architecture does not support 30-bit PCI busmaster DMA");
-               goto error_out_enabled;
+               return -ENXIO;
        }
 
-       memset(sis, 0, sizeof(*sis));
        mutex_init(&sis->ac97_mutex);
        spin_lock_init(&sis->voice_lock);
        sis->card = card;
@@ -1306,31 +1285,31 @@ static int sis_chip_create(struct snd_card *card,
        rc = pci_request_regions(pci, "SiS7019");
        if (rc) {
                dev_err(&pci->dev, "unable request regions\n");
-               goto error_out_enabled;
+               return rc;
        }
 
-       rc = -EIO;
-       sis->ioaddr = ioremap(pci_resource_start(pci, 1), 0x4000);
+       sis->ioaddr = devm_ioremap(&pci->dev, pci_resource_start(pci, 1), 0x4000);
        if (!sis->ioaddr) {
                dev_err(&pci->dev, "unable to remap MMIO, aborting\n");
-               goto error_out_cleanup;
+               return -EIO;
        }
 
        rc = sis_alloc_suspend(sis);
        if (rc < 0) {
                dev_err(&pci->dev, "unable to allocate state storage\n");
-               goto error_out_cleanup;
+               return rc;
        }
 
        rc = sis_chip_init(sis);
        if (rc)
-               goto error_out_cleanup;
+               return rc;
+       card->private_free = sis_chip_free;
 
        rc = request_irq(pci->irq, sis_interrupt, IRQF_SHARED, KBUILD_MODNAME,
                         sis);
        if (rc) {
                dev_err(&pci->dev, "unable to allocate irq %d\n", sis->irq);
-               goto error_out_cleanup;
+               return rc;
        }
 
        sis->irq = pci->irq;
@@ -1349,20 +1328,7 @@ static int sis_chip_create(struct snd_card *card,
        voice->num = SIS_CAPTURE_CHAN_AC97_PCM_IN;
        voice->ctrl_base = SIS_CAPTURE_DMA_ADDR(sis->ioaddr, voice->num);
 
-       rc = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sis, &ops);
-       if (rc)
-               goto error_out_cleanup;
-
        return 0;
-
-error_out_cleanup:
-       sis_chip_free(sis);
-
-error_out_enabled:
-       pci_disable_device(pci);
-
-error_out:
-       return rc;
 }
 
 static int snd_sis7019_probe(struct pci_dev *pci,
@@ -1372,9 +1338,8 @@ static int snd_sis7019_probe(struct pci_dev *pci,
        struct sis7019 *sis;
        int rc;
 
-       rc = -ENOENT;
        if (!enable)
-               goto error_out;
+               return -ENOENT;
 
        /* The user can specify which codecs should be present so that we
         * can wait for them to show up if they are slow to recover from
@@ -1390,23 +1355,23 @@ static int snd_sis7019_probe(struct pci_dev *pci,
        rc = snd_card_new(&pci->dev, index, id, THIS_MODULE,
                          sizeof(*sis), &card);
        if (rc < 0)
-               goto error_out;
+               return rc;
 
        strcpy(card->driver, "SiS7019");
        strcpy(card->shortname, "SiS7019");
        rc = sis_chip_create(card, pci);
        if (rc)
-               goto card_error_out;
+               return rc;
 
        sis = card->private_data;
 
        rc = sis_mixer_create(sis);
        if (rc)
-               goto card_error_out;
+               return rc;
 
        rc = sis_pcm_create(sis);
        if (rc)
-               goto card_error_out;
+               return rc;
 
        snprintf(card->longname, sizeof(card->longname),
                        "%s Audio Accelerator with %s at 0x%lx, irq %d",
@@ -1415,28 +1380,16 @@ static int snd_sis7019_probe(struct pci_dev *pci,
 
        rc = snd_card_register(card);
        if (rc)
-               goto card_error_out;
+               return rc;
 
        pci_set_drvdata(pci, card);
        return 0;
-
-card_error_out:
-       snd_card_free(card);
-
-error_out:
-       return rc;
-}
-
-static void snd_sis7019_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver sis7019_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_sis7019_ids,
        .probe = snd_sis7019_probe,
-       .remove = snd_sis7019_remove,
        .driver = {
                .pm = SIS_PM_OPS,
        },
index 03a48da..c8c4988 100644 (file)
@@ -1193,69 +1193,43 @@ static inline int snd_sonicvibes_create_gameport(struct sonicvibes *sonic) { ret
 static inline void snd_sonicvibes_free_gameport(struct sonicvibes *sonic) { }
 #endif
 
-static int snd_sonicvibes_free(struct sonicvibes *sonic)
+static void snd_sonicvibes_free(struct snd_card *card)
 {
+       struct sonicvibes *sonic = card->private_data;
+
        snd_sonicvibes_free_gameport(sonic);
        pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port);
        pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port);
-       if (sonic->irq >= 0)
-               free_irq(sonic->irq, sonic);
-       release_and_free_resource(sonic->res_dmaa);
-       release_and_free_resource(sonic->res_dmac);
-       pci_release_regions(sonic->pci);
-       pci_disable_device(sonic->pci);
-       kfree(sonic);
-       return 0;
-}
-
-static int snd_sonicvibes_dev_free(struct snd_device *device)
-{
-       struct sonicvibes *sonic = device->device_data;
-       return snd_sonicvibes_free(sonic);
 }
 
 static int snd_sonicvibes_create(struct snd_card *card,
                                 struct pci_dev *pci,
                                 int reverb,
-                                int mge,
-                                struct sonicvibes **rsonic)
+                                int mge)
 {
-       struct sonicvibes *sonic;
+       struct sonicvibes *sonic = card->private_data;
        unsigned int dmaa, dmac;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_sonicvibes_dev_free,
-       };
 
-       *rsonic = NULL;
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 24 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
                dev_err(card->dev,
                        "architecture does not support 24bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                 return -ENXIO;
         }
 
-       sonic = kzalloc(sizeof(*sonic), GFP_KERNEL);
-       if (sonic == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&sonic->reg_lock);
        sonic->card = card;
        sonic->pci = pci;
        sonic->irq = -1;
 
        err = pci_request_regions(pci, "S3 SonicVibes");
-       if (err < 0) {
-               kfree(sonic);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
 
        sonic->sb_port = pci_resource_start(pci, 0);
        sonic->enh_port = pci_resource_start(pci, 1);
@@ -1263,14 +1237,14 @@ static int snd_sonicvibes_create(struct snd_card *card,
        sonic->midi_port = pci_resource_start(pci, 3);
        sonic->game_port = pci_resource_start(pci, 4);
 
-       if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, sonic)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_sonicvibes_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, sonic)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_sonicvibes_free(sonic);
                return -EBUSY;
        }
        sonic->irq = pci->irq;
        card->sync_irq = sonic->irq;
+       card->private_free = snd_sonicvibes_free;
 
        pci_read_config_dword(pci, 0x40, &dmaa);
        pci_read_config_dword(pci, 0x48, &dmac);
@@ -1294,17 +1268,17 @@ static int snd_sonicvibes_create(struct snd_card *card,
        pci_write_config_dword(pci, 0x40, dmaa);
        pci_write_config_dword(pci, 0x48, dmac);
 
-       sonic->res_dmaa = request_region(dmaa, 0x10, "S3 SonicVibes DDMA-A");
+       sonic->res_dmaa = devm_request_region(&pci->dev, dmaa, 0x10,
+                                             "S3 SonicVibes DDMA-A");
        if (!sonic->res_dmaa) {
-               snd_sonicvibes_free(sonic);
                dev_err(card->dev,
                        "unable to grab DDMA-A port at 0x%x-0x%x\n",
                        dmaa, dmaa + 0x10 - 1);
                return -EBUSY;
        }
-       sonic->res_dmac = request_region(dmac, 0x10, "S3 SonicVibes DDMA-C");
+       sonic->res_dmac = devm_request_region(&pci->dev, dmac, 0x10,
+                                             "S3 SonicVibes DDMA-C");
        if (!sonic->res_dmac) {
-               snd_sonicvibes_free(sonic);
                dev_err(card->dev,
                        "unable to grab DDMA-C port at 0x%x-0x%x\n",
                        dmac, dmac + 0x10 - 1);
@@ -1365,15 +1339,7 @@ static int snd_sonicvibes_create(struct snd_card *card,
 #endif
        sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops);
-       if (err < 0) {
-               snd_sonicvibes_free(sonic);
-               return err;
-       }
-
        snd_sonicvibes_proc_init(sonic);
-
-       *rsonic = sonic;
        return 0;
 }
 
@@ -1429,7 +1395,7 @@ static int snd_sonic_probe(struct pci_dev *pci,
        struct sonicvibes *sonic;
        struct snd_rawmidi *midi_uart;
        struct snd_opl3 *opl3;
-       int idx, err;
+       int err;
 
        if (dev >= SNDRV_CARDS)
                return -ENODEV;
@@ -1438,25 +1404,16 @@ static int snd_sonic_probe(struct pci_dev *pci,
                return -ENOENT;
        }
  
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*sonic), &card);
        if (err < 0)
                return err;
-       for (idx = 0; idx < 5; idx++) {
-               if (pci_resource_start(pci, idx) == 0 ||
-                   !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) {
-                       snd_card_free(card);
-                       return -ENODEV;
-               }
-       }
+       sonic = card->private_data;
        err = snd_sonicvibes_create(card, pci,
                                    reverb[dev] ? 1 : 0,
-                                   mge[dev] ? 1 : 0,
-                                   &sonic);
-       if (err < 0) {
-               snd_card_free(card);
+                                   mge[dev] ? 1 : 0);
+       if (err < 0)
                return err;
-       }
 
        strcpy(card->driver, "SonicVibes");
        strcpy(card->shortname, "S3 SonicVibes");
@@ -1467,65 +1424,45 @@ static int snd_sonic_probe(struct pci_dev *pci,
                sonic->irq);
 
        err = snd_sonicvibes_pcm(sonic, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_sonicvibes_mixer(sonic);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES,
                                  sonic->midi_port,
                                  MPU401_INFO_INTEGRATED |
                                  MPU401_INFO_IRQ_HOOK,
                                  -1, &midi_uart);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        snd_sonicvibes_midi(sonic, midi_uart);
        err = snd_opl3_create(card, sonic->synth_port,
                              sonic->synth_port + 2,
                              OPL3_HW_OPL3_SV, 1, &opl3);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_sonicvibes_create_gameport(sonic);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_sonic_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver sonicvibes_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_sonic_ids,
        .probe = snd_sonic_probe,
-       .remove = snd_sonic_remove,
 };
 
 module_pci_driver(sonicvibes_driver);
index 60e4dca..9922ab4 100644 (file)
@@ -62,21 +62,18 @@ static int snd_trident_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*trident), &card);
        if (err < 0)
                return err;
+       trident = card->private_data;
 
        err = snd_trident_create(card, pci,
                                 pcm_channels[dev],
                                 ((pci->vendor << 16) | pci->device) == TRIDENT_DEVICE_ID_SI7018 ? 1 : 2,
-                                wavetable_size[dev],
-                                &trident);
-       if (err < 0) {
-               snd_card_free(card);
+                                wavetable_size[dev]);
+       if (err < 0)
                return err;
-       }
-       card->private_data = trident;
 
        switch (trident->device) {
        case TRIDENT_DEVICE_ID_DX:
@@ -102,26 +99,20 @@ static int snd_trident_probe(struct pci_dev *pci,
                card->shortname, trident->port, trident->irq);
 
        err = snd_trident_pcm(trident, pcm_dev++);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        switch (trident->device) {
        case TRIDENT_DEVICE_ID_DX:
        case TRIDENT_DEVICE_ID_NX:
                err = snd_trident_foldback_pcm(trident, pcm_dev++);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
                break;
        }
        if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) {
                err = snd_trident_spdif_pcm(trident, pcm_dev++);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
        if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
                err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
@@ -129,34 +120,24 @@ static int snd_trident_probe(struct pci_dev *pci,
                                          MPU401_INFO_INTEGRATED |
                                          MPU401_INFO_IRQ_HOOK,
                                          -1, &trident->rmidi);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 
        snd_trident_create_gameport(trident);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_trident_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver trident_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_trident_ids,
        .probe = snd_trident_probe,
-       .remove = snd_trident_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &snd_trident_pm,
index c579a44..9768a7f 100644 (file)
@@ -251,9 +251,9 @@ struct snd_trident_memblk_arg {
 struct snd_trident_tlb {
        __le32 *entries;                /* 16k-aligned TLB table */
        dma_addr_t entries_dmaaddr;     /* 16k-aligned PCI address to TLB table */
-       struct snd_dma_buffer buffer;
+       struct snd_dma_buffer *buffer;
        struct snd_util_memhdr * memhdr;        /* page allocation list */
-       struct snd_dma_buffer silent_page;
+       struct snd_dma_buffer *silent_page;
 };
 
 struct snd_trident_voice {
@@ -400,8 +400,7 @@ int snd_trident_create(struct snd_card *card,
                       struct pci_dev *pci,
                       int pcm_streams,
                       int pcm_spdif_device,
-                      int max_wavetable_size,
-                      struct snd_trident ** rtrident);
+                      int max_wavetable_size);
 int snd_trident_create_gameport(struct snd_trident *trident);
 
 int snd_trident_pcm(struct snd_trident *trident, int device);
index cfbca3b..e98eea1 100644 (file)
@@ -42,7 +42,7 @@ static int snd_trident_sis_reset(struct snd_trident *trident);
 
 static void snd_trident_clear_voices(struct snd_trident * trident,
                                     unsigned short v_min, unsigned short v_max);
-static int snd_trident_free(struct snd_trident *trident);
+static void snd_trident_free(struct snd_card *card);
 
 /*
  *  common I/O routines
@@ -3299,12 +3299,6 @@ static void snd_trident_proc_init(struct snd_trident *trident)
        snd_card_ro_proc_new(trident->card, s, trident, snd_trident_proc_read);
 }
 
-static int snd_trident_dev_free(struct snd_device *device)
-{
-       struct snd_trident *trident = device->device_data;
-       return snd_trident_free(trident);
-}
-
 /*---------------------------------------------------------------------------
    snd_trident_tlb_alloc
   
@@ -3324,23 +3318,27 @@ static int snd_trident_tlb_alloc(struct snd_trident *trident)
        /* TLB array must be aligned to 16kB !!! so we allocate
           32kB region and correct offset when necessary */
 
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev,
-                               2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) {
+       trident->tlb.buffer =
+               snd_devm_alloc_pages(&trident->pci->dev, SNDRV_DMA_TYPE_DEV,
+                                    2 * SNDRV_TRIDENT_MAX_PAGES * 4);
+       if (!trident->tlb.buffer) {
                dev_err(trident->card->dev, "unable to allocate TLB buffer\n");
                return -ENOMEM;
        }
-       trident->tlb.entries = (__le32 *)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4);
-       trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer.addr, SNDRV_TRIDENT_MAX_PAGES * 4);
+       trident->tlb.entries = (__le32 *)ALIGN((unsigned long)trident->tlb.buffer->area, SNDRV_TRIDENT_MAX_PAGES * 4);
+       trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer->addr, SNDRV_TRIDENT_MAX_PAGES * 4);
 
        /* allocate and setup silent page and initialise TLB entries */
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev,
-                               SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) {
+       trident->tlb.silent_page =
+               snd_devm_alloc_pages(&trident->pci->dev, SNDRV_DMA_TYPE_DEV,
+                                    SNDRV_TRIDENT_PAGE_SIZE);
+       if (!trident->tlb.silent_page) {
                dev_err(trident->card->dev, "unable to allocate silent page\n");
                return -ENOMEM;
        }
-       memset(trident->tlb.silent_page.area, 0, SNDRV_TRIDENT_PAGE_SIZE);
+       memset(trident->tlb.silent_page->area, 0, SNDRV_TRIDENT_PAGE_SIZE);
        for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++)
-               trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page.addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));
+               trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page->addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));
 
        /* use emu memory block manager code to manage tlb page allocation */
        trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE * SNDRV_TRIDENT_MAX_PAGES);
@@ -3497,36 +3495,24 @@ int snd_trident_create(struct snd_card *card,
                       struct pci_dev *pci,
                       int pcm_streams,
                       int pcm_spdif_device,
-                      int max_wavetable_size,
-                      struct snd_trident ** rtrident)
+                      int max_wavetable_size)
 {
-       struct snd_trident *trident;
+       struct snd_trident *trident = card->private_data;
        int i, err;
        struct snd_trident_voice *voice;
        struct snd_trident_pcm_mixer *tmix;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_trident_dev_free,
-       };
-
-       *rtrident = NULL;
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 30 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(30))) {
                dev_err(card->dev,
                        "architecture does not support 30bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
        
-       trident = kzalloc(sizeof(*trident), GFP_KERNEL);
-       if (trident == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        trident->device = (pci->vendor << 16) | pci->device;
        trident->card = card;
        trident->pci = pci;
@@ -3542,22 +3528,19 @@ int snd_trident_create(struct snd_card *card,
                max_wavetable_size = 0;
        trident->synth.max_size = max_wavetable_size * 1024;
        trident->irq = -1;
+       card->private_free = snd_trident_free;
 
        trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE);
        pci_set_master(pci);
 
        err = pci_request_regions(pci, "Trident Audio");
-       if (err < 0) {
-               kfree(trident);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        trident->port = pci_resource_start(pci, 0);
 
-       if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, trident)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_trident_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, trident)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_trident_free(trident);
                return -EBUSY;
        }
        trident->irq = pci->irq;
@@ -3565,13 +3548,10 @@ int snd_trident_create(struct snd_card *card,
 
        /* allocate 16k-aligned TLB for NX cards */
        trident->tlb.entries = NULL;
-       trident->tlb.buffer.area = NULL;
        if (trident->device == TRIDENT_DEVICE_ID_NX) {
                err = snd_trident_tlb_alloc(trident);
-               if (err < 0) {
-                       snd_trident_free(trident);
+               if (err < 0)
                        return err;
-               }
        }
 
        trident->spdif_bits = trident->spdif_pcm_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
@@ -3591,16 +3571,8 @@ int snd_trident_create(struct snd_card *card,
                snd_BUG();
                break;
        }
-       if (err < 0) {
-               snd_trident_free(trident);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, trident, &ops);
-       if (err < 0) {
-               snd_trident_free(trident);
+       if (err < 0)
                return err;
-       }
 
        err = snd_trident_mixer(trident, pcm_spdif_device);
        if (err < 0)
@@ -3624,7 +3596,6 @@ int snd_trident_create(struct snd_card *card,
        snd_trident_enable_eso(trident);
 
        snd_trident_proc_init(trident);
-       *rtrident = trident;
        return 0;
 }
 
@@ -3634,14 +3605,16 @@ int snd_trident_create(struct snd_card *card,
    Description: This routine will free the device specific class for
                 the 4DWave card. 
                 
-   Parameters:  trident  - device specific private data for 4DWave card
+   Parameters:  card - card to release
 
    Returns:     None.
   
   ---------------------------------------------------------------------------*/
 
-static int snd_trident_free(struct snd_trident *trident)
+static void snd_trident_free(struct snd_card *card)
 {
+       struct snd_trident *trident = card->private_data;
+
        snd_trident_free_gameport(trident);
        snd_trident_disable_eso(trident);
        // Disable S/PDIF out
@@ -3650,19 +3623,10 @@ static int snd_trident_free(struct snd_trident *trident)
        else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
                outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
        }
-       if (trident->irq >= 0)
-               free_irq(trident->irq, trident);
-       if (trident->tlb.buffer.area) {
+       if (trident->tlb.buffer) {
                outl(0, TRID_REG(trident, NX_TLBC));
                snd_util_memhdr_free(trident->tlb.memhdr);
-               if (trident->tlb.silent_page.area)
-                       snd_dma_free_pages(&trident->tlb.silent_page);
-               snd_dma_free_pages(&trident->tlb.buffer);
        }
-       pci_release_regions(trident->pci);
-       pci_disable_device(trident->pci);
-       kfree(trident);
-       return 0;
 }
 
 /*---------------------------------------------------------------------------
index 4ad3855..05de2b9 100644 (file)
@@ -31,7 +31,7 @@
 /* fill TLB entrie(s) corresponding to page with ptr */
 #define set_tlb_bus(trident,page,addr) __set_tlb_bus(trident,page,addr)
 /* fill TLB entrie(s) corresponding to page with silence pointer */
-#define set_silent_tlb(trident,page)   __set_tlb_bus(trident, page, trident->tlb.silent_page.addr)
+#define set_silent_tlb(trident,page)   __set_tlb_bus(trident, page, trident->tlb.silent_page->addr)
 /* get aligned page from offset address */
 #define get_aligned_page(offset)       ((offset) >> 12)
 /* get offset address from aligned page */
@@ -58,8 +58,8 @@ static inline void set_tlb_bus(struct snd_trident *trident, int page,
 static inline void set_silent_tlb(struct snd_trident *trident, int page)
 {
        page <<= 1;
-       __set_tlb_bus(trident, page, trident->tlb.silent_page.addr);
-       __set_tlb_bus(trident, page+1, trident->tlb.silent_page.addr);
+       __set_tlb_bus(trident, page, trident->tlb.silent_page->addr);
+       __set_tlb_bus(trident, page+1, trident->tlb.silent_page->addr);
 }
 
 #else
@@ -92,7 +92,7 @@ static inline void set_silent_tlb(struct snd_trident *trident, int page)
        int i;
        page *= UNIT_PAGES;
        for (i = 0; i < UNIT_PAGES; i++, page++)
-               __set_tlb_bus(trident, page, trident->tlb.silent_page.addr);
+               __set_tlb_bus(trident, page, trident->tlb.silent_page->addr);
 }
 
 #endif /* PAGE_SIZE */
index 943813a..65514f7 100644 (file)
@@ -1911,13 +1911,12 @@ static int snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_overrid
 static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy)
 {
        struct gameport *gp;
-       struct resource *r;
 
        if (!joystick)
                return -ENODEV;
 
-       r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport");
-       if (!r) {
+       if (!devm_request_region(chip->card->dev, JOYSTICK_ADDR, 8,
+                                "VIA686 gameport")) {
                dev_warn(chip->card->dev, "cannot reserve joystick port %#x\n",
                       JOYSTICK_ADDR);
                return -EBUSY;
@@ -1927,7 +1926,6 @@ static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legac
        if (!gp) {
                dev_err(chip->card->dev,
                        "cannot allocate memory for gameport\n");
-               release_and_free_resource(r);
                return -ENOMEM;
        }
 
@@ -1935,7 +1933,6 @@ static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legac
        gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
        gameport_set_dev_parent(gp, &chip->pci->dev);
        gp->io = JOYSTICK_ADDR;
-       gameport_set_port_data(gp, r);
 
        /* Enable legacy joystick port */
        *legacy |= VIA_FUNC_ENABLE_GAME;
@@ -1949,11 +1946,8 @@ static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legac
 static void snd_via686_free_gameport(struct via82xx *chip)
 {
        if (chip->gameport) {
-               struct resource *r = gameport_get_port_data(chip->gameport);
-
                gameport_unregister_port(chip->gameport);
                chip->gameport = NULL;
-               release_and_free_resource(r);
        }
 }
 #else
@@ -2063,7 +2057,8 @@ static int snd_via686_init_misc(struct via82xx *chip)
                }
        }
        if (mpu_port >= 0x200)
-               chip->mpu_res = request_region(mpu_port, 2, "VIA82xx MPU401");
+               chip->mpu_res = devm_request_region(&chip->pci->dev, mpu_port,
+                                                   2, "VIA82xx MPU401");
        if (chip->mpu_res) {
                if (rev_h)
                        legacy |= VIA_FUNC_MIDI_PNP;    /* enable PCI I/O 2 */
@@ -2302,61 +2297,35 @@ static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume
 #define SND_VIA82XX_PM_OPS     NULL
 #endif /* CONFIG_PM_SLEEP */
 
-static int snd_via82xx_free(struct via82xx *chip)
+static void snd_via82xx_free(struct snd_card *card)
 {
+       struct via82xx *chip = card->private_data;
        unsigned int i;
 
-       if (chip->irq < 0)
-               goto __end_hw;
        /* disable interrupts */
        for (i = 0; i < chip->num_devs; i++)
                snd_via82xx_channel_reset(chip, &chip->devs[i]);
 
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
- __end_hw:
-       release_and_free_resource(chip->mpu_res);
-       pci_release_regions(chip->pci);
-
        if (chip->chip_type == TYPE_VIA686) {
                snd_via686_free_gameport(chip);
                pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, chip->old_legacy);
                pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, chip->old_legacy_cfg);
        }
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_via82xx_dev_free(struct snd_device *device)
-{
-       struct via82xx *chip = device->device_data;
-       return snd_via82xx_free(chip);
 }
 
 static int snd_via82xx_create(struct snd_card *card,
                              struct pci_dev *pci,
                              int chip_type,
                              int revision,
-                             unsigned int ac97_clock,
-                             struct via82xx **r_via)
+                             unsigned int ac97_clock)
 {
-       struct via82xx *chip;
+       struct via82xx *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_via82xx_dev_free,
-        };
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (!chip) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->chip_type = chip_type;
        chip->revision = revision;
 
@@ -2373,44 +2342,31 @@ static int snd_via82xx_create(struct snd_card *card,
                              chip->old_legacy & ~(VIA_FUNC_ENABLE_SB|VIA_FUNC_ENABLE_FM));
 
        err = pci_request_regions(pci, card->driver);
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        chip->port = pci_resource_start(pci, 0);
-       if (request_irq(pci->irq,
-                       chip_type == TYPE_VIA8233 ?
-                       snd_via8233_interrupt : snd_via686_interrupt,
-                       IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq,
+                            chip_type == TYPE_VIA8233 ?
+                            snd_via8233_interrupt : snd_via686_interrupt,
+                            IRQF_SHARED,
+                            KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_via82xx_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_via82xx_free;
        if (ac97_clock >= 8000 && ac97_clock <= 48000)
                chip->ac97_clock = ac97_clock;
 
        err = snd_via82xx_chip_init(chip);
-       if (err < 0) {
-               snd_via82xx_free(chip);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_via82xx_free(chip);
+       if (err < 0)
                return err;
-       }
 
        /* The 8233 ac97 controller does not implement the master bit
         * in the pci command register. IMHO this is a violation of the PCI spec.
         * We call pci_set_master here because it does not hurt. */
        pci_set_master(pci);
-
-       *r_via = chip;
        return 0;
 }
 
@@ -2511,9 +2467,11 @@ static int snd_via82xx_probe(struct pci_dev *pci,
        unsigned int i;
        int err;
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        card_type = pci_id->driver_data;
        switch (card_type) {
@@ -2552,36 +2510,34 @@ static int snd_via82xx_probe(struct pci_dev *pci,
                break;
        default:
                dev_err(card->dev, "invalid card type %d\n", card_type);
-               err = -EINVAL;
-               goto __error;
+               return -EINVAL;
        }
                
        err = snd_via82xx_create(card, pci, chip_type, pci->revision,
-                                ac97_clock, &chip);
+                                ac97_clock);
        if (err < 0)
-               goto __error;
-       card->private_data = chip;
+               return err;
        err = snd_via82xx_mixer_new(chip, ac97_quirk);
        if (err < 0)
-               goto __error;
+               return err;
 
        if (chip_type == TYPE_VIA686) {
                err = snd_via686_pcm_new(chip);
                if (err < 0)
-                       goto __error;
+                       return err;
                err = snd_via686_init_misc(chip);
                if (err < 0)
-                       goto __error;
+                       return err;
        } else {
                if (chip_type == TYPE_VIA8233A) {
                        err = snd_via8233a_pcm_new(chip);
                        if (err < 0)
-                               goto __error;
+                               return err;
                        // chip->dxs_fixed = 1; /* FIXME: use 48k for DXS #3? */
                } else {
                        err = snd_via8233_pcm_new(chip);
                        if (err < 0)
-                               goto __error;
+                               return err;
                        if (dxs_support == VIA_DXS_48K)
                                chip->dxs_fixed = 1;
                        else if (dxs_support == VIA_DXS_NO_VRA)
@@ -2593,7 +2549,7 @@ static int snd_via82xx_probe(struct pci_dev *pci,
                }
                err = snd_via8233_init_misc(chip);
                if (err < 0)
-                       goto __error;
+                       return err;
        }
 
        /* disable interrupts */
@@ -2607,28 +2563,16 @@ static int snd_via82xx_probe(struct pci_dev *pci,
        snd_via82xx_proc_init(chip);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        return 0;
-
- __error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_via82xx_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver via82xx_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_via82xx_ids,
        .probe = snd_via82xx_probe,
-       .remove = snd_via82xx_remove,
        .driver = {
                .pm = SND_VIA82XX_PM_OPS,
        },
index 07278a3..234f7fb 100644 (file)
@@ -1048,95 +1048,57 @@ static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume
 #define SND_VIA82XX_PM_OPS     NULL
 #endif /* CONFIG_PM_SLEEP */
 
-static int snd_via82xx_free(struct via82xx_modem *chip)
+static void snd_via82xx_free(struct snd_card *card)
 {
+       struct via82xx_modem *chip = card->private_data;
        unsigned int i;
 
-       if (chip->irq < 0)
-               goto __end_hw;
        /* disable interrupts */
        for (i = 0; i < chip->num_devs; i++)
                snd_via82xx_channel_reset(chip, &chip->devs[i]);
-
-      __end_hw:
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_via82xx_dev_free(struct snd_device *device)
-{
-       struct via82xx_modem *chip = device->device_data;
-       return snd_via82xx_free(chip);
 }
 
 static int snd_via82xx_create(struct snd_card *card,
                              struct pci_dev *pci,
                              int chip_type,
                              int revision,
-                             unsigned int ac97_clock,
-                             struct via82xx_modem **r_via)
+                             unsigned int ac97_clock)
 {
-       struct via82xx_modem *chip;
+       struct via82xx_modem *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_via82xx_dev_free,
-        };
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (!chip) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&chip->reg_lock);
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
 
        err = pci_request_regions(pci, card->driver);
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        chip->port = pci_resource_start(pci, 0);
-       if (request_irq(pci->irq, snd_via82xx_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_via82xx_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_via82xx_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_via82xx_free;
        if (ac97_clock >= 8000 && ac97_clock <= 48000)
                chip->ac97_clock = ac97_clock;
 
        err = snd_via82xx_chip_init(chip);
-       if (err < 0) {
-               snd_via82xx_free(chip);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_via82xx_free(chip);
+       if (err < 0)
                return err;
-       }
 
        /* The 8233 ac97 controller does not implement the master bit
         * in the pci command register. IMHO this is a violation of the PCI spec.
         * We call pci_set_master here because it does not hurt. */
        pci_set_master(pci);
-
-       *r_via = chip;
        return 0;
 }
 
@@ -1150,9 +1112,11 @@ static int snd_via82xx_probe(struct pci_dev *pci,
        unsigned int i;
        int err;
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        card_type = pci_id->driver_data;
        switch (card_type) {
@@ -1162,22 +1126,20 @@ static int snd_via82xx_probe(struct pci_dev *pci,
                break;
        default:
                dev_err(card->dev, "invalid card type %d\n", card_type);
-               err = -EINVAL;
-               goto __error;
+               return -EINVAL;
        }
                
        err = snd_via82xx_create(card, pci, chip_type, pci->revision,
-                                ac97_clock, &chip);
+                                ac97_clock);
        if (err < 0)
-               goto __error;
-       card->private_data = chip;
+               return err;
        err = snd_via82xx_mixer_new(chip);
        if (err < 0)
-               goto __error;
+               return err;
 
        err = snd_via686_pcm_new(chip);
        if (err < 0)
-               goto __error;
+               return err;
 
        /* disable interrupts */
        for (i = 0; i < chip->num_devs; i++)
@@ -1189,28 +1151,16 @@ static int snd_via82xx_probe(struct pci_dev *pci,
        snd_via82xx_proc_init(chip);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        return 0;
-
- __error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_via82xx_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver via82xx_modem_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_via82xx_modem_ids,
        .probe = snd_via82xx_probe,
-       .remove = snd_via82xx_remove,
        .driver = {
                .pm = SND_VIA82XX_PM_OPS,
        },
index 04c7204..468a6a2 100644 (file)
@@ -100,26 +100,6 @@ static const struct snd_vx_hardware vx222_mic_hw = {
 
 /*
  */
-static int snd_vx222_free(struct vx_core *chip)
-{
-       struct snd_vx222 *vx = to_vx222(chip);
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, (void*)chip);
-       if (vx->port[0])
-               pci_release_regions(vx->pci);
-       pci_disable_device(vx->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_vx222_dev_free(struct snd_device *device)
-{
-       struct vx_core *chip = device->device_data;
-       return snd_vx222_free(chip);
-}
-
-
 static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
                            const struct snd_vx_hardware *hw,
                            struct snd_vx222 **rchip)
@@ -127,13 +107,10 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
        struct vx_core *chip;
        struct snd_vx222 *vx;
        int i, err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_vx222_dev_free,
-       };
        const struct snd_vx_ops *vx_ops;
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        pci_set_master(pci);
@@ -141,38 +118,27 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
        vx_ops = hw->type == VX_TYPE_BOARD ? &vx222_old_ops : &vx222_ops;
        chip = snd_vx_create(card, hw, vx_ops,
                             sizeof(struct snd_vx222) - sizeof(struct vx_core));
-       if (! chip) {
-               pci_disable_device(pci);
+       if (!chip)
                return -ENOMEM;
-       }
        vx = to_vx222(chip);
        vx->pci = pci;
 
        err = pci_request_regions(pci, CARD_NAME);
-       if (err < 0) {
-               snd_vx222_free(chip);
+       if (err < 0)
                return err;
-       }
        for (i = 0; i < 2; i++)
                vx->port[i] = pci_resource_start(pci, i + 1);
 
-       if (request_threaded_irq(pci->irq, snd_vx_irq_handler,
-                                snd_vx_threaded_irq_handler, IRQF_SHARED,
-                                KBUILD_MODNAME, chip)) {
+       if (devm_request_threaded_irq(&pci->dev, pci->irq, snd_vx_irq_handler,
+                                     snd_vx_threaded_irq_handler, IRQF_SHARED,
+                                     KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_vx222_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_vx222_free(chip);
-               return err;
-       }
-
        *rchip = vx;
+
        return 0;
 }
 
@@ -193,8 +159,8 @@ static int snd_vx222_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               0, &card);
        if (err < 0)
                return err;
 
@@ -211,10 +177,8 @@ static int snd_vx222_probe(struct pci_dev *pci,
                break;
        }
        err = snd_vx222_create(card, pci, hw, &vx);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        card->private_data = vx;
        vx->core.ibl.size = ibl[dev];
 
@@ -228,27 +192,18 @@ static int snd_vx222_probe(struct pci_dev *pci,
 #endif
 
        err = snd_vx_setup_firmware(&vx->core);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_vx222_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int snd_vx222_suspend(struct device *dev)
 {
@@ -276,7 +231,6 @@ static struct pci_driver vx222_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_vx222_ids,
        .probe = snd_vx222_probe,
-       .remove = snd_vx222_remove,
        .driver = {
                .pm = SND_VX222_PM_OPS,
        },
index 7e32d57..1e198e4 100644 (file)
@@ -105,7 +105,8 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
        }
 
        if (!r) {
-               r = request_region(io_port, 1, "YMFPCI gameport");
+               r = devm_request_region(&chip->pci->dev, io_port, 1,
+                                       "YMFPCI gameport");
                if (!r) {
                        dev_err(chip->card->dev,
                                "joystick port %#x is in use.\n", io_port);
@@ -117,7 +118,6 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
        if (!gp) {
                dev_err(chip->card->dev,
                        "cannot allocate memory for gameport\n");
-               release_and_free_resource(r);
                return -ENOMEM;
        }
 
@@ -126,7 +126,6 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
        gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
        gameport_set_dev_parent(gp, &chip->pci->dev);
        gp->io = io_port;
-       gameport_set_port_data(gp, r);
 
        if (chip->pci->device >= 0x0010) /* YMF 744/754 */
                pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE, io_port);
@@ -142,12 +141,8 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
 void snd_ymfpci_free_gameport(struct snd_ymfpci *chip)
 {
        if (chip->gameport) {
-               struct resource *r = gameport_get_port_data(chip->gameport);
-
                gameport_unregister_port(chip->gameport);
                chip->gameport = NULL;
-
-               release_and_free_resource(r);
        }
 }
 #else
@@ -176,9 +171,10 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
        }
 
        err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+                          sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        switch (pci_id->device) {
        case 0x0004: str = "YMF724";  model = "DS-1"; break;
@@ -199,7 +195,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                        fm_port[dev] = pci_resource_start(pci, 1);
                }
                if (fm_port[dev] > 0)
-                       fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3");
+                       fm_res = devm_request_region(&pci->dev, fm_port[dev],
+                                                    4, "YMFPCI OPL3");
                if (fm_res) {
                        legacy_ctrl |= YMFPCI_LEGACY_FMEN;
                        pci_write_config_word(pci, PCIR_DSXG_FMBASE, fm_port[dev]);
@@ -209,7 +206,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                        mpu_port[dev] = pci_resource_start(pci, 1) + 0x20;
                }
                if (mpu_port[dev] > 0)
-                       mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401");
+                       mpu_res = devm_request_region(&pci->dev, mpu_port[dev],
+                                                     2, "YMFPCI MPU401");
                if (mpu_res) {
                        legacy_ctrl |= YMFPCI_LEGACY_MEN;
                        pci_write_config_word(pci, PCIR_DSXG_MPU401BASE, mpu_port[dev]);
@@ -223,7 +221,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                default: fm_port[dev] = 0; break;
                }
                if (fm_port[dev] > 0)
-                       fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3");
+                       fm_res = devm_request_region(&pci->dev, fm_port[dev],
+                                                    4, "YMFPCI OPL3");
                if (fm_res) {
                        legacy_ctrl |= YMFPCI_LEGACY_FMEN;
                } else {
@@ -238,7 +237,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                default: mpu_port[dev] = 0; break;
                }
                if (mpu_port[dev] > 0)
-                       mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401");
+                       mpu_res = devm_request_region(&pci->dev, mpu_port[dev],
+                                                     2, "YMFPCI MPU401");
                if (mpu_res) {
                        legacy_ctrl |= YMFPCI_LEGACY_MEN;
                } else {
@@ -253,15 +253,9 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
        pci_read_config_word(pci, PCIR_DSXG_LEGACY, &old_legacy_ctrl);
        pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
        pci_write_config_word(pci, PCIR_DSXG_ELEGACY, legacy_ctrl2);
-       err = snd_ymfpci_create(card, pci, old_legacy_ctrl, &chip);
-       if (err  < 0) {
-               release_and_free_resource(mpu_res);
-               release_and_free_resource(fm_res);
-               goto free_card;
-       }
-       chip->fm_res = fm_res;
-       chip->mpu_res = mpu_res;
-       card->private_data = chip;
+       err = snd_ymfpci_create(card, pci, old_legacy_ctrl);
+       if (err  < 0)
+               return err;
 
        strcpy(card->driver, str);
        sprintf(card->shortname, "Yamaha %s (%s)", model, str);
@@ -271,30 +265,30 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                chip->irq);
        err = snd_ymfpci_pcm(chip, 0);
        if (err < 0)
-               goto free_card;
+               return err;
 
        err = snd_ymfpci_pcm_spdif(chip, 1);
        if (err < 0)
-               goto free_card;
+               return err;
 
        err = snd_ymfpci_mixer(chip, rear_switch[dev]);
        if (err < 0)
-               goto free_card;
+               return err;
 
        if (chip->ac97->ext_id & AC97_EI_SDAC) {
                err = snd_ymfpci_pcm_4ch(chip, 2);
                if (err < 0)
-                       goto free_card;
+                       return err;
 
                err = snd_ymfpci_pcm2(chip, 3);
                if (err < 0)
-                       goto free_card;
+                       return err;
        }
        err = snd_ymfpci_timer(chip, 0);
        if (err < 0)
-               goto free_card;
+               return err;
 
-       if (chip->mpu_res) {
+       if (mpu_res) {
                err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI,
                                          mpu_port[dev],
                                          MPU401_INFO_INTEGRATED |
@@ -308,7 +302,7 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                        pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
                }
        }
-       if (chip->fm_res) {
+       if (fm_res) {
                err = snd_opl3_create(card,
                                      fm_port[dev],
                                      fm_port[dev] + 2,
@@ -323,7 +317,7 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                        err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                        if (err < 0) {
                                dev_err(card->dev, "cannot create opl3 hwdep\n");
-                               goto free_card;
+                               return err;
                        }
                }
        }
@@ -332,27 +326,17 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto free_card;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
-free_card:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_card_ymfpci_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver ymfpci_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ymfpci_ids,
        .probe = snd_card_ymfpci_probe,
-       .remove = snd_card_ymfpci_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &snd_ymfpci_pm,
index c73d8a5..6696877 100644 (file)
@@ -275,16 +275,13 @@ struct snd_ymfpci {
        unsigned char rev;      /* PCI revision */
        unsigned long reg_area_phys;
        void __iomem *reg_area_virt;
-       struct resource *res_reg_area;
-       struct resource *fm_res;
-       struct resource *mpu_res;
 
        unsigned short old_legacy_ctrl;
 #ifdef SUPPORT_JOYSTICK
        struct gameport *gameport;
 #endif
 
-       struct snd_dma_buffer work_ptr;
+       struct snd_dma_buffer *work_ptr;
 
        unsigned int bank_size_playback;
        unsigned int bank_size_capture;
@@ -358,8 +355,7 @@ struct snd_ymfpci {
 
 int snd_ymfpci_create(struct snd_card *card,
                      struct pci_dev *pci,
-                     unsigned short old_legacy_ctrl,
-                     struct snd_ymfpci ** rcodec);
+                     unsigned short old_legacy_ctrl);
 void snd_ymfpci_free_gameport(struct snd_ymfpci *chip);
 
 extern const struct dev_pm_ops snd_ymfpci_pm;
index 8fd0607..c80114c 100644 (file)
@@ -2116,11 +2116,12 @@ static int snd_ymfpci_memalloc(struct snd_ymfpci *chip)
               chip->work_size;
        /* work_ptr must be aligned to 256 bytes, but it's already
           covered with the kernel page allocation mechanism */
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
-                               size, &chip->work_ptr) < 0) 
+       chip->work_ptr = snd_devm_alloc_pages(&chip->pci->dev,
+                                             SNDRV_DMA_TYPE_DEV, size);
+       if (!chip->work_ptr)
                return -ENOMEM;
-       ptr = chip->work_ptr.area;
-       ptr_addr = chip->work_ptr.addr;
+       ptr = chip->work_ptr->area;
+       ptr_addr = chip->work_ptr->addr;
        memset(ptr, 0, size);   /* for sure */
 
        chip->bank_base_playback = ptr;
@@ -2165,7 +2166,7 @@ static int snd_ymfpci_memalloc(struct snd_ymfpci *chip)
        chip->work_base_addr = ptr_addr;
        
        snd_BUG_ON(ptr + chip->work_size !=
-                  chip->work_ptr.area + chip->work_ptr.bytes);
+                  chip->work_ptr->area + chip->work_ptr->bytes);
 
        snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, chip->bank_base_playback_addr);
        snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, chip->bank_base_capture_addr);
@@ -2196,65 +2197,32 @@ static int snd_ymfpci_memalloc(struct snd_ymfpci *chip)
        return 0;
 }
 
-static int snd_ymfpci_free(struct snd_ymfpci *chip)
+static void snd_ymfpci_free(struct snd_card *card)
 {
+       struct snd_ymfpci *chip = card->private_data;
        u16 ctrl;
 
-       if (snd_BUG_ON(!chip))
-               return -EINVAL;
-
-       if (chip->res_reg_area) {       /* don't touch busy hardware */
-               snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
-               snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
-               snd_ymfpci_writel(chip, YDSXGR_LEGACYOUTVOL, 0);
-               snd_ymfpci_writel(chip, YDSXGR_STATUS, ~0);
-               snd_ymfpci_disable_dsp(chip);
-               snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, 0);
-               snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, 0);
-               snd_ymfpci_writel(chip, YDSXGR_EFFCTRLBASE, 0);
-               snd_ymfpci_writel(chip, YDSXGR_WORKBASE, 0);
-               snd_ymfpci_writel(chip, YDSXGR_WORKSIZE, 0);
-               ctrl = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL);
-               snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
-       }
+       snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
+       snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
+       snd_ymfpci_writel(chip, YDSXGR_LEGACYOUTVOL, 0);
+       snd_ymfpci_writel(chip, YDSXGR_STATUS, ~0);
+       snd_ymfpci_disable_dsp(chip);
+       snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, 0);
+       snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, 0);
+       snd_ymfpci_writel(chip, YDSXGR_EFFCTRLBASE, 0);
+       snd_ymfpci_writel(chip, YDSXGR_WORKBASE, 0);
+       snd_ymfpci_writel(chip, YDSXGR_WORKSIZE, 0);
+       ctrl = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL);
+       snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
 
        snd_ymfpci_ac3_done(chip);
 
-       /* Set PCI device to D3 state */
-#if 0
-       /* FIXME: temporarily disabled, otherwise we cannot fire up
-        * the chip again unless reboot.  ACPI bug?
-        */
-       pci_set_power_state(chip->pci, PCI_D3hot);
-#endif
-
-#ifdef CONFIG_PM_SLEEP
-       kfree(chip->saved_regs);
-#endif
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       release_and_free_resource(chip->mpu_res);
-       release_and_free_resource(chip->fm_res);
        snd_ymfpci_free_gameport(chip);
-       iounmap(chip->reg_area_virt);
-       if (chip->work_ptr.area)
-               snd_dma_free_pages(&chip->work_ptr);
        
-       release_and_free_resource(chip->res_reg_area);
-
        pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
        
-       pci_disable_device(chip->pci);
        release_firmware(chip->dsp_microcode);
        release_firmware(chip->controller_microcode);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_ymfpci_dev_free(struct snd_device *device)
-{
-       struct snd_ymfpci *chip = device->device_data;
-       return snd_ymfpci_free(chip);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -2346,27 +2314,16 @@ SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume);
 
 int snd_ymfpci_create(struct snd_card *card,
                      struct pci_dev *pci,
-                     unsigned short old_legacy_ctrl,
-                     struct snd_ymfpci **rchip)
+                     unsigned short old_legacy_ctrl)
 {
-       struct snd_ymfpci *chip;
+       struct snd_ymfpci *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_ymfpci_dev_free,
-       };
        
-       *rchip = NULL;
-
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        chip->old_legacy_ctrl = old_legacy_ctrl;
        spin_lock_init(&chip->reg_lock);
        spin_lock_init(&chip->voice_lock);
@@ -2377,71 +2334,59 @@ int snd_ymfpci_create(struct snd_card *card,
        chip->irq = -1;
        chip->device_id = pci->device;
        chip->rev = pci->revision;
-       chip->reg_area_phys = pci_resource_start(pci, 0);
-       chip->reg_area_virt = ioremap(chip->reg_area_phys, 0x8000);
-       pci_set_master(pci);
-       chip->src441_used = -1;
 
-       chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI");
-       if (!chip->res_reg_area) {
+       err = pci_request_regions(pci, "YMFPCI");
+       if (err < 0)
+               return err;
+
+       chip->reg_area_phys = pci_resource_start(pci, 0);
+       chip->reg_area_virt = devm_ioremap(&pci->dev, chip->reg_area_phys, 0x8000);
+       if (!chip->reg_area_virt) {
                dev_err(chip->card->dev,
                        "unable to grab memory region 0x%lx-0x%lx\n",
                        chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1);
-               err = -EBUSY;
-               goto free_chip;
+               return -EBUSY;
        }
-       if (request_irq(pci->irq, snd_ymfpci_interrupt, IRQF_SHARED,
+       pci_set_master(pci);
+       chip->src441_used = -1;
+
+       if (devm_request_irq(&pci->dev, pci->irq, snd_ymfpci_interrupt, IRQF_SHARED,
                        KBUILD_MODNAME, chip)) {
                dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq);
-               err = -EBUSY;
-               goto free_chip;
+               return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_ymfpci_free;
 
        snd_ymfpci_aclink_reset(pci);
-       if (snd_ymfpci_codec_ready(chip, 0) < 0) {
-               err = -EIO;
-               goto free_chip;
-       }
+       if (snd_ymfpci_codec_ready(chip, 0) < 0)
+               return -EIO;
 
        err = snd_ymfpci_request_firmware(chip);
        if (err < 0) {
                dev_err(chip->card->dev, "firmware request failed: %d\n", err);
-               goto free_chip;
+               return err;
        }
        snd_ymfpci_download_image(chip);
 
        udelay(100); /* seems we need a delay after downloading image.. */
 
-       if (snd_ymfpci_memalloc(chip) < 0) {
-               err = -EIO;
-               goto free_chip;
-       }
+       if (snd_ymfpci_memalloc(chip) < 0)
+               return -EIO;
 
        err = snd_ymfpci_ac3_init(chip);
        if (err < 0)
-               goto free_chip;
+               return err;
 
 #ifdef CONFIG_PM_SLEEP
-       chip->saved_regs = kmalloc_array(YDSXGR_NUM_SAVED_REGS, sizeof(u32),
-                                        GFP_KERNEL);
-       if (chip->saved_regs == NULL) {
-               err = -ENOMEM;
-               goto free_chip;
-       }
+       chip->saved_regs = devm_kmalloc_array(&pci->dev, YDSXGR_NUM_SAVED_REGS,
+                                             sizeof(u32), GFP_KERNEL);
+       if (!chip->saved_regs)
+               return -ENOMEM;
 #endif
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto free_chip;
-
        snd_ymfpci_proc_init(card, chip);
 
-       *rchip = chip;
        return 0;
-
-free_chip:
-       snd_ymfpci_free(chip);
-       return err;
 }
index 0dfb6a9..7a0f0e7 100644 (file)
@@ -50,19 +50,6 @@ static void vxpocket_release(struct pcmcia_device *link)
        pcmcia_disable_device(link);
 }
 
-/*
- * destructor, called from snd_card_free_when_closed()
- */
-static int snd_vxpocket_dev_free(struct snd_device *device)
-{
-       struct vx_core *chip = device->device_data;
-
-       snd_vx_free_firmware(chip);
-       kfree(chip);
-       return 0;
-}
-
-
 /*
  * Hardware information
  */
@@ -122,21 +109,12 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl,
 {
        struct vx_core *chip;
        struct snd_vxpocket *vxp;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_vxpocket_dev_free,
-       };
-       int err;
 
        chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops,
                             sizeof(struct snd_vxpocket) - sizeof(struct vx_core));
        if (!chip)
                return -ENOMEM;
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               kfree(chip);
-               return err;
-       }
        chip->ibl.size = ibl;
 
        vxp = to_vxpocket(chip);
index 7ec8559..b5096f6 100644 (file)
@@ -46,10 +46,6 @@ static int bcm63xx_pcm_hw_params(struct snd_soc_component *component,
 {
        struct i2s_dma_desc *dma_desc;
        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-       runtime->dma_bytes = params_buffer_bytes(params);
 
        dma_desc = kzalloc(sizeof(*dma_desc), GFP_NOWAIT);
        if (!dma_desc)
@@ -68,7 +64,6 @@ static int bcm63xx_pcm_hw_free(struct snd_soc_component *component,
 
        dma_desc = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
        kfree(dma_desc);
-       snd_pcm_set_runtime_buffer(substream, NULL);
 
        return 0;
 }
@@ -190,19 +185,6 @@ bcm63xx_pcm_pointer(struct snd_soc_component *component,
        return x == substream->runtime->buffer_size ? 0 : x;
 }
 
-static int bcm63xx_pcm_mmap(struct snd_soc_component *component,
-                               struct snd_pcm_substream *substream,
-                               struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       return  dma_mmap_wc(substream->pcm->card->dev, vma,
-                           runtime->dma_area,
-                           runtime->dma_addr,
-                           runtime->dma_bytes);
-
-}
-
 static int bcm63xx_pcm_open(struct snd_soc_component *component,
                        struct snd_pcm_substream *substream)
 {
@@ -362,25 +344,6 @@ static irqreturn_t i2s_dma_isr(int irq, void *bcm_i2s_priv)
        return IRQ_HANDLED;
 }
 
-static int bcm63xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
-       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-       struct snd_dma_buffer *buf = &substream->dma_buffer;
-       size_t size = bcm63xx_pcm_hardware.buffer_bytes_max;
-
-       buf->dev.type = SNDRV_DMA_TYPE_DEV;
-       buf->dev.dev = pcm->card->dev;
-       buf->private_data = NULL;
-
-       buf->area = dma_alloc_wc(pcm->card->dev,
-                                size, &buf->addr,
-                                GFP_KERNEL);
-       if (!buf->area)
-               return -ENOMEM;
-       buf->bytes = size;
-       return 0;
-}
-
 static int bcm63xx_soc_pcm_new(struct snd_soc_component *component,
                struct snd_soc_pcm_runtime *rtd)
 {
@@ -394,49 +357,18 @@ static int bcm63xx_soc_pcm_new(struct snd_soc_component *component,
 
        ret = dma_coerce_mask_and_coherent(pcm->card->dev, DMA_BIT_MASK(32));
        if (ret)
-               goto out;
-
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = bcm63xx_pcm_preallocate_dma_buffer(pcm,
-                                                SNDRV_PCM_STREAM_PLAYBACK);
-               if (ret)
-                       goto out;
+               return ret;
 
+       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
                i2s_priv->play_substream =
                        pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = bcm63xx_pcm_preallocate_dma_buffer(pcm,
-                                       SNDRV_PCM_STREAM_CAPTURE);
-               if (ret)
-                       goto out;
+       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream)
                i2s_priv->capture_substream =
                        pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
-       }
 
-out:
-       return ret;
-}
-
-static void bcm63xx_pcm_free_dma_buffers(struct snd_soc_component *component,
-                        struct snd_pcm *pcm)
-{
-       int stream;
-       struct snd_dma_buffer *buf;
-       struct snd_pcm_substream *substream;
-
-       for (stream = 0; stream < 2; stream++) {
-               substream = pcm->streams[stream].substream;
-               if (!substream)
-                       continue;
-               buf = &substream->dma_buffer;
-               if (!buf->area)
-                       continue;
-               dma_free_wc(pcm->card->dev, buf->bytes,
-                                       buf->area, buf->addr);
-               buf->area = NULL;
-       }
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
+                                           pcm->card->dev,
+                                           bcm63xx_pcm_hardware.buffer_bytes_max);
 }
 
 static const struct snd_soc_component_driver bcm63xx_soc_platform = {
@@ -447,9 +379,7 @@ static const struct snd_soc_component_driver bcm63xx_soc_platform = {
        .prepare = bcm63xx_pcm_prepare,
        .trigger = bcm63xx_pcm_trigger,
        .pointer = bcm63xx_pcm_pointer,
-       .mmap = bcm63xx_pcm_mmap,
        .pcm_construct = bcm63xx_soc_pcm_new,
-       .pcm_destruct = bcm63xx_pcm_free_dma_buffers,
 };
 
 int bcm63xx_soc_platform_probe(struct platform_device *pdev,
index c313a26..cd9b36e 100644 (file)
@@ -284,8 +284,6 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
                return ret;
        }
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
        return 0;
 }
 
@@ -297,8 +295,6 @@ static int fsl_asrc_dma_hw_free(struct snd_soc_component *component,
        struct fsl_asrc_pair *pair = runtime->private_data;
        u8 dir = tx ? OUT : IN;
 
-       snd_pcm_set_runtime_buffer(substream, NULL);
-
        if (pair->dma_chan[!dir])
                dma_release_channel(pair->dma_chan[!dir]);
 
@@ -423,9 +419,8 @@ static int fsl_asrc_dma_pcm_new(struct snd_soc_component *component,
                                struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
-       struct snd_pcm_substream *substream;
        struct snd_pcm *pcm = rtd->pcm;
-       int ret, i;
+       int ret;
 
        ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
        if (ret) {
@@ -433,43 +428,8 @@ static int fsl_asrc_dma_pcm_new(struct snd_soc_component *component,
                return ret;
        }
 
-       for_each_pcm_streams(i) {
-               substream = pcm->streams[i].substream;
-               if (!substream)
-                       continue;
-
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
-                               FSL_ASRC_DMABUF_SIZE, &substream->dma_buffer);
-               if (ret) {
-                       dev_err(card->dev, "failed to allocate DMA buffer\n");
-                       goto err;
-               }
-       }
-
-       return 0;
-
-err:
-       if (--i == 0 && pcm->streams[i].substream)
-               snd_dma_free_pages(&pcm->streams[i].substream->dma_buffer);
-
-       return ret;
-}
-
-static void fsl_asrc_dma_pcm_free(struct snd_soc_component *component,
-                                 struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       int i;
-
-       for_each_pcm_streams(i) {
-               substream = pcm->streams[i].substream;
-               if (!substream)
-                       continue;
-
-               snd_dma_free_pages(&substream->dma_buffer);
-               substream->dma_buffer.area = NULL;
-               substream->dma_buffer.addr = 0;
-       }
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                           card->dev, FSL_ASRC_DMABUF_SIZE);
 }
 
 struct snd_soc_component_driver fsl_asrc_component = {
@@ -481,6 +441,5 @@ struct snd_soc_component_driver fsl_asrc_component = {
        .close          = fsl_asrc_dma_shutdown,
        .pointer        = fsl_asrc_dma_pcm_pointer,
        .pcm_construct  = fsl_asrc_dma_pcm_new,
-       .pcm_destruct   = fsl_asrc_dma_pcm_free,
 };
 EXPORT_SYMBOL_GPL(fsl_asrc_component);
index 84bd8a5..808fb61 100644 (file)
@@ -290,32 +290,9 @@ static int fsl_dma_new(struct snd_soc_component *component,
        if (ret)
                return ret;
 
-       /* Some codecs have separate DAIs for playback and capture, so we
-        * should allocate a DMA buffer only for the streams that are valid.
-        */
-
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
-                       fsl_dma_hardware.buffer_bytes_max,
-                       &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
-               if (ret) {
-                       dev_err(card->dev, "can't alloc playback dma buffer\n");
-                       return ret;
-               }
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
-                       fsl_dma_hardware.buffer_bytes_max,
-                       &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
-               if (ret) {
-                       dev_err(card->dev, "can't alloc capture dma buffer\n");
-                       snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
-                       return ret;
-               }
-       }
-
-       return 0;
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                           card->dev,
+                                           fsl_dma_hardware.buffer_bytes_max);
 }
 
 /**
@@ -442,7 +419,6 @@ static int fsl_dma_open(struct snd_soc_component *component,
 
        dma->assigned = true;
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
        snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware);
        runtime->private_data = dma_private;
 
@@ -815,25 +791,6 @@ static int fsl_dma_close(struct snd_soc_component *component,
        return 0;
 }
 
-/*
- * Remove this PCM driver.
- */
-static void fsl_dma_free_dma_buffers(struct snd_soc_component *component,
-                                    struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
-               substream = pcm->streams[i].substream;
-               if (substream) {
-                       snd_dma_free_pages(&substream->dma_buffer);
-                       substream->dma_buffer.area = NULL;
-                       substream->dma_buffer.addr = 0;
-               }
-       }
-}
-
 /**
  * find_ssi_node -- returns the SSI node that points to its DMA channel node
  *
@@ -904,7 +861,6 @@ static int fsl_soc_dma_probe(struct platform_device *pdev)
        dma->dai.hw_free = fsl_dma_hw_free;
        dma->dai.pointer = fsl_dma_pointer;
        dma->dai.pcm_construct = fsl_dma_new;
-       dma->dai.pcm_destruct = fsl_dma_free_dma_buffers;
 
        /* Store the SSI-specific information that we need */
        dma->ssi_stx_phys = res.start + REG_SSI_STX0;
index f20d5b1..0d12400 100644 (file)
@@ -81,7 +81,6 @@ static int snd_imx_pcm_hw_params(struct snd_soc_component *component,
        iprtd->offset = 0;
        iprtd->poll_time_ns = 1000000000 / params_rate(params) *
                                params_period_size(params);
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
        return 0;
 }
@@ -213,40 +212,6 @@ static int snd_imx_close(struct snd_soc_component *component,
        return 0;
 }
 
-static int snd_imx_pcm_mmap(struct snd_soc_component *component,
-                           struct snd_pcm_substream *substream,
-                           struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       int ret;
-
-       ret = dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
-                         runtime->dma_addr, runtime->dma_bytes);
-
-       pr_debug("%s: ret: %d %p %pad 0x%08zx\n", __func__, ret,
-                       runtime->dma_area,
-                       &runtime->dma_addr,
-                       runtime->dma_bytes);
-       return ret;
-}
-
-static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
-       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-       struct snd_dma_buffer *buf = &substream->dma_buffer;
-       size_t size = IMX_SSI_DMABUF_SIZE;
-
-       buf->dev.type = SNDRV_DMA_TYPE_DEV;
-       buf->dev.dev = pcm->card->dev;
-       buf->private_data = NULL;
-       buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL);
-       if (!buf->area)
-               return -ENOMEM;
-       buf->bytes = size;
-
-       return 0;
-}
-
 static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
@@ -257,21 +222,9 @@ static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
        if (ret)
                return ret;
 
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = imx_pcm_preallocate_dma_buffer(pcm,
-                       SNDRV_PCM_STREAM_PLAYBACK);
-               if (ret)
-                       return ret;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = imx_pcm_preallocate_dma_buffer(pcm,
-                       SNDRV_PCM_STREAM_CAPTURE);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
+                                           pcm->card->dev,
+                                           IMX_SSI_DMABUF_SIZE);
 }
 
 static int ssi_irq;
@@ -307,32 +260,11 @@ static int snd_imx_pcm_new(struct snd_soc_component *component,
        return 0;
 }
 
-static void imx_pcm_free(struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       struct snd_dma_buffer *buf;
-       int stream;
-
-       for (stream = 0; stream < 2; stream++) {
-               substream = pcm->streams[stream].substream;
-               if (!substream)
-                       continue;
-
-               buf = &substream->dma_buffer;
-               if (!buf->area)
-                       continue;
-
-               dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr);
-               buf->area = NULL;
-       }
-}
-
 static void snd_imx_pcm_free(struct snd_soc_component *component,
                             struct snd_pcm *pcm)
 {
        mxc_set_irq_fiq(ssi_irq, 0);
        release_fiq(&fh);
-       imx_pcm_free(pcm);
 }
 
 static const struct snd_soc_component_driver imx_soc_component_fiq = {
@@ -342,7 +274,6 @@ static const struct snd_soc_component_driver imx_soc_component_fiq = {
        .prepare        = snd_imx_pcm_prepare,
        .trigger        = snd_imx_pcm_trigger,
        .pointer        = snd_imx_pcm_pointer,
-       .mmap           = snd_imx_pcm_mmap,
        .pcm_construct  = snd_imx_pcm_new,
        .pcm_destruct   = snd_imx_pcm_free,
 };
index 6d6c44c..3504904 100644 (file)
@@ -139,7 +139,6 @@ static int imx_rpmsg_pcm_hw_params(struct snd_soc_component *component,
                                   struct snd_pcm_hw_params *params)
 {
        struct rpmsg_info *info = dev_get_drvdata(component->dev);
-       struct snd_pcm_runtime *runtime = substream->runtime;
        struct rpmsg_msg *msg;
        int ret = 0;
 
@@ -183,21 +182,11 @@ static int imx_rpmsg_pcm_hw_params(struct snd_soc_component *component,
                break;
        }
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-       runtime->dma_bytes = params_buffer_bytes(params);
-
        info->send_message(msg, info);
 
        return ret;
 }
 
-static int imx_rpmsg_pcm_hw_free(struct snd_soc_component *component,
-                                struct snd_pcm_substream *substream)
-{
-       snd_pcm_set_runtime_buffer(substream, NULL);
-       return 0;
-}
-
 static snd_pcm_uframes_t imx_rpmsg_pcm_pointer(struct snd_soc_component *component,
                                               struct snd_pcm_substream *substream)
 {
@@ -347,18 +336,6 @@ static int imx_rpmsg_pcm_prepare(struct snd_soc_component *component,
        return 0;
 }
 
-static int imx_rpmsg_pcm_mmap(struct snd_soc_component *component,
-                             struct snd_pcm_substream *substream,
-                             struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       return dma_mmap_wc(substream->pcm->card->dev, vma,
-                          runtime->dma_area,
-                          runtime->dma_addr,
-                          runtime->dma_bytes);
-}
-
 static void imx_rpmsg_pcm_dma_complete(void *arg)
 {
        struct snd_pcm_substream *substream = arg;
@@ -609,47 +586,6 @@ static int imx_rpmsg_pcm_ack(struct snd_soc_component *component,
        return 0;
 }
 
-static int imx_rpmsg_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
-                                               int stream, int size)
-{
-       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-       struct snd_dma_buffer *buf = &substream->dma_buffer;
-
-       buf->dev.type = SNDRV_DMA_TYPE_DEV;
-       buf->dev.dev = pcm->card->dev;
-       buf->private_data = NULL;
-       buf->area = dma_alloc_wc(pcm->card->dev, size,
-                                &buf->addr, GFP_KERNEL);
-       if (!buf->area)
-               return -ENOMEM;
-
-       buf->bytes = size;
-       return 0;
-}
-
-static void imx_rpmsg_pcm_free_dma_buffers(struct snd_soc_component *component,
-                                          struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       struct snd_dma_buffer *buf;
-       int stream;
-
-       for (stream = SNDRV_PCM_STREAM_PLAYBACK;
-            stream < SNDRV_PCM_STREAM_LAST; stream++) {
-               substream = pcm->streams[stream].substream;
-               if (!substream)
-                       continue;
-
-               buf = &substream->dma_buffer;
-               if (!buf->area)
-                       continue;
-
-               dma_free_wc(pcm->card->dev, buf->bytes,
-                           buf->area, buf->addr);
-               buf->area = NULL;
-       }
-}
-
 static int imx_rpmsg_pcm_new(struct snd_soc_component *component,
                             struct snd_soc_pcm_runtime *rtd)
 {
@@ -663,40 +599,19 @@ static int imx_rpmsg_pcm_new(struct snd_soc_component *component,
        if (ret)
                return ret;
 
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = imx_rpmsg_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-                                                          rpmsg->buffer_size);
-               if (ret)
-                       goto out;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = imx_rpmsg_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE,
-                                                          rpmsg->buffer_size);
-               if (ret)
-                       goto out;
-       }
-
        imx_rpmsg_pcm_hardware.buffer_bytes_max = rpmsg->buffer_size;
-out:
-       /* free preallocated buffers in case of error */
-       if (ret)
-               imx_rpmsg_pcm_free_dma_buffers(component, pcm);
-
-       return ret;
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
+                                           pcm->card->dev, rpmsg->buffer_size);
 }
 
 static const struct snd_soc_component_driver imx_rpmsg_soc_component = {
        .name           = IMX_PCM_DRV_NAME,
        .pcm_construct  = imx_rpmsg_pcm_new,
-       .pcm_destruct   = imx_rpmsg_pcm_free_dma_buffers,
        .open           = imx_rpmsg_pcm_open,
        .close          = imx_rpmsg_pcm_close,
        .hw_params      = imx_rpmsg_pcm_hw_params,
-       .hw_free        = imx_rpmsg_pcm_hw_free,
        .trigger        = imx_rpmsg_pcm_trigger,
        .pointer        = imx_rpmsg_pcm_pointer,
-       .mmap           = imx_rpmsg_pcm_mmap,
        .ack            = imx_rpmsg_pcm_ack,
        .prepare        = imx_rpmsg_pcm_prepare,
 };
index 6c65cd8..9014978 100644 (file)
@@ -98,13 +98,6 @@ static irqreturn_t psc_dma_bcom_irq(int irq, void *_psc_dma_stream)
        return IRQ_HANDLED;
 }
 
-static int psc_dma_hw_free(struct snd_soc_component *component,
-                          struct snd_pcm_substream *substream)
-{
-       snd_pcm_set_runtime_buffer(substream, NULL);
-       return 0;
-}
-
 /**
  * psc_dma_trigger: start and stop the DMA transfer.
  *
@@ -285,15 +278,6 @@ psc_dma_pointer(struct snd_soc_component *component,
        return bytes_to_frames(substream->runtime, count);
 }
 
-static int psc_dma_hw_params(struct snd_soc_component *component,
-                            struct snd_pcm_substream *substream,
-                            struct snd_pcm_hw_params *params)
-{
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
-       return 0;
-}
-
 static int psc_dma_new(struct snd_soc_component *component,
                       struct snd_soc_pcm_runtime *rtd)
 {
@@ -310,60 +294,17 @@ static int psc_dma_new(struct snd_soc_component *component,
        if (rc)
                return rc;
 
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
-                               size, &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
-               if (rc)
-                       goto playback_alloc_err;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
-                               size, &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
-               if (rc)
-                       goto capture_alloc_err;
-       }
-
-       return 0;
-
- capture_alloc_err:
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
-               snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
-
- playback_alloc_err:
-       dev_err(card->dev, "Cannot allocate buffer(s)\n");
-
-       return -ENOMEM;
-}
-
-static void psc_dma_free(struct snd_soc_component *component,
-                        struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       int stream;
-
-       dev_dbg(component->dev, "psc_dma_free(pcm=%p)\n", pcm);
-
-       for (stream = 0; stream < 2; stream++) {
-               substream = pcm->streams[stream].substream;
-               if (substream) {
-                       snd_dma_free_pages(&substream->dma_buffer);
-                       substream->dma_buffer.area = NULL;
-                       substream->dma_buffer.addr = 0;
-               }
-       }
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, card->dev,
+                                           size);
 }
 
 static const struct snd_soc_component_driver mpc5200_audio_dma_component = {
        .name           = DRV_NAME,
        .open           = psc_dma_open,
        .close          = psc_dma_close,
-       .hw_free        = psc_dma_hw_free,
        .pointer        = psc_dma_pointer,
        .trigger        = psc_dma_trigger,
-       .hw_params      = psc_dma_hw_params,
        .pcm_construct  = psc_dma_new,
-       .pcm_destruct   = psc_dma_free,
 };
 
 int mpc5200_audio_dma_create(struct platform_device *op)
index 905c796..5db2f48 100644 (file)
@@ -127,7 +127,7 @@ static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
        snd_pcm_uframes_t period_size;
        ssize_t periodbytes;
        ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
-       u32 buffer_addr = virt_to_phys(substream->runtime->dma_area);
+       u32 buffer_addr = substream->runtime->dma_addr;
 
        channels = substream->runtime->channels;
        period_size = substream->runtime->period_size;
index 939e7e2..7f13a35 100644 (file)
@@ -850,15 +850,12 @@ static struct snd_soc_dai_driver pxa_ssp_dai = {
 static const struct snd_soc_component_driver pxa_ssp_component = {
        .name           = "pxa-ssp",
        .pcm_construct  = pxa2xx_soc_pcm_new,
-       .pcm_destruct   = pxa2xx_soc_pcm_free,
        .open           = pxa2xx_soc_pcm_open,
        .close          = pxa2xx_soc_pcm_close,
        .hw_params      = pxa2xx_soc_pcm_hw_params,
-       .hw_free        = pxa2xx_soc_pcm_hw_free,
        .prepare        = pxa2xx_soc_pcm_prepare,
        .trigger        = pxa2xx_soc_pcm_trigger,
        .pointer        = pxa2xx_soc_pcm_pointer,
-       .mmap           = pxa2xx_soc_pcm_mmap,
        .suspend        = pxa_ssp_suspend,
        .resume         = pxa_ssp_resume,
 };
index 4240fde..58f8541 100644 (file)
@@ -202,15 +202,12 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
 static const struct snd_soc_component_driver pxa_ac97_component = {
        .name           = "pxa-ac97",
        .pcm_construct  = pxa2xx_soc_pcm_new,
-       .pcm_destruct   = pxa2xx_soc_pcm_free,
        .open           = pxa2xx_soc_pcm_open,
        .close          = pxa2xx_soc_pcm_close,
        .hw_params      = pxa2xx_soc_pcm_hw_params,
-       .hw_free        = pxa2xx_soc_pcm_hw_free,
        .prepare        = pxa2xx_soc_pcm_prepare,
        .trigger        = pxa2xx_soc_pcm_trigger,
        .pointer        = pxa2xx_soc_pcm_pointer,
-       .mmap           = pxa2xx_soc_pcm_mmap,
 };
 
 #ifdef CONFIG_OF
index bcde4a9..5bfc1a9 100644 (file)
@@ -359,15 +359,12 @@ static struct snd_soc_dai_driver pxa_i2s_dai = {
 static const struct snd_soc_component_driver pxa_i2s_component = {
        .name           = "pxa-i2s",
        .pcm_construct  = pxa2xx_soc_pcm_new,
-       .pcm_destruct   = pxa2xx_soc_pcm_free,
        .open           = pxa2xx_soc_pcm_open,
        .close          = pxa2xx_soc_pcm_close,
        .hw_params      = pxa2xx_soc_pcm_hw_params,
-       .hw_free        = pxa2xx_soc_pcm_hw_free,
        .prepare        = pxa2xx_soc_pcm_prepare,
        .trigger        = pxa2xx_soc_pcm_trigger,
        .pointer        = pxa2xx_soc_pcm_pointer,
-       .mmap           = pxa2xx_soc_pcm_mmap,
        .suspend        = pxa2xx_soc_pcm_suspend,
        .resume         = pxa2xx_soc_pcm_resume,
 };
index 2b78397..9d6c41f 100644 (file)
 
 static const struct snd_soc_component_driver pxa2xx_soc_platform = {
        .pcm_construct  = pxa2xx_soc_pcm_new,
-       .pcm_destruct   = pxa2xx_soc_pcm_free,
        .open           = pxa2xx_soc_pcm_open,
        .close          = pxa2xx_soc_pcm_close,
        .hw_params      = pxa2xx_soc_pcm_hw_params,
-       .hw_free        = pxa2xx_soc_pcm_hw_free,
        .prepare        = pxa2xx_soc_pcm_prepare,
        .trigger        = pxa2xx_soc_pcm_trigger,
        .pointer        = pxa2xx_soc_pcm_pointer,
-       .mmap           = pxa2xx_soc_pcm_mmap,
 };
 
 static int pxa2xx_soc_platform_probe(struct platform_device *pdev)
index f9df76d..a59e9d2 100644 (file)
@@ -156,8 +156,6 @@ static int lpass_platform_pcmops_open(struct snd_soc_component *component,
                return -EINVAL;
        }
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
        return 0;
 }
 
@@ -630,16 +628,6 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
        return bytes_to_frames(substream->runtime, curr_addr - base_addr);
 }
 
-static int lpass_platform_pcmops_mmap(struct snd_soc_component *component,
-                                     struct snd_pcm_substream *substream,
-                                     struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       return dma_mmap_coherent(component->dev, vma, runtime->dma_area,
-                                runtime->dma_addr, runtime->dma_bytes);
-}
-
 static irqreturn_t lpass_dma_interrupt_handler(
                        struct snd_pcm_substream *substream,
                        struct lpass_data *drvdata,
@@ -787,52 +775,10 @@ static int lpass_platform_pcm_new(struct snd_soc_component *component,
                                  struct snd_soc_pcm_runtime *soc_runtime)
 {
        struct snd_pcm *pcm = soc_runtime->pcm;
-       struct snd_pcm_substream *psubstream, *csubstream;
-       int ret;
        size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
 
-       psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-       if (psubstream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-                                       component->dev,
-                                       size, &psubstream->dma_buffer);
-               if (ret) {
-                       dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n");
-                       return ret;
-               }
-       }
-
-       csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
-       if (csubstream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-                                       component->dev,
-                                       size, &csubstream->dma_buffer);
-               if (ret) {
-                       dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n");
-                       if (psubstream)
-                               snd_dma_free_pages(&psubstream->dma_buffer);
-                       return ret;
-               }
-
-       }
-
-       return 0;
-}
-
-static void lpass_platform_pcm_free(struct snd_soc_component *component,
-                                   struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       int i;
-
-       for_each_pcm_streams(i) {
-               substream = pcm->streams[i].substream;
-               if (substream) {
-                       snd_dma_free_pages(&substream->dma_buffer);
-                       substream->dma_buffer.area = NULL;
-                       substream->dma_buffer.addr = 0;
-               }
-       }
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                           component->dev, size);
 }
 
 static int lpass_platform_pcmops_suspend(struct snd_soc_component *component)
@@ -877,9 +823,7 @@ static const struct snd_soc_component_driver lpass_component_driver = {
        .prepare        = lpass_platform_pcmops_prepare,
        .trigger        = lpass_platform_pcmops_trigger,
        .pointer        = lpass_platform_pcmops_pointer,
-       .mmap           = lpass_platform_pcmops_mmap,
        .pcm_construct  = lpass_platform_pcm_new,
-       .pcm_destruct   = lpass_platform_pcm_free,
        .suspend                = lpass_platform_pcmops_suspend,
        .resume                 = lpass_platform_pcmops_resume,
 
index 5ff56a7..46f3655 100644 (file)
@@ -429,8 +429,6 @@ static int q6asm_dai_open(struct snd_soc_component *component,
        else
                prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32);
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
        return 0;
 }
 
@@ -470,18 +468,6 @@ static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_soc_component *component,
        return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
 }
 
-static int q6asm_dai_mmap(struct snd_soc_component *component,
-                         struct snd_pcm_substream *substream,
-                         struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct device *dev = component->dev;
-
-       return dma_mmap_coherent(dev, vma,
-                       runtime->dma_area, runtime->dma_addr,
-                       runtime->dma_bytes);
-}
-
 static int q6asm_dai_hw_params(struct snd_soc_component *component,
                               struct snd_pcm_substream *substream,
                               struct snd_pcm_hw_params *params)
@@ -1185,52 +1171,11 @@ static const struct snd_compress_ops q6asm_dai_compress_ops = {
 static int q6asm_dai_pcm_new(struct snd_soc_component *component,
                             struct snd_soc_pcm_runtime *rtd)
 {
-       struct snd_pcm_substream *psubstream, *csubstream;
        struct snd_pcm *pcm = rtd->pcm;
-       struct device *dev;
-       int size, ret;
-
-       dev = component->dev;
-       size = q6asm_dai_hardware_playback.buffer_bytes_max;
-       psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-       if (psubstream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
-                                         &psubstream->dma_buffer);
-               if (ret) {
-                       dev_err(dev, "Cannot allocate buffer(s)\n");
-                       return ret;
-               }
-       }
+       size_t size = q6asm_dai_hardware_playback.buffer_bytes_max;
 
-       csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
-       if (csubstream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
-                                         &csubstream->dma_buffer);
-               if (ret) {
-                       dev_err(dev, "Cannot allocate buffer(s)\n");
-                       if (psubstream)
-                               snd_dma_free_pages(&psubstream->dma_buffer);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-static void q6asm_dai_pcm_free(struct snd_soc_component *component,
-                              struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
-               substream = pcm->streams[i].substream;
-               if (substream) {
-                       snd_dma_free_pages(&substream->dma_buffer);
-                       substream->dma_buffer.area = NULL;
-                       substream->dma_buffer.addr = 0;
-               }
-       }
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                           component->dev, size);
 }
 
 static const struct snd_soc_dapm_widget q6asm_dapm_widgets[] = {
@@ -1260,9 +1205,7 @@ static const struct snd_soc_component_driver q6asm_fe_dai_component = {
        .prepare        = q6asm_dai_prepare,
        .trigger        = q6asm_dai_trigger,
        .pointer        = q6asm_dai_pointer,
-       .mmap           = q6asm_dai_mmap,
        .pcm_construct  = q6asm_dai_pcm_new,
-       .pcm_destruct   = q6asm_dai_pcm_free,
        .compress_ops   = &q6asm_dai_compress_ops,
        .dapm_widgets   = q6asm_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(q6asm_dapm_widgets),
index b4f5935..3606080 100644 (file)
@@ -604,7 +604,6 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
                break;
        }
 
-       mutex_init(&compr->lock);
        ret = snd_compress_new(rtd->card->snd_card, num, direction,
                                new_name, compr);
        if (ret < 0) {
index 5e3a96d..48d9061 100644 (file)
@@ -204,8 +204,6 @@ static int sprd_pcm_hw_params(struct snd_soc_component *component,
        if (!dma_params) {
                dev_warn(component->dev, "no dma parameters setting\n");
                dma_private->params = NULL;
-               snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-               runtime->dma_bytes = totsize;
                return 0;
        }
 
@@ -217,9 +215,6 @@ static int sprd_pcm_hw_params(struct snd_soc_component *component,
                        return ret;
        }
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
-       runtime->dma_bytes = totsize;
        sg_num = totsize / period;
        dma_private->dma_addr_offset = totsize / channels;
 
@@ -310,7 +305,6 @@ sg_err:
 static int sprd_pcm_hw_free(struct snd_soc_component *component,
                            struct snd_pcm_substream *substream)
 {
-       snd_pcm_set_runtime_buffer(substream, NULL);
        sprd_pcm_release_dma_channel(substream);
 
        return 0;
@@ -435,73 +429,20 @@ static snd_pcm_uframes_t sprd_pcm_pointer(struct snd_soc_component *component,
        return x;
 }
 
-static int sprd_pcm_mmap(struct snd_soc_component *component,
-                        struct snd_pcm_substream *substream,
-                        struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-       return remap_pfn_range(vma, vma->vm_start,
-                              runtime->dma_addr >> PAGE_SHIFT,
-                              vma->vm_end - vma->vm_start,
-                              vma->vm_page_prot);
-}
-
 static int sprd_pcm_new(struct snd_soc_component *component,
                        struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
-       struct snd_pcm_substream *substream;
        int ret;
 
        ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
        if (ret)
                return ret;
 
-       substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-       if (substream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
-                                         sprd_pcm_hardware.buffer_bytes_max,
-                                         &substream->dma_buffer);
-               if (ret) {
-                       dev_err(card->dev,
-                               "can't alloc playback dma buffer: %d\n", ret);
-                       return ret;
-               }
-       }
-
-       substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
-       if (substream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
-                                         sprd_pcm_hardware.buffer_bytes_max,
-                                         &substream->dma_buffer);
-               if (ret) {
-                       dev_err(card->dev,
-                               "can't alloc capture dma buffer: %d\n", ret);
-                       snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-static void sprd_pcm_free(struct snd_soc_component *component,
-                         struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
-               substream = pcm->streams[i].substream;
-               if (substream) {
-                       snd_dma_free_pages(&substream->dma_buffer);
-                       substream->dma_buffer.area = NULL;
-                       substream->dma_buffer.addr = 0;
-               }
-       }
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                           card->dev,
+                                           sprd_pcm_hardware.buffer_bytes_max);
 }
 
 static const struct snd_soc_component_driver sprd_soc_component = {
@@ -512,9 +453,7 @@ static const struct snd_soc_component_driver sprd_soc_component = {
        .hw_free        = sprd_pcm_hw_free,
        .trigger        = sprd_pcm_trigger,
        .pointer        = sprd_pcm_pointer,
-       .mmap           = sprd_pcm_mmap,
        .pcm_construct  = sprd_pcm_new,
-       .pcm_destruct   = sprd_pcm_free,
        .compress_ops   = &sprd_platform_compress_ops,
 };
 
index 0f9beef..bcccdf3 100644 (file)
@@ -612,12 +612,9 @@ static const struct snd_soc_component_driver tegra210_admaif_cmpnt = {
        .controls               = tegra210_admaif_controls,
        .num_controls           = ARRAY_SIZE(tegra210_admaif_controls),
        .pcm_construct          = tegra_pcm_construct,
-       .pcm_destruct           = tegra_pcm_destruct,
        .open                   = tegra_pcm_open,
        .close                  = tegra_pcm_close,
        .hw_params              = tegra_pcm_hw_params,
-       .hw_free                = tegra_pcm_hw_free,
-       .mmap                   = tegra_pcm_mmap,
        .pointer                = tegra_pcm_pointer,
 };
 
@@ -625,12 +622,9 @@ static const struct snd_soc_component_driver tegra186_admaif_cmpnt = {
        .controls               = tegra186_admaif_controls,
        .num_controls           = ARRAY_SIZE(tegra186_admaif_controls),
        .pcm_construct          = tegra_pcm_construct,
-       .pcm_destruct           = tegra_pcm_destruct,
        .open                   = tegra_pcm_open,
        .close                  = tegra_pcm_close,
        .hw_params              = tegra_pcm_hw_params,
-       .hw_free                = tegra_pcm_hw_free,
-       .mmap                   = tegra_pcm_mmap,
        .pointer                = tegra_pcm_pointer,
 };
 
index d3276b4..ef1e74d 100644 (file)
@@ -171,41 +171,10 @@ int tegra_pcm_hw_params(struct snd_soc_component *component,
                return ret;
        }
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
        return 0;
 }
 EXPORT_SYMBOL_GPL(tegra_pcm_hw_params);
 
-int tegra_pcm_hw_free(struct snd_soc_component *component,
-                     struct snd_pcm_substream *substream)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
-       if (rtd->dai_link->no_pcm)
-               return 0;
-
-       snd_pcm_set_runtime_buffer(substream, NULL);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(tegra_pcm_hw_free);
-
-int tegra_pcm_mmap(struct snd_soc_component *component,
-                  struct snd_pcm_substream *substream,
-                  struct vm_area_struct *vma)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       if (rtd->dai_link->no_pcm)
-               return 0;
-
-       return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
-                          runtime->dma_addr, runtime->dma_bytes);
-}
-EXPORT_SYMBOL_GPL(tegra_pcm_mmap);
-
 snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
                                    struct snd_pcm_substream *substream)
 {
@@ -213,41 +182,6 @@ snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
 }
 EXPORT_SYMBOL_GPL(tegra_pcm_pointer);
 
-static int tegra_pcm_preallocate_dma_buffer(struct device *dev, struct snd_pcm *pcm, int stream,
-                                           size_t size)
-{
-       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-       struct snd_dma_buffer *buf = &substream->dma_buffer;
-
-       buf->area = dma_alloc_wc(dev, size, &buf->addr, GFP_KERNEL);
-       if (!buf->area)
-               return -ENOMEM;
-
-       buf->private_data = NULL;
-       buf->dev.type = SNDRV_DMA_TYPE_DEV;
-       buf->dev.dev = dev;
-       buf->bytes = size;
-
-       return 0;
-}
-
-static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
-       struct snd_pcm_substream *substream;
-       struct snd_dma_buffer *buf;
-
-       substream = pcm->streams[stream].substream;
-       if (!substream)
-               return;
-
-       buf = &substream->dma_buffer;
-       if (!buf->area)
-               return;
-
-       dma_free_wc(buf->dev.dev, buf->bytes, buf->area, buf->addr);
-       buf->area = NULL;
-}
-
 static int tegra_pcm_dma_allocate(struct device *dev, struct snd_soc_pcm_runtime *rtd,
                                  size_t size)
 {
@@ -258,24 +192,7 @@ static int tegra_pcm_dma_allocate(struct device *dev, struct snd_soc_pcm_runtime
        if (ret < 0)
                return ret;
 
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = tegra_pcm_preallocate_dma_buffer(dev, pcm, SNDRV_PCM_STREAM_PLAYBACK, size);
-               if (ret)
-                       goto err;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = tegra_pcm_preallocate_dma_buffer(dev, pcm, SNDRV_PCM_STREAM_CAPTURE, size);
-               if (ret)
-                       goto err_free_play;
-       }
-
-       return 0;
-
-err_free_play:
-       tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
-err:
-       return ret;
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC, dev, size);
 }
 
 int tegra_pcm_construct(struct snd_soc_component *component,
@@ -294,14 +211,6 @@ int tegra_pcm_construct(struct snd_soc_component *component,
 }
 EXPORT_SYMBOL_GPL(tegra_pcm_construct);
 
-void tegra_pcm_destruct(struct snd_soc_component *component,
-                       struct snd_pcm *pcm)
-{
-       tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE);
-       tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
-}
-EXPORT_SYMBOL_GPL(tegra_pcm_destruct);
-
 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 MODULE_DESCRIPTION("Tegra PCM ASoC driver");
 MODULE_LICENSE("GPL");
index 4838cdc..d602126 100644 (file)
@@ -22,8 +22,6 @@
 
 int tegra_pcm_construct(struct snd_soc_component *component,
                        struct snd_soc_pcm_runtime *rtd);
-void tegra_pcm_destruct(struct snd_soc_component *component,
-                       struct snd_pcm *pcm);
 int tegra_pcm_open(struct snd_soc_component *component,
                   struct snd_pcm_substream *substream);
 int tegra_pcm_close(struct snd_soc_component *component,
@@ -31,11 +29,6 @@ int tegra_pcm_close(struct snd_soc_component *component,
 int tegra_pcm_hw_params(struct snd_soc_component *component,
                        struct snd_pcm_substream *substream,
                        struct snd_pcm_hw_params *params);
-int tegra_pcm_hw_free(struct snd_soc_component *component,
-                     struct snd_pcm_substream *substream);
-int tegra_pcm_mmap(struct snd_soc_component *component,
-                  struct snd_pcm_substream *substream,
-                  struct vm_area_struct *vma);
 snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
                                    struct snd_pcm_substream *substream);
 int tegra_pcm_platform_register(struct device *dev);
index a1f8c3a..fd570a4 100644 (file)
@@ -68,9 +68,11 @@ static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
 static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
 static bool ignore_ctl_error;
 static bool autoclock = true;
+static bool lowlatency = true;
 static char *quirk_alias[SNDRV_CARDS];
 static char *delayed_register[SNDRV_CARDS];
 static bool implicit_fb[SNDRV_CARDS];
+static unsigned int quirk_flags[SNDRV_CARDS];
 
 bool snd_usb_use_vmalloc = true;
 bool snd_usb_skip_validation;
@@ -92,12 +94,16 @@ MODULE_PARM_DESC(ignore_ctl_error,
                 "Ignore errors from USB controller for mixer interfaces.");
 module_param(autoclock, bool, 0444);
 MODULE_PARM_DESC(autoclock, "Enable auto-clock selection for UAC2 devices (default: yes).");
+module_param(lowlatency, bool, 0444);
+MODULE_PARM_DESC(lowlatency, "Enable low latency playback (default: yes).");
 module_param_array(quirk_alias, charp, NULL, 0444);
 MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef.");
 module_param_array(delayed_register, charp, NULL, 0444);
 MODULE_PARM_DESC(delayed_register, "Quirk for delayed registration, given by id:iface, e.g. 0123abcd:4.");
 module_param_array(implicit_fb, bool, NULL, 0444);
 MODULE_PARM_DESC(implicit_fb, "Apply generic implicit feedback sync mode.");
+module_param_array(quirk_flags, uint, NULL, 0444);
+MODULE_PARM_DESC(quirk_flags, "Driver quirk bit flags.");
 module_param_named(use_vmalloc, snd_usb_use_vmalloc, bool, 0444);
 MODULE_PARM_DESC(use_vmalloc, "Use vmalloc for PCM intermediate buffers (default: yes).");
 module_param_named(skip_validation, snd_usb_skip_validation, bool, 0444);
@@ -378,6 +384,9 @@ static const struct usb_audio_device_name usb_audio_names[] = {
 
        DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"),
 
+       DEVICE_NAME(0x05e1, 0x0408, "Syntek", "STK1160"),
+       DEVICE_NAME(0x05e1, 0x0480, "Hauppauge", "Woodbury"),
+
        /* ASUS ROG Strix */
        PROFILE_NAME(0x0b05, 0x1917,
                     "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
@@ -406,6 +415,8 @@ static const struct usb_audio_device_name usb_audio_names[] = {
        PROFILE_NAME(0x0db0, 0x543d,
                     "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
 
+       DEVICE_NAME(0x0fd9, 0x0008, "Hauppauge", "HVR-950Q"),
+
        /* Stanton/N2IT Final Scratch v1 device ('Scratchamp') */
        DEVICE_NAME(0x103d, 0x0100, "Stanton", "ScratchAmp"),
        DEVICE_NAME(0x103d, 0x0101, "Stanton", "ScratchAmp"),
@@ -424,6 +435,22 @@ static const struct usb_audio_device_name usb_audio_names[] = {
        PROFILE_NAME(0x26ce, 0x0a01,
                     "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
 
+       DEVICE_NAME(0x2040, 0x7200, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7201, "Hauppauge", "HVR-950Q-MXL"),
+       DEVICE_NAME(0x2040, 0x7210, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7211, "Hauppauge", "HVR-950Q-MXL"),
+       DEVICE_NAME(0x2040, 0x7213, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7217, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x721b, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x721e, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x721f, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7240, "Hauppauge", "HVR-850"),
+       DEVICE_NAME(0x2040, 0x7260, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7280, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7281, "Hauppauge", "HVR-950Q-MXL"),
+       DEVICE_NAME(0x2040, 0x8200, "Hauppauge", "Woodbury"),
+
        { } /* terminator */
 };
 
@@ -599,6 +626,7 @@ static int snd_usb_audio_create(struct usb_interface *intf,
        chip->setup = device_setup[idx];
        chip->generic_implicit_fb = implicit_fb[idx];
        chip->autoclock = autoclock;
+       chip->lowlatency = lowlatency;
        atomic_set(&chip->active, 1); /* avoid autopm during probing */
        atomic_set(&chip->usage_count, 0);
        atomic_set(&chip->shutdown, 0);
@@ -610,6 +638,11 @@ static int snd_usb_audio_create(struct usb_interface *intf,
        INIT_LIST_HEAD(&chip->midi_list);
        INIT_LIST_HEAD(&chip->mixer_list);
 
+       if (quirk_flags[idx])
+               chip->quirk_flags = quirk_flags[idx];
+       else
+               snd_usb_init_quirk_flags(chip);
+
        card->private_free = snd_usb_audio_free;
 
        strcpy(card->driver, "USB-Audio");
@@ -781,6 +814,12 @@ static int usb_audio_probe(struct usb_interface *intf,
 
        dev_set_drvdata(&dev->dev, chip);
 
+       if (ignore_ctl_error)
+               chip->quirk_flags |= QUIRK_FLAG_IGNORE_CTL_ERROR;
+
+       if (chip->quirk_flags & QUIRK_FLAG_DISABLE_AUTOSUSPEND)
+               usb_disable_autosuspend(interface_to_usbdev(intf));
+
        /*
         * For devices with more than one control interface, we assume the
         * first contains the audio controls. We might need a more specific
@@ -789,7 +828,6 @@ static int usb_audio_probe(struct usb_interface *intf,
        if (!chip->ctrl_intf)
                chip->ctrl_intf = alts;
 
-       chip->txfr_quirk = 0;
        err = 1; /* continue */
        if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
                /* need some special handlings */
@@ -803,7 +841,7 @@ static int usb_audio_probe(struct usb_interface *intf,
                err = snd_usb_create_streams(chip, ifnum);
                if (err < 0)
                        goto __error;
-               err = snd_usb_create_mixer(chip, ifnum, ignore_ctl_error);
+               err = snd_usb_create_mixer(chip, ifnum);
                if (err < 0)
                        goto __error;
        }
@@ -825,7 +863,7 @@ static int usb_audio_probe(struct usb_interface *intf,
                        goto __error;
        }
 
-       if (quirk && quirk->shares_media_device) {
+       if (chip->quirk_flags & QUIRK_FLAG_SHARE_MEDIA_DEVICE) {
                /* don't want to fail when snd_media_device_create() fails */
                snd_media_device_create(chip, intf);
        }
@@ -907,7 +945,7 @@ static void usb_audio_disconnect(struct usb_interface *intf)
                }
        }
 
-       if (chip->quirk_type == QUIRK_SETUP_DISABLE_AUTOSUSPEND)
+       if (chip->quirk_flags & QUIRK_FLAG_DISABLE_AUTOSUSPEND)
                usb_enable_autosuspend(interface_to_usbdev(intf));
 
        chip->num_interfaces--;
index 6c0a052..5b19901 100644 (file)
@@ -94,6 +94,7 @@ struct snd_usb_endpoint {
        struct list_head ready_playback_urbs; /* playback URB FIFO for implicit fb */
 
        unsigned int nurbs;             /* # urbs */
+       unsigned int nominal_queue_size; /* total buffer sizes in URBs */
        unsigned long active_mask;      /* bitmask of active urbs */
        unsigned long unlink_mask;      /* bitmask of unlinked urbs */
        char *syncbuf;                  /* sync buffer for all sync URBs */
@@ -187,6 +188,7 @@ struct snd_usb_substream {
        } dsd_dop;
 
        bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */
+       bool early_playback_start;      /* early start needed for playback? */
        struct media_ctl *media_ctl;
 };
 
index 14456f6..81d5ce0 100644 (file)
@@ -324,11 +324,8 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
                                              sources[ret - 1],
                                              visited, validate);
                if (ret > 0) {
-                       /*
-                        * For Samsung USBC Headset (AKG), setting clock selector again
-                        * will result in incorrect default clock setting problems
-                        */
-                       if (chip->usb_id == USB_ID(0x04e8, 0xa051))
+                       /* Skip setting clock selector again for some devices */
+                       if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR)
                                return ret;
                        err = uac_clock_selector_set_val(chip, entity_id, cur);
                        if (err < 0)
@@ -426,7 +423,7 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip,
 
        /* Don't check the sample rate for devices which we know don't
         * support reading */
-       if (snd_usb_get_sample_rate_quirk(chip))
+       if (chip->quirk_flags & QUIRK_FLAG_GET_SAMPLE_RATE)
                return 0;
        /* the firmware is likely buggy, don't repeat to fail too many times */
        if (chip->sample_rate_read_error > 2)
@@ -541,10 +538,8 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip,
                 */
                clock = snd_usb_clock_find_source(chip, fmt, false);
 
-               /* Denon DN-X1600 hardcoded
-                * Sample rate seems to be set on the hardware itself
-                */
-               if (chip->usb_id == USB_ID(0x154e, 0x500e))
+               /* Hardcoded sample rates */
+               if (chip->quirk_flags & QUIRK_FLAG_IGNORE_CLOCK_SOURCE)
                        return 0;
 
                if (clock < 0)
index 4f85677..533919a 100644 (file)
@@ -240,6 +240,11 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep,
        call_retire_callback(ep, urb);
 }
 
+static inline bool has_tx_length_quirk(struct snd_usb_audio *chip)
+{
+       return chip->quirk_flags & QUIRK_FLAG_TX_LENGTH;
+}
+
 static void prepare_silent_urb(struct snd_usb_endpoint *ep,
                               struct snd_urb_ctx *ctx)
 {
@@ -250,7 +255,7 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep,
        int i;
 
        /* For tx_length_quirk, put packet length at start of packet */
-       if (ep->chip->tx_length_quirk)
+       if (has_tx_length_quirk(ep->chip))
                extra = sizeof(packet_length);
 
        for (i = 0; i < ctx->packets; ++i) {
@@ -803,7 +808,8 @@ static int endpoint_set_interface(struct snd_usb_audio *chip,
                return err;
        }
 
-       snd_usb_set_interface_quirk(chip);
+       if (chip->quirk_flags & QUIRK_FLAG_IFACE_DELAY)
+               msleep(50);
        return 0;
 }
 
@@ -952,7 +958,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
        unsigned int max_urbs, i;
        const struct audioformat *fmt = ep->cur_audiofmt;
        int frame_bits = ep->cur_frame_bytes * 8;
-       int tx_length_quirk = (chip->tx_length_quirk &&
+       int tx_length_quirk = (has_tx_length_quirk(chip) &&
                               usb_pipeout(ep->pipe));
 
        usb_audio_dbg(chip, "Setting params for data EP 0x%x, pipe 0x%x\n",
@@ -1126,6 +1132,10 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
                INIT_LIST_HEAD(&u->ready_list);
        }
 
+       /* total buffer bytes of all URBs plus the next queue;
+        * referred in pcm.c
+        */
+       ep->nominal_queue_size = maxsize * urb_packs * (ep->nurbs + 1);
        return 0;
 
 out_of_memory:
@@ -1287,6 +1297,9 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
         * to be set up before parameter setups
         */
        iface_first = ep->cur_audiofmt->protocol == UAC_VERSION_1;
+       /* Workaround for devices that require the interface setup at first like UAC1 */
+       if (chip->quirk_flags & QUIRK_FLAG_SET_IFACE_FIRST)
+               iface_first = true;
        if (iface_first) {
                err = endpoint_set_interface(chip, ep, true);
                if (err < 0)
@@ -1377,7 +1390,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
                goto __error;
 
        if (snd_usb_endpoint_implicit_feedback_sink(ep) &&
-           !ep->chip->playback_first) {
+           !(ep->chip->quirk_flags & QUIRK_FLAG_PLAYBACK_FIRST)) {
                for (i = 0; i < ep->nurbs; i++) {
                        struct snd_urb_ctx *ctx = ep->urb + i;
                        list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
index eb216fe..50efccb 100644 (file)
@@ -472,12 +472,8 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip,
         * behavior afterwards by some unknown reason.  Do this only for the
         * known devices.
         */
-       switch (USB_ID_VENDOR(chip->usb_id)) {
-       case 0x07fd: /* MOTU */
-               break;
-       default:
+       if (!(chip->quirk_flags & QUIRK_FLAG_VALIDATE_RATES))
                return 0; /* don't perform the validation as default */
-       }
 
        table = kcalloc(fp->nr_rates, sizeof(*table), GFP_KERNEL);
        if (!table)
index 590a0db..23767a1 100644 (file)
@@ -171,7 +171,7 @@ static int add_roland_implicit_fb(struct snd_usb_audio *chip,
        if (!usb_endpoint_is_isoc_in(epd) ||
            (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
                return 0;
-       chip->playback_first = 1;
+       chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST;
        return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0,
                                       alts->desc.bInterfaceNumber, alts);
 }
@@ -320,7 +320,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
                case IMPLICIT_FB_FIXED:
                        return 0; /* no quirk */
                case IMPLICIT_FB_BOTH:
-                       chip->playback_first = 1;
+                       chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST;
                        return add_generic_implicit_fb(chip, fmt, alts);
                }
        }
@@ -344,7 +344,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
 
        /* Pioneer devices with vendor spec class */
        if (is_pioneer_implicit_fb(chip, alts)) {
-               chip->playback_first = 1;
+               chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST;
                return add_implicit_fb_sync_ep(chip, fmt,
                                               get_endpoint(alts, 1)->bEndpointAddress,
                                               1, alts->desc.bInterfaceNumber,
index 9b713b4..43bc595 100644 (file)
@@ -1572,9 +1572,9 @@ static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str)
 static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
                                        struct snd_card *card)
 {
-       const char *names_to_check[] = {
+       static const char * const names_to_check[] = {
                "Headset", "headset", "Headphone", "headphone", NULL};
-       const char **s;
+       const char * const *s;
        bool found = false;
 
        if (strcmp("Speaker", kctl->id.name))
@@ -3183,7 +3183,6 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
                        state.map = map->map;
                        state.selector_map = map->selector_map;
                        mixer->connector_map = map->connector_map;
-                       mixer->ignore_ctl_error |= map->ignore_ctl_error;
                        break;
                }
        }
@@ -3508,8 +3507,7 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
        return 0;
 }
 
-int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
-                        int ignore_error)
+int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif)
 {
        static const struct snd_device_ops dev_ops = {
                .dev_free = snd_usb_mixer_dev_free
@@ -3523,7 +3521,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
        if (!mixer)
                return -ENOMEM;
        mixer->chip = chip;
-       mixer->ignore_ctl_error = ignore_error;
+       mixer->ignore_ctl_error = !!(chip->quirk_flags & QUIRK_FLAG_IGNORE_CTL_ERROR);
        mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems),
                                  GFP_KERNEL);
        if (!mixer->id_elems) {
index ea41e7a..876bbc9 100644 (file)
@@ -97,8 +97,7 @@ struct usb_mixer_elem_info {
        void *private_data;
 };
 
-int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
-                        int ignore_error);
+int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif);
 void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer);
 
 void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
index c5794e8..55eea90 100644 (file)
@@ -28,7 +28,6 @@ struct usbmix_ctl_map {
        const struct usbmix_name_map *map;
        const struct usbmix_selector_map *selector_map;
        const struct usbmix_connector_map *connector_map;
-       int ignore_ctl_error;
 };
 
 /*
@@ -432,7 +431,6 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
        {
                .id = USB_ID(0x041e, 0x3000),
                .map = extigy_map,
-               .ignore_ctl_error = 1,
        },
        {
                .id = USB_ID(0x041e, 0x3010),
@@ -452,28 +450,10 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
                .map = audigy2nx_map,
                .selector_map = audigy2nx_selectors,
        },
-       {       /* Logitech, Inc. QuickCam Pro for Notebooks */
-               .id = USB_ID(0x046d, 0x0991),
-               .ignore_ctl_error = 1,
-       },
-       {       /* Logitech, Inc. QuickCam E 3500 */
-               .id = USB_ID(0x046d, 0x09a4),
-               .ignore_ctl_error = 1,
-       },
        {       /* Plantronics GameCom 780 */
                .id = USB_ID(0x047f, 0xc010),
                .map = gamecom780_map,
        },
-       {
-               /* Hercules DJ Console (Windows Edition) */
-               .id = USB_ID(0x06f8, 0xb000),
-               .ignore_ctl_error = 1,
-       },
-       {
-               /* Hercules DJ Console (Macintosh Edition) */
-               .id = USB_ID(0x06f8, 0xd002),
-               .ignore_ctl_error = 1,
-       },
        {
                /* Hercules Gamesurround Muse Pocket LT
                 * (USB 5.1 Channel Audio Adapter)
@@ -492,7 +472,6 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
        {
                .id = USB_ID(0x08bb, 0x2702),
                .map = linex_map,
-               .ignore_ctl_error = 1,
        },
        {
                .id = USB_ID(0x0a92, 0x0091),
@@ -517,7 +496,6 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
        {
                .id = USB_ID(0x13e5, 0x0001),
                .map = scratch_live_map,
-               .ignore_ctl_error = 1,
        },
        {
                .id = USB_ID(0x200c, 0x1018),
index 0a3cb8f..a66ce03 100644 (file)
@@ -594,85 +594,208 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
                                          &snd_xonar_u1_output_switch, NULL);
 }
 
+/* Digidesign Mbox 1 helper functions */
+
+static int snd_mbox1_is_spdif_synced(struct snd_usb_audio *chip)
+{
+       unsigned char buff[3];
+       int err;
+       int is_spdif_synced;
+
+       /* Read clock source */
+       err = snd_usb_ctl_msg(chip->dev,
+                             usb_rcvctrlpipe(chip->dev, 0), 0x81,
+                             USB_DIR_IN |
+                             USB_TYPE_CLASS |
+                             USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+       if (err < 0)
+               return err;
+
+       /* spdif sync: buff is all zeroes */
+       is_spdif_synced = !(buff[0] | buff[1] | buff[2]);
+       return is_spdif_synced;
+}
+
+static int snd_mbox1_set_clk_source(struct snd_usb_audio *chip, int rate_or_zero)
+{
+       /* 2 possibilities:     Internal    -> expects sample rate
+        *                      S/PDIF sync -> expects rate = 0
+        */
+       unsigned char buff[3];
+
+       buff[0] = (rate_or_zero >>  0) & 0xff;
+       buff[1] = (rate_or_zero >>  8) & 0xff;
+       buff[2] = (rate_or_zero >> 16) & 0xff;
+
+       /* Set clock source */
+       return snd_usb_ctl_msg(chip->dev,
+                              usb_sndctrlpipe(chip->dev, 0), 0x1,
+                              USB_TYPE_CLASS |
+                              USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+}
+
+static int snd_mbox1_is_spdif_input(struct snd_usb_audio *chip)
+{
+       /* Hardware gives 2 possibilities:      ANALOG Source  -> 0x01
+        *                                      S/PDIF Source  -> 0x02
+        */
+       int err;
+       unsigned char source[1];
+
+       /* Read input source */
+       err = snd_usb_ctl_msg(chip->dev,
+                             usb_rcvctrlpipe(chip->dev, 0), 0x81,
+                             USB_DIR_IN |
+                             USB_TYPE_CLASS |
+                             USB_RECIP_INTERFACE, 0x00, 0x500, source, 1);
+       if (err < 0)
+               return err;
+
+       return (source[0] == 2);
+}
+
+static int snd_mbox1_set_input_source(struct snd_usb_audio *chip, int is_spdif)
+{
+       /* NB: Setting the input source to S/PDIF resets the clock source to S/PDIF
+        * Hardware expects 2 possibilities:    ANALOG Source  -> 0x01
+        *                                      S/PDIF Source  -> 0x02
+        */
+       unsigned char buff[1];
+
+       buff[0] = (is_spdif & 1) + 1;
+
+       /* Set input source */
+       return snd_usb_ctl_msg(chip->dev,
+                              usb_sndctrlpipe(chip->dev, 0), 0x1,
+                              USB_TYPE_CLASS |
+                              USB_RECIP_INTERFACE, 0x00, 0x500, buff, 1);
+}
+
 /* Digidesign Mbox 1 clock source switch (internal/spdif) */
 
-static int snd_mbox1_switch_get(struct snd_kcontrol *kctl,
-                               struct snd_ctl_elem_value *ucontrol)
+static int snd_mbox1_clk_switch_get(struct snd_kcontrol *kctl,
+                                   struct snd_ctl_elem_value *ucontrol)
 {
+       struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
+       struct snd_usb_audio *chip = list->mixer->chip;
+       int err;
+
+       err = snd_usb_lock_shutdown(chip);
+       if (err < 0)
+               goto err;
+
+       err = snd_mbox1_is_spdif_synced(chip);
+       if (err < 0)
+               goto err;
+
+       kctl->private_value = err;
+       err = 0;
        ucontrol->value.enumerated.item[0] = kctl->private_value;
-       return 0;
+err:
+       snd_usb_unlock_shutdown(chip);
+       return err;
 }
 
-static int snd_mbox1_switch_update(struct usb_mixer_interface *mixer, int val)
+static int snd_mbox1_clk_switch_update(struct usb_mixer_interface *mixer, int is_spdif_sync)
 {
        struct snd_usb_audio *chip = mixer->chip;
        int err;
-       unsigned char buff[3];
 
        err = snd_usb_lock_shutdown(chip);
        if (err < 0)
                return err;
 
-       /* Prepare for magic command to toggle clock source */
-       err = snd_usb_ctl_msg(chip->dev,
-                               usb_rcvctrlpipe(chip->dev, 0), 0x81,
-                               USB_DIR_IN |
-                               USB_TYPE_CLASS |
-                               USB_RECIP_INTERFACE, 0x00, 0x500, buff, 1);
+       err = snd_mbox1_is_spdif_input(chip);
        if (err < 0)
                goto err;
-       err = snd_usb_ctl_msg(chip->dev,
-                               usb_rcvctrlpipe(chip->dev, 0), 0x81,
-                               USB_DIR_IN |
-                               USB_TYPE_CLASS |
-                               USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+
+       err = snd_mbox1_is_spdif_synced(chip);
        if (err < 0)
                goto err;
 
-       /* 2 possibilities:     Internal    -> send sample rate
-        *                      S/PDIF sync -> send zeroes
-        * NB: Sample rate locked to 48kHz on purpose to
-        *     prevent user from resetting the sample rate
-        *     while S/PDIF sync is enabled and confusing
-        *     this configuration.
-        */
-       if (val == 0) {
-               buff[0] = 0x80;
-               buff[1] = 0xbb;
-               buff[2] = 0x00;
-       } else {
-               buff[0] = buff[1] = buff[2] = 0x00;
-       }
+       /* FIXME: hardcoded sample rate */
+       err = snd_mbox1_set_clk_source(chip, is_spdif_sync ? 0 : 48000);
+       if (err < 0)
+               goto err;
 
-       /* Send the magic command to toggle the clock source */
-       err = snd_usb_ctl_msg(chip->dev,
-                               usb_sndctrlpipe(chip->dev, 0), 0x1,
-                               USB_TYPE_CLASS |
-                               USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+       err = snd_mbox1_is_spdif_synced(chip);
+err:
+       snd_usb_unlock_shutdown(chip);
+       return err;
+}
+
+static int snd_mbox1_clk_switch_put(struct snd_kcontrol *kctl,
+                                   struct snd_ctl_elem_value *ucontrol)
+{
+       struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
+       struct usb_mixer_interface *mixer = list->mixer;
+       int err;
+       bool cur_val, new_val;
+
+       cur_val = kctl->private_value;
+       new_val = ucontrol->value.enumerated.item[0];
+       if (cur_val == new_val)
+               return 0;
+
+       kctl->private_value = new_val;
+       err = snd_mbox1_clk_switch_update(mixer, new_val);
+       return err < 0 ? err : 1;
+}
+
+static int snd_mbox1_clk_switch_info(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_info *uinfo)
+{
+       static const char *const texts[2] = {
+               "Internal",
+               "S/PDIF"
+       };
+
+       return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
+}
+
+static int snd_mbox1_clk_switch_resume(struct usb_mixer_elem_list *list)
+{
+       return snd_mbox1_clk_switch_update(list->mixer, list->kctl->private_value);
+}
+
+/* Digidesign Mbox 1 input source switch (analog/spdif) */
+
+static int snd_mbox1_src_switch_get(struct snd_kcontrol *kctl,
+                                   struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.enumerated.item[0] = kctl->private_value;
+       return 0;
+}
+
+static int snd_mbox1_src_switch_update(struct usb_mixer_interface *mixer, int is_spdif_input)
+{
+       struct snd_usb_audio *chip = mixer->chip;
+       int err;
+
+       err = snd_usb_lock_shutdown(chip);
+       if (err < 0)
+               return err;
+
+       err = snd_mbox1_is_spdif_input(chip);
        if (err < 0)
                goto err;
-       err = snd_usb_ctl_msg(chip->dev,
-                               usb_rcvctrlpipe(chip->dev, 0), 0x81,
-                               USB_DIR_IN |
-                               USB_TYPE_CLASS |
-                               USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+
+       err = snd_mbox1_set_input_source(chip, is_spdif_input);
        if (err < 0)
                goto err;
-       err = snd_usb_ctl_msg(chip->dev,
-                               usb_rcvctrlpipe(chip->dev, 0), 0x81,
-                               USB_DIR_IN |
-                               USB_TYPE_CLASS |
-                               USB_RECIP_ENDPOINT, 0x100, 0x2, buff, 3);
+
+       err = snd_mbox1_is_spdif_input(chip);
        if (err < 0)
                goto err;
 
+       err = snd_mbox1_is_spdif_synced(chip);
 err:
        snd_usb_unlock_shutdown(chip);
        return err;
 }
 
-static int snd_mbox1_switch_put(struct snd_kcontrol *kctl,
-                               struct snd_ctl_elem_value *ucontrol)
+static int snd_mbox1_src_switch_put(struct snd_kcontrol *kctl,
+                                   struct snd_ctl_elem_value *ucontrol)
 {
        struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
        struct usb_mixer_interface *mixer = list->mixer;
@@ -685,42 +808,60 @@ static int snd_mbox1_switch_put(struct snd_kcontrol *kctl,
                return 0;
 
        kctl->private_value = new_val;
-       err = snd_mbox1_switch_update(mixer, new_val);
+       err = snd_mbox1_src_switch_update(mixer, new_val);
        return err < 0 ? err : 1;
 }
 
-static int snd_mbox1_switch_info(struct snd_kcontrol *kcontrol,
-                                struct snd_ctl_elem_info *uinfo)
+static int snd_mbox1_src_switch_info(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_info *uinfo)
 {
        static const char *const texts[2] = {
-               "Internal",
+               "Analog",
                "S/PDIF"
        };
 
        return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
 }
 
-static int snd_mbox1_switch_resume(struct usb_mixer_elem_list *list)
+static int snd_mbox1_src_switch_resume(struct usb_mixer_elem_list *list)
 {
-       return snd_mbox1_switch_update(list->mixer, list->kctl->private_value);
+       return snd_mbox1_src_switch_update(list->mixer, list->kctl->private_value);
 }
 
-static const struct snd_kcontrol_new snd_mbox1_switch = {
+static const struct snd_kcontrol_new snd_mbox1_clk_switch = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Clock Source",
        .index = 0,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-       .info = snd_mbox1_switch_info,
-       .get = snd_mbox1_switch_get,
-       .put = snd_mbox1_switch_put,
+       .info = snd_mbox1_clk_switch_info,
+       .get = snd_mbox1_clk_switch_get,
+       .put = snd_mbox1_clk_switch_put,
+       .private_value = 0
+};
+
+static const struct snd_kcontrol_new snd_mbox1_src_switch = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Input Source",
+       .index = 1,
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = snd_mbox1_src_switch_info,
+       .get = snd_mbox1_src_switch_get,
+       .put = snd_mbox1_src_switch_put,
        .private_value = 0
 };
 
-static int snd_mbox1_create_sync_switch(struct usb_mixer_interface *mixer)
+static int snd_mbox1_controls_create(struct usb_mixer_interface *mixer)
 {
-       return add_single_ctl_with_resume(mixer, 0,
-                                         snd_mbox1_switch_resume,
-                                         &snd_mbox1_switch, NULL);
+       int err;
+       err = add_single_ctl_with_resume(mixer, 0,
+                                        snd_mbox1_clk_switch_resume,
+                                        &snd_mbox1_clk_switch, NULL);
+       if (err < 0)
+               return err;
+
+       return add_single_ctl_with_resume(mixer, 1,
+                                         snd_mbox1_src_switch_resume,
+                                         &snd_mbox1_src_switch, NULL);
 }
 
 /* Native Instruments device quirks */
@@ -3029,7 +3170,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
                break;
 
        case USB_ID(0x0dba, 0x1000): /* Digidesign Mbox 1 */
-               err = snd_mbox1_create_sync_switch(mixer);
+               err = snd_mbox1_controls_create(mixer);
                break;
 
        case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */
index 4e5031a..5dc9266 100644 (file)
@@ -614,6 +614,15 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
        subs->period_elapsed_pending = 0;
        runtime->delay = 0;
 
+       /* check whether early start is needed for playback stream */
+       subs->early_playback_start =
+               subs->direction == SNDRV_PCM_STREAM_PLAYBACK &&
+               (!chip->lowlatency ||
+                (subs->data_endpoint->nominal_queue_size >= subs->buffer_bytes));
+
+       if (subs->early_playback_start)
+               ret = start_endpoints(subs);
+
  unlock:
        snd_usb_unlock_shutdown(chip);
        return ret;
@@ -1394,7 +1403,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
                subs->trigger_tstamp_pending_update = false;
        }
 
-       if (period_elapsed && !subs->running) {
+       if (period_elapsed && !subs->running && !subs->early_playback_start) {
                subs->period_elapsed_pending = 1;
                period_elapsed = 0;
        }
@@ -1448,7 +1457,8 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
                                              prepare_playback_urb,
                                              retire_playback_urb,
                                              subs);
-               if (cmd == SNDRV_PCM_TRIGGER_START) {
+               if (!subs->early_playback_start &&
+                   cmd == SNDRV_PCM_TRIGGER_START) {
                        err = start_endpoints(subs);
                        if (err < 0) {
                                snd_usb_endpoint_set_callback(subs->data_endpoint,
index 19bb499..e03043f 100644 (file)
@@ -2730,23 +2730,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 
-/* Lenovo ThinkStation P620 Rear Line-in, Line-out and Microphone */
-{
-       USB_DEVICE(0x17aa, 0x1046),
-       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-               .ifnum = QUIRK_ANY_INTERFACE,
-               .type = QUIRK_SETUP_DISABLE_AUTOSUSPEND
-       }
-},
-/* Lenovo ThinkStation P620 Internal Speaker + Front Headset */
-{
-       USB_DEVICE(0x17aa, 0x104d),
-       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-               .ifnum = QUIRK_ANY_INTERFACE,
-               .type = QUIRK_SETUP_DISABLE_AUTOSUSPEND
-       }
-},
-
 /* Native Instruments MK2 series */
 {
        /* Komplete Audio 6 */
@@ -2802,53 +2785,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 
-/*
- * Auvitek au0828 devices with audio interface.
- * This should be kept in sync with drivers/media/usb/au0828/au0828-cards.c
- * Please notice that some drivers are DVB only, and don't need to be
- * here. That's the case, for example, of DVICO_FUSIONHDTV7.
- */
-
-#define AU0828_DEVICE(vid, pid, vname, pname) { \
-       USB_AUDIO_DEVICE(vid, pid), \
-       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { \
-               .vendor_name = vname, \
-               .product_name = pname, \
-               .ifnum = QUIRK_ANY_INTERFACE, \
-               .type = QUIRK_AUDIO_ALIGN_TRANSFER, \
-               .shares_media_device = 1, \
-       } \
-}
-
-AU0828_DEVICE(0x2040, 0x7200, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7240, "Hauppauge", "HVR-850"),
-AU0828_DEVICE(0x2040, 0x7210, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7217, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x721b, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x721e, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x721f, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7280, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x0fd9, 0x0008, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7201, "Hauppauge", "HVR-950Q-MXL"),
-AU0828_DEVICE(0x2040, 0x7211, "Hauppauge", "HVR-950Q-MXL"),
-AU0828_DEVICE(0x2040, 0x7281, "Hauppauge", "HVR-950Q-MXL"),
-AU0828_DEVICE(0x05e1, 0x0480, "Hauppauge", "Woodbury"),
-AU0828_DEVICE(0x2040, 0x8200, "Hauppauge", "Woodbury"),
-AU0828_DEVICE(0x2040, 0x7260, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7213, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
-
-/* Syntek STK1160 */
-{
-       USB_AUDIO_DEVICE(0x05e1, 0x0408),
-       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
-               .vendor_name = "Syntek",
-               .product_name = "STK1160",
-               .ifnum = QUIRK_ANY_INTERFACE,
-               .type = QUIRK_AUDIO_ALIGN_TRANSFER
-       }
-},
-
 /* Digidesign Mbox */
 {
        /* Thanks to Clemens Ladisch <clemens@ladisch.de> */
@@ -3811,7 +3747,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
  * MacroSilicon MS2109 based HDMI capture cards
  *
  * These claim 96kHz 1ch in the descriptors, but are actually 48kHz 2ch.
- * They also need QUIRK_AUDIO_ALIGN_TRANSFER, which makes one wonder if
+ * They also need QUIRK_FLAG_ALIGN_TRANSFER, which makes one wonder if
  * they pretend to be 96kHz mono as a workaround for stereo being broken
  * by that...
  *
@@ -3826,10 +3762,6 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                .ifnum = QUIRK_ANY_INTERFACE,
                .type = QUIRK_COMPOSITE,
                .data = &(const struct snd_usb_audio_quirk[]) {
-                       {
-                               .ifnum = 2,
-                               .type = QUIRK_AUDIO_ALIGN_TRANSFER,
-                       },
                        {
                                .ifnum = 2,
                                .type = QUIRK_AUDIO_STANDARD_MIXER,
index 326d1b0..6ee6d24 100644 (file)
@@ -75,19 +75,6 @@ static int ignore_interface_quirk(struct snd_usb_audio *chip,
 }
 
 
-/*
- * Allow alignment on audio sub-slot (channel samples) rather than
- * on audio slots (audio frames)
- */
-static int create_align_transfer_quirk(struct snd_usb_audio *chip,
-                                      struct usb_interface *iface,
-                                      struct usb_driver *driver,
-                                      const struct snd_usb_audio_quirk *quirk)
-{
-       chip->txfr_quirk = 1;
-       return 1;       /* Continue with creating streams and mixer */
-}
-
 static int create_any_midi_quirk(struct snd_usb_audio *chip,
                                 struct usb_interface *intf,
                                 struct usb_driver *driver,
@@ -108,9 +95,6 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
        struct usb_interface_descriptor *altsd;
        int err;
 
-       if (chip->usb_id == USB_ID(0x1686, 0x00dd)) /* Zoom R16/24 */
-               chip->tx_length_quirk = 1;
-
        alts = &iface->altsetting[0];
        altsd = get_iface_desc(alts);
        err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber);
@@ -547,16 +531,7 @@ static int create_standard_mixer_quirk(struct snd_usb_audio *chip,
        if (quirk->ifnum < 0)
                return 0;
 
-       return snd_usb_create_mixer(chip, quirk->ifnum, 0);
-}
-
-static int setup_disable_autosuspend(struct snd_usb_audio *chip,
-                                      struct usb_interface *iface,
-                                      struct usb_driver *driver,
-                                      const struct snd_usb_audio_quirk *quirk)
-{
-       usb_disable_autosuspend(interface_to_usbdev(iface));
-       return 1;       /* Continue with creating streams and mixer */
+       return snd_usb_create_mixer(chip, quirk->ifnum);
 }
 
 /*
@@ -595,9 +570,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
                [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
                [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
                [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
-               [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk,
                [QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk,
-               [QUIRK_SETUP_DISABLE_AUTOSUSPEND] = setup_disable_autosuspend,
        };
 
        if (quirk->type < QUIRK_TYPE_COUNT) {
@@ -1518,62 +1491,13 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
        }
 }
 
-bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
-{
-       /* devices which do not support reading the sample rate. */
-       switch (chip->usb_id) {
-       case USB_ID(0x041e, 0x4080): /* Creative Live Cam VF0610 */
-       case USB_ID(0x04d8, 0xfeea): /* Benchmark DAC1 Pre */
-       case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */
-       case USB_ID(0x05a3, 0x9420): /* ELP HD USB Camera */
-       case USB_ID(0x05a7, 0x1020): /* Bose Companion 5 */
-       case USB_ID(0x074d, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
-       case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */
-       case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */
-       case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */
-       case USB_ID(0x2912, 0x30c8): /* Audioengine D1 */
-       case USB_ID(0x413c, 0xa506): /* Dell AE515 sound bar */
-       case USB_ID(0x046d, 0x084c): /* Logitech ConferenceCam Connect */
-               return true;
-       }
-
-       /* devices of these vendors don't support reading rate, either */
-       switch (USB_ID_VENDOR(chip->usb_id)) {
-       case 0x045e: /* MS Lifecam */
-       case 0x047f: /* Plantronics */
-       case 0x1de7: /* Phoenix Audio */
-               return true;
-       }
-
-       return false;
-}
-
-/* ITF-USB DSD based DACs need a vendor cmd to switch
- * between PCM and native DSD mode
- */
-static bool is_itf_usb_dsd_dac(unsigned int id)
-{
-       switch (id) {
-       case USB_ID(0x154e, 0x1002): /* Denon DCD-1500RE */
-       case USB_ID(0x154e, 0x1003): /* Denon DA-300USB */
-       case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */
-       case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */
-       case USB_ID(0x1852, 0x5065): /* Luxman DA-06 */
-       case USB_ID(0x0644, 0x8043): /* TEAC UD-501/UD-501V2/UD-503/NT-503 */
-       case USB_ID(0x0644, 0x8044): /* Esoteric D-05X */
-       case USB_ID(0x0644, 0x804a): /* TEAC UD-301 */
-               return true;
-       }
-       return false;
-}
-
 int snd_usb_select_mode_quirk(struct snd_usb_audio *chip,
                              const struct audioformat *fmt)
 {
        struct usb_device *dev = chip->dev;
        int err;
 
-       if (is_itf_usb_dsd_dac(chip->usb_id)) {
+       if (chip->quirk_flags & QUIRK_FLAG_ITF_USB_DSD_DAC) {
                /* First switch to alt set 0, otherwise the mode switch cmd
                 * will not be accepted by the DAC
                 */
@@ -1636,22 +1560,6 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
                ep->tenor_fb_quirk = 1;
 }
 
-void snd_usb_set_interface_quirk(struct snd_usb_audio *chip)
-{
-       if (!chip)
-               return;
-       /*
-        * "Playback Design" products need a 50ms delay after setting the
-        * USB interface.
-        */
-       switch (USB_ID_VENDOR(chip->usb_id)) {
-       case 0x23ba: /* Playback Design */
-       case 0x0644: /* TEAC Corp. */
-               msleep(50);
-               break;
-       }
-}
-
 /* quirk applied after snd_usb_ctl_msg(); not applied during boot quirks */
 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
                           __u8 request, __u8 requesttype, __u16 value,
@@ -1659,57 +1567,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
 {
        struct snd_usb_audio *chip = dev_get_drvdata(&dev->dev);
 
-       if (!chip)
+       if (!chip || (requesttype & USB_TYPE_MASK) != USB_TYPE_CLASS)
                return;
-       /*
-        * "Playback Design" products need a 20ms delay after each
-        * class compliant request
-        */
-       if (USB_ID_VENDOR(chip->usb_id) == 0x23ba &&
-           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
-               msleep(20);
-
-       /*
-        * "TEAC Corp." products need a 20ms delay after each
-        * class compliant request
-        */
-       if (USB_ID_VENDOR(chip->usb_id) == 0x0644 &&
-           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
-               msleep(20);
-
-       /* ITF-USB DSD based DACs functionality need a delay
-        * after each class compliant request
-        */
-       if (is_itf_usb_dsd_dac(chip->usb_id)
-           && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
-               msleep(20);
 
-       /*
-        * Plantronics headsets (C320, C320-M, etc) need a delay to avoid
-        * random microhpone failures.
-        */
-       if (USB_ID_VENDOR(chip->usb_id) == 0x047f &&
-           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+       if (chip->quirk_flags & QUIRK_FLAG_CTL_MSG_DELAY)
                msleep(20);
-
-       /* Zoom R16/24, many Logitech(at least H650e/H570e/BCC950),
-        * Jabra 550a, Kingston HyperX needs a tiny delay here,
-        * otherwise requests like get/set frequency return
-        * as failed despite actually succeeding.
-        */
-       if ((chip->usb_id == USB_ID(0x1686, 0x00dd) ||
-            USB_ID_VENDOR(chip->usb_id) == 0x046d  || /* Logitech */
-            chip->usb_id == USB_ID(0x0b0e, 0x0349) ||
-            chip->usb_id == USB_ID(0x0951, 0x16ad)) &&
-           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+       else if (chip->quirk_flags & QUIRK_FLAG_CTL_MSG_DELAY_1M)
                usleep_range(1000, 2000);
-
-       /*
-        * Samsung USBC Headset (AKG) need a tiny delay after each
-        * class compliant request. (Model number: AAM625R or AAM627R)
-        */
-       if (chip->usb_id == USB_ID(0x04e8, 0xa051) &&
-           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+       else if (chip->quirk_flags & QUIRK_FLAG_CTL_MSG_DELAY_5M)
                usleep_range(5000, 6000);
 }
 
@@ -1796,7 +1661,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        }
 
        /* ITF-USB DSD based DACs */
-       if (is_itf_usb_dsd_dac(chip->usb_id)) {
+       if (chip->quirk_flags & QUIRK_FLAG_ITF_USB_DSD_DAC) {
                iface = usb_ifnum_to_if(chip->dev, fp->iface);
 
                /* Altsetting 2 support native DSD if the num of altsets is
@@ -1808,29 +1673,9 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
        }
 
-       /* Mostly generic method to detect many DSD-capable implementations -
-        * from XMOS/Thesycon
-        */
-       switch (USB_ID_VENDOR(chip->usb_id)) {
-       case 0x152a:  /* Thesycon devices */
-       case 0x20b1:  /* XMOS based devices */
-       case 0x22d9:  /* Oppo */
-       case 0x23ba:  /* Playback Designs */
-       case 0x25ce:  /* Mytek devices */
-       case 0x278b:  /* Rotel? */
-       case 0x292b:  /* Gustard/Ess based devices */
-       case 0x2972:  /* FiiO devices */
-       case 0x2ab6:  /* T+A devices */
-       case 0x3353:  /* Khadas devices */
-       case 0x3842:  /* EVGA */
-       case 0xc502:  /* HiBy devices */
-               if (fp->dsd_raw)
-                       return SNDRV_PCM_FMTBIT_DSD_U32_BE;
-               break;
-       default:
-               break;
-
-       }
+       /* Mostly generic method to detect many DSD-capable implementations */
+       if ((chip->quirk_flags & QUIRK_FLAG_DSD_RAW) && fp->dsd_raw)
+               return SNDRV_PCM_FMTBIT_DSD_U32_BE;
 
        return 0;
 }
@@ -1898,6 +1743,7 @@ static const struct registration_quirk registration_quirks[] = {
        REG_QUIRK_ENTRY(0x0951, 0x16ed, 2),     /* Kingston HyperX Cloud Alpha S */
        REG_QUIRK_ENTRY(0x0951, 0x16ea, 2),     /* Kingston HyperX Cloud Flight S */
        REG_QUIRK_ENTRY(0x0ecb, 0x1f46, 2),     /* JBL Quantum 600 */
+       REG_QUIRK_ENTRY(0x0ecb, 0x1f47, 2),     /* JBL Quantum 800 */
        REG_QUIRK_ENTRY(0x0ecb, 0x2039, 2),     /* JBL Quantum 400 */
        REG_QUIRK_ENTRY(0x0ecb, 0x203c, 2),     /* JBL Quantum 600 */
        REG_QUIRK_ENTRY(0x0ecb, 0x203e, 2),     /* JBL Quantum 800 */
@@ -1916,3 +1762,189 @@ bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface)
        /* Register as normal */
        return false;
 }
+
+/*
+ * driver behavior quirk flags
+ */
+struct usb_audio_quirk_flags_table {
+       u32 id;
+       u32 flags;
+};
+
+#define DEVICE_FLG(vid, pid, _flags) \
+       { .id = USB_ID(vid, pid), .flags = (_flags) }
+#define VENDOR_FLG(vid, _flags) DEVICE_FLG(vid, 0, _flags)
+
+static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+       /* Device matches */
+       DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x046d, 0x084c, /* Logitech ConferenceCam Connect */
+                  QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY_1M),
+       DEVICE_FLG(0x046d, 0x0991, /* Logitech QuickCam Pro */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x046d, 0x09a4, /* Logitech QuickCam E 3500 */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x04d8, 0xfeea, /* Benchmark DAC1 Pre */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x04e8, 0xa051, /* Samsung USBC Headset (AKG) */
+                  QUIRK_FLAG_SKIP_CLOCK_SELECTOR | QUIRK_FLAG_CTL_MSG_DELAY_5M),
+       DEVICE_FLG(0x054c, 0x0b8c, /* Sony WALKMAN NW-A45 DAC */
+                  QUIRK_FLAG_SET_IFACE_FIRST),
+       DEVICE_FLG(0x0556, 0x0014, /* Phoenix Audio TMX320VC */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x05a3, 0x9420, /* ELP HD USB Camera */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x05a7, 0x1020, /* Bose Companion 5 */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x05e1, 0x0408, /* Syntek STK1160 */
+                  QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x05e1, 0x0480, /* Hauppauge Woodbury */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x0644, 0x8043, /* TEAC UD-501/UD-501V2/UD-503/NT-503 */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+                  QUIRK_FLAG_IFACE_DELAY),
+       DEVICE_FLG(0x0644, 0x8044, /* Esoteric D-05X */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+                  QUIRK_FLAG_IFACE_DELAY),
+       DEVICE_FLG(0x0644, 0x804a, /* TEAC UD-301 */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+                  QUIRK_FLAG_IFACE_DELAY),
+       DEVICE_FLG(0x06f8, 0xb000, /* Hercules DJ Console (Windows Edition) */
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x06f8, 0xd002, /* Hercules DJ Console (Macintosh Edition) */
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x074d, 0x3553, /* Outlaw RR2150 (Micronas UAC3553B) */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x08bb, 0x2702, /* LineX FM Transmitter */
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x0951, 0x16ad, /* Kingston HyperX */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M),
+       DEVICE_FLG(0x0b0e, 0x0349, /* Jabra 550a */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M),
+       DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x13e5, 0x0001, /* Serato Phono */
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x154e, 0x1002, /* Denon DCD-1500RE */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x154e, 0x1003, /* Denon DA-300USB */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x154e, 0x3005, /* Marantz HD-DAC1 */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x154e, 0x3006, /* Marantz SA-14S1 */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x154e, 0x500e, /* Denon DN-X1600 */
+                  QUIRK_FLAG_IGNORE_CLOCK_SOURCE),
+       DEVICE_FLG(0x1686, 0x00dd, /* Zoom R16/24 */
+                  QUIRK_FLAG_TX_LENGTH | QUIRK_FLAG_CTL_MSG_DELAY_1M),
+       DEVICE_FLG(0x17aa, 0x1046, /* Lenovo ThinkStation P620 Rear Line-in, Line-out and Microphone */
+                  QUIRK_FLAG_DISABLE_AUTOSUSPEND),
+       DEVICE_FLG(0x17aa, 0x104d, /* Lenovo ThinkStation P620 Internal Speaker + Front Headset */
+                  QUIRK_FLAG_DISABLE_AUTOSUSPEND),
+       DEVICE_FLG(0x1852, 0x5065, /* Luxman DA-06 */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7210, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7211, /* Hauppauge HVR-950Q-MXL */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7213, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7217, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x721b, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x721e, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x721f, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7240, /* Hauppauge HVR-850 */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7260, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7270, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7280, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7281, /* Hauppauge HVR-950Q-MXL */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x8200, /* Hauppauge Woodbury */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */
+                  QUIRK_FLAG_ALIGN_TRANSFER),
+
+       /* Vendor matches */
+       VENDOR_FLG(0x045e, /* MS Lifecam */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       VENDOR_FLG(0x046d, /* Logitech */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M),
+       VENDOR_FLG(0x047f, /* Plantronics */
+                  QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY),
+       VENDOR_FLG(0x0644, /* TEAC Corp. */
+                  QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY),
+       VENDOR_FLG(0x07fd, /* MOTU */
+                  QUIRK_FLAG_VALIDATE_RATES),
+       VENDOR_FLG(0x152a, /* Thesycon devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x1de7, /* Phoenix Audio */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       VENDOR_FLG(0x20b1, /* XMOS based devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x22d9, /* Oppo */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x23ba, /* Playback Design */
+                  QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY |
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x25ce, /* Mytek devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x278b, /* Rotel? */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x292b, /* Gustard/Ess based devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x2972, /* FiiO devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x2ab6, /* T+A devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x3353, /* Khadas devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x3842, /* EVGA */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0xc502, /* HiBy devices */
+                  QUIRK_FLAG_DSD_RAW),
+
+       {} /* terminator */
+};
+
+void snd_usb_init_quirk_flags(struct snd_usb_audio *chip)
+{
+       const struct usb_audio_quirk_flags_table *p;
+
+       for (p = quirk_flags_table; p->id; p++) {
+               if (chip->usb_id == p->id ||
+                   (!USB_ID_PRODUCT(p->id) &&
+                    USB_ID_VENDOR(chip->usb_id) == USB_ID_VENDOR(p->id))) {
+                       usb_audio_dbg(chip,
+                                     "Set quirk_flags 0x%x for device %04x:%04x\n",
+                                     p->flags, USB_ID_VENDOR(chip->usb_id),
+                                     USB_ID_PRODUCT(chip->usb_id));
+                       chip->quirk_flags |= p->flags;
+                       return;
+               }
+       }
+}
index 67a0230..31abb7c 100644 (file)
@@ -28,14 +28,11 @@ int snd_usb_apply_boot_quirk_once(struct usb_device *dev,
 void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
                              const struct audioformat *fmt);
 
-bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip);
-
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
                                 const struct audioformat *fp);
 
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);
 
-void snd_usb_set_interface_quirk(struct snd_usb_audio *chip);
 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
                           __u8 request, __u8 requesttype, __u16 value,
                           __u16 index, void *data, __u16 size);
@@ -53,4 +50,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip,
 
 bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface);
 
+void snd_usb_init_quirk_flags(struct snd_usb_audio *chip);
+
 #endif /* __USBAUDIO_QUIRKS_H */
index ee9aa1d..ceb93d7 100644 (file)
@@ -89,8 +89,8 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,
        subs->stream = as;
        subs->direction = stream;
        subs->dev = as->chip->dev;
-       subs->txfr_quirk = as->chip->txfr_quirk;
-       subs->tx_length_quirk = as->chip->tx_length_quirk;
+       subs->txfr_quirk = !!(as->chip->quirk_flags & QUIRK_FLAG_ALIGN_TRANSFER);
+       subs->tx_length_quirk = !!(as->chip->quirk_flags & QUIRK_FLAG_TX_LENGTH);
        subs->speed = snd_usb_get_speed(subs->dev);
        subs->pkt_offset_adj = 0;
        subs->stream_offset_adj = 0;
index 538831c..1678341 100644 (file)
@@ -34,10 +34,8 @@ struct snd_usb_audio {
        atomic_t shutdown;
        atomic_t usage_count;
        wait_queue_head_t shutdown_wait;
-       unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
-       unsigned int tx_length_quirk:1; /* Put length specifier in transfers */
+       unsigned int quirk_flags;
        unsigned int need_delayed_register:1; /* warn for delayed registration */
-       unsigned int playback_first:1;  /* for implicit fb: don't wait for the first capture URBs */
        int num_interfaces;
        int num_suspended_intf;
        int sample_rate_read_error;
@@ -57,6 +55,7 @@ struct snd_usb_audio {
        bool generic_implicit_fb;       /* from the 'implicit_fb' module param */
        bool autoclock;                 /* from the 'autoclock' module param */
 
+       bool lowlatency;                /* from the 'lowlatency' module param */
        struct usb_host_interface *ctrl_intf;   /* the audio control interface */
        struct media_device *media_dev;
        struct media_intf_devnode *ctl_intf_media_devnode;
@@ -102,10 +101,7 @@ enum quirk_type {
        QUIRK_AUDIO_STANDARD_INTERFACE,
        QUIRK_AUDIO_FIXED_ENDPOINT,
        QUIRK_AUDIO_EDIROL_UAXX,
-       QUIRK_AUDIO_ALIGN_TRANSFER,
        QUIRK_AUDIO_STANDARD_MIXER,
-       QUIRK_SETUP_FMT_AFTER_RESUME,
-       QUIRK_SETUP_DISABLE_AUTOSUSPEND,
 
        QUIRK_TYPE_COUNT
 };
@@ -115,7 +111,6 @@ struct snd_usb_audio_quirk {
        const char *product_name;
        int16_t ifnum;
        uint16_t type;
-       bool shares_media_device;
        const void *data;
 };
 
@@ -129,4 +124,64 @@ void snd_usb_unlock_shutdown(struct snd_usb_audio *chip);
 extern bool snd_usb_use_vmalloc;
 extern bool snd_usb_skip_validation;
 
+/*
+ * Driver behavior quirk flags, stored in chip->quirk_flags
+ *
+ * QUIRK_FLAG_GET_SAMPLE_RATE:
+ *  Skip reading sample rate for devices, as some devices behave inconsistently
+ *  or return error
+ * QUIRK_FLAG_SHARE_MEDIA_DEVICE:
+ *  Create Media Controller API entries
+ * QUIRK_FLAG_ALIGN_TRANSFER:
+ *  Allow alignment on audio sub-slot (channel samples) rather than on audio
+ *  slots (audio frames)
+ * QUIRK_TX_LENGTH:
+ *  Add length specifier to transfers
+ * QUIRK_FLAG_PLAYBACK_FIRST:
+ *  Start playback stream at first even in implement feedback mode
+ * QUIRK_FLAG_SKIP_CLOCK_SELECTOR:
+ *  Skip clock selector setup; the device may reset to invalid state
+ * QUIRK_FLAG_IGNORE_CLOCK_SOURCE:
+ *  Ignore errors from clock source search; i.e. hardcoded clock
+ * QUIRK_FLAG_ITF_USB_DSD_DAC:
+ *  Indicates the device is for ITF-USB DSD based DACs that need a vendor cmd
+ *  to switch between PCM and native DSD mode
+ * QUIRK_FLAG_CTL_MSG_DELAY:
+ *  Add a delay of 20ms at each control message handling
+ * QUIRK_FLAG_CTL_MSG_DELAY_1M:
+ *  Add a delay of 1-2ms at each control message handling
+ * QUIRK_FLAG_CTL_MSG_DELAY_5M:
+ *  Add a delay of 5-6ms at each control message handling
+ * QUIRK_FLAG_IFACE_DELAY:
+ *  Add a delay of 50ms at each interface setup
+ * QUIRK_FLAG_VALIDATE_RATES:
+ *  Perform sample rate validations at probe
+ * QUIRK_FLAG_DISABLE_AUTOSUSPEND:
+ *  Disable runtime PM autosuspend
+ * QUIRK_FLAG_IGNORE_CTL_ERROR:
+ *  Ignore errors for mixer access
+ * QUIRK_FLAG_DSD_RAW:
+ *  Support generic DSD raw U32_BE format
+ * QUIRK_FLAG_SET_IFACE_FIRST:
+ *  Set up the interface at first like UAC1
+ */
+
+#define QUIRK_FLAG_GET_SAMPLE_RATE     (1U << 0)
+#define QUIRK_FLAG_SHARE_MEDIA_DEVICE  (1U << 1)
+#define QUIRK_FLAG_ALIGN_TRANSFER      (1U << 2)
+#define QUIRK_FLAG_TX_LENGTH           (1U << 3)
+#define QUIRK_FLAG_PLAYBACK_FIRST      (1U << 4)
+#define QUIRK_FLAG_SKIP_CLOCK_SELECTOR (1U << 5)
+#define QUIRK_FLAG_IGNORE_CLOCK_SOURCE (1U << 6)
+#define QUIRK_FLAG_ITF_USB_DSD_DAC     (1U << 7)
+#define QUIRK_FLAG_CTL_MSG_DELAY       (1U << 8)
+#define QUIRK_FLAG_CTL_MSG_DELAY_1M    (1U << 9)
+#define QUIRK_FLAG_CTL_MSG_DELAY_5M    (1U << 10)
+#define QUIRK_FLAG_IFACE_DELAY         (1U << 11)
+#define QUIRK_FLAG_VALIDATE_RATES      (1U << 12)
+#define QUIRK_FLAG_DISABLE_AUTOSUSPEND (1U << 13)
+#define QUIRK_FLAG_IGNORE_CTL_ERROR    (1U << 14)
+#define QUIRK_FLAG_DSD_RAW             (1U << 15)
+#define QUIRK_FLAG_SET_IFACE_FIRST     (1U << 16)
+
 #endif /* __USBAUDIO_H */
index a34d7d9..3788263 100644 (file)
@@ -1024,19 +1024,21 @@ static void wait_clear_underrun_bit(struct snd_intelhad *intelhaddata)
        dev_err(intelhaddata->dev, "Unable to clear UNDERRUN bits\n");
 }
 
-/* Perform some reset procedure but only when need_reset is set;
+/* Perform some reset procedure after stopping the stream;
  * this is called from prepare or hw_free callbacks once after trigger STOP
  * or underrun has been processed in order to settle down the h/w state.
  */
-static void had_do_reset(struct snd_intelhad *intelhaddata)
+static int had_pcm_sync_stop(struct snd_pcm_substream *substream)
 {
-       if (!intelhaddata->need_reset || !intelhaddata->connected)
-               return;
+       struct snd_intelhad *intelhaddata = snd_pcm_substream_chip(substream);
+
+       if (!intelhaddata->connected)
+               return 0;
 
        /* Reset buffer pointers */
        had_reset_audio(intelhaddata);
        wait_clear_underrun_bit(intelhaddata);
-       intelhaddata->need_reset = false;
+       return 0;
 }
 
 /* called from irq handler */
@@ -1050,7 +1052,6 @@ static void had_process_buffer_underrun(struct snd_intelhad *intelhaddata)
                snd_pcm_stop_xrun(substream);
                had_substream_put(intelhaddata);
        }
-       intelhaddata->need_reset = true;
 }
 
 /*
@@ -1141,19 +1142,6 @@ static int had_pcm_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-/*
- * ALSA PCM hw_free callback
- */
-static int had_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       struct snd_intelhad *intelhaddata;
-
-       intelhaddata = snd_pcm_substream_chip(substream);
-       had_do_reset(intelhaddata);
-
-       return 0;
-}
-
 /*
  * ALSA PCM trigger callback
  */
@@ -1178,7 +1166,6 @@ static int had_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                /* Disable Audio */
                had_enable_audio(intelhaddata, false);
-               intelhaddata->need_reset = true;
                break;
 
        default:
@@ -1210,8 +1197,6 @@ static int had_pcm_prepare(struct snd_pcm_substream *substream)
        dev_dbg(intelhaddata->dev, "rate=%d\n", runtime->rate);
        dev_dbg(intelhaddata->dev, "channels=%d\n", runtime->channels);
 
-       had_do_reset(intelhaddata);
-
        /* Get N value in KHz */
        disp_samp_freq = intelhaddata->tmds_clock_speed;
 
@@ -1287,9 +1272,9 @@ static const struct snd_pcm_ops had_pcm_ops = {
        .open =         had_pcm_open,
        .close =        had_pcm_close,
        .hw_params =    had_pcm_hw_params,
-       .hw_free =      had_pcm_hw_free,
        .prepare =      had_pcm_prepare,
        .trigger =      had_pcm_trigger,
+       .sync_stop =    had_pcm_sync_stop,
        .pointer =      had_pcm_pointer,
        .mmap =         had_pcm_mmap,
 };
@@ -1672,11 +1657,6 @@ static void hdmi_lpe_audio_free(struct snd_card *card)
 
                cancel_work_sync(&ctx->hdmi_audio_wq);
        }
-
-       if (card_ctx->mmio_start)
-               iounmap(card_ctx->mmio_start);
-       if (card_ctx->irq >= 0)
-               free_irq(card_ctx->irq, card_ctx);
 }
 
 /*
@@ -1714,8 +1694,8 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
        }
 
        /* create a card instance with ALSA framework */
-       ret = snd_card_new(&pdev->dev, hdmi_card_index, hdmi_card_id,
-                          THIS_MODULE, sizeof(*card_ctx), &card);
+       ret = snd_devm_card_new(&pdev->dev, hdmi_card_index, hdmi_card_id,
+                               THIS_MODULE, sizeof(*card_ctx), &card);
        if (ret)
                return ret;
 
@@ -1751,20 +1731,20 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
                __func__, (unsigned int)res_mmio->start,
                (unsigned int)res_mmio->end);
 
-       card_ctx->mmio_start = ioremap(res_mmio->start,
-                                              (size_t)(resource_size(res_mmio)));
+       card_ctx->mmio_start =
+               devm_ioremap(&pdev->dev, res_mmio->start,
+                            (size_t)(resource_size(res_mmio)));
        if (!card_ctx->mmio_start) {
                dev_err(&pdev->dev, "Could not get ioremap\n");
-               ret = -EACCES;
-               goto err;
+               return -EACCES;
        }
 
        /* setup interrupt handler */
-       ret = request_irq(irq, display_pipe_interrupt_handler, 0,
-                         pdev->name, card_ctx);
+       ret = devm_request_irq(&pdev->dev, irq, display_pipe_interrupt_handler,
+                              0, pdev->name, card_ctx);
        if (ret < 0) {
                dev_err(&pdev->dev, "request_irq failed\n");
-               goto err;
+               return ret;
        }
 
        card_ctx->irq = irq;
@@ -1784,7 +1764,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
                ret = snd_pcm_new(card, INTEL_HAD, port, MAX_PB_STREAMS,
                                  MAX_CAP_STREAMS, &pcm);
                if (ret)
-                       goto err;
+                       return ret;
 
                /* setup private data which can be retrieved when required */
                pcm->private_data = ctx;
@@ -1796,7 +1776,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
                /* allocate dma pages;
                 * try to allocate 600k buffer as default which is large enough
                 */
-               snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_UC,
+               snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
                                               card->dev, HAD_DEFAULT_BUFFER,
                                               HAD_MAX_BUFFER);
 
@@ -1805,31 +1785,29 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
                        struct snd_kcontrol *kctl;
 
                        kctl = snd_ctl_new1(&had_controls[i], ctx);
-                       if (!kctl) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
+                       if (!kctl)
+                               return -ENOMEM;
 
                        kctl->id.device = pcm->device;
 
                        ret = snd_ctl_add(card, kctl);
                        if (ret < 0)
-                               goto err;
+                               return ret;
                }
 
                /* Register channel map controls */
                ret = had_register_chmap_ctls(ctx, pcm);
                if (ret < 0)
-                       goto err;
+                       return ret;
 
                ret = had_create_jack(ctx, pcm);
                if (ret < 0)
-                       goto err;
+                       return ret;
        }
 
        ret = snd_card_register(card);
        if (ret)
-               goto err;
+               return ret;
 
        spin_lock_irq(&pdata->lpe_audio_slock);
        pdata->notify_audio_lpe = notify_audio_lpe;
@@ -1846,23 +1824,6 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
        }
 
        return 0;
-
-err:
-       snd_card_free(card);
-       return ret;
-}
-
-/*
- * hdmi_lpe_audio_remove - stop bridge with i915
- *
- * This function is called when the platform device is destroyed.
- */
-static int hdmi_lpe_audio_remove(struct platform_device *pdev)
-{
-       struct snd_intelhad_card *card_ctx = platform_get_drvdata(pdev);
-
-       snd_card_free(card_ctx->card);
-       return 0;
 }
 
 static const struct dev_pm_ops hdmi_lpe_audio_pm = {
@@ -1875,7 +1836,6 @@ static struct platform_driver hdmi_lpe_audio_driver = {
                .pm = &hdmi_lpe_audio_pm,
        },
        .probe          = hdmi_lpe_audio_probe,
-       .remove         = hdmi_lpe_audio_remove,
 };
 
 module_platform_driver(hdmi_lpe_audio_driver);
index bb38531..7ce8c2a 100644 (file)
@@ -127,7 +127,6 @@ struct snd_intelhad {
        union aud_cfg aud_config;       /* AUD_CONFIG reg value cache */
        struct work_struct hdmi_audio_wq;
        struct mutex mutex; /* for protecting chmap and eld */
-       bool need_reset;
        struct snd_jack *jack;
 };