aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-09-01 10:29:29 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2021-09-01 10:29:29 -0700
commit0d290223a6c77107b1c3988959e49279a8dafaba (patch)
tree2b250c9e698b84a38d17920c0712558226c93c78
parentea7b4244b3656ca33b19a950f092b5bbc718b40c (diff)
parenta8729efbbb847f6ea9b06e73491ec8ddb560465e (diff)
Merge tag 'sound-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "There are a few intensive changes in ALSA core side at this time that helped with significant code reduction. Meanwhile we keep getting new stuff, so the total size still grows... Anyway, the below are some highlights in this development cycle. ALSA core: - New helpers to manage page allocations and card object with devres - Refactoring for memory allocation with wc-pages - A new PCM hardware flag SNDRV_PCM_INFO_EXPLICIT_SYNC for controlling the explicit sync of the stream control; it'll be used for ASoC SOF and non-coherent memory in future ASoC: - Lots of cleanups and improvements to the Intel drivers, including some new systems support - New support for AMD Vangoh, CUI CMM-4030D-261, Mediatek Mt8195, Renesas RZ/G2L Mediatek Mt8195, RealTek RT101P, Renesas RZ/G2L, Rockchip RK3568 S/PDIF USB-audio: - Re-organized the quirk handling and a new option quirk_flags - Fix for a regression in 5.14 code change for JACK - Quirks for Sony WALKMAN, Digidesign mbox HD-audio: - Enhanced support for CS8409 codec - More consistent shutdown behavior with the runtime PM - The model option can accept the PCI or codec SSID as an alias - Quirks for ASUS ROG, HP Spectre x360 Others: - Lots of code reduction in legacy drivers with devres helpers - FireWire MOTU 896HD support" * tag 'sound-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (421 commits) ASoC: Revert PCM trigger changes ALSA: usb-audio: Add lowlatency module option ALSA: hda/cs8409: Initialize Codec only in init fixup. ALSA: hda/cs8409: Ensure Type Detection is only run on startup when necessary ALSA: usb-audio: Work around for XRUN with low latency playback ALSA: pcm: fix divide error in snd_pcm_lib_ioctl ASoC: soc-pcm: test refcount before triggering ASoC: soc-pcm: protect BE dailink state changes in trigger ASoC: wcd9335: Disable irq on slave ports in the remove function ASoC: wcd9335: Fix a memory leak in the error handling path of the probe function ASoC: wcd9335: Fix a double irq free in the remove function ALSA: hda: Disable runtime resume at shutdown ASoC: rockchip: i2s: Add support for frame inversion ASoC: dt-bindings: rockchip: Add compatible strings for more SoCs ASoC: rockchip: i2s: Add compatible for more SoCs ASoC: rockchip: i2s: Make playback/capture optional ASoC: rockchip: i2s: Fixup config for DAIFMT_DSP_A/B ASoC: dt-bindings: rockchip: Document reset property for i2s ASoC: rockchip: i2s: Fix regmap_ops hang ASoC: rockchip: i2s: Improve dma data transfer efficiency ...
-rw-r--r--Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt1
-rw-r--r--Documentation/devicetree/bindings/sound/ics43432.txt6
-rw-r--r--Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml184
-rw-r--r--Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml47
-rw-r--r--Documentation/devicetree/bindings/sound/realtek,rt1015p.yaml4
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml118
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip-i2s.yaml11
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip-spdif.yaml1
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.yaml2
-rw-r--r--Documentation/sound/alsa-configuration.rst34
-rw-r--r--Documentation/sound/hd-audio/notes.rst11
-rw-r--r--Documentation/sound/kernel-api/writing-an-alsa-driver.rst33
-rw-r--r--drivers/soundwire/intel.c74
-rw-r--r--drivers/soundwire/intel_init.c14
-rw-r--r--include/linux/platform_data/davinci_asp.h1
-rw-r--r--include/linux/soundwire/sdw_intel.h87
-rw-r--r--include/sound/compress_driver.h2
-rw-r--r--include/sound/core.h6
-rw-r--r--include/sound/emu10k1.h6
-rw-r--r--include/sound/emu8000.h3
-rw-r--r--include/sound/hda_codec.h1
-rw-r--r--include/sound/hdaudio_ext.h2
-rw-r--r--include/sound/memalloc.h10
-rw-r--r--include/sound/pcm.h47
-rw-r--r--include/sound/pxa2xx-lib.h13
-rw-r--r--include/sound/sof.h1
-rw-r--r--include/uapi/sound/asound.h1
-rw-r--r--include/uapi/sound/snd_sst_tokens.h6
-rw-r--r--sound/arm/pxa2xx-ac97.c18
-rw-r--r--sound/arm/pxa2xx-pcm-lib.c90
-rw-r--r--sound/core/compress_offload.c69
-rw-r--r--sound/core/control_led.c2
-rw-r--r--sound/core/init.c105
-rw-r--r--sound/core/isadma.c38
-rw-r--r--sound/core/memalloc.c177
-rw-r--r--sound/core/memalloc_local.h2
-rw-r--r--sound/core/pcm_lib.c2
-rw-r--r--sound/core/pcm_memory.c67
-rw-r--r--sound/core/pcm_native.c18
-rw-r--r--sound/core/seq/seq_dummy.c8
-rw-r--r--sound/core/sgbuf.c30
-rw-r--r--sound/drivers/Kconfig2
-rw-r--r--sound/drivers/aloop.c26
-rw-r--r--sound/drivers/dummy.c24
-rw-r--r--sound/drivers/mpu401/mpu401.c34
-rw-r--r--sound/drivers/mtpav.c30
-rw-r--r--sound/drivers/pcsp/pcsp.c49
-rw-r--r--sound/drivers/pcsp/pcsp_input.c14
-rw-r--r--sound/drivers/pcsp/pcsp_input.h1
-rw-r--r--sound/drivers/serial-u16550.c57
-rw-r--r--sound/drivers/virmidi.c21
-rw-r--r--sound/drivers/vx/vx_core.c12
-rw-r--r--sound/firewire/motu/motu-protocol-v2.c22
-rw-r--r--sound/firewire/motu/motu.c1
-rw-r--r--sound/firewire/motu/motu.h1
-rw-r--r--sound/isa/ad1816a/ad1816a.c41
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c49
-rw-r--r--sound/isa/ad1848/ad1848.c19
-rw-r--r--sound/isa/adlib.c28
-rw-r--r--sound/isa/als100.c41
-rw-r--r--sound/isa/azt2320.c49
-rw-r--r--sound/isa/cmi8328.c31
-rw-r--r--sound/isa/cmi8330.c27
-rw-r--r--sound/isa/cs423x/cs4231.c21
-rw-r--r--sound/isa/cs423x/cs4236.c52
-rw-r--r--sound/isa/cs423x/cs4236_lib.c2
-rw-r--r--sound/isa/es1688/es1688.c33
-rw-r--r--sound/isa/es18xx.c112
-rw-r--r--sound/isa/galaxy/galaxy.c82
-rw-r--r--sound/isa/gus/gus_main.c44
-rw-r--r--sound/isa/gus/gusclassic.c28
-rw-r--r--sound/isa/gus/gusextreme.c39
-rw-r--r--sound/isa/gus/gusmax.c65
-rw-r--r--sound/isa/gus/interwave.c53
-rw-r--r--sound/isa/msnd/msnd.c8
-rw-r--r--sound/isa/msnd/msnd_pinnacle.c119
-rw-r--r--sound/isa/opl3sa2.c60
-rw-r--r--sound/isa/opti9xx/miro.c76
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c77
-rw-r--r--sound/isa/sb/emu8000.c48
-rw-r--r--sound/isa/sb/jazz16.c39
-rw-r--r--sound/isa/sb/sb16.c42
-rw-r--r--sound/isa/sb/sb8.c48
-rw-r--r--sound/isa/sb/sb_common.c64
-rw-r--r--sound/isa/sc6000.c84
-rw-r--r--sound/isa/sscape.c92
-rw-r--r--sound/isa/wavefront/wavefront.c46
-rw-r--r--sound/isa/wss/wss_lib.c67
-rw-r--r--sound/parisc/harmony.c14
-rw-r--r--sound/pci/ad1889.c144
-rw-r--r--sound/pci/ali5451/ali5451.c90
-rw-r--r--sound/pci/als300.c80
-rw-r--r--sound/pci/als4000.c59
-rw-r--r--sound/pci/atiixp.c92
-rw-r--r--sound/pci/atiixp_modem.c92
-rw-r--r--sound/pci/au88x0/au88x0.c134
-rw-r--r--sound/pci/aw2/aw2-alsa.c102
-rw-r--r--sound/pci/azt3328.c124
-rw-r--r--sound/pci/bt87x.c98
-rw-r--r--sound/pci/ca0106/ca0106.h3
-rw-r--r--sound/pci/ca0106/ca0106_main.c114
-rw-r--r--sound/pci/cmipci.c104
-rw-r--r--sound/pci/cs4281.c114
-rw-r--r--sound/pci/cs46xx/cs46xx.c51
-rw-r--r--sound/pci/cs46xx/cs46xx.h4
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c141
-rw-r--r--sound/pci/cs5530.c86
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c94
-rw-r--r--sound/pci/cs5535audio/cs5535audio_olpc.c7
-rw-r--r--sound/pci/echoaudio/echoaudio.c168
-rw-r--r--sound/pci/echoaudio/echoaudio.h2
-rw-r--r--sound/pci/emu10k1/emu10k1.c53
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c102
-rw-r--r--sound/pci/emu10k1/emu10k1x.c128
-rw-r--r--sound/pci/emu10k1/p16v.c22
-rw-r--r--sound/pci/ens1370.c115
-rw-r--r--sound/pci/es1938.c97
-rw-r--r--sound/pci/es1968.c112
-rw-r--r--sound/pci/fm801.c103
-rw-r--r--sound/pci/hda/Kconfig10
-rw-r--r--sound/pci/hda/Makefile2
-rw-r--r--sound/pci/hda/hda_auto_parser.c84
-rw-r--r--sound/pci/hda/hda_bind.c8
-rw-r--r--sound/pci/hda/hda_codec.c12
-rw-r--r--sound/pci/hda/hda_controller.c13
-rw-r--r--sound/pci/hda/hda_controller.h3
-rw-r--r--sound/pci/hda/hda_generic.c19
-rw-r--r--sound/pci/hda/hda_generic.h1
-rw-r--r--sound/pci/hda/hda_intel.c52
-rw-r--r--sound/pci/hda/hda_local.h2
-rw-r--r--sound/pci/hda/patch_analog.c11
-rw-r--r--sound/pci/hda/patch_ca0132.c8
-rw-r--r--sound/pci/hda/patch_cirrus.c1074
-rw-r--r--sound/pci/hda/patch_conexant.c15
-rw-r--r--sound/pci/hda/patch_cs8409-tables.c560
-rw-r--r--sound/pci/hda/patch_cs8409.c1299
-rw-r--r--sound/pci/hda/patch_cs8409.h371
-rw-r--r--sound/pci/hda/patch_hdmi.c7
-rw-r--r--sound/pci/hda/patch_realtek.c24
-rw-r--r--sound/pci/hda/patch_sigmatel.c23
-rw-r--r--sound/pci/ice1712/ice1712.c133
-rw-r--r--sound/pci/ice1712/ice1724.c167
-rw-r--r--sound/pci/intel8x0.c144
-rw-r--r--sound/pci/intel8x0m.c139
-rw-r--r--sound/pci/korg1212/korg1212.c211
-rw-r--r--sound/pci/lola/lola.c127
-rw-r--r--sound/pci/lola/lola.h5
-rw-r--r--sound/pci/lola/lola_pcm.c20
-rw-r--r--sound/pci/lx6464es/lx6464es.c112
-rw-r--r--sound/pci/maestro3.c106
-rw-r--r--sound/pci/nm256/nm256.c131
-rw-r--r--sound/pci/oxygen/oxygen.c1
-rw-r--r--sound/pci/oxygen/oxygen.h1
-rw-r--r--sound/pci/oxygen/oxygen_lib.c66
-rw-r--r--sound/pci/oxygen/se6x.c1
-rw-r--r--sound/pci/oxygen/virtuoso.c1
-rw-r--r--sound/pci/pcxhr/pcxhr.c47
-rw-r--r--sound/pci/riptide/riptide.c89
-rw-r--r--sound/pci/rme32.c49
-rw-r--r--sound/pci/rme96.c57
-rw-r--r--sound/pci/rme9652/hdsp.c95
-rw-r--r--sound/pci/rme9652/hdspm.c64
-rw-r--r--sound/pci/rme9652/rme9652.c91
-rw-r--r--sound/pci/sis7019.c87
-rw-r--r--sound/pci/sonicvibes.c117
-rw-r--r--sound/pci/trident/trident.c39
-rw-r--r--sound/pci/trident/trident.h7
-rw-r--r--sound/pci/trident/trident_main.c90
-rw-r--r--sound/pci/trident/trident_memory.c8
-rw-r--r--sound/pci/via82xx.c116
-rw-r--r--sound/pci/via82xx_modem.c88
-rw-r--r--sound/pci/vx222/vx222.c69
-rw-r--r--sound/pci/ymfpci/ymfpci.c66
-rw-r--r--sound/pci/ymfpci/ymfpci.h8
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c149
-rw-r--r--sound/pcmcia/vx/vxpocket.c22
-rw-r--r--sound/soc/amd/Kconfig9
-rw-r--r--sound/soc/amd/Makefile1
-rw-r--r--sound/soc/amd/acp-da7219-max98357a.c12
-rw-r--r--sound/soc/amd/acp-pcm-dma.c20
-rw-r--r--sound/soc/amd/acp3x-rt5682-max9836.c14
-rw-r--r--sound/soc/amd/raven/acp3x-pcm-dma.c10
-rw-r--r--sound/soc/amd/renoir/acp3x-pdm-dma.c8
-rw-r--r--sound/soc/amd/renoir/acp3x-rn.c7
-rw-r--r--sound/soc/amd/vangogh/Makefile9
-rw-r--r--sound/soc/amd/vangogh/acp5x-i2s.c427
-rw-r--r--sound/soc/amd/vangogh/acp5x-pcm-dma.c517
-rw-r--r--sound/soc/amd/vangogh/acp5x.h193
-rw-r--r--sound/soc/amd/vangogh/pci-acp5x.c326
-rw-r--r--sound/soc/amd/vangogh/vg_chip_offset_byte.h337
-rw-r--r--sound/soc/atmel/Kconfig1
-rw-r--r--sound/soc/atmel/mchp-spdifrx.c6
-rw-r--r--sound/soc/atmel/mchp-spdiftx.c2
-rw-r--r--sound/soc/atmel/tse850-pcm5142.c2
-rw-r--r--sound/soc/bcm/bcm63xx-pcm-whistler.c82
-rw-r--r--sound/soc/bcm/cygnus-pcm.c2
-rw-r--r--sound/soc/codecs/Kconfig3
-rw-r--r--sound/soc/codecs/ad193x.c30
-rw-r--r--sound/soc/codecs/ad193x.h4
-rw-r--r--sound/soc/codecs/cs42l42.c28
-rw-r--r--sound/soc/codecs/cx20442.c8
-rw-r--r--sound/soc/codecs/ics43432.c4
-rw-r--r--sound/soc/codecs/lpass-rx-macro.c65
-rw-r--r--sound/soc/codecs/max98090.c4
-rw-r--r--sound/soc/codecs/max98390.c26
-rw-r--r--sound/soc/codecs/max98390.h1
-rw-r--r--sound/soc/codecs/mt6359-accdet.c25
-rw-r--r--sound/soc/codecs/rt1015.c46
-rw-r--r--sound/soc/codecs/rt1015.h2
-rw-r--r--sound/soc/codecs/rt1015p.c2
-rw-r--r--sound/soc/codecs/rt5514.c2
-rw-r--r--sound/soc/codecs/rt5640.c133
-rw-r--r--sound/soc/codecs/rt5640.h6
-rw-r--r--sound/soc/codecs/rt5682-i2c.c15
-rw-r--r--sound/soc/codecs/rt5682.c57
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c10
-rw-r--r--sound/soc/codecs/wcd9335.c23
-rw-r--r--sound/soc/codecs/wcd938x.c854
-rw-r--r--sound/soc/codecs/wcd938x.h1
-rw-r--r--sound/soc/codecs/wm_adsp.c9
-rw-r--r--sound/soc/dwc/dwc-i2s.c2
-rw-r--r--sound/soc/fsl/fsl_asrc_dma.c47
-rw-r--r--sound/soc/fsl/fsl_dma.c50
-rw-r--r--sound/soc/fsl/fsl_rpmsg.c20
-rw-r--r--sound/soc/fsl/fsl_xcvr.c4
-rw-r--r--sound/soc/fsl/imx-pcm-fiq.c75
-rw-r--r--sound/soc/fsl/imx-pcm-rpmsg.c89
-rw-r--r--sound/soc/fsl/imx-rpmsg.c2
-rw-r--r--sound/soc/fsl/mpc5200_dma.c63
-rw-r--r--sound/soc/generic/simple-card-utils.c4
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-pcm.c2
-rw-r--r--sound/soc/intel/atom/sst/sst_ipc.c2
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c31
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c328
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c63
-rw-r--r--sound/soc/intel/boards/kbl_da7219_max98927.c55
-rw-r--r--sound/soc/intel/boards/sof_cs42l42.c361
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.c17
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.h4
-rw-r--r--sound/soc/intel/boards/sof_pcm512x.c13
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c66
-rw-r--r--sound/soc/intel/boards/sof_sdw.c66
-rw-r--r--sound/soc/intel/boards/sof_sdw_common.h64
-rw-r--r--sound/soc/intel/boards/sof_sdw_max98373.c7
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt1308.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt1316.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt5682.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt700.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt711.c51
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt711_sdca.c52
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt715.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt715_sdca.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cml-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-jsl-match.c8
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-kbl-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-tgl-match.c15
-rw-r--r--sound/soc/intel/skylake/skl-messages.c155
-rw-r--r--sound/soc/intel/skylake/skl-pcm.c33
-rw-r--r--sound/soc/intel/skylake/skl-topology.c155
-rw-r--r--sound/soc/intel/skylake/skl-topology.h26
-rw-r--r--sound/soc/mediatek/Kconfig24
-rw-r--r--sound/soc/mediatek/Makefile1
-rw-r--r--sound/soc/mediatek/common/mtk-afe-fe-dai.c22
-rw-r--r--sound/soc/mediatek/common/mtk-base-afe.h10
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-afe-pcm.c43
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-afe-pcm.c27
-rw-r--r--sound/soc/mediatek/mt8195/Makefile15
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-clk.c441
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-clk.h109
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-common.h158
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-pcm.c3281
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-audsys-clk.c214
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-audsys-clk.h15
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-audsys-clkid.h93
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-dai-adda.c830
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-dai-etdm.c2639
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-dai-pcm.c389
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c1087
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-reg.h2796
-rw-r--r--sound/soc/pxa/pxa-ssp.c3
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c3
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c3
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c3
-rw-r--r--sound/soc/qcom/apq8016_sbc.c17
-rw-r--r--sound/soc/qcom/lpass-platform.c60
-rw-r--r--sound/soc/qcom/qdsp6/q6adm.c2
-rw-r--r--sound/soc/qcom/qdsp6/q6asm-dai.c63
-rw-r--r--sound/soc/qcom/qdsp6/q6asm.c2
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c212
-rw-r--r--sound/soc/rockchip/rockchip_i2s.h10
-rw-r--r--sound/soc/rockchip/rockchip_spdif.c38
-rw-r--r--sound/soc/samsung/aries_wm8994.c2
-rw-r--r--sound/soc/samsung/arndale.c4
-rw-r--r--sound/soc/samsung/h1940_uda1380.c2
-rw-r--r--sound/soc/samsung/littlemill.c2
-rw-r--r--sound/soc/samsung/midas_wm1811.c2
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c4
-rw-r--r--sound/soc/samsung/rx1950_uda1380.c2
-rw-r--r--sound/soc/samsung/smartq_wm8987.c2
-rw-r--r--sound/soc/samsung/smdk_wm8580.c2
-rw-r--r--sound/soc/samsung/smdk_wm8994.c2
-rw-r--r--sound/soc/samsung/smdk_wm8994pcm.c2
-rw-r--r--sound/soc/samsung/tm2_wm5110.c6
-rw-r--r--sound/soc/samsung/tobermory.c2
-rw-r--r--sound/soc/sh/Kconfig6
-rw-r--r--sound/soc/sh/Makefile4
-rw-r--r--sound/soc/sh/rcar/adg.c12
-rw-r--r--sound/soc/sh/rcar/core.c6
-rw-r--r--sound/soc/sh/rcar/dma.c2
-rw-r--r--sound/soc/sh/rcar/ssi.c6
-rw-r--r--sound/soc/sh/rz-ssi.c1074
-rw-r--r--sound/soc/soc-ac97.c14
-rw-r--r--sound/soc/soc-component.c4
-rw-r--r--sound/soc/soc-compress.c1
-rw-r--r--sound/soc/soc-core.c36
-rw-r--r--sound/soc/soc-dai.c18
-rw-r--r--sound/soc/soc-dapm.c65
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c9
-rw-r--r--sound/soc/soc-jack.c15
-rw-r--r--sound/soc/soc-ops.c21
-rw-r--r--sound/soc/soc-pcm.c22
-rw-r--r--sound/soc/soc-topology.c23
-rw-r--r--sound/soc/sof/intel/Kconfig10
-rw-r--r--sound/soc/sof/intel/cnl.c6
-rw-r--r--sound/soc/sof/intel/hda-pcm.c16
-rw-r--r--sound/soc/sof/intel/hda-stream.c11
-rw-r--r--sound/soc/sof/intel/hda.c39
-rw-r--r--sound/soc/sof/intel/hda.h8
-rw-r--r--sound/soc/sof/intel/icl.c3
-rw-r--r--sound/soc/sof/intel/pci-tng.c1
-rw-r--r--sound/soc/sof/intel/shim.h3
-rw-r--r--sound/soc/sof/intel/tgl.c12
-rw-r--r--sound/soc/sof/sof-audio.c42
-rw-r--r--sound/soc/sof/sof-pci-dev.c9
-rw-r--r--sound/soc/sprd/sprd-pcm-dma.c67
-rw-r--r--sound/soc/tegra/tegra210_admaif.c6
-rw-r--r--sound/soc/tegra/tegra30_ahub.c6
-rw-r--r--sound/soc/tegra/tegra30_i2s.c8
-rw-r--r--sound/soc/tegra/tegra_pcm.c93
-rw-r--r--sound/soc/tegra/tegra_pcm.h7
-rw-r--r--sound/soc/ti/Kconfig1
-rw-r--r--sound/soc/ti/davinci-mcasp.c176
-rw-r--r--sound/soc/ti/j721e-evm.c30
-rw-r--r--sound/soc/ti/omap-abe-twl6040.c5
-rw-r--r--sound/soc/uniphier/aio-cpu.c4
-rw-r--r--sound/usb/card.c46
-rw-r--r--sound/usb/card.h2
-rw-r--r--sound/usb/clock.c15
-rw-r--r--sound/usb/endpoint.c21
-rw-r--r--sound/usb/format.c6
-rw-r--r--sound/usb/implicit.c6
-rw-r--r--sound/usb/mixer.c10
-rw-r--r--sound/usb/mixer.h3
-rw-r--r--sound/usb/mixer_maps.c22
-rw-r--r--sound/usb/mixer_quirks.c265
-rw-r--r--sound/usb/pcm.c14
-rw-r--r--sound/usb/quirks-table.h70
-rw-r--r--sound/usb/quirks.c361
-rw-r--r--sound/usb/quirks.h5
-rw-r--r--sound/usb/stream.c4
-rw-r--r--sound/usb/usbaudio.h69
-rw-r--r--sound/x86/intel_hdmi_audio.c90
-rw-r--r--sound/x86/intel_hdmi_audio.h1
363 files changed, 23700 insertions, 9452 deletions
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
index c483dcec01f8..bd863bd69501 100644
--- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
+++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
@@ -6,6 +6,7 @@ Required properties:
"ti,da830-mcasp-audio" : for both DA830 & DA850 platforms
"ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, AM43xx, TI81xx)
"ti,dra7-mcasp-audio" : for DRA7xx platforms
+ "ti,omap4-mcasp-audio" : for OMAP4
- reg : Should contain reg specifiers for the entries in the reg-names property.
- reg-names : Should contain:
diff --git a/Documentation/devicetree/bindings/sound/ics43432.txt b/Documentation/devicetree/bindings/sound/ics43432.txt
index b02e3a6c0fef..e6f05f2f6c4e 100644
--- a/Documentation/devicetree/bindings/sound/ics43432.txt
+++ b/Documentation/devicetree/bindings/sound/ics43432.txt
@@ -1,4 +1,4 @@
-Invensense ICS-43432 MEMS microphone with I2S output.
+Invensense ICS-43432-compatible MEMS microphone with I2S output.
There are no software configuration options for this device, indeed, the only
host connection is the I2S interface. Apart from requirements on clock
@@ -8,7 +8,9 @@ contain audio data. A hardware pin determines if the device outputs data
on the left or right channel of the I2S frame.
Required properties:
- - compatible : Must be "invensense,ics43432"
+ - compatible: should be one of the following.
+ "invensense,ics43432": For the Invensense ICS43432
+ "cui,cmm-4030d-261": For the CUI CMM-4030D-261-I2S-TR
Example:
diff --git a/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml b/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml
new file mode 100644
index 000000000000..53e9434a6d9d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml
@@ -0,0 +1,184 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mt8195-afe-pcm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek AFE PCM controller for mt8195
+
+maintainers:
+ - Trevor Wu <trevor.wu@mediatek.com>
+
+properties:
+ compatible:
+ const: mediatek,mt8195-audio
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ mediatek,topckgen:
+ $ref: "/schemas/types.yaml#/definitions/phandle"
+ description: The phandle of the mediatek topckgen controller
+
+ power-domains:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: 26M clock
+ - description: audio pll1 clock
+ - description: audio pll2 clock
+ - description: clock divider for i2si1_mck
+ - description: clock divider for i2si2_mck
+ - description: clock divider for i2so1_mck
+ - description: clock divider for i2so2_mck
+ - description: clock divider for dptx_mck
+ - description: a1sys hoping clock
+ - description: audio intbus clock
+ - description: audio hires clock
+ - description: audio local bus clock
+ - description: mux for dptx_mck
+ - description: mux for i2so1_mck
+ - description: mux for i2so2_mck
+ - description: mux for i2si1_mck
+ - description: mux for i2si2_mck
+ - description: audio infra 26M clock
+ - description: infra bus clock
+
+ clock-names:
+ items:
+ - const: clk26m
+ - const: apll1_ck
+ - const: apll2_ck
+ - const: apll12_div0
+ - const: apll12_div1
+ - const: apll12_div2
+ - const: apll12_div3
+ - const: apll12_div9
+ - const: a1sys_hp_sel
+ - const: aud_intbus_sel
+ - const: audio_h_sel
+ - const: audio_local_bus_sel
+ - const: dptx_m_sel
+ - const: i2so1_m_sel
+ - const: i2so2_m_sel
+ - const: i2si1_m_sel
+ - const: i2si2_m_sel
+ - const: infra_ao_audio_26m_b
+ - const: scp_adsp_audiodsp
+
+ mediatek,etdm-in1-chn-disabled:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ maxItems: 24
+ description: Specify which input channel should be disabled.
+
+ mediatek,etdm-in2-chn-disabled:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ maxItems: 16
+ description: Specify which input channel should be disabled.
+
+patternProperties:
+ "^mediatek,etdm-in[1-2]-mclk-always-on-rate-hz$":
+ description: Specify etdm in mclk output rate for always on case.
+
+ "^mediatek,etdm-out[1-3]-mclk-always-on-rate-hz$":
+ description: Specify etdm out mclk output rate for always on case.
+
+ "^mediatek,etdm-in[1-2]-multi-pin-mode$":
+ type: boolean
+ description: if present, the etdm data mode is I2S.
+
+ "^mediatek,etdm-out[1-3]-multi-pin-mode$":
+ type: boolean
+ description: if present, the etdm data mode is I2S.
+
+ "^mediatek,etdm-in[1-2]-cowork-source$":
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ etdm modules can share the same external clock pin. Specify
+ which etdm clock source is required by this etdm in moudule.
+ enum:
+ - 0 # etdm1_in
+ - 1 # etdm2_in
+ - 2 # etdm1_out
+ - 3 # etdm2_out
+
+ "^mediatek,etdm-out[1-2]-cowork-source$":
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ etdm modules can share the same external clock pin. Specify
+ which etdm clock source is required by this etdm out moudule.
+ enum:
+ - 0 # etdm1_in
+ - 1 # etdm2_in
+ - 2 # etdm1_out
+ - 3 # etdm2_out
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - mediatek,topckgen
+ - power-domains
+ - clocks
+ - clock-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/mt8195-clk.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/power/mt8195-power.h>
+
+ afe: mt8195-afe-pcm@10890000 {
+ compatible = "mediatek,mt8195-audio";
+ reg = <0x10890000 0x10000>;
+ interrupts = <GIC_SPI 822 IRQ_TYPE_LEVEL_HIGH 0>;
+ mediatek,topckgen = <&topckgen>;
+ power-domains = <&spm MT8195_POWER_DOMAIN_AUDIO>;
+ clocks = <&clk26m>,
+ <&topckgen CLK_TOP_APLL1>,
+ <&topckgen CLK_TOP_APLL2>,
+ <&topckgen CLK_TOP_APLL12_DIV0>,
+ <&topckgen CLK_TOP_APLL12_DIV1>,
+ <&topckgen CLK_TOP_APLL12_DIV2>,
+ <&topckgen CLK_TOP_APLL12_DIV3>,
+ <&topckgen CLK_TOP_APLL12_DIV9>,
+ <&topckgen CLK_TOP_A1SYS_HP_SEL>,
+ <&topckgen CLK_TOP_AUD_INTBUS_SEL>,
+ <&topckgen CLK_TOP_AUDIO_H_SEL>,
+ <&topckgen CLK_TOP_AUDIO_LOCAL_BUS_SEL>,
+ <&topckgen CLK_TOP_DPTX_M_SEL>,
+ <&topckgen CLK_TOP_I2SO1_M_SEL>,
+ <&topckgen CLK_TOP_I2SO2_M_SEL>,
+ <&topckgen CLK_TOP_I2SI1_M_SEL>,
+ <&topckgen CLK_TOP_I2SI2_M_SEL>,
+ <&infracfg_ao CLK_INFRA_AO_AUDIO_26M_B>,
+ <&scp_adsp CLK_SCP_ADSP_AUDIODSP>;
+ clock-names = "clk26m",
+ "apll1_ck",
+ "apll2_ck",
+ "apll12_div0",
+ "apll12_div1",
+ "apll12_div2",
+ "apll12_div3",
+ "apll12_div9",
+ "a1sys_hp_sel",
+ "aud_intbus_sel",
+ "audio_h_sel",
+ "audio_local_bus_sel",
+ "dptx_m_sel",
+ "i2so1_m_sel",
+ "i2so2_m_sel",
+ "i2si1_m_sel",
+ "i2si2_m_sel",
+ "infra_ao_audio_26m_b",
+ "scp_adsp_audiodsp";
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml b/Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml
new file mode 100644
index 000000000000..20bc0ffd0e34
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mt8195-mt6359-rt1019-rt5682.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT8195 with MT6359, RT1019 and RT5682 ASoC sound card driver
+
+maintainers:
+ - Trevor Wu <trevor.wu@mediatek.com>
+
+description:
+ This binding describes the MT8195 sound card.
+
+properties:
+ compatible:
+ const: mediatek,mt8195_mt6359_rt1019_rt5682
+
+ mediatek,platform:
+ $ref: "/schemas/types.yaml#/definitions/phandle"
+ description: The phandle of MT8195 ASoC platform.
+
+ mediatek,dptx-codec:
+ $ref: "/schemas/types.yaml#/definitions/phandle"
+ description: The phandle of MT8195 Display Port Tx codec node.
+
+ mediatek,hdmi-codec:
+ $ref: "/schemas/types.yaml#/definitions/phandle"
+ description: The phandle of MT8195 HDMI codec node.
+
+additionalProperties: false
+
+required:
+ - compatible
+ - mediatek,platform
+
+examples:
+ - |
+
+ sound: mt8195-sound {
+ compatible = "mediatek,mt8195_mt6359_rt1019_rt5682";
+ mediatek,platform = <&afe>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&aud_pins_default>;
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/realtek,rt1015p.yaml b/Documentation/devicetree/bindings/sound/realtek,rt1015p.yaml
index 644b68edf3e1..fdb7f295ef2d 100644
--- a/Documentation/devicetree/bindings/sound/realtek,rt1015p.yaml
+++ b/Documentation/devicetree/bindings/sound/realtek,rt1015p.yaml
@@ -15,7 +15,9 @@ description: |
properties:
compatible:
- const: realtek,rt1015p
+ enum:
+ - realtek,rt1015p
+ - realtek,rt1019p
sdb-gpios:
description:
diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
new file mode 100644
index 000000000000..414ff8035a4e
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
@@ -0,0 +1,118 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/renesas,rz-ssi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G2L ASoC Sound Serial Interface (SSIF-2)
+
+maintainers:
+ - Biju Das <biju.das.jz@bp.renesas.com>
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,r9a07g044-ssi # RZ/G2{L,LC}
+ - const: renesas,rz-ssi
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 4
+
+ interrupt-names:
+ items:
+ - const: int_req
+ - const: dma_rx
+ - const: dma_tx
+ - const: dma_rt
+
+ clocks:
+ maxItems: 4
+
+ clock-names:
+ items:
+ - const: ssi
+ - const: ssi_sfr
+ - const: audio_clk1
+ - const: audio_clk2
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+ dmas:
+ minItems: 1
+ maxItems: 2
+ description:
+ The first cell represents a phandle to dmac
+ The second cell specifies the encoded MID/RID values of the SSI port
+ connected to the DMA client and the slave channel configuration
+ parameters.
+ bits[0:9] - Specifies MID/RID value of a SSI channel as below
+ MID/RID value of SSI rx0 = 0x256
+ MID/RID value of SSI tx0 = 0x255
+ MID/RID value of SSI rx1 = 0x25a
+ MID/RID value of SSI tx1 = 0x259
+ MID/RID value of SSI rt2 = 0x25f
+ MID/RID value of SSI rx3 = 0x262
+ MID/RID value of SSI tx3 = 0x261
+ bit[10] - HIEN = 1, Detects a request in response to the rising edge
+ of the signal
+ bit[11] - LVL = 0, Detects based on the edge
+ bits[12:14] - AM = 2, Bus cycle mode
+ bit[15] - TM = 0, Single transfer mode
+
+ dma-names:
+ oneOf:
+ - items:
+ - const: tx
+ - const: rx
+ - items:
+ - const: rt
+
+ '#sound-dai-cells':
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-names
+ - clocks
+ - clock-names
+ - resets
+ - '#sound-dai-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/r9a07g044-cpg.h>
+
+ ssi0: ssi@10049c00 {
+ compatible = "renesas,r9a07g044-ssi",
+ "renesas,rz-ssi";
+ reg = <0x10049c00 0x400>;
+ interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 327 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 329 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt";
+ clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>,
+ <&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>,
+ <&audio_clk1>,
+ <&audio_clk2>;
+ clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
+ power-domains = <&cpg>;
+ resets = <&cpg R9A07G044_SSI0_RST_M2_REG>;
+ dmas = <&dmac 0x2655>,
+ <&dmac 0x2656>;
+ dma-names = "tx", "rx";
+ #sound-dai-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
index 245895b58a2f..5ea16b8ef93f 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
@@ -20,7 +20,9 @@ properties:
- items:
- enum:
- rockchip,px30-i2s
+ - rockchip,rk1808-i2s
- rockchip,rk3036-i2s
+ - rockchip,rk3128-i2s
- rockchip,rk3188-i2s
- rockchip,rk3228-i2s
- rockchip,rk3288-i2s
@@ -29,6 +31,7 @@ properties:
- rockchip,rk3366-i2s
- rockchip,rk3368-i2s
- rockchip,rk3399-i2s
+ - rockchip,rv1126-i2s
- const: rockchip,rk3066-i2s
reg:
@@ -61,6 +64,14 @@ properties:
power-domains:
maxItems: 1
+ reset-names:
+ items:
+ - const: reset-m
+ - const: reset-h
+
+ resets:
+ maxItems: 2
+
rockchip,capture-channels:
$ref: /schemas/types.yaml#/definitions/uint32
default: 2
diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
index 62a61b68dfef..d0a24bf928d6 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
+++ b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
@@ -23,6 +23,7 @@ properties:
- const: rockchip,rk3366-spdif
- const: rockchip,rk3368-spdif
- const: rockchip,rk3399-spdif
+ - const: rockchip,rk3568-spdif
- items:
- enum:
- rockchip,rk3188-spdif
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 07fb0d25fc15..ed4f66ec9a65 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -271,6 +271,8 @@ patternProperties:
description: Shenzen Chuangsiqi Technology Co.,Ltd.
"^cubietech,.*":
description: Cubietech, Ltd.
+ "^cui,.*":
+ description: CUI Devices
"^cypress,.*":
description: Cypress Semiconductor Corporation
"^cznic,.*":
diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst
index b36af65a08ed..65f61695f561 100644
--- a/Documentation/sound/alsa-configuration.rst
+++ b/Documentation/sound/alsa-configuration.rst
@@ -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
--------------------
diff --git a/Documentation/sound/hd-audio/notes.rst b/Documentation/sound/hd-audio/notes.rst
index cf4d7158af78..d118b6fe269b 100644
--- a/Documentation/sound/hd-audio/notes.rst
+++ b/Documentation/sound/hd-audio/notes.rst
@@ -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
----------------------------
diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
index 01d59b8aea92..255b7d3bebd6 100644
--- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
+++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
@@ -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
=====================================
diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index f66fcbc33a2f..78037ffdb09b 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -41,80 +41,6 @@ static int md_flags;
module_param_named(sdw_md_flags, md_flags, int, 0444);
MODULE_PARM_DESC(sdw_md_flags, "SoundWire Intel Master device flags (0x0 all off)");
-/* Intel SHIM Registers Definition */
-#define SDW_SHIM_LCAP 0x0
-#define SDW_SHIM_LCTL 0x4
-#define SDW_SHIM_IPPTR 0x8
-#define SDW_SHIM_SYNC 0xC
-
-#define SDW_SHIM_CTLSCAP(x) (0x010 + 0x60 * (x))
-#define SDW_SHIM_CTLS0CM(x) (0x012 + 0x60 * (x))
-#define SDW_SHIM_CTLS1CM(x) (0x014 + 0x60 * (x))
-#define SDW_SHIM_CTLS2CM(x) (0x016 + 0x60 * (x))
-#define SDW_SHIM_CTLS3CM(x) (0x018 + 0x60 * (x))
-#define SDW_SHIM_PCMSCAP(x) (0x020 + 0x60 * (x))
-
-#define SDW_SHIM_PCMSYCHM(x, y) (0x022 + (0x60 * (x)) + (0x2 * (y)))
-#define SDW_SHIM_PCMSYCHC(x, y) (0x042 + (0x60 * (x)) + (0x2 * (y)))
-#define SDW_SHIM_PDMSCAP(x) (0x062 + 0x60 * (x))
-#define SDW_SHIM_IOCTL(x) (0x06C + 0x60 * (x))
-#define SDW_SHIM_CTMCTL(x) (0x06E + 0x60 * (x))
-
-#define SDW_SHIM_WAKEEN 0x190
-#define SDW_SHIM_WAKESTS 0x192
-
-#define SDW_SHIM_LCTL_SPA BIT(0)
-#define SDW_SHIM_LCTL_SPA_MASK GENMASK(3, 0)
-#define SDW_SHIM_LCTL_CPA BIT(8)
-#define SDW_SHIM_LCTL_CPA_MASK GENMASK(11, 8)
-
-#define SDW_SHIM_SYNC_SYNCPRD_VAL_24 (24000 / SDW_CADENCE_GSYNC_KHZ - 1)
-#define SDW_SHIM_SYNC_SYNCPRD_VAL_38_4 (38400 / SDW_CADENCE_GSYNC_KHZ - 1)
-#define SDW_SHIM_SYNC_SYNCPRD GENMASK(14, 0)
-#define SDW_SHIM_SYNC_SYNCCPU BIT(15)
-#define SDW_SHIM_SYNC_CMDSYNC_MASK GENMASK(19, 16)
-#define SDW_SHIM_SYNC_CMDSYNC BIT(16)
-#define SDW_SHIM_SYNC_SYNCGO BIT(24)
-
-#define SDW_SHIM_PCMSCAP_ISS GENMASK(3, 0)
-#define SDW_SHIM_PCMSCAP_OSS GENMASK(7, 4)
-#define SDW_SHIM_PCMSCAP_BSS GENMASK(12, 8)
-
-#define SDW_SHIM_PCMSYCM_LCHN GENMASK(3, 0)
-#define SDW_SHIM_PCMSYCM_HCHN GENMASK(7, 4)
-#define SDW_SHIM_PCMSYCM_STREAM GENMASK(13, 8)
-#define SDW_SHIM_PCMSYCM_DIR BIT(15)
-
-#define SDW_SHIM_PDMSCAP_ISS GENMASK(3, 0)
-#define SDW_SHIM_PDMSCAP_OSS GENMASK(7, 4)
-#define SDW_SHIM_PDMSCAP_BSS GENMASK(12, 8)
-#define SDW_SHIM_PDMSCAP_CPSS GENMASK(15, 13)
-
-#define SDW_SHIM_IOCTL_MIF BIT(0)
-#define SDW_SHIM_IOCTL_CO BIT(1)
-#define SDW_SHIM_IOCTL_COE BIT(2)
-#define SDW_SHIM_IOCTL_DO BIT(3)
-#define SDW_SHIM_IOCTL_DOE BIT(4)
-#define SDW_SHIM_IOCTL_BKE BIT(5)
-#define SDW_SHIM_IOCTL_WPDD BIT(6)
-#define SDW_SHIM_IOCTL_CIBD BIT(8)
-#define SDW_SHIM_IOCTL_DIBD BIT(9)
-
-#define SDW_SHIM_CTMCTL_DACTQE BIT(0)
-#define SDW_SHIM_CTMCTL_DODS BIT(1)
-#define SDW_SHIM_CTMCTL_DOAIS GENMASK(4, 3)
-
-#define SDW_SHIM_WAKEEN_ENABLE BIT(0)
-#define SDW_SHIM_WAKESTS_STATUS BIT(0)
-
-/* Intel ALH Register definitions */
-#define SDW_ALH_STRMZCFG(x) (0x000 + (0x4 * (x)))
-#define SDW_ALH_NUM_STREAMS 64
-
-#define SDW_ALH_STRMZCFG_DMAT_VAL 0x3
-#define SDW_ALH_STRMZCFG_DMAT GENMASK(7, 0)
-#define SDW_ALH_STRMZCFG_CHN GENMASK(19, 16)
-
enum intel_pdi_type {
INTEL_PDI_IN = 0,
INTEL_PDI_OUT = 1,
diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c
index 9e283bef53d2..e329022e1669 100644
--- a/drivers/soundwire/intel_init.c
+++ b/drivers/soundwire/intel_init.c
@@ -18,12 +18,6 @@
#include "cadence_master.h"
#include "intel.h"
-#define SDW_SHIM_LCAP 0x0
-#define SDW_SHIM_BASE 0x2C000
-#define SDW_ALH_BASE 0x2C800
-#define SDW_LINK_BASE 0x30000
-#define SDW_LINK_SIZE 0x10000
-
static void intel_link_dev_release(struct device *dev)
{
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
@@ -69,8 +63,8 @@ static struct sdw_intel_link_dev *intel_link_dev_register(struct sdw_intel_res *
link->mmio_base = res->mmio_base;
link->registers = res->mmio_base + SDW_LINK_BASE
+ (SDW_LINK_SIZE * link_id);
- link->shim = res->mmio_base + SDW_SHIM_BASE;
- link->alh = res->mmio_base + SDW_ALH_BASE;
+ link->shim = res->mmio_base + res->shim_base;
+ link->alh = res->mmio_base + res->alh_base;
link->ops = res->ops;
link->dev = res->dev;
@@ -220,6 +214,8 @@ static struct sdw_intel_ctx
}
ctx->mmio_base = res->mmio_base;
+ ctx->shim_base = res->shim_base;
+ ctx->alh_base = res->alh_base;
ctx->link_mask = res->link_mask;
ctx->handle = res->handle;
mutex_init(&ctx->shim_lock);
@@ -308,7 +304,7 @@ sdw_intel_startup_controller(struct sdw_intel_ctx *ctx)
return -EINVAL;
/* Check SNDWLCAP.LCOUNT */
- caps = ioread32(ctx->mmio_base + SDW_SHIM_BASE + SDW_SHIM_LCAP);
+ caps = ioread32(ctx->mmio_base + ctx->shim_base + SDW_SHIM_LCAP);
caps &= GENMASK(2, 0);
/* Check HW supported vs property value */
diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h
index 5d1fb0d78a22..76b13ef67562 100644
--- a/include/linux/platform_data/davinci_asp.h
+++ b/include/linux/platform_data/davinci_asp.h
@@ -96,6 +96,7 @@ enum {
MCASP_VERSION_2, /* DA8xx/OMAPL1x */
MCASP_VERSION_3, /* TI81xx/AM33xx */
MCASP_VERSION_4, /* DRA7xxx */
+ MCASP_VERSION_OMAP, /* OMAP4/5 */
};
enum mcbsp_clk_input_pin {
diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h
index 1ebea7764011..8a463b8fc12a 100644
--- a/include/linux/soundwire/sdw_intel.h
+++ b/include/linux/soundwire/sdw_intel.h
@@ -7,6 +7,85 @@
#include <linux/irqreturn.h>
#include <linux/soundwire/sdw.h>
+#define SDW_SHIM_BASE 0x2C000
+#define SDW_ALH_BASE 0x2C800
+#define SDW_LINK_BASE 0x30000
+#define SDW_LINK_SIZE 0x10000
+
+/* Intel SHIM Registers Definition */
+#define SDW_SHIM_LCAP 0x0
+#define SDW_SHIM_LCTL 0x4
+#define SDW_SHIM_IPPTR 0x8
+#define SDW_SHIM_SYNC 0xC
+
+#define SDW_SHIM_CTLSCAP(x) (0x010 + 0x60 * (x))
+#define SDW_SHIM_CTLS0CM(x) (0x012 + 0x60 * (x))
+#define SDW_SHIM_CTLS1CM(x) (0x014 + 0x60 * (x))
+#define SDW_SHIM_CTLS2CM(x) (0x016 + 0x60 * (x))
+#define SDW_SHIM_CTLS3CM(x) (0x018 + 0x60 * (x))
+#define SDW_SHIM_PCMSCAP(x) (0x020 + 0x60 * (x))
+
+#define SDW_SHIM_PCMSYCHM(x, y) (0x022 + (0x60 * (x)) + (0x2 * (y)))
+#define SDW_SHIM_PCMSYCHC(x, y) (0x042 + (0x60 * (x)) + (0x2 * (y)))
+#define SDW_SHIM_PDMSCAP(x) (0x062 + 0x60 * (x))
+#define SDW_SHIM_IOCTL(x) (0x06C + 0x60 * (x))
+#define SDW_SHIM_CTMCTL(x) (0x06E + 0x60 * (x))
+
+#define SDW_SHIM_WAKEEN 0x190
+#define SDW_SHIM_WAKESTS 0x192
+
+#define SDW_SHIM_LCTL_SPA BIT(0)
+#define SDW_SHIM_LCTL_SPA_MASK GENMASK(3, 0)
+#define SDW_SHIM_LCTL_CPA BIT(8)
+#define SDW_SHIM_LCTL_CPA_MASK GENMASK(11, 8)
+
+#define SDW_SHIM_SYNC_SYNCPRD_VAL_24 (24000 / SDW_CADENCE_GSYNC_KHZ - 1)
+#define SDW_SHIM_SYNC_SYNCPRD_VAL_38_4 (38400 / SDW_CADENCE_GSYNC_KHZ - 1)
+#define SDW_SHIM_SYNC_SYNCPRD GENMASK(14, 0)
+#define SDW_SHIM_SYNC_SYNCCPU BIT(15)
+#define SDW_SHIM_SYNC_CMDSYNC_MASK GENMASK(19, 16)
+#define SDW_SHIM_SYNC_CMDSYNC BIT(16)
+#define SDW_SHIM_SYNC_SYNCGO BIT(24)
+
+#define SDW_SHIM_PCMSCAP_ISS GENMASK(3, 0)
+#define SDW_SHIM_PCMSCAP_OSS GENMASK(7, 4)
+#define SDW_SHIM_PCMSCAP_BSS GENMASK(12, 8)
+
+#define SDW_SHIM_PCMSYCM_LCHN GENMASK(3, 0)
+#define SDW_SHIM_PCMSYCM_HCHN GENMASK(7, 4)
+#define SDW_SHIM_PCMSYCM_STREAM GENMASK(13, 8)
+#define SDW_SHIM_PCMSYCM_DIR BIT(15)
+
+#define SDW_SHIM_PDMSCAP_ISS GENMASK(3, 0)
+#define SDW_SHIM_PDMSCAP_OSS GENMASK(7, 4)
+#define SDW_SHIM_PDMSCAP_BSS GENMASK(12, 8)
+#define SDW_SHIM_PDMSCAP_CPSS GENMASK(15, 13)
+
+#define SDW_SHIM_IOCTL_MIF BIT(0)
+#define SDW_SHIM_IOCTL_CO BIT(1)
+#define SDW_SHIM_IOCTL_COE BIT(2)
+#define SDW_SHIM_IOCTL_DO BIT(3)
+#define SDW_SHIM_IOCTL_DOE BIT(4)
+#define SDW_SHIM_IOCTL_BKE BIT(5)
+#define SDW_SHIM_IOCTL_WPDD BIT(6)
+#define SDW_SHIM_IOCTL_CIBD BIT(8)
+#define SDW_SHIM_IOCTL_DIBD BIT(9)
+
+#define SDW_SHIM_CTMCTL_DACTQE BIT(0)
+#define SDW_SHIM_CTMCTL_DODS BIT(1)
+#define SDW_SHIM_CTMCTL_DOAIS GENMASK(4, 3)
+
+#define SDW_SHIM_WAKEEN_ENABLE BIT(0)
+#define SDW_SHIM_WAKESTS_STATUS BIT(0)
+
+/* Intel ALH Register definitions */
+#define SDW_ALH_STRMZCFG(x) (0x000 + (0x4 * (x)))
+#define SDW_ALH_NUM_STREAMS 64
+
+#define SDW_ALH_STRMZCFG_DMAT_VAL 0x3
+#define SDW_ALH_STRMZCFG_DMAT GENMASK(7, 0)
+#define SDW_ALH_STRMZCFG_CHN GENMASK(19, 16)
+
/**
* struct sdw_intel_stream_params_data: configuration passed during
* the @params_stream callback, e.g. for interaction with DSP
@@ -116,6 +195,8 @@ struct sdw_intel_slave_id {
* @link_list: list to handle interrupts across all links
* @shim_lock: mutex to handle concurrent rmw access to shared SHIM registers.
* @shim_mask: flags to track initialization of SHIM shared registers
+ * @shim_base: sdw shim base.
+ * @alh_base: sdw alh base.
*/
struct sdw_intel_ctx {
int count;
@@ -128,6 +209,8 @@ struct sdw_intel_ctx {
struct list_head link_list;
struct mutex shim_lock; /* lock for access to shared SHIM registers */
u32 shim_mask;
+ u32 shim_base;
+ u32 alh_base;
};
/**
@@ -146,6 +229,8 @@ struct sdw_intel_ctx {
* machine-specific quirks are handled in the DSP driver.
* @clock_stop_quirks: mask array of possible behaviors requested by the
* DSP driver. The quirks are common for all links for now.
+ * @shim_base: sdw shim base.
+ * @alh_base: sdw alh base.
*/
struct sdw_intel_res {
int count;
@@ -157,6 +242,8 @@ struct sdw_intel_res {
struct device *dev;
u32 link_mask;
u32 clock_stop_quirks;
+ u32 shim_base;
+ u32 alh_base;
};
/*
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
index 277087f635f3..d91289c6f00e 100644
--- a/include/sound/compress_driver.h
+++ b/include/sound/compress_driver.h
@@ -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);
diff --git a/include/sound/core.h b/include/sound/core.h
index c4ade121727d..b7e9b58d3c78 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -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 */
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 468e38c54dd3..39787fecc8d9 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -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);
diff --git a/include/sound/emu8000.h b/include/sound/emu8000.h
index ad0365d6de5e..072791bbcf5c 100644
--- a/include/sound/emu8000.h
+++ b/include/sound/emu8000.h
@@ -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;
diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h
index 2e8d51937acd..01570dbda503 100644
--- a/include/sound/hda_codec.h
+++ b/include/sound/hda_codec.h
@@ -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);
};
diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h
index a125e3814b58..375581634143 100644
--- a/include/sound/hdaudio_ext.h
+++ b/include/sound/hdaudio_ext.h
@@ -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;
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
index 44d87775b352..b197e3f431c1 100644
--- a/include/sound/memalloc.h
+++ b/include/sound/memalloc.h
@@ -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 */
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 938f36050a5e..33451f8ff755 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -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);
diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h
index 0feaf16e6ac0..95100cff25d1 100644
--- a/include/sound/pxa2xx-lib.h
+++ b/include/sound/pxa2xx-lib.h
@@ -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 */
diff --git a/include/sound/sof.h b/include/sound/sof.h
index 502ed9b8d6a1..6a1cd8e783d8 100644
--- a/include/sound/sof.h
+++ b/include/sound/sof.h
@@ -101,5 +101,6 @@ struct sof_dev_desc {
};
int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd);
+int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd);
#endif
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index d17c061950df..1d84ec9db93b 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -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 */
diff --git a/include/uapi/sound/snd_sst_tokens.h b/include/uapi/sound/snd_sst_tokens.h
index 8ba0112e5336..ff3748e9308a 100644
--- a/include/uapi/sound/snd_sst_tokens.h
+++ b/include/uapi/sound/snd_sst_tokens.h
@@ -233,6 +233,8 @@
*
* %SKL_TKN_U32_ASTATE_CLK_SRC: Clock source for A-State entry
*
+ * %SKL_TKN_U32_FMT_CFG_IDX: Format config index
+ *
* module_id and loadable flags dont have tokens as these values will be
* read from the DSP FW manifest
*
@@ -324,7 +326,9 @@ enum SKL_TKNS {
SKL_TKN_U32_ASTATE_COUNT,
SKL_TKN_U32_ASTATE_KCPS,
SKL_TKN_U32_ASTATE_CLK_SRC,
- SKL_TKN_MAX = SKL_TKN_U32_ASTATE_CLK_SRC,
+
+ SKL_TKN_U32_FMT_CFG_IDX = 96,
+ SKL_TKN_MAX = SKL_TKN_U32_FMT_CFG_IDX,
};
#endif
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index a67e6685b00c..c17a19fe59ed 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -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;
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c
index e81083e1bc68..0a48805e513a 100644
--- a/sound/arm/pxa2xx-pcm-lib.c
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -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");
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 21ce4c056a92..de514ec8c83d 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -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");
diff --git a/sound/core/control_led.c b/sound/core/control_led.c
index 764058cc345d..a95332b2b90b 100644
--- a/sound/core/control_led.c
+++ b/sound/core/control_led.c
@@ -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;
}
diff --git a/sound/core/init.c b/sound/core/init.c
index 1490568efdb0..ac335f5906c6 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -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);
diff --git a/sound/core/isadma.c b/sound/core/isadma.c
index c3d789ef6975..1f45ede023b4 100644
--- a/sound/core/isadma.c
+++ b/sound/core/isadma.c
@@ -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);
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 439a358ecfe9..c7c943c661e6 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -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
};
diff --git a/sound/core/memalloc_local.h b/sound/core/memalloc_local.h
index dbea7f2aed07..9f2e0a608b49 100644
--- a/sound/core/memalloc_local.h
+++ b/sound/core/memalloc_local.h
@@ -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);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 7d5883432085..a144a3f68e9e 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -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;
}
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index d7621ed105bd..7fbd1ccbb5b0 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -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;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 71323d807dbf..d233cb3b41d8 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -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.
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index ac760b1e3d12..8c18d8c4177e 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -20,15 +20,15 @@
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
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c
index 232cf3f1bcb3..8352a5cdb19f 100644
--- a/sound/core/sgbuf.c
+++ b/sound/core/sgbuf.c
@@ -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,
};
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 7141f73cddd3..ca4cdf666f82 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -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).
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 80b814b9922a..9b4a7cdb103a 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -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,
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 01a3eab50d7b..2a7fc49c1a7c 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -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,
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index d0b55dbb411a..3398aee33baa 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -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;
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index 0e95b08d34d6..11235baaf6fa 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -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,
},
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index 7689fa2f9531..c7be1c395bcb 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -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,
};
diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c
index e79603fe743d..5a799f7f00a2 100644
--- a/sound/drivers/pcsp/pcsp_input.c
+++ b/sound/drivers/pcsp/pcsp_input.c
@@ -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;
-}
diff --git a/sound/drivers/pcsp/pcsp_input.h b/sound/drivers/pcsp/pcsp_input.h
index e80079b38a56..42bfc9eab6eb 100644
--- a/sound/drivers/pcsp/pcsp_input.h
+++ b/sound/drivers/pcsp/pcsp_input.h
@@ -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
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index da9983cba01c..3cbc7a4adcb4 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -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,
},
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index 4206d93ab47e..7f7eed6faaae 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -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,
},
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index a10449af5a76..18901e5bcfcf 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -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;
diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c
index 93d5df1ae550..2bd4485e4bc7 100644
--- a/sound/firewire/motu/motu-protocol-v2.c
+++ b/sound/firewire/motu/motu-protocol-v2.c
@@ -12,11 +12,11 @@
#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,
diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c
index 543136578c70..f65426238d4c 100644
--- a/sound/firewire/motu/motu.c
+++ b/sound/firewire/motu/motu.c
@@ -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),
diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h
index 73f36d1be515..f1a830b358d4 100644
--- a/sound/firewire/motu/motu.h
+++ b/sound/firewire/motu/motu.h
@@ -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;
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index fa5bed0d5a6f..9ac873773129 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -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,
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index 6d4999b30461..132a095dca2c 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -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;
}
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index edafb49797e7..c471ac2aa450 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -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,
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
index e6cd7c4da38e..f079ba4ef1a0 100644
--- a/sound/isa/adlib.c
+++ b/sound/isa/adlib.c
@@ -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
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index d4597fdfe091..d582eff64082 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -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,
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
index dd5c059b3744..761cd198df2b 100644
--- a/sound/isa/azt2320.c
+++ b/sound/isa/azt2320.c
@@ -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,
diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c
index 3b9fbb02864b..8902cfb830f7 100644
--- a/sound/isa/cmi8328.c
+++ b/sound/isa/cmi8328.c
@@ -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
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index ef6d0a20efd8..f209b16c5229 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -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,
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index ec054b929214..1e8923385366 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -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,
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 0b7fd17f8ecc..b6bdebd9ef27 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -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,
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
index 63957aea456b..35f25911adcf 100644
--- a/sound/isa/cs423x/cs4236_lib.c
+++ b/sound/isa/cs423x/cs4236_lib.c
@@ -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);
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 750d4995634f..f935b56eeec7 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -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;
}
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 68b9c59e1127..3fcd168480b6 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -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,
diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c
index d33d69f29924..ea001c80149d 100644
--- a/sound/isa/galaxy/galaxy.c
+++ b/sound/isa/galaxy/galaxy.c
@@ -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
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index 3b46490271fe..ae1e2542ee4a 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -87,24 +87,10 @@ static void snd_gus_init_control(struct snd_gus_card *gus)
static int snd_gus_free(struct snd_gus_card *gus)
{
- if (gus->gf1.res_port2 == NULL)
- goto __hw_end;
- snd_gf1_stop(gus);
- snd_gus_init_dma_irq(gus, 0);
- __hw_end:
- release_and_free_resource(gus->gf1.res_port1);
- release_and_free_resource(gus->gf1.res_port2);
- if (gus->gf1.irq >= 0)
- free_irq(gus->gf1.irq, (void *) gus);
- if (gus->gf1.dma1 >= 0) {
- disable_dma(gus->gf1.dma1);
- free_dma(gus->gf1.dma1);
+ if (gus->gf1.res_port2) {
+ snd_gf1_stop(gus);
+ snd_gus_init_dma_irq(gus, 0);
}
- if (!gus->equal_dma && gus->gf1.dma2 >= 0) {
- disable_dma(gus->gf1.dma2);
- free_dma(gus->gf1.dma2);
- }
- kfree(gus);
return 0;
}
@@ -130,7 +116,7 @@ int snd_gus_create(struct snd_card *card,
};
*rgus = NULL;
- gus = kzalloc(sizeof(*gus), GFP_KERNEL);
+ gus = devm_kzalloc(card->dev, sizeof(*gus), GFP_KERNEL);
if (gus == NULL)
return -ENOMEM;
spin_lock_init(&gus->reg_lock);
@@ -156,35 +142,33 @@ int snd_gus_create(struct snd_card *card,
gus->gf1.reg_timerctrl = GUSP(gus, TIMERCNTRL);
gus->gf1.reg_timerdata = GUSP(gus, TIMERDATA);
/* allocate resources */
- gus->gf1.res_port1 = request_region(port, 16, "GUS GF1 (Adlib/SB)");
+ gus->gf1.res_port1 = devm_request_region(card->dev, port, 16,
+ "GUS GF1 (Adlib/SB)");
if (!gus->gf1.res_port1) {
snd_printk(KERN_ERR "gus: can't grab SB port 0x%lx\n", port);
- snd_gus_free(gus);
return -EBUSY;
}
- gus->gf1.res_port2 = request_region(port + 0x100, 12, "GUS GF1 (Synth)");
+ gus->gf1.res_port2 = devm_request_region(card->dev, port + 0x100, 12,
+ "GUS GF1 (Synth)");
if (!gus->gf1.res_port2) {
snd_printk(KERN_ERR "gus: can't grab synth port 0x%lx\n", port + 0x100);
- snd_gus_free(gus);
return -EBUSY;
}
- if (irq >= 0 && request_irq(irq, snd_gus_interrupt, 0, "GUS GF1", (void *) gus)) {
+ if (irq >= 0 && devm_request_irq(card->dev, irq, snd_gus_interrupt, 0,
+ "GUS GF1", (void *) gus)) {
snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq);
- snd_gus_free(gus);
return -EBUSY;
}
gus->gf1.irq = irq;
card->sync_irq = irq;
- if (request_dma(dma1, "GUS - 1")) {
+ if (snd_devm_request_dma(card->dev, dma1, "GUS - 1")) {
snd_printk(KERN_ERR "gus: can't grab DMA1 %d\n", dma1);
- snd_gus_free(gus);
return -EBUSY;
}
gus->gf1.dma1 = dma1;
if (dma2 >= 0 && dma1 != dma2) {
- if (request_dma(dma2, "GUS - 2")) {
+ if (snd_devm_request_dma(card->dev, dma2, "GUS - 2")) {
snd_printk(KERN_ERR "gus: can't grab DMA2 %d\n", dma2);
- snd_gus_free(gus);
return -EBUSY;
}
gus->gf1.dma2 = dma2;
@@ -209,10 +193,8 @@ int snd_gus_create(struct snd_card *card,
gus->gf1.volume_ramp = 25;
gus->gf1.smooth_pan = 1;
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops);
- if (err < 0) {
- snd_gus_free(gus);
+ if (err < 0)
return err;
- }
*rgus = gus;
return 0;
}
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index bca1caa4968c..09cc53ceea2a 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -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
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index a409a4a29afc..63d9f2d75df0 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -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,
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index ad118d462142..6834c0560064 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -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
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 755de47d0bb6..20f490e9d563 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -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,14 +607,13 @@ 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;
}
@@ -671,8 +659,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;
}
@@ -779,10 +767,8 @@ static int snd_interwave_isa_probe1(int dev, struct device *devptr)
return err;
err = snd_interwave_probe(card, dev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
dev_set_drvdata(devptr, card);
return 0;
}
@@ -843,15 +829,9 @@ static int snd_interwave_isa_probe(struct device *pdev,
}
}
-static void snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
-{
- snd_card_free(dev_get_drvdata(devptr));
-}
-
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
@@ -878,32 +858,21 @@ 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);
+ 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 */
};
diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c
index 4fbc22a5bc5a..c3fd1eb301bb 100644
--- a/sound/isa/msnd/msnd.c
+++ b/sound/isa/msnd/msnd.c
@@ -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,
};
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
index 69647b41300d..4433a92f08e7 100644
--- a/sound/isa/msnd/msnd_pinnacle.c
+++ b/sound/isa/msnd/msnd_pinnacle.c
@@ -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 */
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 6f42f869928c..bad1490a66a0 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -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,
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index e1fb7567fdcc..59242baed576 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -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;
}
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 4bd1dc6707fc..4beeb32fe2a7 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -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;
}
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 5e4187940265..e02029677743 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -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) {
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
index 7ba5dd1ec810..64936c917170 100644
--- a/sound/isa/sb/jazz16.c
+++ b/sound/isa/sb/jazz16.c
@@ -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,
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index d0f797c02841..e89b095aa282 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -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,
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index b08e6e7690c9..e5ef1777161f 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -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,
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index 57121218ed24..c0e319d14210 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -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;
}
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
index 3462663050bb..26ab7ff80768 100644
--- a/sound/isa/sc6000.c
+++ b/sound/isa/sc6000.c
@@ -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,
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index e70ef9aee545..0bc0025f7c19 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -328,17 +328,6 @@ static void activate_ad1845_unsafe(unsigned io_base)
}
/*
- * 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 */
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index dfdeaf7b6bf4..e6e46a0266b0 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -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 */
};
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 743e0f05e335..026061b55ee9 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -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;
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index 1440db8b4177..ec4fda324760 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -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,
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 5c78951dd596..bba4dae8dcc7 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -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);
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 0d66b92466d5..92eb59db106d 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -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,
},
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 668008fc21f7..b86565dcdbe4 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -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,
},
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 509f317ee682..535eccd124be 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -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,
},
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 5f8aa35c4bea..b8e035d5930d 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -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,
},
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 9739c3a82777..178dce8ef1e9 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -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,
},
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 1f7fee470266..342ef2a6655e 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -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);
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index 43396849a01c..d56f126d6fdd 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -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)
{
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 4ee7ab409807..089050470ff2 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -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,
},
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 39bcfb81e81c..d23f93163841 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -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)
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index 62a22ca3b9de..f246e6094289 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -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;
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 99778711006a..36fb150b72fb 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -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,
},
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index f44f118aacad..ea20236f35db 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -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,
},
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index e122a168c148..e7367402b84a 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -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,
},
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 358ca84cbdea..bd60308769ff 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -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,
diff --git a/sound/pci/cs46xx/cs46xx.h b/sound/pci/cs46xx/cs46xx.h
index b275df883d06..c4f0a0b94270 100644
--- a/sound/pci/cs46xx/cs46xx.h
+++ b/sound/pci/cs46xx/cs46xx.h
@@ -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);
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 1e1eb17f8e07..62f45847b351 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -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;
}
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c
index 20b4faea50a6..93ff029e6583 100644
--- a/sound/pci/cs5530.c
+++ b/sound/pci/cs5530.c
@@ -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);
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index e048b45d9e7e..499fa0148f9a 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -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,
diff --git a/sound/pci/cs5535audio/cs5535audio_olpc.c b/sound/pci/cs5535audio/cs5535audio_olpc.c
index 110d3209441b..122170a410d9 100644
--- a/sound/pci/cs5535audio/cs5535audio_olpc.c
+++ b/sound/pci/cs5535audio/cs5535audio_olpc.c
@@ -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);
}
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index a62e5581ad14..25b012ef5c3e 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -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,
},
diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h
index 0afe13f7b6e5..d51de3e4edfa 100644
--- a/sound/pci/echoaudio/echoaudio.h
+++ b/sound/pci/echoaudio/echoaudio.h
@@ -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;
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 887bfb3c1e17..672af4b9597b 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -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,
},
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 24a2fd706d69..86cc1ca025e4 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -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
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 89b0f3884067..c49c44dc1082 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -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);
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index ff2a3974c824..18a1b0740e6b 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -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;
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 728b69dad21b..2651f0c64c06 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -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,
},
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 33b1eb347a27..00b976f42a3d 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -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,
},
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index c038c1035c39..6a8a02a9ecf4 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -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,
},
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index ed9dae87145b..9c22ff19e56d 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -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,
},
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index c4360cdbc728..ab9d2746e804 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -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
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index b57432f00056..b8fa682ce66a 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -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
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 1a001ecf7f63..4a854475a0e6 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -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);
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c
index e8dee24c309d..2523b23389e9 100644
--- a/sound/pci/hda/hda_bind.c
+++ b/sound/pci/hda/hda_bind.c
@@ -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,
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 7a717e151156..a9ebefd60cf6 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -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
*/
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index ca2f2ecd1488..7cd452831fd3 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -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;
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h
index 68f9668788ea..3062f87380b1 100644
--- a/sound/pci/hda/hda_controller.h
+++ b/sound/pci/hda/hda_controller.h
@@ -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;
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 481d8f8d3396..3bf5e3410703 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -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
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index d4dd1b8a2e7e..c43bd0f0338e 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -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,
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 0062c18b646a..3aa432d814a2 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -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 */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 8d2503e8dad8..ea8ab8b43337 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -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
*/
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 2132b2acec4d..8afe6000f7da 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -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,
};
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index b66e7bdbf483..208933792787 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -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 = {
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 8629e84fef23..678fbcaf2a3b 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -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);
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index d111258c6f45..0515137a75b0 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -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
index 000000000000..0fb0a428428b
--- /dev/null
+++ b/sound/pci/hda/patch_cs8409-tables.c
@@ -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
index 000000000000..3c7ef55d016e
--- /dev/null
+++ b/sound/pci/hda/patch_cs8409.c
@@ -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)