summary refs log tree commit diff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-06 20:07:24 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-06 20:07:24 -0700
commit930e0312bcdc96d15f02ed6812d4a6c947855a2d (patch)
treed2d620c06359510562b25987cf329c77e41b7c11
parentec6c0a77786524e44003e70ea69651ad7fb35aec (diff)
parenta509574e5ea7b617268943526773ebf7e2d20a9b (diff)
downloadlinux-930e0312bcdc96d15f02ed6812d4a6c947855a2d.tar.gz
Merge tag 'sound-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
 "There've been many updates in ASoC side at this time, especially the
  framework enhancement for multiple CODECs on a single DAI and more
  componentization works.

  The only major change in ALSA core is the addition of timestamp type
  in sw_params field.  This should behave in backward compatible way.

  Other than that, there are lots of small changes and new drivers in
  wide range, including a large code cut in HD-audio driver for
  deprecated static quirks.  Some highlights are below:

  ALSA Core:
   - Add the new timestamp type field to sw_params to choose
     MONOTONIC_RAW type

  HD-audio:
   - Continued conversion to standard printk macros, generic code
     cleanups
   - Removal of obsoleted static quirk codes for Conexant and C-Media
     codecs
   - Fixups for HP Envy TS, Dell XPS 15, HP and Dell mute/mic LED,
     Gigabyte BXBT-2807 mobo
   - Intel Braswell support

  ASoC:
   - Support for multiple CODECs attached to a single DAI, enabling
     systems with for example multiple DAC/speaker drivers on a single
     link, contributed by Benoit Cousson based on work from Misael Lopez
     Cruz
   - Support for byte controls larger than 256 bytes based on the use of
     TLVs contributed by Omair Mohammed Abdullah
   - More componentisation work from Lars-Peter Clausen
   - The remainder of the conversions of CODEC drivers to params_width()
     by Mark Brown
   - Drivers for Cirrus Logic CS4265, Freescale i.MX ASRC blocks,
     Realtek RT286 and RT5670, Rockchip RK3xxx I2S controllers and Texas
     Instruments TAS2552
   - Lots of updates and fixes, especially to the DaVinci, Intel,
     Freescale, Realtek, and rcar drivers"

* tag 'sound-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (402 commits)
  ALSA: usb-audio: Whitespace cleanups for sound/usb/midi.*
  ALSA: usb-audio: Respond to suspend and resume callbacks for MIDI input
  sound/oss/pss: Remove typedefs pss_mixerdata and pss_confdata
  sound/oss/opl3: Remove typedef opl_devinfo
  ALSA: fireworks: fix specifiers in format strings for propper output
  ASoC: imx-audmux: Use uintptr_t for port numbers
  ASoC: davinci: Enable menuconfig entry for McASP
  ASoC: fsl_asrc: Don't access members of config before checking it
  ASoC: fsl_sarc_dma: Check pair before using it
  ASoC: adau1977: Fix truncation warning on 64 bit architectures
  ALSA: virtuoso: add Xonar Essence STX II support
  ALSA: riptide: fix %d confusingly prefixed with 0x in format strings
  ALSA: fireworks: fix %d confusingly prefixed with 0x in format strings
  ALSA: hda - add codec ID for Braswell display audio codec
  ALSA: hda - add PCI IDs for Intel Braswell
  ALSA: usb-audio: Adjust Gamecom 780 volume level
  ALSA: usb-audio: improve dmesg source grepability
  ASoC: rt5670: Fix duplicate const warnings
  ASoC: rt5670: Staticise non-exported symbols
  ASoC: Intel: update stream only on stream IPC msgs
  ...
-rw-r--r--Documentation/devicetree/bindings/sound/ak5386.txt4
-rw-r--r--Documentation/devicetree/bindings/sound/cs4265.txt29
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,asrc.txt60
-rw-r--r--Documentation/devicetree/bindings/sound/max98090.txt2
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,rsnd.txt9
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip-i2s.txt37
-rw-r--r--Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt35
-rw-r--r--Documentation/devicetree/bindings/sound/sirf-usp.txt27
-rw-r--r--Documentation/devicetree/bindings/sound/snow.txt5
-rw-r--r--Documentation/devicetree/bindings/sound/tas2552.txt26
-rw-r--r--Documentation/devicetree/bindings/sound/ti,tas5086.txt5
-rw-r--r--Documentation/devicetree/bindings/sound/wm8904.txt33
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt4
-rw-r--r--Documentation/sound/alsa/HD-Audio-Models.txt5
-rw-r--r--MAINTAINERS7
-rw-r--r--arch/arm/mach-shmobile/board-armadillo800eva.c4
-rw-r--r--arch/arm/mach-shmobile/board-kzm9g.c2
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c4
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c2
-rw-r--r--arch/x86/include/asm/platform_sst_audio.h78
-rw-r--r--drivers/dma/edma.c1
-rw-r--r--drivers/misc/atmel-ssc.c13
-rw-r--r--include/linux/atmel-ssc.h13
-rw-r--r--include/linux/dmaengine.h1
-rw-r--r--include/linux/mfd/arizona/core.h6
-rw-r--r--include/linux/platform_data/asoc-s3c.h9
-rw-r--r--include/linux/platform_data/dma-imx.h1
-rw-r--r--include/sound/control.h7
-rw-r--r--include/sound/pcm.h11
-rw-r--r--include/sound/rcar_snd.h1
-rw-r--r--include/sound/rt286.h19
-rw-r--r--include/sound/rt5670.h27
-rw-r--r--include/sound/soc-dai.h5
-rw-r--r--include/sound/soc-dapm.h8
-rw-r--r--include/sound/soc.h94
-rw-r--r--include/sound/tas2552-plat.h25
-rw-r--r--include/sound/wm8962.h1
-rw-r--r--include/trace/events/asoc.h6
-rw-r--r--include/uapi/sound/asound.h9
-rw-r--r--sound/aoa/soundbus/i2sbus/core.c12
-rw-r--r--sound/arm/pxa2xx-ac97-lib.c12
-rw-r--r--sound/core/compress_offload.c2
-rw-r--r--sound/core/control.c6
-rw-r--r--sound/core/pcm_compat.c8
-rw-r--r--sound/core/pcm_dmaengine.c4
-rw-r--r--sound/core/pcm_native.c9
-rw-r--r--sound/core/seq/seq_memory.c4
-rw-r--r--sound/firewire/Kconfig14
-rw-r--r--sound/firewire/fireworks/fireworks_proc.c4
-rw-r--r--sound/oss/mpu401.c2
-rw-r--r--sound/oss/opl3.c4
-rw-r--r--sound/oss/pss.c46
-rw-r--r--sound/pci/Kconfig4
-rw-r--r--sound/pci/echoaudio/echoaudio.c6
-rw-r--r--sound/pci/hda/dell_wmi_helper.c76
-rw-r--r--sound/pci/hda/hda_auto_parser.c17
-rw-r--r--sound/pci/hda/hda_codec.c45
-rw-r--r--sound/pci/hda/hda_codec.h4
-rw-r--r--sound/pci/hda/hda_controller.c203
-rw-r--r--sound/pci/hda/hda_controller.h9
-rw-r--r--sound/pci/hda/hda_eld.c46
-rw-r--r--sound/pci/hda/hda_generic.c22
-rw-r--r--sound/pci/hda/hda_i915.c4
-rw-r--r--sound/pci/hda/hda_intel.c372
-rw-r--r--sound/pci/hda/hda_local.h9
-rw-r--r--sound/pci/hda/hda_priv.h253
-rw-r--r--sound/pci/hda/hda_tegra.c36
-rw-r--r--sound/pci/hda/patch_ca0132.c6
-rw-r--r--sound/pci/hda/patch_cirrus.c4
-rw-r--r--sound/pci/hda/patch_cmedia.c624
-rw-r--r--sound/pci/hda/patch_conexant.c2631
-rw-r--r--sound/pci/hda/patch_hdmi.c13
-rw-r--r--sound/pci/hda/patch_realtek.c170
-rw-r--r--sound/pci/hda/patch_sigmatel.c29
-rw-r--r--sound/pci/ice1712/ice1712.h15
-rw-r--r--sound/pci/mixart/mixart_core.c4
-rw-r--r--sound/pci/oxygen/virtuoso.c1
-rw-r--r--sound/pci/oxygen/xonar_pcm179x.c12
-rw-r--r--sound/pci/riptide/riptide.c4
-rw-r--r--sound/pci/trident/trident_main.c2
-rw-r--r--sound/pci/trident/trident_memory.c3
-rw-r--r--sound/soc/Kconfig1
-rw-r--r--sound/soc/Makefile1
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c34
-rw-r--r--sound/soc/atmel/atmel_wm8904.c50
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c8
-rw-r--r--sound/soc/codecs/88pm860x-codec.c12
-rw-r--r--sound/soc/codecs/Kconfig27
-rw-r--r--sound/soc/codecs/Makefile8
-rw-r--r--sound/soc/codecs/ac97.c4
-rw-r--r--sound/soc/codecs/adau1701.c6
-rw-r--r--sound/soc/codecs/adau17x1.c8
-rw-r--r--sound/soc/codecs/adau1977.c2
-rw-r--r--sound/soc/codecs/ak4642.c4
-rw-r--r--sound/soc/codecs/ak5386.c50
-rw-r--r--sound/soc/codecs/arizona.c288
-rw-r--r--sound/soc/codecs/arizona.h1
-rw-r--r--sound/soc/codecs/cs4265.c682
-rw-r--r--sound/soc/codecs/cs4265.h64
-rw-r--r--sound/soc/codecs/cs4270.c4
-rw-r--r--sound/soc/codecs/cs42l52.c14
-rw-r--r--sound/soc/codecs/cs42l56.c76
-rw-r--r--sound/soc/codecs/cs42l73.c6
-rw-r--r--sound/soc/codecs/cs42xx8.c5
-rw-r--r--sound/soc/codecs/cs42xx8.h8
-rw-r--r--sound/soc/codecs/cx20442.c10
-rw-r--r--sound/soc/codecs/max98088.c6
-rw-r--r--sound/soc/codecs/max98090.c44
-rw-r--r--sound/soc/codecs/max98095.c12
-rw-r--r--sound/soc/codecs/mc13783.c6
-rw-r--r--sound/soc/codecs/pcm1792a.c3
-rw-r--r--sound/soc/codecs/pcm1792a.h3
-rw-r--r--sound/soc/codecs/rl6231.c19
-rw-r--r--sound/soc/codecs/rt286.c1222
-rw-r--r--sound/soc/codecs/rt286.h198
-rw-r--r--sound/soc/codecs/rt5631.c10
-rw-r--r--sound/soc/codecs/rt5640.c10
-rw-r--r--sound/soc/codecs/rt5645.c10
-rw-r--r--sound/soc/codecs/rt5651.c10
-rw-r--r--sound/soc/codecs/rt5670-dsp.h54
-rw-r--r--sound/soc/codecs/rt5670.c2657
-rw-r--r--sound/soc/codecs/rt5670.h2000
-rw-r--r--sound/soc/codecs/rt5677.c272
-rw-r--r--sound/soc/codecs/rt5677.h15
-rw-r--r--sound/soc/codecs/sgtl5000.c25
-rw-r--r--sound/soc/codecs/si476x.c10
-rw-r--r--sound/soc/codecs/sirf-audio-codec.c4
-rw-r--r--sound/soc/codecs/sn95031.c6
-rw-r--r--sound/soc/codecs/spdif_transmitter.c2
-rw-r--r--sound/soc/codecs/ssm2518.c6
-rw-r--r--sound/soc/codecs/ssm2602.c10
-rw-r--r--sound/soc/codecs/sta32x.c19
-rw-r--r--sound/soc/codecs/sta529.c12
-rw-r--r--sound/soc/codecs/tas2552.c544
-rw-r--r--sound/soc/codecs/tas2552.h129
-rw-r--r--sound/soc/codecs/tas5086.c75
-rw-r--r--sound/soc/codecs/tlv320aic23.c10
-rw-r--r--sound/soc/codecs/tlv320aic26.c14
-rw-r--r--sound/soc/codecs/tlv320aic31xx.c40
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c31
-rw-r--r--sound/soc/codecs/tlv320aic3x.c21
-rw-r--r--sound/soc/codecs/tlv320dac33.c12
-rw-r--r--sound/soc/codecs/tpa6130a2.c4
-rw-r--r--sound/soc/codecs/twl4030.c19
-rw-r--r--sound/soc/codecs/uda134x.c10
-rw-r--r--sound/soc/codecs/wl1273.c9
-rw-r--r--sound/soc/codecs/wm0010.c14
-rw-r--r--sound/soc/codecs/wm1250-ev1.c1
-rw-r--r--sound/soc/codecs/wm2000.c4
-rw-r--r--sound/soc/codecs/wm5100.c3
-rw-r--r--sound/soc/codecs/wm5102.c65
-rw-r--r--sound/soc/codecs/wm5110.c4
-rw-r--r--sound/soc/codecs/wm8350.c13
-rw-r--r--sound/soc/codecs/wm8400.c10
-rw-r--r--sound/soc/codecs/wm8510.c10
-rw-r--r--sound/soc/codecs/wm8523.c10
-rw-r--r--sound/soc/codecs/wm8580.c10
-rw-r--r--sound/soc/codecs/wm8711.c8
-rw-r--r--sound/soc/codecs/wm8728.c8
-rw-r--r--sound/soc/codecs/wm8731.c8
-rw-r--r--sound/soc/codecs/wm8737.c10
-rw-r--r--sound/soc/codecs/wm8741.c14
-rw-r--r--sound/soc/codecs/wm8750.c10
-rw-r--r--sound/soc/codecs/wm8753.c20
-rw-r--r--sound/soc/codecs/wm8770.c10
-rw-r--r--sound/soc/codecs/wm8804.c10
-rw-r--r--sound/soc/codecs/wm8900.c10
-rw-r--r--sound/soc/codecs/wm8903.c13
-rw-r--r--sound/soc/codecs/wm8904.c27
-rw-r--r--sound/soc/codecs/wm8940.c12
-rw-r--r--sound/soc/codecs/wm8955.c10
-rw-r--r--sound/soc/codecs/wm8958-dsp2.c24
-rw-r--r--sound/soc/codecs/wm8960.c17
-rw-r--r--sound/soc/codecs/wm8961.c10
-rw-r--r--sound/soc/codecs/wm8962.c29
-rw-r--r--sound/soc/codecs/wm8971.c10
-rw-r--r--sound/soc/codecs/wm8974.c10
-rw-r--r--sound/soc/codecs/wm8978.c14
-rw-r--r--sound/soc/codecs/wm8983.c12
-rw-r--r--sound/soc/codecs/wm8985.c15
-rw-r--r--sound/soc/codecs/wm8988.c10
-rw-r--r--sound/soc/codecs/wm8990.c10
-rw-r--r--sound/soc/codecs/wm8991.c10
-rw-r--r--sound/soc/codecs/wm8993.c10
-rw-r--r--sound/soc/codecs/wm8994.c35
-rw-r--r--sound/soc/codecs/wm8995.c12
-rw-r--r--sound/soc/codecs/wm8996.c6
-rw-r--r--sound/soc/codecs/wm8997.c2
-rw-r--r--sound/soc/codecs/wm9081.c10
-rw-r--r--sound/soc/codecs/wm9090.c4
-rw-r--r--sound/soc/codecs/wm9713.c10
-rw-r--r--sound/soc/codecs/wm_adsp.c6
-rw-r--r--sound/soc/codecs/wm_hubs.c4
-rw-r--r--sound/soc/davinci/Kconfig25
-rw-r--r--sound/soc/davinci/Makefile2
-rw-r--r--sound/soc/davinci/davinci-mcasp.c93
-rw-r--r--sound/soc/davinci/edma-pcm.c2
-rw-r--r--sound/soc/davinci/edma-pcm.h7
-rw-r--r--sound/soc/fsl/Kconfig16
-rw-r--r--sound/soc/fsl/Makefile2
-rw-r--r--sound/soc/fsl/fsl_asrc.c995
-rw-r--r--sound/soc/fsl/fsl_asrc.h461
-rw-r--r--sound/soc/fsl/fsl_asrc_dma.c391
-rw-r--r--sound/soc/fsl/fsl_esai.c2
-rw-r--r--sound/soc/fsl/fsl_sai.c39
-rw-r--r--sound/soc/fsl/fsl_spdif.c88
-rw-r--r--sound/soc/fsl/fsl_spdif.h10
-rw-r--r--sound/soc/fsl/fsl_ssi.c6
-rw-r--r--sound/soc/fsl/imx-audmux.c8
-rw-r--r--sound/soc/generic/simple-card.c13
-rw-r--r--sound/soc/intel/Kconfig12
-rw-r--r--sound/soc/intel/Makefile2
-rw-r--r--sound/soc/intel/broadwell.c251
-rw-r--r--sound/soc/intel/byt-max98090.c27
-rw-r--r--sound/soc/intel/byt-rt5640.c1
-rw-r--r--sound/soc/intel/sst-atom-controls.h30
-rw-r--r--sound/soc/intel/sst-baytrail-ipc.c30
-rw-r--r--sound/soc/intel/sst-baytrail-pcm.c2
-rw-r--r--sound/soc/intel/sst-dsp.c10
-rw-r--r--sound/soc/intel/sst-dsp.h39
-rw-r--r--sound/soc/intel/sst-haswell-dsp.c70
-rw-r--r--sound/soc/intel/sst-haswell-ipc.c40
-rw-r--r--sound/soc/intel/sst-haswell-pcm.c27
-rw-r--r--sound/soc/intel/sst-mfld-dsp.h429
-rw-r--r--sound/soc/intel/sst-mfld-platform-compress.c11
-rw-r--r--sound/soc/intel/sst-mfld-platform-pcm.c319
-rw-r--r--sound/soc/intel/sst-mfld-platform.h29
-rw-r--r--sound/soc/kirkwood/Kconfig19
-rw-r--r--sound/soc/kirkwood/Makefile4
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c11
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c33
-rw-r--r--sound/soc/kirkwood/kirkwood-openrd.c109
-rw-r--r--sound/soc/kirkwood/kirkwood-t5325.c116
-rw-r--r--sound/soc/kirkwood/kirkwood.h7
-rw-r--r--sound/soc/omap/ams-delta.c2
-rw-r--r--sound/soc/omap/omap-dmic.c35
-rw-r--r--sound/soc/omap/omap-mcbsp.c7
-rw-r--r--sound/soc/omap/omap-pcm.c1
-rw-r--r--sound/soc/pxa/pxa-ssp.c3
-rw-r--r--sound/soc/rockchip/Kconfig12
-rw-r--r--sound/soc/rockchip/Makefile4
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c529
-rw-r--r--sound/soc/rockchip/rockchip_i2s.h223
-rw-r--r--sound/soc/s6000/Kconfig13
-rw-r--r--sound/soc/s6000/Makefile2
-rw-r--r--sound/soc/s6000/s6000-i2s.c4
-rw-r--r--sound/soc/s6000/s6105-ipcam.c17
-rw-r--r--sound/soc/samsung/Kconfig40
-rw-r--r--sound/soc/samsung/Makefile6
-rw-r--r--sound/soc/samsung/ac97.c32
-rw-r--r--sound/soc/samsung/dma.c454
-rw-r--r--sound/soc/samsung/dma.h7
-rw-r--r--sound/soc/samsung/dmaengine.c3
-rw-r--r--sound/soc/samsung/i2s.c35
-rw-r--r--sound/soc/samsung/idma.c3
-rw-r--r--sound/soc/samsung/odroidx2_max98090.c177
-rw-r--r--sound/soc/samsung/pcm.c12
-rw-r--r--sound/soc/samsung/s3c-i2s-v2.c19
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c43
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c58
-rw-r--r--sound/soc/samsung/smdk_wm8580pcm.c2
-rw-r--r--sound/soc/samsung/snow.c4
-rw-r--r--sound/soc/samsung/spdif.c5
-rw-r--r--sound/soc/sh/Kconfig2
-rw-r--r--sound/soc/sh/fsi.c201
-rw-r--r--sound/soc/sh/rcar/core.c247
-rw-r--r--sound/soc/sh/rcar/dvc.c135
-rw-r--r--sound/soc/sh/rcar/gen.c554
-rw-r--r--sound/soc/sh/rcar/rsnd.h26
-rw-r--r--sound/soc/sh/rcar/src.c86
-rw-r--r--sound/soc/sh/rcar/ssi.c33
-rw-r--r--sound/soc/sirf/Kconfig6
-rw-r--r--sound/soc/sirf/Makefile2
-rw-r--r--sound/soc/sirf/sirf-usp.c415
-rw-r--r--sound/soc/sirf/sirf-usp.h293
-rw-r--r--sound/soc/soc-cache.c7
-rw-r--r--sound/soc/soc-compress.c13
-rw-r--r--sound/soc/soc-core.c900
-rw-r--r--sound/soc/soc-dapm.c279
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c37
-rw-r--r--sound/soc/soc-jack.c4
-rw-r--r--sound/soc/soc-pcm.c581
-rw-r--r--sound/soc/tegra/tegra_alc5632.c5
-rw-r--r--sound/soc/tegra/tegra_max98090.c5
-rw-r--r--sound/soc/tegra/tegra_rt5640.c5
-rw-r--r--sound/soc/tegra/tegra_wm8753.c3
-rw-r--r--sound/soc/tegra/tegra_wm8903.c5
-rw-r--r--sound/soc/tegra/trimslice.c3
-rw-r--r--sound/sparc/dbri.c6
-rw-r--r--sound/usb/card.c9
-rw-r--r--sound/usb/midi.c401
-rw-r--r--sound/usb/midi.h6
-rw-r--r--sound/usb/mixer.c9
-rw-r--r--sound/usb/quirks.c2
294 files changed, 17264 insertions, 7462 deletions
diff --git a/Documentation/devicetree/bindings/sound/ak5386.txt b/Documentation/devicetree/bindings/sound/ak5386.txt
index dc3914fe6ce8..ec3df3abba0c 100644
--- a/Documentation/devicetree/bindings/sound/ak5386.txt
+++ b/Documentation/devicetree/bindings/sound/ak5386.txt
@@ -10,10 +10,14 @@ Optional properties:
 
   - reset-gpio : a GPIO spec for the reset/power down pin.
 		 If specified, it will be deasserted at probe time.
+  - va-supply : a regulator spec, providing 5.0V
+  - vd-supply : a regulator spec, providing 3.3V
 
 Example:
 
 spdif: ak5386@0 {
 	compatible = "asahi-kasei,ak5386";
 	reset-gpio = <&gpio0 23>;
+	va-supply = <&vdd_5v0_reg>;
+	vd-supply = <&vdd_3v3_reg>;
 };
diff --git a/Documentation/devicetree/bindings/sound/cs4265.txt b/Documentation/devicetree/bindings/sound/cs4265.txt
new file mode 100644
index 000000000000..380fff8e4e83
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/cs4265.txt
@@ -0,0 +1,29 @@
+CS4265 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+  - compatible : "cirrus,cs4265"
+
+  - reg : the I2C address of the device for I2C. The I2C address depends on
+          the state of the AD0 pin.  If AD0 is high, the i2c address is 0x4f.
+          If it is low, the i2c address is 0x4e.
+
+Optional properties:
+
+  - reset-gpios : a GPIO spec for the reset pin. If specified, it will be
+		 deasserted before communication to the codec starts.
+
+Examples:
+
+codec_ad0_high: cs4265@4f { /* AD0 Pin is high */
+	compatible = "cirrus,cs4265";
+	reg = <0x4f>;
+};
+
+
+codec_ad0_low: cs4265@4e { /* AD0 Pin is low */
+	compatible = "cirrus,cs4265";
+	reg = <0x4e>;
+};
diff --git a/Documentation/devicetree/bindings/sound/fsl,asrc.txt b/Documentation/devicetree/bindings/sound/fsl,asrc.txt
new file mode 100644
index 000000000000..b93362a570be
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,asrc.txt
@@ -0,0 +1,60 @@
+Freescale Asynchronous Sample Rate Converter (ASRC) Controller
+
+The Asynchronous Sample Rate Converter (ASRC) converts the sampling rate of a
+signal associated with an input clock into a signal associated with a different
+output clock. The driver currently works as a Front End of DPCM with other Back
+Ends Audio controller such as ESAI, SSI and SAI. It has three pairs to support
+three substreams within totally 10 channels.
+
+Required properties:
+
+  - compatible		: Contains "fsl,imx35-asrc" or "fsl,imx53-asrc".
+
+  - reg			: Offset and length of the register set for the device.
+
+  - interrupts		: Contains the spdif interrupt.
+
+  - dmas		: Generic dma devicetree binding as described in
+			  Documentation/devicetree/bindings/dma/dma.txt.
+
+  - dma-names		: Contains "rxa", "rxb", "rxc", "txa", "txb" and "txc".
+
+  - clocks		: Contains an entry for each entry in clock-names.
+
+  - clock-names		: Contains the following entries
+	"mem"		  Peripheral access clock to access registers.
+	"ipg"		  Peripheral clock to driver module.
+	"asrck_<0-f>"	  Clock sources for input and output clock.
+
+   - big-endian		: If this property is absent, the little endian mode
+			  will be in use as default. Otherwise, the big endian
+			  mode will be in use for all the device registers.
+
+   - fsl,asrc-rate	: Defines a mutual sample rate used by DPCM Back Ends.
+
+   - fsl,asrc-width	: Defines a mutual sample width used by DPCM Back Ends.
+
+Example:
+
+asrc: asrc@02034000 {
+	compatible = "fsl,imx53-asrc";
+	reg = <0x02034000 0x4000>;
+	interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&clks 107>, <&clks 107>, <&clks 0>,
+	       <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+	       <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+	       <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+	       <&clks 107>, <&clks 0>, <&clks 0>;
+	clock-names = "mem", "ipg", "asrck0",
+		"asrck_1", "asrck_2", "asrck_3", "asrck_4",
+		"asrck_5", "asrck_6", "asrck_7", "asrck_8",
+		"asrck_9", "asrck_a", "asrck_b", "asrck_c",
+		"asrck_d", "asrck_e", "asrck_f";
+	dmas = <&sdma 17 23 1>, <&sdma 18 23 1>, <&sdma 19 23 1>,
+	     <&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
+	dma-names = "rxa", "rxb", "rxc",
+		"txa", "txb", "txc";
+	fsl,asrc-rate  = <48000>;
+	fsl,asrc-width = <16>;
+	status = "okay";
+};
diff --git a/Documentation/devicetree/bindings/sound/max98090.txt b/Documentation/devicetree/bindings/sound/max98090.txt
index a5e63fa47dc5..c454e67f54bb 100644
--- a/Documentation/devicetree/bindings/sound/max98090.txt
+++ b/Documentation/devicetree/bindings/sound/max98090.txt
@@ -4,7 +4,7 @@ This device supports I2C only.
 
 Required properties:
 
-- compatible : "maxim,max98090".
+- compatible : "maxim,max98090" or "maxim,max98091".
 
 - reg : The I2C address of the device.
 
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
index 8346cab046cd..aa697abf337e 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
+++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
@@ -13,6 +13,9 @@ Required properties:
 - rcar_sound,src		: Should contain SRC feature.
 				  The number of SRC subnode should be same as HW.
 				  see below for detail.
+- rcar_sound,dvc		: Should contain DVC feature.
+				  The number of DVC subnode should be same as HW.
+				  see below for detail.
 - rcar_sound,dai		: DAI contents.
 				  The number of DAI subnode should be same as HW.
 				  see below for detail.
@@ -21,6 +24,7 @@ SSI subnode properties:
 - interrupts			: Should contain SSI interrupt for PIO transfer
 - shared-pin			: if shared clock pin
 - pio-transfer			: use PIO transfer mode
+- no-busif			: BUSIF is not ussed when [mem -> SSI] via DMA case
 
 SRC subnode properties:
 no properties at this point
@@ -39,6 +43,11 @@ rcar_sound: rcar_sound@0xffd90000 {
 		<0 0xec540000 0 0x1000>, /* SSIU */
 		<0 0xec541000 0 0x1280>; /* SSI */
 
+	rcar_sound,dvc {
+		dvc0: dvc@0 { };
+		dvc1: dvc@1 { };
+	};
+
 	rcar_sound,src {
 		src0: src@0 { };
 		src1: src@1 { };
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
new file mode 100644
index 000000000000..6c55fcfe5e1d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -0,0 +1,37 @@
+* Rockchip I2S controller
+
+The I2S bus (Inter-IC sound bus) is a serial link for digital
+audio data transfer between devices in the system.
+
+Required properties:
+
+- compatible: should be one of the followings
+   - "rockchip,rk3066-i2s": for rk3066
+   - "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188
+   - "rockchip,rk3288-i2s", "rockchip,rk3066-i2s": for rk3288
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: should contain the I2S interrupt.
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
+	Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: should include "tx" and "rx".
+- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
+- clock-names: should contain followings:
+   - "i2s_hclk": clock for I2S BUS
+   - "i2s_clk" : clock for I2S controller
+
+Example for rk3288 I2S controller:
+
+i2s@ff890000 {
+	compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s";
+	reg = <0xff890000 0x10000>;
+	interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	dmas = <&pdma1 0>, <&pdma1 1>;
+	dma-names = "rx", "tx";
+	clock-names = "i2s_hclk", "i2s_clk";
+	clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
+};
diff --git a/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt b/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt
new file mode 100644
index 000000000000..9148f72319e1
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt
@@ -0,0 +1,35 @@
+Samsung Exynos Odroid X2/U3 audio complex with MAX98090 codec
+
+Required properties:
+ - compatible : "samsung,odroidx2-audio" - for Odroid X2 board,
+		"samsung,odroidu3-audio" - for Odroid U3 board
+ - samsung,model : the user-visible name of this sound complex
+ - samsung,i2s-controller : the phandle of the I2S controller
+ - samsung,audio-codec : the phandle of the MAX98090 audio codec
+ - samsung,audio-routing : a list of the connections between audio
+   components;  each entry is a pair of strings, the first being the
+   connection's sink, the second being the connection's source;
+   valid names for sources and sinks are the MAX98090's pins (as
+   documented in its binding), and the jacks on the board
+   For Odroid X2:
+     * Headphone Jack
+     * Mic Jack
+     * DMIC
+
+   For Odroid U3:
+     * Headphone Jack
+     * Speakers
+
+Example:
+
+sound {
+	compatible = "samsung,odroidu3-audio";
+	samsung,i2s-controller = <&i2s0>;
+	samsung,audio-codec = <&max98090>;
+	samsung,model = "Odroid-X2";
+	samsung,audio-routing =
+		"Headphone Jack", "HPL",
+		"Headphone Jack", "HPR",
+		"IN1", "Mic Jack",
+		"Mic Jack", "MICBIAS";
+};
diff --git a/Documentation/devicetree/bindings/sound/sirf-usp.txt b/Documentation/devicetree/bindings/sound/sirf-usp.txt
new file mode 100644
index 000000000000..02f85b32d359
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/sirf-usp.txt
@@ -0,0 +1,27 @@
+* SiRF SoC USP module
+
+Required properties:
+- compatible: "sirf,prima2-usp-pcm"
+- reg: Base address and size entries:
+- dmas: List of DMA controller phandle and DMA request line ordered pairs.
+- dma-names: Identifier string for each DMA request line in the dmas property.
+  These strings correspond 1:1 with the ordered pairs in dmas.
+
+  One of the DMA channels will be responsible for transmission (should be
+  named "tx") and one for reception (should be named "rx").
+
+- clocks: USP controller clock source
+- pinctrl-names: Must contain a "default" entry.
+- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
+
+Example:
+usp0: usp@b0080000 {
+	compatible = "sirf,prima2-usp-pcm";
+	reg = <0xb0080000 0x10000>;
+	clocks = <&clks 28>;
+	dmas = <&dmac1 1>, <&dmac1 2>;
+	dma-names = "rx", "tx";
+	pinctrl-names = "default";
+	pinctrl-0 = <&usp0_only_utfs_pins_a>;
+};
+
diff --git a/Documentation/devicetree/bindings/sound/snow.txt b/Documentation/devicetree/bindings/sound/snow.txt
index 678b191c37b8..6df74f15687f 100644
--- a/Documentation/devicetree/bindings/sound/snow.txt
+++ b/Documentation/devicetree/bindings/sound/snow.txt
@@ -3,15 +3,20 @@ Audio Binding for Snow boards
 Required properties:
 - compatible : Can be one of the following,
 			"google,snow-audio-max98090" or
+			"google,snow-audio-max98091" or
 			"google,snow-audio-max98095"
 - samsung,i2s-controller: The phandle of the Samsung I2S controller
 - samsung,audio-codec: The phandle of the audio codec
 
+Optional:
+- samsung,model: The name of the sound-card
+
 Example:
 
 sound {
 		compatible = "google,snow-audio-max98095";
 
+		samsung,model = "Snow-I2S-MAX98095";
 		samsung,i2s-controller = <&i2s0>;
 		samsung,audio-codec = <&max98095>;
 };
diff --git a/Documentation/devicetree/bindings/sound/tas2552.txt b/Documentation/devicetree/bindings/sound/tas2552.txt
new file mode 100644
index 000000000000..55e2a0af5645
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tas2552.txt
@@ -0,0 +1,26 @@
+Texas Instruments - tas2552 Codec module
+
+The tas2552 serial control bus communicates through I2C protocols
+
+Required properties:
+	- compatible - One of:
+		"ti,tas2552" - TAS2552
+	- reg -  I2C slave address
+	- supply-*: Required supply regulators are:
+		"vbat"		battery voltage
+		"iovdd"		I/O Voltage
+		"avdd"		Analog DAC Voltage
+
+Optional properties:
+	- enable-gpio - gpio pin to enable/disable the device
+
+Example:
+
+tas2552: tas2552@41 {
+	compatible = "ti,tas2552";
+	reg = <0x41>;
+	enable-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
+};
+
+For more product information please see the link below:
+http://www.ti.com/product/TAS2552
diff --git a/Documentation/devicetree/bindings/sound/ti,tas5086.txt b/Documentation/devicetree/bindings/sound/ti,tas5086.txt
index d2866a0d6a26..234dad296da7 100644
--- a/Documentation/devicetree/bindings/sound/ti,tas5086.txt
+++ b/Documentation/devicetree/bindings/sound/ti,tas5086.txt
@@ -31,6 +31,9 @@ Optional properties:
 
 			Most systems should not set any of these properties.
 
+ - avdd-supply:         Power supply for AVDD, providing 3.3V
+ - dvdd-supply:         Power supply for DVDD, providing 3.3V
+
 Examples:
 
 	i2c_bus {
@@ -39,5 +42,7 @@ Examples:
 			reg = <0x1b>;
 			reset-gpio = <&gpio 23 0>;
 			ti,charge-period = <156000>;
+			avdd-supply = <&vdd_3v3_reg>;
+			dvdd-supply = <&vdd_3v3_reg>;
 		};
 	};
diff --git a/Documentation/devicetree/bindings/sound/wm8904.txt b/Documentation/devicetree/bindings/sound/wm8904.txt
new file mode 100644
index 000000000000..e99f4097c83c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8904.txt
@@ -0,0 +1,33 @@
+WM8904 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+  - compatible: "wlf,wm8904"
+  - reg: the I2C address of the device.
+  - clock-names: "mclk"
+  - clocks: reference to
+    <Documentation/devicetree/bindings/clock/clock-bindings.txt>
+
+Pins on the device (for linking into audio routes):
+
+  * IN1L
+  * IN1R
+  * IN2L
+  * IN2R
+  * IN3L
+  * IN3R
+  * HPOUTL
+  * HPOUTR
+  * LINEOUTL
+  * LINEOUTR
+  * MICBIAS
+
+Examples:
+
+codec: wm8904@1a {
+	compatible = "wlf,wm8904";
+	reg = <0x1a>;
+	clocks = <&pck0>;
+	clock-names = "mclk";
+};
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 7ccf933bfbe0..48148d6d9307 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -2026,8 +2026,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
   -------------------
 
     Module for sound cards based on the Asus AV66/AV100/AV200 chips,
-    i.e., Xonar D1, DX, D2, D2X, DS, Essence ST (Deluxe), Essence STX,
-    HDAV1.3 (Deluxe), and HDAV1.3 Slim.
+    i.e., Xonar D1, DX, D2, D2X, DS, DSX, Essence ST (Deluxe),
+    Essence STX (II), HDAV1.3 (Deluxe), and HDAV1.3 Slim.
 
     This module supports autoprobe and multiple cards.
 
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index d1ab5e17eb13..a5e754714344 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -284,6 +284,11 @@ STAC92HD83*
   hp-zephyr	HP Zephyr
   hp-led	HP with broken BIOS for mute LED
   hp-inv-led	HP with broken BIOS for inverted mute LED
+  hp-mic-led	HP with mic-mute LED
+  headset-jack	Dell Latitude with a 4-pin headset jack
+  hp-envy-bass	Pin fixup for HP Envy bass speaker (NID 0x0f)
+  hp-envy-ts-bass Pin fixup for HP Envy TS bass speaker (NID 0x10)
+  hp-bnb13-eq	Hardware equalizer setup for HP laptops
   auto		BIOS setup (default)
 
 STAC92HD95
diff --git a/MAINTAINERS b/MAINTAINERS
index 12fee4ef936b..731c8a48e19c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7526,6 +7526,13 @@ F:	drivers/rtc/
 F:	include/linux/rtc.h
 F:	include/uapi/linux/rtc.h
 
+REALTEK AUDIO CODECS
+M:	Bard Liao <bardliao@realtek.com>
+M:	Oder Chiou <oder_chiou@realtek.com>
+S:	Maintained
+F:	sound/soc/codecs/rt*
+F:	include/sound/rt*.h
+
 REISERFS FILE SYSTEM
 L:	reiserfs-devel@vger.kernel.org
 S:	Supported
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index 30fcac73a540..689c121157ec 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -998,6 +998,8 @@ static struct platform_device fsi_wm8978_device = {
 	.id	= 0,
 	.dev	= {
 		.platform_data	= &fsi_wm8978_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_wm8978_device.dev.coherent_dma_mask,
 	},
 };
 
@@ -1021,6 +1023,8 @@ static struct platform_device fsi_hdmi_device = {
 	.id	= 1,
 	.dev	= {
 		.platform_data	= &fsi2_hdmi_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
 	},
 };
 
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
index f94ec8ca42c1..01e0d1386db7 100644
--- a/arch/arm/mach-shmobile/board-kzm9g.c
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -603,6 +603,8 @@ static struct platform_device fsi_ak4648_device = {
 	.name	= "asoc-simple-card",
 	.dev	= {
 		.platform_data	= &fsi2_ak4648_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_ak4648_device.dev.coherent_dma_mask,
 	},
 };
 
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 0ff4d8e45cf7..112553f0f9bf 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -523,6 +523,8 @@ static struct platform_device fsi_hdmi_device = {
 	.id	= 1,
 	.dev	= {
 		.platform_data	= &fsi2_hdmi_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
 	},
 };
 
@@ -919,6 +921,8 @@ static struct platform_device fsi_ak4643_device = {
 	.name	= "asoc-simple-card",
 	.dev	= {
 		.platform_data	= &fsi2_ak4643_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_ak4643_device.dev.coherent_dma_mask,
 	},
 };
 
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 85d5255d259f..0d3049244cd3 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -874,6 +874,8 @@ static struct platform_device fsi_da7210_device = {
 	.name	= "asoc-simple-card",
 	.dev	= {
 		.platform_data	= &fsi_da7210_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_da7210_device.dev.coherent_dma_mask,
 	},
 };
 
diff --git a/arch/x86/include/asm/platform_sst_audio.h b/arch/x86/include/asm/platform_sst_audio.h
new file mode 100644
index 000000000000..0a4e140315b6
--- /dev/null
+++ b/arch/x86/include/asm/platform_sst_audio.h
@@ -0,0 +1,78 @@
+/*
+ * platform_sst_audio.h:  sst audio platform data header file
+ *
+ * Copyright (C) 2012-14 Intel Corporation
+ * Author: Jeeja KP <jeeja.kp@intel.com>
+ * 	Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
+ *	Vinod Koul ,vinod.koul@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#ifndef _PLATFORM_SST_AUDIO_H_
+#define _PLATFORM_SST_AUDIO_H_
+
+#include <linux/sfi.h>
+
+enum sst_audio_task_id_mrfld {
+	SST_TASK_ID_NONE = 0,
+	SST_TASK_ID_SBA = 1,
+	SST_TASK_ID_MEDIA = 3,
+	SST_TASK_ID_MAX = SST_TASK_ID_MEDIA,
+};
+
+/* Device IDs for Merrifield are Pipe IDs,
+ * ref: DSP spec v0.75 */
+enum sst_audio_device_id_mrfld {
+	/* Output pipeline IDs */
+	PIPE_ID_OUT_START = 0x0,
+	PIPE_CODEC_OUT0 = 0x2,
+	PIPE_CODEC_OUT1 = 0x3,
+	PIPE_SPROT_LOOP_OUT = 0x4,
+	PIPE_MEDIA_LOOP1_OUT = 0x5,
+	PIPE_MEDIA_LOOP2_OUT = 0x6,
+	PIPE_VOIP_OUT = 0xC,
+	PIPE_PCM0_OUT = 0xD,
+	PIPE_PCM1_OUT = 0xE,
+	PIPE_PCM2_OUT = 0xF,
+	PIPE_MEDIA0_OUT = 0x12,
+	PIPE_MEDIA1_OUT = 0x13,
+/* Input Pipeline IDs */
+	PIPE_ID_IN_START = 0x80,
+	PIPE_CODEC_IN0 = 0x82,
+	PIPE_CODEC_IN1 = 0x83,
+	PIPE_SPROT_LOOP_IN = 0x84,
+	PIPE_MEDIA_LOOP1_IN = 0x85,
+	PIPE_MEDIA_LOOP2_IN = 0x86,
+	PIPE_VOIP_IN = 0x8C,
+	PIPE_PCM0_IN = 0x8D,
+	PIPE_PCM1_IN = 0x8E,
+	PIPE_MEDIA0_IN = 0x8F,
+	PIPE_MEDIA1_IN = 0x90,
+	PIPE_MEDIA2_IN = 0x91,
+	PIPE_RSVD = 0xFF,
+};
+
+/* The stream map for each platform consists of an array of the below
+ * stream map structure.
+ */
+struct sst_dev_stream_map {
+	u8 dev_num;		/* device id */
+	u8 subdev_num;		/* substream */
+	u8 direction;
+	u8 device_id;		/* fw id */
+	u8 task_id;		/* fw task */
+	u8 status;
+};
+
+struct sst_platform_data {
+	/* Intel software platform id*/
+	struct sst_dev_stream_map *pdev_strm_map;
+	unsigned int strm_map_size;
+};
+
+int add_sst_platform_device(void);
+#endif
+
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index d08c4dedef35..b512caf46944 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -982,6 +982,7 @@ static void __init edma_chan_init(struct edma_cc *ecc,
 
 #define EDMA_DMA_BUSWIDTHS	(BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
 				 BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+				 BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
 				 BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
 
 static int edma_dma_device_slave_caps(struct dma_chan *dchan,
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 22de13727641..60843a275abd 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -83,10 +83,17 @@ EXPORT_SYMBOL(ssc_free);
 
 static struct atmel_ssc_platform_data at91rm9200_config = {
 	.use_dma = 0,
+	.has_fslen_ext = 0,
+};
+
+static struct atmel_ssc_platform_data at91sam9rl_config = {
+	.use_dma = 0,
+	.has_fslen_ext = 1,
 };
 
 static struct atmel_ssc_platform_data at91sam9g45_config = {
 	.use_dma = 1,
+	.has_fslen_ext = 1,
 };
 
 static const struct platform_device_id atmel_ssc_devtypes[] = {
@@ -94,6 +101,9 @@ static const struct platform_device_id atmel_ssc_devtypes[] = {
 		.name = "at91rm9200_ssc",
 		.driver_data = (unsigned long) &at91rm9200_config,
 	}, {
+		.name = "at91sam9rl_ssc",
+		.driver_data = (unsigned long) &at91sam9rl_config,
+	}, {
 		.name = "at91sam9g45_ssc",
 		.driver_data = (unsigned long) &at91sam9g45_config,
 	}, {
@@ -107,6 +117,9 @@ static const struct of_device_id atmel_ssc_dt_ids[] = {
 		.compatible = "atmel,at91rm9200-ssc",
 		.data = &at91rm9200_config,
 	}, {
+		.compatible = "atmel,at91sam9rl-ssc",
+		.data = &at91sam9rl_config,
+	}, {
 		.compatible = "atmel,at91sam9g45-ssc",
 		.data = &at91sam9g45_config,
 	}, {
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index 571a12ebb018..7c0f6549898b 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -7,6 +7,7 @@
 
 struct atmel_ssc_platform_data {
 	int			use_dma;
+	int			has_fslen_ext;
 };
 
 struct ssc_device {
@@ -71,6 +72,12 @@ void ssc_free(struct ssc_device *ssc);
 #define SSC_RFMR_DATNB_OFFSET			 8
 #define SSC_RFMR_FSEDGE_SIZE			 1
 #define SSC_RFMR_FSEDGE_OFFSET			24
+/*
+ * The FSLEN_EXT exist on at91sam9rl, at91sam9g10,
+ * at91sam9g20, and at91sam9g45 and newer SoCs
+ */
+#define SSC_RFMR_FSLEN_EXT_SIZE			 4
+#define SSC_RFMR_FSLEN_EXT_OFFSET		28
 #define SSC_RFMR_FSLEN_SIZE			 4
 #define SSC_RFMR_FSLEN_OFFSET			16
 #define SSC_RFMR_FSOS_SIZE			 4
@@ -109,6 +116,12 @@ void ssc_free(struct ssc_device *ssc);
 #define SSC_TFMR_FSDEN_OFFSET			23
 #define SSC_TFMR_FSEDGE_SIZE			 1
 #define SSC_TFMR_FSEDGE_OFFSET			24
+/*
+ * The FSLEN_EXT exist on at91sam9rl, at91sam9g10,
+ * at91sam9g20, and at91sam9g45 and newer SoCs
+ */
+#define SSC_TFMR_FSLEN_EXT_SIZE			 4
+#define SSC_TFMR_FSLEN_EXT_OFFSET		28
 #define SSC_TFMR_FSLEN_SIZE			 4
 #define SSC_TFMR_FSLEN_OFFSET			16
 #define SSC_TFMR_FSOS_SIZE			 3
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index d2c5cc7c583c..3d1c2aa51530 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -299,6 +299,7 @@ enum dma_slave_buswidth {
 	DMA_SLAVE_BUSWIDTH_UNDEFINED = 0,
 	DMA_SLAVE_BUSWIDTH_1_BYTE = 1,
 	DMA_SLAVE_BUSWIDTH_2_BYTES = 2,
+	DMA_SLAVE_BUSWIDTH_3_BYTES = 3,
 	DMA_SLAVE_BUSWIDTH_4_BYTES = 4,
 	DMA_SLAVE_BUSWIDTH_8_BYTES = 8,
 };
diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h
index 6d9371f88875..a614b33d0a39 100644
--- a/include/linux/mfd/arizona/core.h
+++ b/include/linux/mfd/arizona/core.h
@@ -110,6 +110,12 @@ struct arizona {
 	int clk32k_ref;
 
 	struct snd_soc_dapm_context *dapm;
+
+	int tdm_width[ARIZONA_MAX_AIF];
+	int tdm_slots[ARIZONA_MAX_AIF];
+
+	uint16_t dac_comp_coeff;
+	uint8_t dac_comp_enabled;
 };
 
 int arizona_clk32k_enable(struct arizona *arizona);
diff --git a/include/linux/platform_data/asoc-s3c.h b/include/linux/platform_data/asoc-s3c.h
index 709c6f7e2f8c..a6591c693ebb 100644
--- a/include/linux/platform_data/asoc-s3c.h
+++ b/include/linux/platform_data/asoc-s3c.h
@@ -15,15 +15,6 @@
 #define S3C64XX_AC97_GPE  1
 extern void s3c64xx_ac97_setup_gpio(int);
 
-/*
- * The machine init code calls s5p*_spdif_setup_gpio with
- * one of these defines in order to select appropriate bank
- * of GPIO for S/PDIF pins
- */
-#define S5PC100_SPDIF_GPD  0
-#define S5PC100_SPDIF_GPG3 1
-extern void s5pc100_spdif_setup_gpio(int);
-
 struct samsung_i2s {
 /* If the Primary DAI has 5.1 Channels */
 #define QUIRK_PRI_6CHAN		(1 << 0)
diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h
index bcbc6c3c14c0..d05542aafa3e 100644
--- a/include/linux/platform_data/dma-imx.h
+++ b/include/linux/platform_data/dma-imx.h
@@ -50,6 +50,7 @@ enum imx_dma_prio {
 
 struct imx_dma_data {
 	int dma_request; /* DMA request line */
+	int dma_request2; /* secondary DMA request line */
 	enum sdma_peripheral_type peripheral_type;
 	int priority;
 };
diff --git a/include/sound/control.h b/include/sound/control.h
index 5358892b1b39..042613938a1d 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -31,10 +31,15 @@ typedef int (snd_kcontrol_info_t) (struct snd_kcontrol * kcontrol, struct snd_ct
 typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
 typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
 typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol,
-				    int op_flag, /* 0=read,1=write,-1=command */
+				    int op_flag, /* SNDRV_CTL_TLV_OP_XXX */
 				    unsigned int size,
 				    unsigned int __user *tlv);
 
+enum {
+	SNDRV_CTL_TLV_OP_READ = 0,
+	SNDRV_CTL_TLV_OP_WRITE = 1,
+	SNDRV_CTL_TLV_OP_CMD = -1,
+};
 
 struct snd_kcontrol_new {
 	snd_ctl_elem_iface_t iface;	/* interface identifier */
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index d854fb31c000..6f3e10ca0e32 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -931,10 +931,17 @@ void snd_pcm_timer_done(struct snd_pcm_substream *substream);
 static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime,
 				   struct timespec *tv)
 {
-	if (runtime->tstamp_type == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
+	switch (runtime->tstamp_type) {
+	case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC:
 		ktime_get_ts(tv);
-	else
+		break;
+	case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW:
+		getrawmonotonic(tv);
+		break;
+	default:
 		getnstimeofday(tv);
+		break;
+	}
 }
 
 /*
diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h
index f4a706f82cb7..d76412b84b48 100644
--- a/include/sound/rcar_snd.h
+++ b/include/sound/rcar_snd.h
@@ -34,6 +34,7 @@
  * B : SSI direction
  */
 #define RSND_SSI_CLK_PIN_SHARE		(1 << 31)
+#define RSND_SSI_NO_BUSIF		(1 << 30) /* SSI+DMA without BUSIF */
 
 #define RSND_SSI(_dma_id, _pio_irq, _flags)		\
 { .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
diff --git a/include/sound/rt286.h b/include/sound/rt286.h
new file mode 100644
index 000000000000..eb773d1485f2
--- /dev/null
+++ b/include/sound/rt286.h
@@ -0,0 +1,19 @@
+/*
+ * linux/sound/rt286.h -- Platform data for RT286
+ *
+ * Copyright 2013 Realtek Microelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_RT286_H
+#define __LINUX_SND_RT286_H
+
+struct rt286_platform_data {
+	bool cbj_en; /*combo jack enable*/
+	bool gpio2_en; /*GPIO2 enable*/
+};
+
+#endif
diff --git a/include/sound/rt5670.h b/include/sound/rt5670.h
new file mode 100644
index 000000000000..bd311197a3b5
--- /dev/null
+++ b/include/sound/rt5670.h
@@ -0,0 +1,27 @@
+/*
+ * linux/sound/rt5670.h -- Platform data for RT5670
+ *
+ * Copyright 2014 Realtek Microelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_RT5670_H
+#define __LINUX_SND_RT5670_H
+
+struct rt5670_platform_data {
+	int jd_mode;
+	bool in2_diff;
+
+	bool dmic_en;
+	unsigned int dmic1_data_pin;
+	/* 0 = GPIO6; 1 = IN2P; 3 = GPIO7*/
+	unsigned int dmic2_data_pin;
+	/* 0 = GPIO8; 1 = IN3N; */
+	unsigned int dmic3_data_pin;
+	/* 0 = GPIO9; 1 = GPIO10; 2 = GPIO5*/
+};
+
+#endif
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 688f2ba8009f..e8b3080d196a 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -257,7 +257,6 @@ struct snd_soc_dai {
 
 	struct snd_soc_dapm_widget *playback_widget;
 	struct snd_soc_dapm_widget *capture_widget;
-	struct snd_soc_dapm_context dapm;
 
 	/* DAI DMA data */
 	void *playback_dma_data;
@@ -273,6 +272,10 @@ struct snd_soc_dai {
 	struct snd_soc_codec *codec;
 	struct snd_soc_component *component;
 
+	/* CODEC TDM slot masks and params (for fixup) */
+	unsigned int tx_mask;
+	unsigned int rx_mask;
+
 	struct snd_soc_card *card;
 
 	struct list_head list;
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 6b59471cdf44..aac04ff84eea 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -431,7 +431,7 @@ int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
 					   const char *pin);
 int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
 				const char *pin);
-void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
+void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card);
 
 /* Mostly internal - should not normally be used */
 void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
@@ -441,6 +441,8 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
 	struct snd_soc_dapm_widget_list **list);
 
 struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol);
+struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(
+	struct snd_kcontrol *kcontrol);
 
 /* dapm widget types */
 enum snd_soc_dapm_type {
@@ -524,7 +526,6 @@ struct snd_soc_dapm_widget {
 	const char *name;		/* widget name */
 	const char *sname;	/* stream name */
 	struct snd_soc_codec *codec;
-	struct snd_soc_platform *platform;
 	struct list_head list;
 	struct snd_soc_dapm_context *dapm;
 
@@ -593,7 +594,6 @@ struct snd_soc_dapm_context {
 	struct device *dev; /* from parent - for debug */
 	struct snd_soc_component *component; /* parent component */
 	struct snd_soc_codec *codec; /* parent codec */
-	struct snd_soc_platform *platform; /* parent platform */
 	struct snd_soc_card *card; /* parent card */
 
 	/* used during DAPM updates */
@@ -601,6 +601,8 @@ struct snd_soc_dapm_context {
 	struct list_head list;
 
 	int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
+	int (*set_bias_level)(struct snd_soc_dapm_context *dapm,
+			      enum snd_soc_bias_level level);
 
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_dapm;
diff --git a/include/sound/soc.h b/include/sound/soc.h
index ed9e2d7e5fdc..be6ecae247b0 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -248,6 +248,8 @@
 	.info = snd_soc_info_enum_double, \
 	.get = xhandler_get, .put = xhandler_put, \
 	.private_value = (unsigned long)&xenum }
+#define SOC_VALUE_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
+	SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put)
 
 #define SND_SOC_BYTES(xname, xbase, xregs)		      \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,   \
@@ -270,7 +272,14 @@
 	.get = xhandler_get, .put = xhandler_put, \
 	.private_value = (unsigned long)&(struct soc_bytes_ext) \
 		{.max = xcount} }
-
+#define SND_SOC_BYTES_TLV(xname, xcount, xhandler_get, xhandler_put) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE | \
+		  SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
+	.tlv.c = (snd_soc_bytes_tlv_callback), \
+	.info = snd_soc_info_bytes_ext, \
+	.private_value = (unsigned long)&(struct soc_bytes_ext) \
+		{.max = xcount, .get = xhandler_get, .put = xhandler_put, } }
 #define SOC_SINGLE_XR_SX(xname, xregbase, xregcount, xnbits, \
 		xmin, xmax, xinvert) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
@@ -436,6 +445,10 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
 int snd_soc_platform_trigger(struct snd_pcm_substream *substream,
 		int cmd, struct snd_soc_platform *platform);
 
+int soc_dai_hw_params(struct snd_pcm_substream *substream,
+		      struct snd_pcm_hw_params *params,
+		      struct snd_soc_dai *dai);
+
 /* Jack reporting */
 int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
 		     struct snd_soc_jack *jack);
@@ -503,10 +516,12 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
 				  const char *prefix);
 struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
 					       const char *name);
+int snd_soc_add_component_controls(struct snd_soc_component *component,
+	const struct snd_kcontrol_new *controls, unsigned int num_controls);
 int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
-	const struct snd_kcontrol_new *controls, int num_controls);
+	const struct snd_kcontrol_new *controls, unsigned int num_controls);
 int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
-	const struct snd_kcontrol_new *controls, int num_controls);
+	const struct snd_kcontrol_new *controls, unsigned int num_controls);
 int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
 	const struct snd_kcontrol_new *controls, int num_controls);
 int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
@@ -552,6 +567,8 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
 		      struct snd_ctl_elem_value *ucontrol);
 int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *ucontrol);
+int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
+	unsigned int size, unsigned int __user *tlv);
 int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *uinfo);
 int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
@@ -677,12 +694,17 @@ struct snd_soc_component_driver {
 	int (*of_xlate_dai_name)(struct snd_soc_component *component,
 				 struct of_phandle_args *args,
 				 const char **dai_name);
+	void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type,
+		int subseq);
+	int (*stream_event)(struct snd_soc_component *, int event);
 };
 
 struct snd_soc_component {
 	const char *name;
 	int id;
+	const char *name_prefix;
 	struct device *dev;
+	struct snd_soc_card *card;
 
 	unsigned int active;
 
@@ -705,18 +727,18 @@ struct snd_soc_component {
 	int val_bytes;
 
 	struct mutex io_mutex;
+
+	/* Don't use these, use snd_soc_component_get_dapm() */
+	struct snd_soc_dapm_context dapm;
+	struct snd_soc_dapm_context *dapm_ptr;
 };
 
 /* SoC Audio Codec device */
 struct snd_soc_codec {
-	const char *name;
-	const char *name_prefix;
-	int id;
 	struct device *dev;
 	const struct snd_soc_codec_driver *driver;
 
 	struct mutex mutex;
-	struct snd_soc_card *card;
 	struct list_head list;
 	struct list_head card_list;
 
@@ -790,9 +812,6 @@ struct snd_soc_codec_driver {
 	void (*seq_notifier)(struct snd_soc_dapm_context *,
 			     enum snd_soc_dapm_type, int);
 
-	/* codec stream completion event */
-	int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
-
 	bool ignore_pmdown_time;  /* Doesn't benefit from pmdown delay */
 
 	/* probe ordering - for components with runtime dependencies */
@@ -834,9 +853,6 @@ struct snd_soc_platform_driver {
 	/* platform stream compress ops */
 	const struct snd_compr_ops *compr_ops;
 
-	/* platform stream completion event */
-	int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
-
 	/* probe ordering - for components with runtime dependencies */
 	int probe_order;
 	int remove_order;
@@ -847,23 +863,23 @@ struct snd_soc_platform_driver {
 	int (*bespoke_trigger)(struct snd_pcm_substream *, int);
 };
 
-struct snd_soc_platform {
+struct snd_soc_dai_link_component {
 	const char *name;
-	int id;
+	const struct device_node *of_node;
+	const char *dai_name;
+};
+
+struct snd_soc_platform {
 	struct device *dev;
 	const struct snd_soc_platform_driver *driver;
 
 	unsigned int suspended:1; /* platform is suspended */
 	unsigned int probed:1;
 
-	struct snd_soc_card *card;
 	struct list_head list;
-	struct list_head card_list;
 
 	struct snd_soc_component component;
 
-	struct snd_soc_dapm_context dapm;
-
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_platform_root;
 #endif
@@ -896,6 +912,10 @@ struct snd_soc_dai_link {
 	const struct device_node *codec_of_node;
 	/* You MUST specify the DAI name within the codec */
 	const char *codec_dai_name;
+
+	struct snd_soc_dai_link_component *codecs;
+	unsigned int num_codecs;
+
 	/*
 	 * You MAY specify the link's platform/PCM/DMA driver, either by
 	 * device name, or by DT/OF node, but not both. Some forms of link
@@ -1047,7 +1067,6 @@ struct snd_soc_card {
 
 	/* lists of probed devices belonging to this card */
 	struct list_head codec_dev_list;
-	struct list_head platform_dev_list;
 
 	struct list_head widgets;
 	struct list_head paths;
@@ -1094,6 +1113,9 @@ struct snd_soc_pcm_runtime {
 	struct snd_soc_dai *codec_dai;
 	struct snd_soc_dai *cpu_dai;
 
+	struct snd_soc_dai **codec_dais;
+	unsigned int num_codecs;
+
 	struct delayed_work delayed_work;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_dpcm_root;
@@ -1119,6 +1141,9 @@ struct soc_bytes {
 
 struct soc_bytes_ext {
 	int max;
+	/* used for TLV byte control */
+	int (*get)(unsigned int __user *bytes, unsigned int size);
+	int (*put)(const unsigned int __user *bytes, unsigned int size);
 };
 
 /* multi register control */
@@ -1165,6 +1190,21 @@ static inline struct snd_soc_platform *snd_soc_component_to_platform(
 }
 
 /**
+ * snd_soc_dapm_to_component() - Casts a DAPM context to the component it is
+ *  embedded in
+ * @dapm: The DAPM context to cast to the component
+ *
+ * This function must only be used on DAPM contexts that are known to be part of
+ * a component (e.g. in a component driver). Otherwise the behavior is
+ * undefined.
+ */
+static inline struct snd_soc_component *snd_soc_dapm_to_component(
+	struct snd_soc_dapm_context *dapm)
+{
+	return container_of(dapm, struct snd_soc_component, dapm);
+}
+
+/**
  * snd_soc_dapm_to_codec() - Casts a DAPM context to the CODEC it is embedded in
  * @dapm: The DAPM context to cast to the CODEC
  *
@@ -1188,7 +1228,18 @@ static inline struct snd_soc_codec *snd_soc_dapm_to_codec(
 static inline struct snd_soc_platform *snd_soc_dapm_to_platform(
 	struct snd_soc_dapm_context *dapm)
 {
-	return container_of(dapm, struct snd_soc_platform, dapm);
+	return snd_soc_component_to_platform(snd_soc_dapm_to_component(dapm));
+}
+
+/**
+ * snd_soc_component_get_dapm() - Returns the DAPM context associated with a
+ *  component
+ * @component: The component for which to get the DAPM context
+ */
+static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm(
+	struct snd_soc_component *component)
+{
+	return component->dapm_ptr;
 }
 
 /* codec IO */
@@ -1261,7 +1312,6 @@ static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd)
 static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
 {
 	INIT_LIST_HEAD(&card->codec_dev_list);
-	INIT_LIST_HEAD(&card->platform_dev_list);
 	INIT_LIST_HEAD(&card->widgets);
 	INIT_LIST_HEAD(&card->paths);
 	INIT_LIST_HEAD(&card->dapm_list);
diff --git a/include/sound/tas2552-plat.h b/include/sound/tas2552-plat.h
new file mode 100644
index 000000000000..65e7627ba38e
--- /dev/null
+++ b/include/sound/tas2552-plat.h
@@ -0,0 +1,25 @@
+/*
+ * TAS2552 driver platform header
+ *
+ * Copyright (C) 2014 Texas Instruments Inc.
+ *
+ * Author: Dan Murphy <dmurphy@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef TAS2552_PLAT_H
+#define TAS2552_PLAT_H
+
+struct tas2552_platform_data {
+	int enable_gpio;
+};
+
+#endif
diff --git a/include/sound/wm8962.h b/include/sound/wm8962.h
index 79e6d427b858..0af7c1674cbf 100644
--- a/include/sound/wm8962.h
+++ b/include/sound/wm8962.h
@@ -37,6 +37,7 @@
 #define WM8962_GPIO_FN_MICSCD          22
 
 struct wm8962_pdata {
+	struct clk *mclk;
 	int gpio_base;
 	u32 gpio_init[WM8962_MAX_GPIO];
 
diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h
index c75c795a377b..0194a641e4e2 100644
--- a/include/trace/events/asoc.h
+++ b/include/trace/events/asoc.h
@@ -296,17 +296,17 @@ TRACE_EVENT(snd_soc_cache_sync,
 	TP_ARGS(codec, type, status),
 
 	TP_STRUCT__entry(
-		__string(	name,		codec->name	)
+		__string(	name,		codec->component.name)
 		__string(	status,		status		)
 		__string(	type,		type		)
 		__field(	int,		id		)
 	),
 
 	TP_fast_assign(
-		__assign_str(name, codec->name);
+		__assign_str(name, codec->component.name);
 		__assign_str(status, status);
 		__assign_str(type, type);
-		__entry->id = codec->id;
+		__entry->id = codec->component.id;
 	),
 
 	TP_printk("codec=%s.%d type=%s status=%s", __get_str(name),
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index 224948342f14..32168f7ffce3 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -139,7 +139,7 @@ struct snd_hwdep_dsp_image {
  *                                                                           *
  *****************************************************************************/
 
-#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 11)
+#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 12)
 
 typedef unsigned long snd_pcm_uframes_t;
 typedef signed long snd_pcm_sframes_t;
@@ -391,7 +391,9 @@ struct snd_pcm_sw_params {
 	snd_pcm_uframes_t silence_threshold;	/* min distance from noise for silence filling */
 	snd_pcm_uframes_t silence_size;		/* silence block size */
 	snd_pcm_uframes_t boundary;		/* pointers wrap point */
-	unsigned char reserved[64];		/* reserved for future */
+	unsigned int proto;			/* protocol version */
+	unsigned int tstamp_type;		/* timestamp type (req. proto >= 2.0.12) */
+	unsigned char reserved[56];		/* reserved for future */
 };
 
 struct snd_pcm_channel_info {
@@ -462,7 +464,8 @@ struct snd_xfern {
 enum {
 	SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0,	/* gettimeofday equivalent */
 	SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,	/* posix_clock_monotonic equivalent */
-	SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+	SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW,    /* monotonic_raw (no NTP) */
+	SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW,
 };
 
 /* channel positions */
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c
index 467836057ee5..a80d5ea87ccd 100644
--- a/sound/aoa/soundbus/i2sbus/core.c
+++ b/sound/aoa/soundbus/i2sbus/core.c
@@ -47,15 +47,11 @@ static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
 	/* We use the PCI APIs for now until the generic one gets fixed
 	 * enough or until we get some macio-specific versions
 	 */
-	r->space = dma_alloc_coherent(
-			&macio_get_pci_dev(i2sdev->macio)->dev,
-			r->size,
-			&r->bus_addr,
-			GFP_KERNEL);
+	r->space = dma_zalloc_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
+				       r->size, &r->bus_addr, GFP_KERNEL);
+	if (!r->space)
+		return -ENOMEM;
 
-	if (!r->space) return -ENOMEM;
-
-	memset(r->space, 0, r->size);
 	r->cmds = (void*)DBDMA_ALIGN(r->space);
 	r->bus_cmd_start = r->bus_addr +
 			   (dma_addr_t)((char*)r->cmds - (char*)r->space);
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index 66de90ed30ca..39c3969ac1c7 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -152,9 +152,9 @@ static inline void pxa_ac97_cold_pxa27x(void)
 	gsr_bits = 0;
 
 	/* PXA27x Developers Manual section 13.5.2.2.1 */
-	clk_enable(ac97conf_clk);
+	clk_prepare_enable(ac97conf_clk);
 	udelay(5);
-	clk_disable(ac97conf_clk);
+	clk_disable_unprepare(ac97conf_clk);
 	GCR = GCR_COLD_RST | GCR_WARM_RST;
 }
 #endif
@@ -299,14 +299,14 @@ static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
 int pxa2xx_ac97_hw_suspend(void)
 {
 	GCR |= GCR_ACLINK_OFF;
-	clk_disable(ac97_clk);
+	clk_disable_unprepare(ac97_clk);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);
 
 int pxa2xx_ac97_hw_resume(void)
 {
-	clk_enable(ac97_clk);
+	clk_prepare_enable(ac97_clk);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
@@ -368,7 +368,7 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev)
 		goto err_clk;
 	}
 
-	ret = clk_enable(ac97_clk);
+	ret = clk_prepare_enable(ac97_clk);
 	if (ret)
 		goto err_clk2;
 
@@ -403,7 +403,7 @@ void pxa2xx_ac97_hw_remove(struct platform_device *dev)
 		clk_put(ac97conf_clk);
 		ac97conf_clk = NULL;
 	}
-	clk_disable(ac97_clk);
+	clk_disable_unprepare(ac97_clk);
 	clk_put(ac97_clk);
 	ac97_clk = NULL;
 }
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 7403f348ed14..89028fab64fd 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -491,7 +491,7 @@ static int snd_compress_check_input(struct snd_compr_params *params)
 {
 	/* first let's check the buffer parameter's */
 	if (params->buffer.fragment_size == 0 ||
-			params->buffer.fragments > SIZE_MAX / params->buffer.fragment_size)
+	    params->buffer.fragments > INT_MAX / params->buffer.fragment_size)
 		return -EINVAL;
 
 	/* now codec parameters */
diff --git a/sound/core/control.c b/sound/core/control.c
index f0b0e14497a5..b9611344ff9e 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1406,11 +1406,11 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
 	case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
 		return snd_ctl_subscribe_events(ctl, ip);
 	case SNDRV_CTL_IOCTL_TLV_READ:
-		return snd_ctl_tlv_ioctl(ctl, argp, 0);
+		return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ);
 	case SNDRV_CTL_IOCTL_TLV_WRITE:
-		return snd_ctl_tlv_ioctl(ctl, argp, 1);
+		return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE);
 	case SNDRV_CTL_IOCTL_TLV_COMMAND:
-		return snd_ctl_tlv_ioctl(ctl, argp, -1);
+		return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD);
 	case SNDRV_CTL_IOCTL_POWER:
 		return -ENOPROTOOPT;
 	case SNDRV_CTL_IOCTL_POWER_STATE:
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index af49721ba0e3..102e8fd1d450 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -101,7 +101,9 @@ struct snd_pcm_sw_params32 {
 	u32 silence_threshold;
 	u32 silence_size;
 	u32 boundary;
-	unsigned char reserved[64];
+	u32 proto;
+	u32 tstamp_type;
+	unsigned char reserved[56];
 };
 
 /* recalcuate the boundary within 32bit */
@@ -133,7 +135,9 @@ static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream,
 	    get_user(params.start_threshold, &src->start_threshold) ||
 	    get_user(params.stop_threshold, &src->stop_threshold) ||
 	    get_user(params.silence_threshold, &src->silence_threshold) ||
-	    get_user(params.silence_size, &src->silence_size))
+	    get_user(params.silence_size, &src->silence_size) ||
+	    get_user(params.tstamp_type, &src->tstamp_type) ||
+	    get_user(params.proto, &src->proto))
 		return -EFAULT;
 	/*
 	 * Check silent_size parameter.  Since we have 64bit boundary,
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index 76cbb9ec953a..6542c4083594 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -65,13 +65,15 @@ int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
 	enum dma_slave_buswidth buswidth;
 	int bits;
 
-	bits = snd_pcm_format_physical_width(params_format(params));
+	bits = params_physical_width(params);
 	if (bits < 8 || bits > 64)
 		return -EINVAL;
 	else if (bits == 8)
 		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
 	else if (bits == 16)
 		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	else if (bits == 24)
+		buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES;
 	else if (bits <= 32)
 		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
 	else
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index b653ab001fba..8cd2f930ad0b 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -543,6 +543,9 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
 
 	if (params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST)
 		return -EINVAL;
+	if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12) &&
+	    params->tstamp_type > SNDRV_PCM_TSTAMP_TYPE_LAST)
+		return -EINVAL;
 	if (params->avail_min == 0)
 		return -EINVAL;
 	if (params->silence_size >= runtime->boundary) {
@@ -557,6 +560,8 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
 	err = 0;
 	snd_pcm_stream_lock_irq(substream);
 	runtime->tstamp_mode = params->tstamp_mode;
+	if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12))
+		runtime->tstamp_type = params->tstamp_type;
 	runtime->period_step = params->period_step;
 	runtime->control->avail_min = params->avail_min;
 	runtime->start_threshold = params->start_threshold;
@@ -2540,9 +2545,7 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
 		return -EFAULT;
 	if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST)
 		return -EINVAL;
-	runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
-	if (arg == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
-		runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
+	runtime->tstamp_type = arg;
 	return 0;
 }
 		
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index 1e206de0c2dd..ba8e4a64e13e 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -101,9 +101,9 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
 			len -= size;
 		}
 		return 0;
-	} if (! (event->data.ext.len & SNDRV_SEQ_EXT_CHAINED)) {
-		return func(private_data, event->data.ext.ptr, len);
 	}
+	if (!(event->data.ext.len & SNDRV_SEQ_EXT_CHAINED))
+		return func(private_data, event->data.ext.ptr, len);
 
 	cell = (struct snd_seq_event_cell *)event->data.ext.ptr;
 	for (; len > 0 && cell; cell = cell->next) {
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig
index 775ef2efc296..46dff64908c8 100644
--- a/sound/firewire/Kconfig
+++ b/sound/firewire/Kconfig
@@ -83,8 +83,8 @@ config SND_BEBOB
 	  * Edirol FA-66/FA-101
 	  * PreSonus FIREBOX/FIREPOD/FP10/Inspire1394
 	  * BridgeCo RDAudio1/Audio5
-	  * Mackie Onyx 1220/1620/1640 (Firewire I/O Card)
-	  * Mackie d.2 (Firewire Option)
+	  * Mackie Onyx 1220/1620/1640 (FireWire I/O Card)
+	  * Mackie d.2 (FireWire Option)
 	  * Stanton FinalScratch 2 (ScratchAmp)
 	  * Tascam IF-FW/DM
 	  * Behringer XENIX UFX 1204/1604
@@ -92,7 +92,7 @@ config SND_BEBOB
 	  * Apogee Rosetta 200/400 (X-FireWire card)
 	  * Apogee DA/AD/DD-16X (X-FireWire card)
 	  * Apogee Ensemble
-	  * ESI Quotafire610
+	  * ESI QuataFire 610
 	  * AcousticReality eARMasterOne
 	  * CME MatrixKFW
 	  * Phonic Helix Board 12 MkII/18 MkII/24 MkII
@@ -101,13 +101,13 @@ config SND_BEBOB
 	  * ICON FireXon
 	  * PrismSound Orpheus/ADA-8XR
 	  * TerraTec PHASE 24 FW/PHASE X24 FW/PHASE 88 Rack FW
-	  * Terratec EWS MIC2/EWS MIC4
-	  * Terratec Aureon 7.1 Firewire
+	  * TerraTec EWS MIC2/EWS MIC8
+	  * TerraTec Aureon 7.1 FireWire
 	  * Yamaha GO44/GO46
 	  * Focusrite Saffire/Saffire LE/SaffirePro10 IO/SaffirePro26 IO
-	  * M-Audio Firewire410/AudioPhile/Solo
+	  * M-Audio FireWire410/AudioPhile/Solo
 	  * M-Audio Ozonic/NRV10/ProfireLightBridge
-	  * M-Audio Firewire 1814/ProjectMix IO
+	  * M-Audio FireWire 1814/ProjectMix IO
 
           To compile this driver as a module, choose M here: the module
           will be called snd-bebob.
diff --git a/sound/firewire/fireworks/fireworks_proc.c b/sound/firewire/fireworks/fireworks_proc.c
index f29d4aaf56a1..0639dcb13f7d 100644
--- a/sound/firewire/fireworks/fireworks_proc.c
+++ b/sound/firewire/fireworks/fireworks_proc.c
@@ -64,7 +64,7 @@ proc_read_hwinfo(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 		    hwinfo->phys_in_grp_count);
 	for (i = 0; i < hwinfo->phys_in_grp_count; i++) {
 		snd_iprintf(buffer,
-			    "phys in grp[0x%d]: type 0x%d, count 0x%d\n",
+			    "phys in grp[%d]: type 0x%X, count 0x%X\n",
 			    i, hwinfo->phys_out_grps[i].type,
 			    hwinfo->phys_out_grps[i].count);
 	}
@@ -73,7 +73,7 @@ proc_read_hwinfo(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 		    hwinfo->phys_out_grp_count);
 	for (i = 0; i < hwinfo->phys_out_grp_count; i++) {
 		snd_iprintf(buffer,
-			    "phys out grps[0x%d]: type 0x%d, count 0x%d\n",
+			    "phys out grps[%d]: type 0x%X, count 0x%X\n",
 			    i, hwinfo->phys_out_grps[i].type,
 			    hwinfo->phys_out_grps[i].count);
 	}
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c
index 3bbc3ec5be82..862735005b43 100644
--- a/sound/oss/mpu401.c
+++ b/sound/oss/mpu401.c
@@ -316,6 +316,7 @@ static int mpu_input_scanner(struct mpu_config *devc, unsigned char midic)
 				case 0xf6:
 					/* printk( "tune_request\n"); */
 					devc->m_state = ST_INIT;
+					break;
 
 					/*
 					 *    Real time messages
@@ -972,7 +973,6 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner)
 	devc->m_busy = 0;
 	devc->m_state = ST_INIT;
 	devc->shared_irq = hw_config->always_detect;
-	devc->irq = hw_config->irq;
 	spin_lock_init(&devc->lock);
 
 	if (devc->irq < 0)
diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c
index 4709e592e2cc..607cee4d545e 100644
--- a/sound/oss/opl3.c
+++ b/sound/oss/opl3.c
@@ -52,7 +52,7 @@ struct voice_info
 	int             panning;	/* 0xffff means not set */
 };
 
-typedef struct opl_devinfo
+struct opl_devinfo
 {
 	int             base;
 	int             left_io, right_io;
@@ -73,7 +73,7 @@ typedef struct opl_devinfo
 	unsigned char   cmask;
 
 	int             is_opl4;
-} opl_devinfo;
+};
 
 static struct opl_devinfo *devc = NULL;
 
diff --git a/sound/oss/pss.c b/sound/oss/pss.c
index 145e36b2cfd0..ca0d6e9f49f5 100644
--- a/sound/oss/pss.c
+++ b/sound/oss/pss.c
@@ -123,25 +123,25 @@ static bool pss_mixer;
 #endif
 
 
-typedef struct pss_mixerdata {
+struct pss_mixerdata {
 	unsigned int volume_l;
 	unsigned int volume_r;
 	unsigned int bass;
 	unsigned int treble;
 	unsigned int synth;
-} pss_mixerdata;
+};
 
-typedef struct pss_confdata {
+struct pss_confdata {
 	int             base;
 	int             irq;
 	int             dma;
 	int            *osp;
-	pss_mixerdata   mixer;
+	struct pss_mixerdata mixer;
 	int             ad_mixer_dev;
-} pss_confdata;
+};
   
-static pss_confdata pss_data;
-static pss_confdata *devc = &pss_data;
+static struct pss_confdata pss_data;
+static struct pss_confdata *devc = &pss_data;
 static DEFINE_SPINLOCK(lock);
 
 static int      pss_initialized;
@@ -150,7 +150,7 @@ static int	pss_cdrom_port = -1;	/* Parameter for the PSS cdrom port */
 static bool	pss_enable_joystick;    /* Parameter for enabling the joystick */
 static coproc_operations pss_coproc_operations;
 
-static void pss_write(pss_confdata *devc, int data)
+static void pss_write(struct pss_confdata *devc, int data)
 {
 	unsigned long i, limit;
 
@@ -206,7 +206,7 @@ static int __init probe_pss(struct address_info *hw_config)
 	return 1;
 }
 
-static int set_irq(pss_confdata * devc, int dev, int irq)
+static int set_irq(struct pss_confdata *devc, int dev, int irq)
 {
 	static unsigned short irq_bits[16] =
 	{
@@ -232,7 +232,7 @@ static int set_irq(pss_confdata * devc, int dev, int irq)
 	return 1;
 }
 
-static void set_io_base(pss_confdata * devc, int dev, int base)
+static void set_io_base(struct pss_confdata *devc, int dev, int base)
 {
 	unsigned short  tmp = inw(REG(dev)) & 0x003f;
 	unsigned short  bits = (base & 0x0ffc) << 4;
@@ -240,7 +240,7 @@ static void set_io_base(pss_confdata * devc, int dev, int base)
 	outw(bits | tmp, REG(dev));
 }
 
-static int set_dma(pss_confdata * devc, int dev, int dma)
+static int set_dma(struct pss_confdata *devc, int dev, int dma)
 {
 	static unsigned short dma_bits[8] =
 	{
@@ -264,7 +264,7 @@ static int set_dma(pss_confdata * devc, int dev, int dma)
 	return 1;
 }
 
-static int pss_reset_dsp(pss_confdata * devc)
+static int pss_reset_dsp(struct pss_confdata *devc)
 {
 	unsigned long   i, limit = jiffies + HZ/10;
 
@@ -275,7 +275,7 @@ static int pss_reset_dsp(pss_confdata * devc)
 	return 1;
 }
 
-static int pss_put_dspword(pss_confdata * devc, unsigned short word)
+static int pss_put_dspword(struct pss_confdata *devc, unsigned short word)
 {
 	int i, val;
 
@@ -291,7 +291,7 @@ static int pss_put_dspword(pss_confdata * devc, unsigned short word)
 	return 0;
 }
 
-static int pss_get_dspword(pss_confdata * devc, unsigned short *word)
+static int pss_get_dspword(struct pss_confdata *devc, unsigned short *word)
 {
 	int i, val;
 
@@ -307,7 +307,8 @@ static int pss_get_dspword(pss_confdata * devc, unsigned short *word)
 	return 0;
 }
 
-static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size, int flags)
+static int pss_download_boot(struct pss_confdata *devc, unsigned char *block,
+			     int size, int flags)
 {
 	int i, val, count;
 	unsigned long limit;
@@ -397,7 +398,7 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size
 }
 
 /* Mixer */
-static void set_master_volume(pss_confdata *devc, int left, int right)
+static void set_master_volume(struct pss_confdata *devc, int left, int right)
 {
 	static unsigned char log_scale[101] =  {
 		0xdb, 0xe0, 0xe3, 0xe5, 0xe7, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee,
@@ -416,7 +417,7 @@ static void set_master_volume(pss_confdata *devc, int left, int right)
 	pss_write(devc, log_scale[right] | 0x0100);
 }
 
-static void set_synth_volume(pss_confdata *devc, int volume)
+static void set_synth_volume(struct pss_confdata *devc, int volume)
 {
 	int vol = ((0x8000*volume)/100L);
 	pss_write(devc, 0x0080);
@@ -425,21 +426,21 @@ static void set_synth_volume(pss_confdata *devc, int volume)
 	pss_write(devc, vol);
 }
 
-static void set_bass(pss_confdata *devc, int level)
+static void set_bass(struct pss_confdata *devc, int level)
 {
 	int vol = (int)(((0xfd - 0xf0) * level)/100L) + 0xf0;
 	pss_write(devc, 0x0010);
 	pss_write(devc, vol | 0x0200);
 };
 
-static void set_treble(pss_confdata *devc, int level)
+static void set_treble(struct pss_confdata *devc, int level)
 {	
 	int vol = (((0xfd - 0xf0) * level)/100L) + 0xf0;
 	pss_write(devc, 0x0010);
 	pss_write(devc, vol | 0x0300);
 };
 
-static void pss_mixer_reset(pss_confdata *devc)
+static void pss_mixer_reset(struct pss_confdata *devc)
 {
 	set_master_volume(devc, 33, 33);
 	set_bass(devc, 50);
@@ -499,7 +500,8 @@ static int ret_vol_stereo(int left, int right)
 	return ((right << 8) | left);
 }
 
-static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, void __user *arg)
+static int call_ad_mixer(struct pss_confdata *devc, unsigned int cmd,
+			 void __user *arg)
 {
 	if (devc->ad_mixer_dev != NO_WSS_MIXER) 
 		return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, cmd, arg);
@@ -509,7 +511,7 @@ static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, void __user *arg)
 
 static int pss_mixer_ioctl (int dev, unsigned int cmd, void __user *arg)
 {
-	pss_confdata *devc = mixer_devs[dev]->devc;
+	struct pss_confdata *devc = mixer_devs[dev]->devc;
 	int cmdf = cmd & 0xff;
 	
 	if ((cmdf != SOUND_MIXER_VOLUME) && (cmdf != SOUND_MIXER_BASS) &&
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 3a3a3a71088b..50dd0086cfb1 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -858,8 +858,8 @@ config SND_VIRTUOSO
 	select SND_JACK if INPUT=y || INPUT=SND
 	help
 	  Say Y here to include support for sound cards based on the
-	  Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS,
-	  Essence ST (Deluxe), and Essence STX.
+	  Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS, DSX,
+	  Essence ST (Deluxe), and Essence STX (II).
 	  Support for the HDAV1.3 (Deluxe) and HDAV1.3 Slim is experimental;
 	  for the Xense, missing.
 
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 9f10c9e0df5e..631aaa4046ad 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -1754,9 +1754,6 @@ static struct snd_kcontrol_new snd_echo_vumeters_switch = {
 static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_info *uinfo)
 {
-	struct echoaudio *chip;
-
-	chip = snd_kcontrol_chip(kcontrol);
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = 96;
 	uinfo->value.integer.min = ECHOGAIN_MINOUT;
@@ -1798,9 +1795,6 @@ static struct snd_kcontrol_new snd_echo_vumeters = {
 static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
-	struct echoaudio *chip;
-
-	chip = snd_kcontrol_chip(kcontrol);
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = 6;
 	uinfo->value.integer.min = 0;
diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c
new file mode 100644
index 000000000000..9c22f95838ef
--- /dev/null
+++ b/sound/pci/hda/dell_wmi_helper.c
@@ -0,0 +1,76 @@
+/* Helper functions for Dell Mic Mute LED control;
+ * to be included from codec driver
+ */
+
+#if IS_ENABLED(CONFIG_LEDS_DELL_NETBOOKS)
+#include <linux/dell-led.h>
+
+static int dell_led_value;
+static int (*dell_led_set_func)(int, int);
+static void (*dell_old_cap_hook)(struct hda_codec *,
+			         struct snd_kcontrol *,
+				 struct snd_ctl_elem_value *);
+
+static void update_dell_wmi_micmute_led(struct hda_codec *codec,
+				        struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	if (dell_old_cap_hook)
+		dell_old_cap_hook(codec, kcontrol, ucontrol);
+
+	if (!ucontrol || !dell_led_set_func)
+		return;
+	if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
+		/* TODO: How do I verify if it's a mono or stereo here? */
+		int val = (ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]) ? 0 : 1;
+		if (val == dell_led_value)
+			return;
+		dell_led_value = val;
+		if (dell_led_set_func)
+			dell_led_set_func(DELL_LED_MICMUTE, dell_led_value);
+	}
+}
+
+
+static void alc_fixup_dell_wmi(struct hda_codec *codec,
+			       const struct hda_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	bool removefunc = false;
+
+	if (action == HDA_FIXUP_ACT_PROBE) {
+		if (!dell_led_set_func)
+			dell_led_set_func = symbol_request(dell_app_wmi_led_set);
+		if (!dell_led_set_func) {
+			codec_warn(codec, "Failed to find dell wmi symbol dell_app_wmi_led_set\n");
+			return;
+		}
+
+		removefunc = true;
+		if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) {
+			dell_led_value = 0;
+			if (spec->gen.num_adc_nids > 1)
+				codec_dbg(codec, "Skipping micmute LED control due to several ADCs");
+			else {
+				dell_old_cap_hook = spec->gen.cap_sync_hook;
+				spec->gen.cap_sync_hook = update_dell_wmi_micmute_led;
+				removefunc = false;
+			}
+		}
+
+	}
+
+	if (dell_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
+		symbol_put(dell_app_wmi_led_set);
+		dell_led_set_func = NULL;
+		dell_old_cap_hook = NULL;
+	}
+}
+
+#else /* CONFIG_LEDS_DELL_NETBOOKS */
+static void alc_fixup_dell_wmi(struct hda_codec *codec,
+			       const struct hda_fixup *fix, int action)
+{
+}
+
+#endif /* CONFIG_LEDS_DELL_NETBOOKS */
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index dabe41975a9d..51dea49aadd4 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -17,8 +17,6 @@
 #include "hda_local.h"
 #include "hda_auto_parser.h"
 
-#define SFX	"hda_codec: "
-
 /*
  * Helper for automatic pin configuration
  */
@@ -856,7 +854,7 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec,
 {
 	const struct snd_hda_pin_quirk *pq;
 
-	if (codec->fixup_forced)
+	if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
 		return;
 
 	for (pq = pin_quirk; pq->subvendor; pq++) {
@@ -882,14 +880,17 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
 			const struct hda_fixup *fixlist)
 {
 	const struct snd_pci_quirk *q;
-	int id = -1;
+	int id = HDA_FIXUP_ID_NOT_SET;
 	const char *name = NULL;
 
+	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_id = -1;
-		codec->fixup_forced = 1;
+		codec->fixup_name = NULL;
+		codec->fixup_id = HDA_FIXUP_ID_NO_FIXUP;
 		return;
 	}
 
@@ -899,13 +900,12 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
 				codec->fixup_id = models->id;
 				codec->fixup_name = models->name;
 				codec->fixup_list = fixlist;
-				codec->fixup_forced = 1;
 				return;
 			}
 			models++;
 		}
 	}
-	if (id < 0 && quirk) {
+	if (quirk) {
 		q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
 		if (q) {
 			id = q->value;
@@ -929,7 +929,6 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
 		}
 	}
 
-	codec->fixup_forced = 0;
 	codec->fixup_id = id;
 	if (id >= 0) {
 		codec->fixup_list = fixlist;
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 4c20277a6835..ec6a7d0d1886 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1476,6 +1476,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
 
 	INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
 	codec->depop_delay = -1;
+	codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
 
 #ifdef CONFIG_PM
 	spin_lock_init(&codec->power_lock);
@@ -2727,7 +2728,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
 	return 0;
 }
 
-typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *);
+typedef int (*map_slave_func_t)(struct hda_codec *, void *, struct snd_kcontrol *);
 
 /* apply the function to all matching slave ctls in the mixer list */
 static int map_slaves(struct hda_codec *codec, const char * const *slaves,
@@ -2751,7 +2752,7 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves,
 				name = tmpname;
 			}
 			if (!strcmp(sctl->id.name, name)) {
-				err = func(data, sctl);
+				err = func(codec, data, sctl);
 				if (err)
 					return err;
 				break;
@@ -2761,13 +2762,15 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves,
 	return 0;
 }
 
-static int check_slave_present(void *data, struct snd_kcontrol *sctl)
+static int check_slave_present(struct hda_codec *codec,
+			       void *data, struct snd_kcontrol *sctl)
 {
 	return 1;
 }
 
 /* guess the value corresponding to 0dB */
-static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check)
+static int get_kctl_0dB_offset(struct hda_codec *codec,
+			       struct snd_kcontrol *kctl, int *step_to_check)
 {
 	int _tlv[4];
 	const int *tlv = NULL;
@@ -2788,7 +2791,7 @@ static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check)
 		if (!step)
 			return -1;
 		if (*step_to_check && *step_to_check != step) {
-			snd_printk(KERN_ERR "hda_codec: Mismatching dB step for vmaster slave (%d!=%d)\n",
+			codec_err(codec, "Mismatching dB step for vmaster slave (%d!=%d)\n",
 -				   *step_to_check, step);
 			return -1;
 		}
@@ -2813,20 +2816,28 @@ static int put_kctl_with_value(struct snd_kcontrol *kctl, int val)
 }
 
 /* initialize the slave volume with 0dB */
-static int init_slave_0dB(void *data, struct snd_kcontrol *slave)
+static int init_slave_0dB(struct hda_codec *codec,
+			  void *data, struct snd_kcontrol *slave)
 {
-	int offset = get_kctl_0dB_offset(slave, data);
+	int offset = get_kctl_0dB_offset(codec, slave, data);
 	if (offset > 0)
 		put_kctl_with_value(slave, offset);
 	return 0;
 }
 
 /* unmute the slave */
-static int init_slave_unmute(void *data, struct snd_kcontrol *slave)
+static int init_slave_unmute(struct hda_codec *codec,
+			     void *data, struct snd_kcontrol *slave)
 {
 	return put_kctl_with_value(slave, 1);
 }
 
+static int add_slave(struct hda_codec *codec,
+		     void *data, struct snd_kcontrol *slave)
+{
+	return snd_ctl_add_slave(data, slave);
+}
+
 /**
  * snd_hda_add_vmaster - create a virtual master control and add slaves
  * @codec: HD-audio codec
@@ -2869,8 +2880,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
 	if (err < 0)
 		return err;
 
-	err = map_slaves(codec, slaves, suffix,
-			 (map_slave_func_t)snd_ctl_add_slave, kctl);
+	err = map_slaves(codec, slaves, suffix, add_slave, kctl);
 	if (err < 0)
 		return err;
 
@@ -4280,6 +4290,7 @@ static struct hda_rate_tbl rate_bits[] = {
 
 /**
  * snd_hda_calc_stream_format - calculate format bitset
+ * @codec: HD-audio codec
  * @rate: the sample rate
  * @channels: the number of channels
  * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
@@ -4289,7 +4300,8 @@ static struct hda_rate_tbl rate_bits[] = {
  *
  * Return zero if invalid.
  */
-unsigned int snd_hda_calc_stream_format(unsigned int rate,
+unsigned int snd_hda_calc_stream_format(struct hda_codec *codec,
+					unsigned int rate,
 					unsigned int channels,
 					unsigned int format,
 					unsigned int maxbps,
@@ -4304,12 +4316,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
 			break;
 		}
 	if (!rate_bits[i].hz) {
-		snd_printdd("invalid rate %d\n", rate);
+		codec_dbg(codec, "invalid rate %d\n", rate);
 		return 0;
 	}
 
 	if (channels == 0 || channels > 8) {
-		snd_printdd("invalid channels %d\n", channels);
+		codec_dbg(codec, "invalid channels %d\n", channels);
 		return 0;
 	}
 	val |= channels - 1;
@@ -4332,7 +4344,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
 			val |= AC_FMT_BITS_20;
 		break;
 	default:
-		snd_printdd("invalid format width %d\n",
+		codec_dbg(codec, "invalid format width %d\n",
 			  snd_pcm_format_width(format));
 		return 0;
 	}
@@ -5670,12 +5682,13 @@ EXPORT_SYMBOL_GPL(_snd_hda_set_pin_ctl);
  * suffix is appended to the label.  This label index number is stored
  * to type_idx when non-NULL pointer is given.
  */
-int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
+int snd_hda_add_imux_item(struct hda_codec *codec,
+			  struct hda_input_mux *imux, const char *label,
 			  int index, int *type_idx)
 {
 	int i, label_idx = 0;
 	if (imux->num_items >= HDA_MAX_NUM_INPUTS) {
-		snd_printd(KERN_ERR "hda_codec: Too many imux items!\n");
+		codec_err(codec, "hda_codec: Too many imux items!\n");
 		return -EINVAL;
 	}
 	for (i = 0; i < imux->num_items; i++) {
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 5825aa17d8e3..bbc5a1392c75 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -402,7 +402,6 @@ struct hda_codec {
 
 	/* fix-up list */
 	int fixup_id;
-	unsigned int fixup_forced:1; /* fixup explicitly set by user */
 	const struct hda_fixup *fixup_list;
 	const char *fixup_name;
 
@@ -538,7 +537,8 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
 				    int do_now);
 #define snd_hda_codec_cleanup_stream(codec, nid) \
 	__snd_hda_codec_cleanup_stream(codec, nid, 0)
-unsigned int snd_hda_calc_stream_format(unsigned int rate,
+unsigned int snd_hda_calc_stream_format(struct hda_codec *codec,
+					unsigned int rate,
 					unsigned int channels,
 					unsigned int format,
 					unsigned int maxbps,
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 6df04d91c93c..8337645aa7a5 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
+#include <linux/reboot.h>
 #include <sound/core.h>
 #include <sound/initval.h>
 #include "hda_priv.h"
@@ -152,11 +153,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
 		      upper_32_bits(azx_dev->bdl.addr));
 
 	/* enable the position buffer */
-	if (chip->position_fix[0] != POS_FIX_LPIB ||
-	    chip->position_fix[1] != POS_FIX_LPIB) {
-		if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+	if (chip->get_position[0] != azx_get_pos_lpib ||
+	    chip->get_position[1] != azx_get_pos_lpib) {
+		if (!(azx_readl(chip, DPLBASE) & AZX_DPLBASE_ENABLE))
 			azx_writel(chip, DPLBASE,
-				(u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
+				(u32)chip->posbuf.addr | AZX_DPLBASE_ENABLE);
 	}
 
 	/* set the interrupt enable bits in the descriptor control register */
@@ -482,7 +483,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
 	}
 
 	azx_stream_reset(chip, azx_dev);
-	format_val = snd_hda_calc_stream_format(runtime->rate,
+	format_val = snd_hda_calc_stream_format(apcm->codec,
+						runtime->rate,
 						runtime->channels,
 						runtime->format,
 						hinfo->maxbps,
@@ -673,125 +675,40 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 	return 0;
 }
 
-/* get the current DMA position with correction on VIA chips */
-static unsigned int azx_via_get_position(struct azx *chip,
-					 struct azx_dev *azx_dev)
+unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev)
 {
-	unsigned int link_pos, mini_pos, bound_pos;
-	unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos;
-	unsigned int fifo_size;
-
-	link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
-	if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		/* Playback, no problem using link position */
-		return link_pos;
-	}
-
-	/* Capture */
-	/* For new chipset,
-	 * use mod to get the DMA position just like old chipset
-	 */
-	mod_dma_pos = le32_to_cpu(*azx_dev->posbuf);
-	mod_dma_pos %= azx_dev->period_bytes;
-
-	/* azx_dev->fifo_size can't get FIFO size of in stream.
-	 * Get from base address + offset.
-	 */
-	fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET);
-
-	if (azx_dev->insufficient) {
-		/* Link position never gather than FIFO size */
-		if (link_pos <= fifo_size)
-			return 0;
-
-		azx_dev->insufficient = 0;
-	}
-
-	if (link_pos <= fifo_size)
-		mini_pos = azx_dev->bufsize + link_pos - fifo_size;
-	else
-		mini_pos = link_pos - fifo_size;
-
-	/* Find nearest previous boudary */
-	mod_mini_pos = mini_pos % azx_dev->period_bytes;
-	mod_link_pos = link_pos % azx_dev->period_bytes;
-	if (mod_link_pos >= fifo_size)
-		bound_pos = link_pos - mod_link_pos;
-	else if (mod_dma_pos >= mod_mini_pos)
-		bound_pos = mini_pos - mod_mini_pos;
-	else {
-		bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes;
-		if (bound_pos >= azx_dev->bufsize)
-			bound_pos = 0;
-	}
+	return azx_sd_readl(chip, azx_dev, SD_LPIB);
+}
+EXPORT_SYMBOL_GPL(azx_get_pos_lpib);
 
-	/* Calculate real DMA position we want */
-	return bound_pos + mod_dma_pos;
+unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev)
+{
+	return le32_to_cpu(*azx_dev->posbuf);
 }
+EXPORT_SYMBOL_GPL(azx_get_pos_posbuf);
 
 unsigned int azx_get_position(struct azx *chip,
-			      struct azx_dev *azx_dev,
-			      bool with_check)
+			      struct azx_dev *azx_dev)
 {
 	struct snd_pcm_substream *substream = azx_dev->substream;
-	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
 	unsigned int pos;
 	int stream = substream->stream;
-	struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
 	int delay = 0;
 
-	switch (chip->position_fix[stream]) {
-	case POS_FIX_LPIB:
-		/* read LPIB */
-		pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
-		break;
-	case POS_FIX_VIACOMBO:
-		pos = azx_via_get_position(chip, azx_dev);
-		break;
-	default:
-		/* use the position buffer */
-		pos = le32_to_cpu(*azx_dev->posbuf);
-		if (with_check && chip->position_fix[stream] == POS_FIX_AUTO) {
-			if (!pos || pos == (u32)-1) {
-				dev_info(chip->card->dev,
-					 "Invalid position buffer, using LPIB read method instead.\n");
-				chip->position_fix[stream] = POS_FIX_LPIB;
-				pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
-			} else
-				chip->position_fix[stream] = POS_FIX_POSBUF;
-		}
-		break;
-	}
+	if (chip->get_position[stream])
+		pos = chip->get_position[stream](chip, azx_dev);
+	else /* use the position buffer as default */
+		pos = azx_get_pos_posbuf(chip, azx_dev);
 
 	if (pos >= azx_dev->bufsize)
 		pos = 0;
 
-	/* calculate runtime delay from LPIB */
-	if (substream->runtime &&
-	    chip->position_fix[stream] == POS_FIX_POSBUF &&
-	    (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
-		unsigned int lpib_pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
-		if (stream == SNDRV_PCM_STREAM_PLAYBACK)
-			delay = pos - lpib_pos;
-		else
-			delay = lpib_pos - pos;
-		if (delay < 0) {
-			if (delay >= azx_dev->delay_negative_threshold)
-				delay = 0;
-			else
-				delay += azx_dev->bufsize;
-		}
-		if (delay >= azx_dev->period_bytes) {
-			dev_info(chip->card->dev,
-				 "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n",
-				 delay, azx_dev->period_bytes);
-			delay = 0;
-			chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
-		}
-		delay = bytes_to_frames(substream->runtime, delay);
-	}
-
 	if (substream->runtime) {
+		struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+		struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
+
+		if (chip->get_delay[stream])
+			delay += chip->get_delay[stream](chip, azx_dev, pos);
 		if (hinfo->ops.get_delay)
 			delay += hinfo->ops.get_delay(hinfo, apcm->codec,
 						      substream);
@@ -809,7 +726,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
 	struct azx *chip = apcm->chip;
 	struct azx_dev *azx_dev = get_azx_dev(substream);
 	return bytes_to_frames(substream->runtime,
-			       azx_get_position(chip, azx_dev, false));
+			       azx_get_position(chip, azx_dev));
 }
 
 static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
@@ -1059,10 +976,10 @@ static void azx_init_cmd_io(struct azx *chip)
 	azx_writew(chip, CORBWP, 0);
 
 	/* reset the corb hw read pointer */
-	azx_writew(chip, CORBRP, ICH6_CORBRP_RST);
+	azx_writew(chip, CORBRP, AZX_CORBRP_RST);
 	if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) {
 		for (timeout = 1000; timeout > 0; timeout--) {
-			if ((azx_readw(chip, CORBRP) & ICH6_CORBRP_RST) == ICH6_CORBRP_RST)
+			if ((azx_readw(chip, CORBRP) & AZX_CORBRP_RST) == AZX_CORBRP_RST)
 				break;
 			udelay(1);
 		}
@@ -1082,7 +999,7 @@ static void azx_init_cmd_io(struct azx *chip)
 	}
 
 	/* enable corb dma */
-	azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN);
+	azx_writeb(chip, CORBCTL, AZX_CORBCTL_RUN);
 
 	/* RIRB set up */
 	chip->rirb.addr = chip->rb.addr + 2048;
@@ -1095,14 +1012,14 @@ static void azx_init_cmd_io(struct azx *chip)
 	/* set the rirb size to 256 entries (ULI requires explicitly) */
 	azx_writeb(chip, RIRBSIZE, 0x02);
 	/* reset the rirb hw write pointer */
-	azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST);
+	azx_writew(chip, RIRBWP, AZX_RIRBWP_RST);
 	/* set N=1, get RIRB response interrupt for new entry */
 	if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
 		azx_writew(chip, RINTCNT, 0xc0);
 	else
 		azx_writew(chip, RINTCNT, 1);
 	/* enable rirb dma and response irq */
-	azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
+	azx_writeb(chip, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN);
 	spin_unlock_irq(&chip->reg_lock);
 }
 EXPORT_SYMBOL_GPL(azx_init_cmd_io);
@@ -1146,7 +1063,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
 		return -EIO;
 	}
 	wp++;
-	wp %= ICH6_MAX_CORB_ENTRIES;
+	wp %= AZX_MAX_CORB_ENTRIES;
 
 	rp = azx_readw(chip, CORBRP);
 	if (wp == rp) {
@@ -1164,7 +1081,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
 	return 0;
 }
 
-#define ICH6_RIRB_EX_UNSOL_EV	(1<<4)
+#define AZX_RIRB_EX_UNSOL_EV	(1<<4)
 
 /* retrieve RIRB entry - called from interrupt handler */
 static void azx_update_rirb(struct azx *chip)
@@ -1185,7 +1102,7 @@ static void azx_update_rirb(struct azx *chip)
 
 	while (chip->rirb.rp != wp) {
 		chip->rirb.rp++;
-		chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES;
+		chip->rirb.rp %= AZX_MAX_RIRB_ENTRIES;
 
 		rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
 		res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
@@ -1196,8 +1113,7 @@ static void azx_update_rirb(struct azx *chip)
 				res, res_ex,
 				chip->rirb.rp, wp);
 			snd_BUG();
-		}
-		else if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
+		} else if (res_ex & AZX_RIRB_EX_UNSOL_EV)
 			snd_hda_queue_unsol_event(chip->bus, res, res_ex);
 		else if (chip->rirb.cmds[addr]) {
 			chip->rirb.res[addr] = res;
@@ -1305,7 +1221,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
 	/* release CORB/RIRB */
 	azx_free_cmd_io(chip);
 	/* disable unsolicited responses */
-	azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_UNSOL);
+	azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_UNSOL);
 	return -1;
 }
 
@@ -1326,7 +1242,7 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
 
 	while (timeout--) {
 		/* check IRV busy bit */
-		if (azx_readw(chip, IRS) & ICH6_IRS_VALID) {
+		if (azx_readw(chip, IRS) & AZX_IRS_VALID) {
 			/* reuse rirb.res as the response return value */
 			chip->rirb.res[addr] = azx_readl(chip, IR);
 			return 0;
@@ -1350,13 +1266,13 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
 	bus->rirb_error = 0;
 	while (timeout--) {
 		/* check ICB busy bit */
-		if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) {
+		if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) {
 			/* Clear IRV valid bit */
 			azx_writew(chip, IRS, azx_readw(chip, IRS) |
-				   ICH6_IRS_VALID);
+				   AZX_IRS_VALID);
 			azx_writel(chip, IC, val);
 			azx_writew(chip, IRS, azx_readw(chip, IRS) |
-				   ICH6_IRS_BUSY);
+				   AZX_IRS_BUSY);
 			return azx_single_wait_for_response(chip, addr);
 		}
 		udelay(1);
@@ -1585,10 +1501,10 @@ void azx_enter_link_reset(struct azx *chip)
 	unsigned long timeout;
 
 	/* reset controller */
-	azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET);
+	azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_RESET);
 
 	timeout = jiffies + msecs_to_jiffies(100);
-	while ((azx_readb(chip, GCTL) & ICH6_GCTL_RESET) &&
+	while ((azx_readb(chip, GCTL) & AZX_GCTL_RESET) &&
 			time_before(jiffies, timeout))
 		usleep_range(500, 1000);
 }
@@ -1599,7 +1515,7 @@ static void azx_exit_link_reset(struct azx *chip)
 {
 	unsigned long timeout;
 
-	azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET);
+	azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | AZX_GCTL_RESET);
 
 	timeout = jiffies + msecs_to_jiffies(100);
 	while (!azx_readb(chip, GCTL) &&
@@ -1640,7 +1556,7 @@ static int azx_reset(struct azx *chip, bool full_reset)
 	/* Accept unsolicited responses */
 	if (!chip->single_cmd)
 		azx_writel(chip, GCTL, azx_readl(chip, GCTL) |
-			   ICH6_GCTL_UNSOL);
+			   AZX_GCTL_UNSOL);
 
 	/* detect codecs */
 	if (!chip->codec_mask) {
@@ -1657,7 +1573,7 @@ static void azx_int_enable(struct azx *chip)
 {
 	/* enable controller CIE and GIE */
 	azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) |
-		   ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN);
+		   AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN);
 }
 
 /* disable interrupts */
@@ -1678,7 +1594,7 @@ static void azx_int_disable(struct azx *chip)
 
 	/* disable controller CIE and GIE */
 	azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) &
-		   ~(ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN));
+		   ~(AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN));
 }
 
 /* clear interrupts */
@@ -1699,7 +1615,7 @@ static void azx_int_clear(struct azx *chip)
 	azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
 
 	/* clear int status */
-	azx_writel(chip, INTSTS, ICH6_INT_CTRL_EN | ICH6_INT_ALL_STREAM);
+	azx_writel(chip, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM);
 }
 
 /*
@@ -2031,5 +1947,30 @@ int azx_init_stream(struct azx *chip)
 }
 EXPORT_SYMBOL_GPL(azx_init_stream);
 
+/*
+ * reboot notifier for hang-up problem at power-down
+ */
+static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf)
+{
+	struct azx *chip = container_of(nb, struct azx, reboot_notifier);
+	snd_hda_bus_reboot_notify(chip->bus);
+	azx_stop_chip(chip);
+	return NOTIFY_OK;
+}
+
+void azx_notifier_register(struct azx *chip)
+{
+	chip->reboot_notifier.notifier_call = azx_halt;
+	register_reboot_notifier(&chip->reboot_notifier);
+}
+EXPORT_SYMBOL_GPL(azx_notifier_register);
+
+void azx_notifier_unregister(struct azx *chip)
+{
+	if (chip->reboot_notifier.notifier_call)
+		unregister_reboot_notifier(&chip->reboot_notifier);
+}
+EXPORT_SYMBOL_GPL(azx_notifier_unregister);
+
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Common HDA driver funcitons");
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h
index baf0e77330af..c90d10fd4d8f 100644
--- a/sound/pci/hda/hda_controller.h
+++ b/sound/pci/hda/hda_controller.h
@@ -25,9 +25,9 @@ static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream)
 {
 	return substream->runtime->private_data;
 }
-unsigned int azx_get_position(struct azx *chip,
-			      struct azx_dev *azx_dev,
-			      bool with_check);
+unsigned int azx_get_position(struct azx *chip, struct azx_dev *azx_dev);
+unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev);
+unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev);
 
 /* Stream control. */
 void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev);
@@ -50,4 +50,7 @@ int azx_codec_configure(struct azx *chip);
 int azx_mixer_create(struct azx *chip);
 int azx_init_stream(struct azx *chip);
 
+void azx_notifier_register(struct azx *chip);
+void azx_notifier_unregister(struct azx *chip);
+
 #endif /* __SOUND_HDA_CONTROLLER_H */
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 46690a7f48f6..e1cd34d9011d 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -167,7 +167,8 @@ static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid,
 	(buf[byte] >> (lowbit)) & ((1 << (bits)) - 1);	\
 })
 
-static void hdmi_update_short_audio_desc(struct cea_sad *a,
+static void hdmi_update_short_audio_desc(struct hda_codec *codec,
+					 struct cea_sad *a,
 					 const unsigned char *buf)
 {
 	int i;
@@ -188,8 +189,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
 	a->format = GRAB_BITS(buf, 0, 3, 4);
 	switch (a->format) {
 	case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
-		snd_printd(KERN_INFO
-				"HDMI: audio coding type 0 not expected\n");
+		codec_info(codec, "HDMI: audio coding type 0 not expected\n");
 		break;
 
 	case AUDIO_CODING_TYPE_LPCM:
@@ -233,9 +233,9 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
 		a->format = GRAB_BITS(buf, 2, 3, 5);
 		if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT ||
 		    a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) {
-			snd_printd(KERN_INFO
-				"HDMI: audio coding xtype %d not expected\n",
-				a->format);
+			codec_info(codec,
+				   "HDMI: audio coding xtype %d not expected\n",
+				   a->format);
 			a->format = 0;
 		} else
 			a->format += AUDIO_CODING_TYPE_HE_AAC -
@@ -247,7 +247,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
 /*
  * Be careful, ELD buf could be totally rubbish!
  */
-int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e,
+int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e,
 			  const unsigned char *buf, int size)
 {
 	int mnl;
@@ -256,8 +256,7 @@ int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e,
 	e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
 	if (e->eld_ver != ELD_VER_CEA_861D &&
 	    e->eld_ver != ELD_VER_PARTIAL) {
-		snd_printd(KERN_INFO "HDMI: Unknown ELD version %d\n",
-								e->eld_ver);
+		codec_info(codec, "HDMI: Unknown ELD version %d\n", e->eld_ver);
 		goto out_fail;
 	}
 
@@ -280,20 +279,20 @@ int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e,
 	e->product_id	  = get_unaligned_le16(buf + 18);
 
 	if (mnl > ELD_MAX_MNL) {
-		snd_printd(KERN_INFO "HDMI: MNL is reserved value %d\n", mnl);
+		codec_info(codec, "HDMI: MNL is reserved value %d\n", mnl);
 		goto out_fail;
 	} else if (ELD_FIXED_BYTES + mnl > size) {
-		snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl);
+		codec_info(codec, "HDMI: out of range MNL %d\n", mnl);
 		goto out_fail;
 	} else
 		strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1);
 
 	for (i = 0; i < e->sad_count; i++) {
 		if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) {
-			snd_printd(KERN_INFO "HDMI: out of range SAD %d\n", i);
+			codec_info(codec, "HDMI: out of range SAD %d\n", i);
 			goto out_fail;
 		}
-		hdmi_update_short_audio_desc(e->sad + i,
+		hdmi_update_short_audio_desc(codec, e->sad + i,
 					buf + ELD_FIXED_BYTES + mnl + 3 * i);
 	}
 
@@ -394,7 +393,8 @@ static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
 
 #define SND_PRINT_RATES_ADVISED_BUFSIZE	80
 
-static void hdmi_show_short_audio_desc(struct cea_sad *a)
+static void hdmi_show_short_audio_desc(struct hda_codec *codec,
+				       struct cea_sad *a)
 {
 	char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
 	char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits =";
@@ -412,12 +412,10 @@ static void hdmi_show_short_audio_desc(struct cea_sad *a)
 	else
 		buf2[0] = '\0';
 
-	_snd_printd(SND_PR_VERBOSE, "HDMI: supports coding type %s:"
-			" channels = %d, rates =%s%s\n",
-			cea_audio_coding_type_names[a->format],
-			a->channels,
-			buf,
-			buf2);
+	codec_dbg(codec,
+		  "HDMI: supports coding type %s: channels = %d, rates =%s%s\n",
+		  cea_audio_coding_type_names[a->format],
+		  a->channels, buf, buf2);
 }
 
 void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
@@ -432,22 +430,22 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
 	buf[j] = '\0';	/* necessary when j == 0 */
 }
 
-void snd_hdmi_show_eld(struct parsed_hdmi_eld *e)
+void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e)
 {
 	int i;
 
-	_snd_printd(SND_PR_VERBOSE, "HDMI: detected monitor %s at connection type %s\n",
+	codec_dbg(codec, "HDMI: detected monitor %s at connection type %s\n",
 			e->monitor_name,
 			eld_connection_type_names[e->conn_type]);
 
 	if (e->spk_alloc) {
 		char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
 		snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
-		_snd_printd(SND_PR_VERBOSE, "HDMI: available speakers:%s\n", buf);
+		codec_dbg(codec, "HDMI: available speakers:%s\n", buf);
 	}
 
 	for (i = 0; i < e->sad_count; i++)
-		hdmi_show_short_audio_desc(e->sad + i);
+		hdmi_show_short_audio_desc(codec, e->sad + i);
 }
 
 #ifdef CONFIG_PROC_FS
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 589e47c5aeb3..b956449ddada 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -350,16 +350,16 @@ static void print_nid_path(struct hda_codec *codec,
 			   const char *pfx, struct nid_path *path)
 {
 	char buf[40];
+	char *pos = buf;
 	int i;
 
+	*pos = 0;
+	for (i = 0; i < path->depth; i++)
+		pos += scnprintf(pos, sizeof(buf) - (pos - buf), "%s%02x",
+				 pos != buf ? ":" : "",
+				 path->path[i]);
 
-	buf[0] = 0;
-	for (i = 0; i < path->depth; i++) {
-		char tmp[4];
-		sprintf(tmp, ":%02x", path->path[i]);
-		strlcat(buf, tmp, sizeof(buf));
-	}
-	codec_dbg(codec, "%s path: depth=%d %s\n", pfx, path->depth, buf);
+	codec_dbg(codec, "%s path: depth=%d '%s'\n", pfx, path->depth, buf);
 }
 
 /* called recursively */
@@ -1700,9 +1700,11 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
 #define DEBUG_BADNESS
 
 #ifdef DEBUG_BADNESS
-#define debug_badness(fmt, args...)	codec_dbg(codec, fmt, ##args)
+#define debug_badness(fmt, ...)						\
+	codec_dbg(codec, fmt, ##__VA_ARGS__)
 #else
-#define debug_badness(...)
+#define debug_badness(fmt, ...)						\
+	do { if (0) codec_dbg(codec, fmt, ##__VA_ARGS__); } while (0)
 #endif
 
 #ifdef DEBUG_BADNESS
@@ -3054,7 +3056,7 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
 			if (spec->hp_mic_pin == pin)
 				spec->hp_mic_mux_idx = imux->num_items;
 			spec->imux_pins[imux->num_items] = pin;
-			snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
+			snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL);
 			imux_added = true;
 			if (spec->dyn_adc_switch)
 				spec->dyn_adc_idx[imux_idx] = c;
diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c
index 8b4940ba33d6..d4d0375ac181 100644
--- a/sound/pci/hda/hda_i915.c
+++ b/sound/pci/hda/hda_i915.c
@@ -28,8 +28,8 @@
  * Clock) to 24MHz BCLK: BCLK = CDCLK * M / N
  * The values will be lost when the display power well is disabled.
  */
-#define ICH6_REG_EM4			0x100c
-#define ICH6_REG_EM5			0x1010
+#define AZX_REG_EM4			0x100c
+#define AZX_REG_EM5			0x1010
 
 static int (*get_power)(void);
 static int (*put_power)(void);
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 83cd19017cf3..5db1948699d8 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -44,7 +44,6 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/mutex.h>
-#include <linux/reboot.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
 #include <linux/clocksource.h>
@@ -66,6 +65,52 @@
 #include "hda_priv.h"
 #include "hda_i915.h"
 
+/* position fix mode */
+enum {
+	POS_FIX_AUTO,
+	POS_FIX_LPIB,
+	POS_FIX_POSBUF,
+	POS_FIX_VIACOMBO,
+	POS_FIX_COMBO,
+};
+
+/* Defines for ATI HD Audio support in SB450 south bridge */
+#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR   0x42
+#define ATI_SB450_HDAUDIO_ENABLE_SNOOP      0x02
+
+/* Defines for Nvidia HDA support */
+#define NVIDIA_HDA_TRANSREG_ADDR      0x4e
+#define NVIDIA_HDA_ENABLE_COHBITS     0x0f
+#define NVIDIA_HDA_ISTRM_COH          0x4d
+#define NVIDIA_HDA_OSTRM_COH          0x4c
+#define NVIDIA_HDA_ENABLE_COHBIT      0x01
+
+/* Defines for Intel SCH HDA snoop control */
+#define INTEL_SCH_HDA_DEVC      0x78
+#define INTEL_SCH_HDA_DEVC_NOSNOOP       (0x1<<11)
+
+/* Define IN stream 0 FIFO size offset in VIA controller */
+#define VIA_IN_STREAM0_FIFO_SIZE_OFFSET	0x90
+/* Define VIA HD Audio Device ID*/
+#define VIA_HDAC_DEVICE_ID		0x3288
+
+/* max number of SDs */
+/* ICH, ATI and VIA have 4 playback and 4 capture */
+#define ICH6_NUM_CAPTURE	4
+#define ICH6_NUM_PLAYBACK	4
+
+/* ULI has 6 playback and 5 capture */
+#define ULI_NUM_CAPTURE		5
+#define ULI_NUM_PLAYBACK	6
+
+/* ATI HDMI may have up to 8 playbacks and 0 capture */
+#define ATIHDMI_NUM_CAPTURE	0
+#define ATIHDMI_NUM_PLAYBACK	8
+
+/* TERA has 4 playback and 3 capture */
+#define TERA_NUM_CAPTURE	3
+#define TERA_NUM_PLAYBACK	4
+
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
@@ -290,8 +335,28 @@ static char *driver_short_names[] = {
 
 struct hda_intel {
 	struct azx chip;
-};
 
+	/* for pending irqs */
+	struct work_struct irq_pending_work;
+
+	/* sync probing */
+	struct completion probe_wait;
+	struct work_struct probe_work;
+
+	/* card list (for power_save trigger) */
+	struct list_head list;
+
+	/* extra flags */
+	unsigned int irq_pending_warned:1;
+
+	/* VGA-switcheroo setup */
+	unsigned int use_vga_switcheroo:1;
+	unsigned int vga_switcheroo_registered:1;
+	unsigned int init_failed:1; /* delayed init failed */
+
+	/* secondary power domain for hdmi audio under vga device */
+	struct dev_pm_domain hdmi_pm_domain;
+};
 
 #ifdef CONFIG_X86
 static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
@@ -373,7 +438,7 @@ static void azx_init_pci(struct azx *chip)
 	 */
 	if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) {
 		dev_dbg(chip->card->dev, "Clearing TCSEL\n");
-		update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0);
+		update_pci_byte(chip->pci, AZX_PCIREG_TCSEL, 0x07, 0);
 	}
 
 	/* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio,
@@ -421,11 +486,44 @@ static void azx_init_pci(struct azx *chip)
         }
 }
 
+/* calculate runtime delay from LPIB */
+static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev,
+				   unsigned int pos)
+{
+	struct snd_pcm_substream *substream = azx_dev->substream;
+	int stream = substream->stream;
+	unsigned int lpib_pos = azx_get_pos_lpib(chip, azx_dev);
+	int delay;
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+		delay = pos - lpib_pos;
+	else
+		delay = lpib_pos - pos;
+	if (delay < 0) {
+		if (delay >= azx_dev->delay_negative_threshold)
+			delay = 0;
+		else
+			delay += azx_dev->bufsize;
+	}
+
+	if (delay >= azx_dev->period_bytes) {
+		dev_info(chip->card->dev,
+			 "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n",
+			 delay, azx_dev->period_bytes);
+		delay = 0;
+		chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
+		chip->get_delay[stream] = NULL;
+	}
+
+	return bytes_to_frames(substream->runtime, delay);
+}
+
 static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev);
 
 /* called from IRQ */
 static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
 {
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	int ok;
 
 	ok = azx_position_ok(chip, azx_dev);
@@ -435,7 +533,7 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
 	} else if (ok == 0 && chip->bus && chip->bus->workq) {
 		/* bogus IRQ, process it later */
 		azx_dev->irq_pending = 1;
-		queue_work(chip->bus->workq, &chip->irq_pending_work);
+		queue_work(chip->bus->workq, &hda->irq_pending_work);
 	}
 	return 0;
 }
@@ -451,6 +549,8 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
  */
 static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
 {
+	struct snd_pcm_substream *substream = azx_dev->substream;
+	int stream = substream->stream;
 	u32 wallclk;
 	unsigned int pos;
 
@@ -458,7 +558,25 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
 	if (wallclk < (azx_dev->period_wallclk * 2) / 3)
 		return -1;	/* bogus (too early) interrupt */
 
-	pos = azx_get_position(chip, azx_dev, true);
+	if (chip->get_position[stream])
+		pos = chip->get_position[stream](chip, azx_dev);
+	else { /* use the position buffer as default */
+		pos = azx_get_pos_posbuf(chip, azx_dev);
+		if (!pos || pos == (u32)-1) {
+			dev_info(chip->card->dev,
+				 "Invalid position buffer, using LPIB read method instead.\n");
+			chip->get_position[stream] = azx_get_pos_lpib;
+			pos = azx_get_pos_lpib(chip, azx_dev);
+			chip->get_delay[stream] = NULL;
+		} else {
+			chip->get_position[stream] = azx_get_pos_posbuf;
+			if (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)
+				chip->get_delay[stream] = azx_get_delay_from_lpib;
+		}
+	}
+
+	if (pos >= azx_dev->bufsize)
+		pos = 0;
 
 	if (WARN_ONCE(!azx_dev->period_bytes,
 		      "hda-intel: zero azx_dev->period_bytes"))
@@ -476,14 +594,15 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
  */
 static void azx_irq_pending_work(struct work_struct *work)
 {
-	struct azx *chip = container_of(work, struct azx, irq_pending_work);
+	struct hda_intel *hda = container_of(work, struct hda_intel, irq_pending_work);
+	struct azx *chip = &hda->chip;
 	int i, pending, ok;
 
-	if (!chip->irq_pending_warned) {
+	if (!hda->irq_pending_warned) {
 		dev_info(chip->card->dev,
 			 "IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n",
 			 chip->card->number);
-		chip->irq_pending_warned = 1;
+		hda->irq_pending_warned = 1;
 	}
 
 	for (;;) {
@@ -541,27 +660,86 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect)
 	return 0;
 }
 
+/* get the current DMA position with correction on VIA chips */
+static unsigned int azx_via_get_position(struct azx *chip,
+					 struct azx_dev *azx_dev)
+{
+	unsigned int link_pos, mini_pos, bound_pos;
+	unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos;
+	unsigned int fifo_size;
+
+	link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
+	if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/* Playback, no problem using link position */
+		return link_pos;
+	}
+
+	/* Capture */
+	/* For new chipset,
+	 * use mod to get the DMA position just like old chipset
+	 */
+	mod_dma_pos = le32_to_cpu(*azx_dev->posbuf);
+	mod_dma_pos %= azx_dev->period_bytes;
+
+	/* azx_dev->fifo_size can't get FIFO size of in stream.
+	 * Get from base address + offset.
+	 */
+	fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET);
+
+	if (azx_dev->insufficient) {
+		/* Link position never gather than FIFO size */
+		if (link_pos <= fifo_size)
+			return 0;
+
+		azx_dev->insufficient = 0;
+	}
+
+	if (link_pos <= fifo_size)
+		mini_pos = azx_dev->bufsize + link_pos - fifo_size;
+	else
+		mini_pos = link_pos - fifo_size;
+
+	/* Find nearest previous boudary */
+	mod_mini_pos = mini_pos % azx_dev->period_bytes;
+	mod_link_pos = link_pos % azx_dev->period_bytes;
+	if (mod_link_pos >= fifo_size)
+		bound_pos = link_pos - mod_link_pos;
+	else if (mod_dma_pos >= mod_mini_pos)
+		bound_pos = mini_pos - mod_mini_pos;
+	else {
+		bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes;
+		if (bound_pos >= azx_dev->bufsize)
+			bound_pos = 0;
+	}
+
+	/* Calculate real DMA position we want */
+	return bound_pos + mod_dma_pos;
+}
+
 #ifdef CONFIG_PM
 static DEFINE_MUTEX(card_list_lock);
 static LIST_HEAD(card_list);
 
 static void azx_add_card_list(struct azx *chip)
 {
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	mutex_lock(&card_list_lock);
-	list_add(&chip->list, &card_list);
+	list_add(&hda->list, &card_list);
 	mutex_unlock(&card_list_lock);
 }
 
 static void azx_del_card_list(struct azx *chip)
 {
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	mutex_lock(&card_list_lock);
-	list_del_init(&chip->list);
+	list_del_init(&hda->list);
 	mutex_unlock(&card_list_lock);
 }
 
 /* trigger power-save check at writing parameter */
 static int param_set_xint(const char *val, const struct kernel_param *kp)
 {
+	struct hda_intel *hda;
 	struct azx *chip;
 	struct hda_codec *c;
 	int prev = power_save;
@@ -571,7 +749,8 @@ static int param_set_xint(const char *val, const struct kernel_param *kp)
 		return ret;
 
 	mutex_lock(&card_list_lock);
-	list_for_each_entry(chip, &card_list, list) {
+	list_for_each_entry(hda, &card_list, list) {
+		chip = &hda->chip;
 		if (!chip->bus || chip->disabled)
 			continue;
 		list_for_each_entry(c, &chip->bus->codec_list, list)
@@ -593,10 +772,16 @@ static int azx_suspend(struct device *dev)
 {
 	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
-	struct azx *chip = card->private_data;
+	struct azx *chip;
+	struct hda_intel *hda;
 	struct azx_pcm *p;
 
-	if (chip->disabled || chip->init_failed)
+	if (!card)
+		return 0;
+
+	chip = card->private_data;
+	hda = container_of(chip, struct hda_intel, chip);
+	if (chip->disabled || hda->init_failed)
 		return 0;
 
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
@@ -626,9 +811,15 @@ static int azx_resume(struct device *dev)
 {
 	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
-	struct azx *chip = card->private_data;
+	struct azx *chip;
+	struct hda_intel *hda;
 
-	if (chip->disabled || chip->init_failed)
+	if (!card)
+		return 0;
+
+	chip = card->private_data;
+	hda = container_of(chip, struct hda_intel, chip);
+	if (chip->disabled || hda->init_failed)
 		return 0;
 
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
@@ -663,9 +854,15 @@ static int azx_resume(struct device *dev)
 static int azx_runtime_suspend(struct device *dev)
 {
 	struct snd_card *card = dev_get_drvdata(dev);
-	struct azx *chip = card->private_data;
+	struct azx *chip;
+	struct hda_intel *hda;
+
+	if (!card)
+		return 0;
 
-	if (chip->disabled || chip->init_failed)
+	chip = card->private_data;
+	hda = container_of(chip, struct hda_intel, chip);
+	if (chip->disabled || hda->init_failed)
 		return 0;
 
 	if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
@@ -687,12 +884,18 @@ static int azx_runtime_suspend(struct device *dev)
 static int azx_runtime_resume(struct device *dev)
 {
 	struct snd_card *card = dev_get_drvdata(dev);
-	struct azx *chip = card->private_data;
+	struct azx *chip;
+	struct hda_intel *hda;
 	struct hda_bus *bus;
 	struct hda_codec *codec;
 	int status;
 
-	if (chip->disabled || chip->init_failed)
+	if (!card)
+		return 0;
+
+	chip = card->private_data;
+	hda = container_of(chip, struct hda_intel, chip);
+	if (chip->disabled || hda->init_failed)
 		return 0;
 
 	if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
@@ -727,9 +930,15 @@ static int azx_runtime_resume(struct device *dev)
 static int azx_runtime_idle(struct device *dev)
 {
 	struct snd_card *card = dev_get_drvdata(dev);
-	struct azx *chip = card->private_data;
+	struct azx *chip;
+	struct hda_intel *hda;
+
+	if (!card)
+		return 0;
 
-	if (chip->disabled || chip->init_failed)
+	chip = card->private_data;
+	hda = container_of(chip, struct hda_intel, chip);
+	if (chip->disabled || hda->init_failed)
 		return 0;
 
 	if (!power_save_controller ||
@@ -753,29 +962,6 @@ static const struct dev_pm_ops azx_pm = {
 #endif /* CONFIG_PM */
 
 
-/*
- * reboot notifier for hang-up problem at power-down
- */
-static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf)
-{
-	struct azx *chip = container_of(nb, struct azx, reboot_notifier);
-	snd_hda_bus_reboot_notify(chip->bus);
-	azx_stop_chip(chip);
-	return NOTIFY_OK;
-}
-
-static void azx_notifier_register(struct azx *chip)
-{
-	chip->reboot_notifier.notifier_call = azx_halt;
-	register_reboot_notifier(&chip->reboot_notifier);
-}
-
-static void azx_notifier_unregister(struct azx *chip)
-{
-	if (chip->reboot_notifier.notifier_call)
-		unregister_reboot_notifier(&chip->reboot_notifier);
-}
-
 static int azx_probe_continue(struct azx *chip);
 
 #ifdef SUPPORT_VGA_SWITCHEROO
@@ -786,10 +972,11 @@ static void azx_vs_set_state(struct pci_dev *pci,
 {
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct azx *chip = card->private_data;
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	bool disabled;
 
-	wait_for_completion(&chip->probe_wait);
-	if (chip->init_failed)
+	wait_for_completion(&hda->probe_wait);
+	if (hda->init_failed)
 		return;
 
 	disabled = (state == VGA_SWITCHEROO_OFF);
@@ -803,7 +990,7 @@ static void azx_vs_set_state(struct pci_dev *pci,
 				 "Start delayed initialization\n");
 			if (azx_probe_continue(chip) < 0) {
 				dev_err(chip->card->dev, "initialization error\n");
-				chip->init_failed = true;
+				hda->init_failed = true;
 			}
 		}
 	} else {
@@ -833,9 +1020,10 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
 {
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct azx *chip = card->private_data;
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 
-	wait_for_completion(&chip->probe_wait);
-	if (chip->init_failed)
+	wait_for_completion(&hda->probe_wait);
+	if (hda->init_failed)
 		return false;
 	if (chip->disabled || !chip->bus)
 		return true;
@@ -847,11 +1035,12 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
 
 static void init_vga_switcheroo(struct azx *chip)
 {
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	struct pci_dev *p = get_bound_vga(chip->pci);
 	if (p) {
 		dev_info(chip->card->dev,
 			 "Handle VGA-switcheroo audio client\n");
-		chip->use_vga_switcheroo = 1;
+		hda->use_vga_switcheroo = 1;
 		pci_dev_put(p);
 	}
 }
@@ -863,9 +1052,10 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = {
 
 static int register_vga_switcheroo(struct azx *chip)
 {
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	int err;
 
-	if (!chip->use_vga_switcheroo)
+	if (!hda->use_vga_switcheroo)
 		return 0;
 	/* FIXME: currently only handling DIS controller
 	 * is there any machine with two switchable HDMI audio controllers?
@@ -875,11 +1065,11 @@ static int register_vga_switcheroo(struct azx *chip)
 						    chip->bus != NULL);
 	if (err < 0)
 		return err;
-	chip->vga_switcheroo_registered = 1;
+	hda->vga_switcheroo_registered = 1;
 
 	/* register as an optimus hdmi audio power domain */
 	vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev,
-							 &chip->hdmi_pm_domain);
+							 &hda->hdmi_pm_domain);
 	return 0;
 }
 #else
@@ -895,7 +1085,6 @@ static int azx_free(struct azx *chip)
 {
 	struct pci_dev *pci = chip->pci;
 	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
-
 	int i;
 
 	if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME)
@@ -906,13 +1095,13 @@ static int azx_free(struct azx *chip)
 
 	azx_notifier_unregister(chip);
 
-	chip->init_failed = 1; /* to be sure */
-	complete_all(&chip->probe_wait);
+	hda->init_failed = 1; /* to be sure */
+	complete_all(&hda->probe_wait);
 
-	if (use_vga_switcheroo(chip)) {
+	if (use_vga_switcheroo(hda)) {
 		if (chip->disabled && chip->bus)
 			snd_hda_unlock_devices(chip->bus);
-		if (chip->vga_switcheroo_registered)
+		if (hda->vga_switcheroo_registered)
 			vga_switcheroo_unregister_client(chip->pci);
 	}
 
@@ -1048,6 +1237,30 @@ static int check_position_fix(struct azx *chip, int fix)
 	return POS_FIX_AUTO;
 }
 
+static void assign_position_fix(struct azx *chip, int fix)
+{
+	static azx_get_pos_callback_t callbacks[] = {
+		[POS_FIX_AUTO] = NULL,
+		[POS_FIX_LPIB] = azx_get_pos_lpib,
+		[POS_FIX_POSBUF] = azx_get_pos_posbuf,
+		[POS_FIX_VIACOMBO] = azx_via_get_position,
+		[POS_FIX_COMBO] = azx_get_pos_lpib,
+	};
+
+	chip->get_position[0] = chip->get_position[1] = callbacks[fix];
+
+	/* combo mode uses LPIB only for playback */
+	if (fix == POS_FIX_COMBO)
+		chip->get_position[1] = NULL;
+
+	if (fix == POS_FIX_POSBUF &&
+	    (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
+		chip->get_delay[0] = chip->get_delay[1] =
+			azx_get_delay_from_lpib;
+	}
+
+}
+
 /*
  * black-lists for probe_mask
  */
@@ -1173,7 +1386,8 @@ static void azx_check_snoop_available(struct azx *chip)
 
 static void azx_probe_work(struct work_struct *work)
 {
-	azx_probe_continue(container_of(work, struct azx, probe_work));
+	struct hda_intel *hda = container_of(work, struct hda_intel, probe_work);
+	azx_probe_continue(&hda->chip);
 }
 
 /*
@@ -1216,19 +1430,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
 	check_msi(chip);
 	chip->dev_index = dev;
 	chip->jackpoll_ms = jackpoll_ms;
-	INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
 	INIT_LIST_HEAD(&chip->pcm_list);
-	INIT_LIST_HEAD(&chip->list);
+	INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work);
+	INIT_LIST_HEAD(&hda->list);
 	init_vga_switcheroo(chip);
-	init_completion(&chip->probe_wait);
-
-	chip->position_fix[0] = chip->position_fix[1] =
-		check_position_fix(chip, position_fix[dev]);
-	/* combo mode uses LPIB for playback */
-	if (chip->position_fix[0] == POS_FIX_COMBO) {
-		chip->position_fix[0] = POS_FIX_LPIB;
-		chip->position_fix[1] = POS_FIX_AUTO;
-	}
+	init_completion(&hda->probe_wait);
+
+	assign_position_fix(chip, check_position_fix(chip, position_fix[dev]));
 
 	check_probe_mask(chip, dev);
 
@@ -1257,7 +1465,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
 	}
 
 	/* continue probing in work context as may trigger request module */
-	INIT_WORK(&chip->probe_work, azx_probe_work);
+	INIT_WORK(&hda->probe_work, azx_probe_work);
 
 	*rchip = chip;
 
@@ -1315,7 +1523,7 @@ static int azx_first_init(struct azx *chip)
 					 NULL);
 		if (p_smbus) {
 			if (p_smbus->revision < 0x30)
-				gcap &= ~ICH6_GCAP_64OK;
+				gcap &= ~AZX_GCAP_64OK;
 			pci_dev_put(p_smbus);
 		}
 	}
@@ -1323,7 +1531,7 @@ static int azx_first_init(struct azx *chip)
 	/* disable 64bit DMA address on some devices */
 	if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
 		dev_dbg(card->dev, "Disabling 64bit DMA\n");
-		gcap &= ~ICH6_GCAP_64OK;
+		gcap &= ~AZX_GCAP_64OK;
 	}
 
 	/* disable buffer size rounding to 128-byte multiples if supported */
@@ -1339,7 +1547,7 @@ static int azx_first_init(struct azx *chip)
 	}
 
 	/* allow 64bit DMA address if supported by H/W */
-	if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
+	if ((gcap & AZX_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
 		pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
 	else {
 		pci_set_dma_mask(pci, DMA_BIT_MASK(32));
@@ -1583,6 +1791,7 @@ static int azx_probe(struct pci_dev *pci,
 {
 	static int dev;
 	struct snd_card *card;
+	struct hda_intel *hda;
 	struct azx *chip;
 	bool schedule_probe;
 	int err;
@@ -1606,6 +1815,7 @@ static int azx_probe(struct pci_dev *pci,
 	if (err < 0)
 		goto out_free;
 	card->private_data = chip;
+	hda = container_of(chip, struct hda_intel, chip);
 
 	pci_set_drvdata(pci, card);
 
@@ -1642,11 +1852,11 @@ static int azx_probe(struct pci_dev *pci,
 #endif
 
 	if (schedule_probe)
-		schedule_work(&chip->probe_work);
+		schedule_work(&hda->probe_work);
 
 	dev++;
 	if (chip->disabled)
-		complete_all(&chip->probe_wait);
+		complete_all(&hda->probe_wait);
 	return 0;
 
 out_free:
@@ -1662,6 +1872,7 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
 
 static int azx_probe_continue(struct azx *chip)
 {
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	struct pci_dev *pci = chip->pci;
 	int dev = chip->dev_index;
 	int err;
@@ -1735,13 +1946,13 @@ static int azx_probe_continue(struct azx *chip)
 	power_down_all_codecs(chip);
 	azx_notifier_register(chip);
 	azx_add_card_list(chip);
-	if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || chip->use_vga_switcheroo)
+	if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || hda->use_vga_switcheroo)
 		pm_runtime_put_noidle(&pci->dev);
 
 out_free:
 	if (err < 0)
-		chip->init_failed = 1;
-	complete_all(&chip->probe_wait);
+		hda->init_failed = 1;
+	complete_all(&hda->probe_wait);
 	return err;
 }
 
@@ -1806,6 +2017,9 @@ static const struct pci_device_id azx_ids[] = {
 	/* BayTrail */
 	{ PCI_DEVICE(0x8086, 0x0f04),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
+	/* Braswell */
+	{ PCI_DEVICE(0x8086, 0x2284),
+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
 	/* ICH */
 	{ PCI_DEVICE(0x8086, 0x2668),
 	  .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 4e2d4863daa1..364bb413e02a 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -268,7 +268,8 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
 			  const struct hda_input_mux *imux,
 			  struct snd_ctl_elem_value *ucontrol, hda_nid_t nid,
 			  unsigned int *cur_val);
-int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
+int snd_hda_add_imux_item(struct hda_codec *codec,
+			  struct hda_input_mux *imux, const char *label,
 			  int index, int *type_index_ret);
 
 /*
@@ -437,6 +438,8 @@ struct snd_hda_pin_quirk {
 
 #endif
 
+#define HDA_FIXUP_ID_NOT_SET -1
+#define HDA_FIXUP_ID_NO_FIXUP -2
 
 /* fixup types */
 enum {
@@ -773,9 +776,9 @@ struct hdmi_eld {
 int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid);
 int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
 		     unsigned char *buf, int *eld_size);
-int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e,
+int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e,
 		       const unsigned char *buf, int size);
-void snd_hdmi_show_eld(struct parsed_hdmi_eld *e);
+void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e);
 void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e,
 			      struct hda_pcm_stream *hinfo);
 
diff --git a/sound/pci/hda/hda_priv.h b/sound/pci/hda/hda_priv.h
index e9d1a5762a55..949cd437eeb2 100644
--- a/sound/pci/hda/hda_priv.h
+++ b/sound/pci/hda/hda_priv.h
@@ -22,107 +22,87 @@
 /*
  * registers
  */
-#define ICH6_REG_GCAP			0x00
-#define   ICH6_GCAP_64OK	(1 << 0)   /* 64bit address support */
-#define   ICH6_GCAP_NSDO	(3 << 1)   /* # of serial data out signals */
-#define   ICH6_GCAP_BSS		(31 << 3)  /* # of bidirectional streams */
-#define   ICH6_GCAP_ISS		(15 << 8)  /* # of input streams */
-#define   ICH6_GCAP_OSS		(15 << 12) /* # of output streams */
-#define ICH6_REG_VMIN			0x02
-#define ICH6_REG_VMAJ			0x03
-#define ICH6_REG_OUTPAY			0x04
-#define ICH6_REG_INPAY			0x06
-#define ICH6_REG_GCTL			0x08
-#define   ICH6_GCTL_RESET	(1 << 0)   /* controller reset */
-#define   ICH6_GCTL_FCNTRL	(1 << 1)   /* flush control */
-#define   ICH6_GCTL_UNSOL	(1 << 8)   /* accept unsol. response enable */
-#define ICH6_REG_WAKEEN			0x0c
-#define ICH6_REG_STATESTS		0x0e
-#define ICH6_REG_GSTS			0x10
-#define   ICH6_GSTS_FSTS	(1 << 1)   /* flush status */
-#define ICH6_REG_INTCTL			0x20
-#define ICH6_REG_INTSTS			0x24
-#define ICH6_REG_WALLCLK		0x30	/* 24Mhz source */
-#define ICH6_REG_OLD_SSYNC		0x34	/* SSYNC for old ICH */
-#define ICH6_REG_SSYNC			0x38
-#define ICH6_REG_CORBLBASE		0x40
-#define ICH6_REG_CORBUBASE		0x44
-#define ICH6_REG_CORBWP			0x48
-#define ICH6_REG_CORBRP			0x4a
-#define   ICH6_CORBRP_RST	(1 << 15)  /* read pointer reset */
-#define ICH6_REG_CORBCTL		0x4c
-#define   ICH6_CORBCTL_RUN	(1 << 1)   /* enable DMA */
-#define   ICH6_CORBCTL_CMEIE	(1 << 0)   /* enable memory error irq */
-#define ICH6_REG_CORBSTS		0x4d
-#define   ICH6_CORBSTS_CMEI	(1 << 0)   /* memory error indication */
-#define ICH6_REG_CORBSIZE		0x4e
-
-#define ICH6_REG_RIRBLBASE		0x50
-#define ICH6_REG_RIRBUBASE		0x54
-#define ICH6_REG_RIRBWP			0x58
-#define   ICH6_RIRBWP_RST	(1 << 15)  /* write pointer reset */
-#define ICH6_REG_RINTCNT		0x5a
-#define ICH6_REG_RIRBCTL		0x5c
-#define   ICH6_RBCTL_IRQ_EN	(1 << 0)   /* enable IRQ */
-#define   ICH6_RBCTL_DMA_EN	(1 << 1)   /* enable DMA */
-#define   ICH6_RBCTL_OVERRUN_EN	(1 << 2)   /* enable overrun irq */
-#define ICH6_REG_RIRBSTS		0x5d
-#define   ICH6_RBSTS_IRQ	(1 << 0)   /* response irq */
-#define   ICH6_RBSTS_OVERRUN	(1 << 2)   /* overrun irq */
-#define ICH6_REG_RIRBSIZE		0x5e
-
-#define ICH6_REG_IC			0x60
-#define ICH6_REG_IR			0x64
-#define ICH6_REG_IRS			0x68
-#define   ICH6_IRS_VALID	(1<<1)
-#define   ICH6_IRS_BUSY		(1<<0)
-
-#define ICH6_REG_DPLBASE		0x70
-#define ICH6_REG_DPUBASE		0x74
-#define   ICH6_DPLBASE_ENABLE	0x1	/* Enable position buffer */
+#define AZX_REG_GCAP			0x00
+#define   AZX_GCAP_64OK		(1 << 0)   /* 64bit address support */
+#define   AZX_GCAP_NSDO		(3 << 1)   /* # of serial data out signals */
+#define   AZX_GCAP_BSS		(31 << 3)  /* # of bidirectional streams */
+#define   AZX_GCAP_ISS		(15 << 8)  /* # of input streams */
+#define   AZX_GCAP_OSS		(15 << 12) /* # of output streams */
+#define AZX_REG_VMIN			0x02
+#define AZX_REG_VMAJ			0x03
+#define AZX_REG_OUTPAY			0x04
+#define AZX_REG_INPAY			0x06
+#define AZX_REG_GCTL			0x08
+#define   AZX_GCTL_RESET	(1 << 0)   /* controller reset */
+#define   AZX_GCTL_FCNTRL	(1 << 1)   /* flush control */
+#define   AZX_GCTL_UNSOL	(1 << 8)   /* accept unsol. response enable */
+#define AZX_REG_WAKEEN			0x0c
+#define AZX_REG_STATESTS		0x0e
+#define AZX_REG_GSTS			0x10
+#define   AZX_GSTS_FSTS		(1 << 1)   /* flush status */
+#define AZX_REG_INTCTL			0x20
+#define AZX_REG_INTSTS			0x24
+#define AZX_REG_WALLCLK			0x30	/* 24Mhz source */
+#define AZX_REG_OLD_SSYNC		0x34	/* SSYNC for old ICH */
+#define AZX_REG_SSYNC			0x38
+#define AZX_REG_CORBLBASE		0x40
+#define AZX_REG_CORBUBASE		0x44
+#define AZX_REG_CORBWP			0x48
+#define AZX_REG_CORBRP			0x4a
+#define   AZX_CORBRP_RST	(1 << 15)  /* read pointer reset */
+#define AZX_REG_CORBCTL			0x4c
+#define   AZX_CORBCTL_RUN	(1 << 1)   /* enable DMA */
+#define   AZX_CORBCTL_CMEIE	(1 << 0)   /* enable memory error irq */
+#define AZX_REG_CORBSTS			0x4d
+#define   AZX_CORBSTS_CMEI	(1 << 0)   /* memory error indication */
+#define AZX_REG_CORBSIZE		0x4e
+
+#define AZX_REG_RIRBLBASE		0x50
+#define AZX_REG_RIRBUBASE		0x54
+#define AZX_REG_RIRBWP			0x58
+#define   AZX_RIRBWP_RST	(1 << 15)  /* write pointer reset */
+#define AZX_REG_RINTCNT			0x5a
+#define AZX_REG_RIRBCTL			0x5c
+#define   AZX_RBCTL_IRQ_EN	(1 << 0)   /* enable IRQ */
+#define   AZX_RBCTL_DMA_EN	(1 << 1)   /* enable DMA */
+#define   AZX_RBCTL_OVERRUN_EN	(1 << 2)   /* enable overrun irq */
+#define AZX_REG_RIRBSTS			0x5d
+#define   AZX_RBSTS_IRQ		(1 << 0)   /* response irq */
+#define   AZX_RBSTS_OVERRUN	(1 << 2)   /* overrun irq */
+#define AZX_REG_RIRBSIZE		0x5e
+
+#define AZX_REG_IC			0x60
+#define AZX_REG_IR			0x64
+#define AZX_REG_IRS			0x68
+#define   AZX_IRS_VALID		(1<<1)
+#define   AZX_IRS_BUSY		(1<<0)
+
+#define AZX_REG_DPLBASE			0x70
+#define AZX_REG_DPUBASE			0x74
+#define   AZX_DPLBASE_ENABLE	0x1	/* Enable position buffer */
 
 /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
 enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 
 /* stream register offsets from stream base */
-#define ICH6_REG_SD_CTL			0x00
-#define ICH6_REG_SD_STS			0x03
-#define ICH6_REG_SD_LPIB		0x04
-#define ICH6_REG_SD_CBL			0x08
-#define ICH6_REG_SD_LVI			0x0c
-#define ICH6_REG_SD_FIFOW		0x0e
-#define ICH6_REG_SD_FIFOSIZE		0x10
-#define ICH6_REG_SD_FORMAT		0x12
-#define ICH6_REG_SD_BDLPL		0x18
-#define ICH6_REG_SD_BDLPU		0x1c
+#define AZX_REG_SD_CTL			0x00
+#define AZX_REG_SD_STS			0x03
+#define AZX_REG_SD_LPIB			0x04
+#define AZX_REG_SD_CBL			0x08
+#define AZX_REG_SD_LVI			0x0c
+#define AZX_REG_SD_FIFOW		0x0e
+#define AZX_REG_SD_FIFOSIZE		0x10
+#define AZX_REG_SD_FORMAT		0x12
+#define AZX_REG_SD_BDLPL		0x18
+#define AZX_REG_SD_BDLPU		0x1c
 
 /* PCI space */
-#define ICH6_PCIREG_TCSEL	0x44
+#define AZX_PCIREG_TCSEL		0x44
 
 /*
  * other constants
  */
 
-/* max number of SDs */
-/* ICH, ATI and VIA have 4 playback and 4 capture */
-#define ICH6_NUM_CAPTURE	4
-#define ICH6_NUM_PLAYBACK	4
-
-/* ULI has 6 playback and 5 capture */
-#define ULI_NUM_CAPTURE		5
-#define ULI_NUM_PLAYBACK	6
-
-/* ATI HDMI may have up to 8 playbacks and 0 capture */
-#define ATIHDMI_NUM_CAPTURE	0
-#define ATIHDMI_NUM_PLAYBACK	8
-
-/* TERA has 4 playback and 3 capture */
-#define TERA_NUM_CAPTURE	3
-#define TERA_NUM_PLAYBACK	4
-
-/* this number is statically defined for simplicity */
-#define MAX_AZX_DEV		16
-
 /* max number of fragments - we may use more if allocating more pages for BDL */
 #define BDL_SIZE		4096
 #define AZX_MAX_BDL_ENTRIES	(BDL_SIZE / 16)
@@ -160,13 +140,13 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define SD_STS_FIFO_READY	0x20	/* FIFO ready */
 
 /* INTCTL and INTSTS */
-#define ICH6_INT_ALL_STREAM	0xff	   /* all stream interrupts */
-#define ICH6_INT_CTRL_EN	0x40000000 /* controller interrupt enable bit */
-#define ICH6_INT_GLOBAL_EN	0x80000000 /* global interrupt enable bit */
+#define AZX_INT_ALL_STREAM	0xff	   /* all stream interrupts */
+#define AZX_INT_CTRL_EN	0x40000000 /* controller interrupt enable bit */
+#define AZX_INT_GLOBAL_EN	0x80000000 /* global interrupt enable bit */
 
 /* below are so far hardcoded - should read registers in future */
-#define ICH6_MAX_CORB_ENTRIES	256
-#define ICH6_MAX_RIRB_ENTRIES	256
+#define AZX_MAX_CORB_ENTRIES	256
+#define AZX_MAX_RIRB_ENTRIES	256
 
 /* driver quirks (capabilities) */
 /* bits 0-7 are used for indicating driver type */
@@ -192,35 +172,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define AZX_DCAPS_I915_POWERWELL (1 << 27)	/* HSW i915 powerwell support */
 #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28)	/* CORBRP clears itself after reset */
 
-/* position fix mode */
-enum {
-	POS_FIX_AUTO,
-	POS_FIX_LPIB,
-	POS_FIX_POSBUF,
-	POS_FIX_VIACOMBO,
-	POS_FIX_COMBO,
-};
-
-/* Defines for ATI HD Audio support in SB450 south bridge */
-#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR   0x42
-#define ATI_SB450_HDAUDIO_ENABLE_SNOOP      0x02
-
-/* Defines for Nvidia HDA support */
-#define NVIDIA_HDA_TRANSREG_ADDR      0x4e
-#define NVIDIA_HDA_ENABLE_COHBITS     0x0f
-#define NVIDIA_HDA_ISTRM_COH          0x4d
-#define NVIDIA_HDA_OSTRM_COH          0x4c
-#define NVIDIA_HDA_ENABLE_COHBIT      0x01
-
-/* Defines for Intel SCH HDA snoop control */
-#define INTEL_SCH_HDA_DEVC      0x78
-#define INTEL_SCH_HDA_DEVC_NOSNOOP       (0x1<<11)
-
-/* Define IN stream 0 FIFO size offset in VIA controller */
-#define VIA_IN_STREAM0_FIFO_SIZE_OFFSET	0x90
-/* Define VIA HD Audio Device ID*/
-#define VIA_HDAC_DEVICE_ID		0x3288
-
 /* HD Audio class code */
 #define PCI_CLASS_MULTIMEDIA_HD_AUDIO	0x0403
 
@@ -325,6 +276,9 @@ struct azx_pcm {
 	struct list_head list;
 };
 
+typedef unsigned int (*azx_get_pos_callback_t)(struct azx *, struct azx_dev *);
+typedef int (*azx_get_delay_callback_t)(struct azx *, struct azx_dev *, unsigned int pos);
+
 struct azx {
 	struct snd_card *card;
 	struct pci_dev *pci;
@@ -343,6 +297,10 @@ struct azx {
 	/* Register interaction. */
 	const struct hda_controller_ops *ops;
 
+	/* position adjustment callbacks */
+	azx_get_pos_callback_t get_position[2];
+	azx_get_delay_callback_t get_delay[2];
+
 	/* pci resources */
 	unsigned long addr;
 	void __iomem *remap_addr;
@@ -351,7 +309,6 @@ struct azx {
 	/* locks */
 	spinlock_t reg_lock;
 	struct mutex open_mutex; /* Prevents concurrent open/close operations */
-	struct completion probe_wait;
 
 	/* streams (x num_streams) */
 	struct azx_dev *azx_dev;
@@ -378,7 +335,6 @@ struct azx {
 #endif
 
 	/* flags */
-	int position_fix[2]; /* for both playback/capture streams */
 	const int *bdl_pos_adj;
 	int poll_count;
 	unsigned int running:1;
@@ -386,46 +342,23 @@ struct azx {
 	unsigned int single_cmd:1;
 	unsigned int polling_mode:1;
 	unsigned int msi:1;
-	unsigned int irq_pending_warned:1;
 	unsigned int probing:1; /* codec probing phase */
 	unsigned int snoop:1;
 	unsigned int align_buffer_size:1;
 	unsigned int region_requested:1;
-
-	/* VGA-switcheroo setup */
-	unsigned int use_vga_switcheroo:1;
-	unsigned int vga_switcheroo_registered:1;
-	unsigned int init_failed:1; /* delayed init failed */
 	unsigned int disabled:1; /* disabled by VGA-switcher */
 
 	/* for debugging */
 	unsigned int last_cmd[AZX_MAX_CODECS];
 
-	/* for pending irqs */
-	struct work_struct irq_pending_work;
-
-	struct work_struct probe_work;
-
 	/* reboot notifier (for mysterious hangup problem at power-down) */
 	struct notifier_block reboot_notifier;
 
-	/* card list (for power_save trigger) */
-	struct list_head list;
-
 #ifdef CONFIG_SND_HDA_DSP_LOADER
 	struct azx_dev saved_azx_dev;
 #endif
-
-	/* secondary power domain for hdmi audio under vga device */
-	struct dev_pm_domain hdmi_pm_domain;
 };
 
-#ifdef CONFIG_SND_VERBOSE_PRINTK
-#define SFX	/* nop */
-#else
-#define SFX	"hda-intel "
-#endif
-
 #ifdef CONFIG_X86
 #define azx_snoop(chip)		((chip)->snoop)
 #else
@@ -437,29 +370,29 @@ struct azx {
  */
 
 #define azx_writel(chip, reg, value) \
-	((chip)->ops->reg_writel(value, (chip)->remap_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_writel(value, (chip)->remap_addr + AZX_REG_##reg))
 #define azx_readl(chip, reg) \
-	((chip)->ops->reg_readl((chip)->remap_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_readl((chip)->remap_addr + AZX_REG_##reg))
 #define azx_writew(chip, reg, value) \
-	((chip)->ops->reg_writew(value, (chip)->remap_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_writew(value, (chip)->remap_addr + AZX_REG_##reg))
 #define azx_readw(chip, reg) \
-	((chip)->ops->reg_readw((chip)->remap_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_readw((chip)->remap_addr + AZX_REG_##reg))
 #define azx_writeb(chip, reg, value) \
-	((chip)->ops->reg_writeb(value, (chip)->remap_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_writeb(value, (chip)->remap_addr + AZX_REG_##reg))
 #define azx_readb(chip, reg) \
-	((chip)->ops->reg_readb((chip)->remap_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_readb((chip)->remap_addr + AZX_REG_##reg))
 
 #define azx_sd_writel(chip, dev, reg, value) \
-	((chip)->ops->reg_writel(value, (dev)->sd_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_writel(value, (dev)->sd_addr + AZX_REG_##reg))
 #define azx_sd_readl(chip, dev, reg) \
-	((chip)->ops->reg_readl((dev)->sd_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_readl((dev)->sd_addr + AZX_REG_##reg))
 #define azx_sd_writew(chip, dev, reg, value) \
-	((chip)->ops->reg_writew(value, (dev)->sd_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_writew(value, (dev)->sd_addr + AZX_REG_##reg))
 #define azx_sd_readw(chip, dev, reg) \
-	((chip)->ops->reg_readw((dev)->sd_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_readw((dev)->sd_addr + AZX_REG_##reg))
 #define azx_sd_writeb(chip, dev, reg, value) \
-	((chip)->ops->reg_writeb(value, (dev)->sd_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_writeb(value, (dev)->sd_addr + AZX_REG_##reg))
 #define azx_sd_readb(chip, dev, reg) \
-	((chip)->ops->reg_readb((dev)->sd_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_readb((dev)->sd_addr + AZX_REG_##reg))
 
 #endif /* __SOUND_HDA_PRIV_H */
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
index 358414da6418..227990bc02e3 100644
--- a/sound/pci/hda/hda_tegra.c
+++ b/sound/pci/hda/hda_tegra.c
@@ -29,7 +29,6 @@
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
 #include <linux/of_device.h>
-#include <linux/reboot.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 
@@ -272,13 +271,9 @@ static int hda_tegra_resume(struct device *dev)
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct azx *chip = card->private_data;
 	struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
-	int status;
 
 	hda_tegra_enable_clocks(hda);
 
-	/* Read STATESTS before controller reset */
-	status = azx_readw(chip, STATESTS);
-
 	hda_tegra_init(hda);
 
 	azx_init_chip(chip, 1);
@@ -295,30 +290,6 @@ static const struct dev_pm_ops hda_tegra_pm = {
 };
 
 /*
- * reboot notifier for hang-up problem at power-down
- */
-static int hda_tegra_halt(struct notifier_block *nb, unsigned long event,
-			  void *buf)
-{
-	struct azx *chip = container_of(nb, struct azx, reboot_notifier);
-	snd_hda_bus_reboot_notify(chip->bus);
-	azx_stop_chip(chip);
-	return NOTIFY_OK;
-}
-
-static void hda_tegra_notifier_register(struct azx *chip)
-{
-	chip->reboot_notifier.notifier_call = hda_tegra_halt;
-	register_reboot_notifier(&chip->reboot_notifier);
-}
-
-static void hda_tegra_notifier_unregister(struct azx *chip)
-{
-	if (chip->reboot_notifier.notifier_call)
-		unregister_reboot_notifier(&chip->reboot_notifier);
-}
-
-/*
  * destructor
  */
 static int hda_tegra_dev_free(struct snd_device *device)
@@ -326,7 +297,7 @@ static int hda_tegra_dev_free(struct snd_device *device)
 	int i;
 	struct azx *chip = device->device_data;
 
-	hda_tegra_notifier_unregister(chip);
+	azx_notifier_unregister(chip);
 
 	if (chip->initialized) {
 		for (i = 0; i < chip->num_streams; i++)
@@ -478,10 +449,7 @@ static int hda_tegra_create(struct snd_card *card,
 	chip->driver_type = driver_caps & 0xff;
 	chip->dev_index = 0;
 	INIT_LIST_HEAD(&chip->pcm_list);
-	INIT_LIST_HEAD(&chip->list);
 
-	chip->position_fix[0] = POS_FIX_AUTO;
-	chip->position_fix[1] = POS_FIX_AUTO;
 	chip->codec_probe_mask = -1;
 
 	chip->single_cmd = false;
@@ -559,7 +527,7 @@ static int hda_tegra_probe(struct platform_device *pdev)
 
 	chip->running = 1;
 	power_down_all_codecs(chip);
-	hda_tegra_notifier_register(chip);
+	azx_notifier_register(chip);
 
 	return 0;
 
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 092f2bd030bd..4f3aba78f720 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -2046,14 +2046,14 @@ enum dma_state {
 	DMA_STATE_RUN   = 1
 };
 
-static int dma_convert_to_hda_format(
+static int dma_convert_to_hda_format(struct hda_codec *codec,
 		unsigned int sample_rate,
 		unsigned short channels,
 		unsigned short *hda_format)
 {
 	unsigned int format_val;
 
-	format_val = snd_hda_calc_stream_format(
+	format_val = snd_hda_calc_stream_format(codec,
 				sample_rate,
 				channels,
 				SNDRV_PCM_FORMAT_S32_LE,
@@ -2452,7 +2452,7 @@ static int dspxfr_image(struct hda_codec *codec,
 	}
 
 	dma_engine->codec = codec;
-	dma_convert_to_hda_format(sample_rate, channels, &hda_format);
+	dma_convert_to_hda_format(codec, sample_rate, channels, &hda_format);
 	dma_engine->m_converter_format = hda_format;
 	dma_engine->buf_size = (ovly ? DSP_DMA_WRITE_BUFLEN_OVLY :
 			DSP_DMA_WRITE_BUFLEN_INIT) * 2;
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 387f0b551889..3db724eaa53c 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -657,8 +657,10 @@ static void cs4208_fixup_mac(struct hda_codec *codec,
 {
 	if (action != HDA_FIXUP_ACT_PRE_PROBE)
 		return;
+
+	codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
 	snd_hda_pick_fixup(codec, NULL, cs4208_mac_fixup_tbl, cs4208_fixups);
-	if (codec->fixup_id < 0 || codec->fixup_id == CS4208_MAC_AUTO)
+	if (codec->fixup_id == HDA_FIXUP_ID_NOT_SET)
 		codec->fixup_id = CS4208_GPIO0; /* default fixup */
 	snd_hda_apply_fixup(codec, action);
 }
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 061ea5965dd5..ed3d133ffbb6 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -31,550 +31,11 @@
 #include "hda_jack.h"
 #include "hda_generic.h"
 
-#undef ENABLE_CMI_STATIC_QUIRKS
-
-#ifdef ENABLE_CMI_STATIC_QUIRKS
-#define NUM_PINS	11
-
-
-/* board config type */
-enum {
-	CMI_MINIMAL,	/* back 3-jack */
-	CMI_MIN_FP,	/* back 3-jack + front-panel 2-jack */
-	CMI_FULL,	/* back 6-jack + front-panel 2-jack */
-	CMI_FULL_DIG,	/* back 6-jack + front-panel 2-jack + digital I/O */
-	CMI_ALLOUT,	/* back 5-jack + front-panel 2-jack + digital out */
-	CMI_AUTO,	/* let driver guess it */
-	CMI_MODELS
-};
-#endif /* ENABLE_CMI_STATIC_QUIRKS */
-
 struct cmi_spec {
 	struct hda_gen_spec gen;
-
-#ifdef ENABLE_CMI_STATIC_QUIRKS
-	/* below are only for static models */
-
-	int board_config;
-	unsigned int no_line_in: 1;	/* no line-in (5-jack) */
-	unsigned int front_panel: 1;	/* has front-panel 2-jack */
-
-	/* playback */
-	struct hda_multi_out multiout;
-	hda_nid_t dac_nids[AUTO_CFG_MAX_OUTS];	/* NID for each DAC */
-	int num_dacs;
-
-	/* capture */
-	const hda_nid_t *adc_nids;
-	hda_nid_t dig_in_nid;
-
-	/* capture source */
-	const struct hda_input_mux *input_mux;
-	unsigned int cur_mux[2];
-
-	/* channel mode */
-	int num_channel_modes;
-	const struct hda_channel_mode *channel_modes;
-
-	struct hda_pcm pcm_rec[2];	/* PCM information */
-
-	/* pin default configuration */
-	hda_nid_t pin_nid[NUM_PINS];
-	unsigned int def_conf[NUM_PINS];
-	unsigned int pin_def_confs;
-
-	/* multichannel pins */
-	struct hda_verb multi_init[9];	/* 2 verbs for each pin + terminator */
-#endif /* ENABLE_CMI_STATIC_QUIRKS */
-};
-
-#ifdef ENABLE_CMI_STATIC_QUIRKS
-/*
- * input MUX
- */
-static int cmi_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_input_mux_info(spec->input_mux, uinfo);
-}
-
-static int cmi_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct cmi_spec *spec = codec->spec;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
-	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
-	return 0;
-}
-
-static int cmi_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct cmi_spec *spec = codec->spec;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
-	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
-				     spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
-}
-
-/*
- * shared line-in, mic for surrounds
- */
-
-/* 3-stack / 2 channel */
-static const struct hda_verb cmi9880_ch2_init[] = {
-	/* set line-in PIN for input */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	/* set mic PIN for input, also enable vref */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	/* route front PCM (DAC1) to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	{}
-};
-
-/* 3-stack / 6 channel */
-static const struct hda_verb cmi9880_ch6_init[] = {
-	/* set line-in PIN for output */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	/* set mic PIN for output */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	/* route front PCM (DAC1) to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	{}
-};
-
-/* 3-stack+front / 8 channel */
-static const struct hda_verb cmi9880_ch8_init[] = {
-	/* set line-in PIN for output */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	/* set mic PIN for output */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	/* route rear-surround PCM (DAC4) to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 },
-	{}
-};
-
-static const struct hda_channel_mode cmi9880_channel_modes[3] = {
-	{ 2, cmi9880_ch2_init },
-	{ 6, cmi9880_ch6_init },
-	{ 8, cmi9880_ch8_init },
-};
-
-static int cmi_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_modes,
-				    spec->num_channel_modes);
-}
-
-static int cmi_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_modes,
-				   spec->num_channel_modes, spec->multiout.max_channels);
-}
-
-static int cmi_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_modes,
-				   spec->num_channel_modes, &spec->multiout.max_channels);
-}
-
-/*
- */
-static const struct snd_kcontrol_new cmi9880_basic_mixer[] = {
-	/* CMI9880 has no playback volumes! */
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), /* front */
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Side Playback Switch", 0x06, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 2,
-		.info = cmi_mux_enum_info,
-		.get = cmi_mux_enum_get,
-		.put = cmi_mux_enum_put,
-	},
-	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x23, 0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x23, 0, HDA_OUTPUT),
-	{ } /* end */
 };
 
 /*
- * shared I/O pins
- */
-static const struct snd_kcontrol_new cmi9880_ch_mode_mixer[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = cmi_ch_mode_info,
-		.get = cmi_ch_mode_get,
-		.put = cmi_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-/* AUD-in selections:
- * 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x1f 0x20
- */
-static const struct hda_input_mux cmi9880_basic_mux = {
-	.num_items = 4,
-	.items = {
-		{ "Front Mic", 0x5 },
-		{ "Rear Mic", 0x2 },
-		{ "Line", 0x1 },
-		{ "CD", 0x7 },
-	}
-};
-
-static const struct hda_input_mux cmi9880_no_line_mux = {
-	.num_items = 3,
-	.items = {
-		{ "Front Mic", 0x5 },
-		{ "Rear Mic", 0x2 },
-		{ "CD", 0x7 },
-	}
-};
-
-/* front, rear, clfe, rear_surr */
-static const hda_nid_t cmi9880_dac_nids[4] = {
-	0x03, 0x04, 0x05, 0x06
-};
-/* ADC0, ADC1 */
-static const hda_nid_t cmi9880_adc_nids[2] = {
-	0x08, 0x09
-};
-
-#define CMI_DIG_OUT_NID	0x07
-#define CMI_DIG_IN_NID	0x0a
-
-/*
- */
-static const struct hda_verb cmi9880_basic_init[] = {
-	/* port-D for line out (rear panel) */
-	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* port-E for HP out (front panel) */
-	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* route front PCM to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-A for surround (rear panel) */
-	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* port-G for CLFE (rear panel) */
-	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
-	/* port-H for side (rear panel) */
-	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	/* port-C for line-in (rear panel) */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	/* port-B for mic-in (rear panel) with vref */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	/* port-F for mic-in (front panel) with vref */
-	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	/* CD-in */
-	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	/* route front mic to ADC1/2 */
-	{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
-	{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
-	{} /* terminator */
-};
-
-static const struct hda_verb cmi9880_allout_init[] = {
-	/* port-D for line out (rear panel) */
-	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* port-E for HP out (front panel) */
-	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* route front PCM to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-A for side (rear panel) */
-	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* port-G for CLFE (rear panel) */
-	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
-	/* port-H for side (rear panel) */
-	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	/* port-C for surround (rear panel) */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* port-B for mic-in (rear panel) with vref */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	/* port-F for mic-in (front panel) with vref */
-	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	/* CD-in */
-	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	/* route front mic to ADC1/2 */
-	{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
-	{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
-	{} /* terminator */
-};
-
-/*
- */
-static int cmi9880_build_controls(struct hda_codec *codec)
-{
-	struct cmi_spec *spec = codec->spec;
-	struct snd_kcontrol *kctl;
-	int i, err;
-
-	err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer);
-	if (err < 0)
-		return err;
-	if (spec->channel_modes) {
-		err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer);
-		if (err < 0)
-			return err;
-	}
-	if (spec->multiout.dig_out_nid) {
-		err = snd_hda_create_spdif_out_ctls(codec,
-						    spec->multiout.dig_out_nid,
-						    spec->multiout.dig_out_nid);
-		if (err < 0)
-			return err;
-		err = snd_hda_create_spdif_share_sw(codec,
-						    &spec->multiout);
-		if (err < 0)
-			return err;
-		spec->multiout.share_spdif = 1;
-	}
-	if (spec->dig_in_nid) {
-		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
-		if (err < 0)
-			return err;
-	}
-
-	/* assign Capture Source enums to NID */
-	kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
-	for (i = 0; kctl && i < kctl->count; i++) {
-		err = snd_hda_add_nid(codec, kctl, i, spec->adc_nids[i]);
-		if (err < 0)
-			return err;
-	}
-	return 0;
-}
-
-static int cmi9880_init(struct hda_codec *codec)
-{
-	struct cmi_spec *spec = codec->spec;
-	if (spec->board_config == CMI_ALLOUT)
-		snd_hda_sequence_write(codec, cmi9880_allout_init);
-	else
-		snd_hda_sequence_write(codec, cmi9880_basic_init);
-	if (spec->board_config == CMI_AUTO)
-		snd_hda_sequence_write(codec, spec->multi_init);
-	return 0;
-}
-
-/*
- * Analog playback callbacks
- */
-static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo,
-				     struct hda_codec *codec,
-				     struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
-					     hinfo);
-}
-
-static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-					struct hda_codec *codec,
-					unsigned int stream_tag,
-					unsigned int format,
-					struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
-						format, substream);
-}
-
-static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				       struct hda_codec *codec,
-				       struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
-}
-
-/*
- * Digital out
- */
-static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
-					 struct hda_codec *codec,
-					 struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
-					  struct hda_codec *codec,
-					  struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-static int cmi9880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-					    struct hda_codec *codec,
-					    unsigned int stream_tag,
-					    unsigned int format,
-					    struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
-					     format, substream);
-}
-
-/*
- * Analog capture
- */
-static int cmi9880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      unsigned int stream_tag,
-				      unsigned int format,
-				      struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-				   stream_tag, 0, format);
-	return 0;
-}
-
-static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-
-	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
-	return 0;
-}
-
-
-/*
- */
-static const struct hda_pcm_stream cmi9880_pcm_analog_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 8,
-	.nid = 0x03, /* NID to query formats and rates */
-	.ops = {
-		.open = cmi9880_playback_pcm_open,
-		.prepare = cmi9880_playback_pcm_prepare,
-		.cleanup = cmi9880_playback_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream cmi9880_pcm_analog_capture = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x08, /* NID to query formats and rates */
-	.ops = {
-		.prepare = cmi9880_capture_pcm_prepare,
-		.cleanup = cmi9880_capture_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream cmi9880_pcm_digital_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in cmi9880_build_pcms */
-	.ops = {
-		.open = cmi9880_dig_playback_pcm_open,
-		.close = cmi9880_dig_playback_pcm_close,
-		.prepare = cmi9880_dig_playback_pcm_prepare
-	},
-};
-
-static const struct hda_pcm_stream cmi9880_pcm_digital_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in cmi9880_build_pcms */
-};
-
-static int cmi9880_build_pcms(struct hda_codec *codec)
-{
-	struct cmi_spec *spec = codec->spec;
-	struct hda_pcm *info = spec->pcm_rec;
-
-	codec->num_pcms = 1;
-	codec->pcm_info = info;
-
-	info->name = "CMI9880";
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_analog_playback;
-	info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_analog_capture;
-
-	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
-		codec->num_pcms++;
-		info++;
-		info->name = "CMI9880 Digital";
-		info->pcm_type = HDA_PCM_TYPE_SPDIF;
-		if (spec->multiout.dig_out_nid) {
-			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback;
-			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
-		}
-		if (spec->dig_in_nid) {
-			info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_digital_capture;
-			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
-		}
-	}
-
-	return 0;
-}
-
-static void cmi9880_free(struct hda_codec *codec)
-{
-	kfree(codec->spec);
-}
-
-/*
- */
-
-static const char * const cmi9880_models[CMI_MODELS] = {
-	[CMI_MINIMAL]	= "minimal",
-	[CMI_MIN_FP]	= "min_fp",
-	[CMI_FULL]	= "full",
-	[CMI_FULL_DIG]	= "full_dig",
-	[CMI_ALLOUT]	= "allout",
-	[CMI_AUTO]	= "auto",
-};
-
-static const struct snd_pci_quirk cmi9880_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG),
-	SND_PCI_QUIRK(0x1854, 0x002b, "LG LS75", CMI_MINIMAL),
-	SND_PCI_QUIRK(0x1854, 0x0032, "LG", CMI_FULL_DIG),
-	{} /* terminator */
-};
-
-static const struct hda_codec_ops cmi9880_patch_ops = {
-	.build_controls = cmi9880_build_controls,
-	.build_pcms = cmi9880_build_pcms,
-	.init = cmi9880_init,
-	.free = cmi9880_free,
-};
-#endif /* ENABLE_CMI_STATIC_QUIRKS */
-
-/*
  * stuff for auto-parser
  */
 static const struct hda_codec_ops cmi_auto_patch_ops = {
@@ -585,12 +46,18 @@ static const struct hda_codec_ops cmi_auto_patch_ops = {
 	.unsol_event = snd_hda_jack_unsol_event,
 };
 
-static int cmi_parse_auto_config(struct hda_codec *codec)
+static int patch_cmi9880(struct hda_codec *codec)
 {
-	struct cmi_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->gen.autocfg;
+	struct cmi_spec *spec;
+	struct auto_pin_cfg *cfg;
 	int err;
 
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+	cfg = &spec->gen.autocfg;
 	snd_hda_gen_spec_init(&spec->gen);
 
 	err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
@@ -608,79 +75,6 @@ static int cmi_parse_auto_config(struct hda_codec *codec)
 	return err;
 }
 
-
-static int patch_cmi9880(struct hda_codec *codec)
-{
-	struct cmi_spec *spec;
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (spec == NULL)
-		return -ENOMEM;
-
-	codec->spec = spec;
-#ifdef ENABLE_CMI_STATIC_QUIRKS
-	spec->board_config = snd_hda_check_board_config(codec, CMI_MODELS,
-							cmi9880_models,
-							cmi9880_cfg_tbl);
-	if (spec->board_config < 0) {
-		codec_dbg(codec, "%s: BIOS auto-probing.\n",
-			    codec->chip_name);
-		spec->board_config = CMI_AUTO; /* try everything */
-	}
-
-	if (spec->board_config == CMI_AUTO)
-		return cmi_parse_auto_config(codec);
-
-	/* copy default DAC NIDs */
-	memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids));
-	spec->num_dacs = 4;
-
-	switch (spec->board_config) {
-	case CMI_MINIMAL:
-	case CMI_MIN_FP:
-		spec->channel_modes = cmi9880_channel_modes;
-		if (spec->board_config == CMI_MINIMAL)
-			spec->num_channel_modes = 2;
-		else {
-			spec->front_panel = 1;
-			spec->num_channel_modes = 3;
-		}
-		spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
-		spec->input_mux = &cmi9880_basic_mux;
-		break;
-	case CMI_FULL:
-	case CMI_FULL_DIG:
-		spec->front_panel = 1;
-		spec->multiout.max_channels = 8;
-		spec->input_mux = &cmi9880_basic_mux;
-		if (spec->board_config == CMI_FULL_DIG) {
-			spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
-			spec->dig_in_nid = CMI_DIG_IN_NID;
-		}
-		break;
-	case CMI_ALLOUT:
-	default:
-		spec->front_panel = 1;
-		spec->multiout.max_channels = 8;
-		spec->no_line_in = 1;
-		spec->input_mux = &cmi9880_no_line_mux;
-		spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
-		break;
-	}
-
-	spec->multiout.num_dacs = spec->num_dacs;
-	spec->multiout.dac_nids = spec->dac_nids;
-
-	spec->adc_nids = cmi9880_adc_nids;
-
-	codec->patch_ops = cmi9880_patch_ops;
-
-	return 0;
-#else
-	return cmi_parse_auto_config(codec);
-#endif
-}
-
 /*
  * patch entries
  */
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 1dc7e974f3b1..7627a69ca6d7 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -34,27 +34,6 @@
 #include "hda_jack.h"
 #include "hda_generic.h"
 
-#undef ENABLE_CXT_STATIC_QUIRKS
-
-#define CXT_PIN_DIR_IN              0x00
-#define CXT_PIN_DIR_OUT             0x01
-#define CXT_PIN_DIR_INOUT           0x02
-#define CXT_PIN_DIR_IN_NOMICBIAS    0x03
-#define CXT_PIN_DIR_INOUT_NOMICBIAS 0x04
-
-#define CONEXANT_HP_EVENT	0x37
-#define CONEXANT_MIC_EVENT	0x38
-#define CONEXANT_LINE_EVENT	0x39
-
-/* Conexant 5051 specific */
-
-#define CXT5051_SPDIF_OUT	0x12
-#define CXT5051_PORTB_EVENT	0x38
-#define CXT5051_PORTC_EVENT	0x39
-
-#define AUTO_MIC_PORTB		(1 << 1)
-#define AUTO_MIC_PORTC		(1 << 2)
-
 struct conexant_spec {
 	struct hda_gen_spec gen;
 
@@ -72,64 +51,6 @@ struct conexant_spec {
 	bool dc_enable;
 	unsigned int dc_input_bias; /* offset into olpc_xo_dc_bias */
 	struct nid_path *dc_mode_path;
-
-#ifdef ENABLE_CXT_STATIC_QUIRKS
-	const struct snd_kcontrol_new *mixers[5];
-	int num_mixers;
-	hda_nid_t vmaster_nid;
-
-	const struct hda_verb *init_verbs[5];	/* initialization verbs
-						 * don't forget NULL
-						 * termination!
-						 */
-	unsigned int num_init_verbs;
-
-	/* playback */
-	struct hda_multi_out multiout;	/* playback set-up
-					 * max_channels, dacs must be set
-					 * dig_out_nid and hp_nid are optional
-					 */
-	unsigned int cur_eapd;
-	unsigned int hp_present;
-	unsigned int line_present;
-	unsigned int auto_mic;
-
-	/* capture */
-	unsigned int num_adc_nids;
-	const hda_nid_t *adc_nids;
-	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
-
-	unsigned int cur_adc_idx;
-	hda_nid_t cur_adc;
-	unsigned int cur_adc_stream_tag;
-	unsigned int cur_adc_format;
-
-	const struct hda_pcm_stream *capture_stream;
-
-	/* capture source */
-	const struct hda_input_mux *input_mux;
-	const hda_nid_t *capsrc_nids;
-	unsigned int cur_mux[3];
-
-	/* channel model */
-	const struct hda_channel_mode *channel_mode;
-	int num_channel_mode;
-
-	/* PCM information */
-	struct hda_pcm pcm_rec[2];	/* used in build_pcms() */
-
-	unsigned int spdif_route;
-
-	unsigned int port_d_mode;
-	unsigned int dell_automute:1;
-	unsigned int dell_vostro:1;
-	unsigned int ideapad:1;
-	unsigned int thinkpad:1;
-	unsigned int hp_laptop:1;
-	unsigned int asus:1;
-
-	unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */
-#endif /* ENABLE_CXT_STATIC_QUIRKS */
 };
 
 
@@ -173,2533 +94,6 @@ static int add_beep_ctls(struct hda_codec *codec)
 #define add_beep_ctls(codec)	0
 #endif
 
-
-#ifdef ENABLE_CXT_STATIC_QUIRKS
-static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
-					     hinfo);
-}
-
-static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-					 struct hda_codec *codec,
-					 unsigned int stream_tag,
-					 unsigned int format,
-					 struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
-						stream_tag,
-						format, substream);
-}
-
-static int conexant_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
-					 struct hda_codec *codec,
-					 struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
-}
-
-/*
- * Digital out
- */
-static int conexant_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
-					  struct hda_codec *codec,
-					  struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
-					 struct hda_codec *codec,
-					 struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-					 struct hda_codec *codec,
-					 unsigned int stream_tag,
-					 unsigned int format,
-					 struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
-					     stream_tag,
-					     format, substream);
-}
-
-/*
- * Analog capture
- */
-static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      unsigned int stream_tag,
-				      unsigned int format,
-				      struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-				   stream_tag, 0, format);
-	return 0;
-}
-
-static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
-	return 0;
-}
-
-
-
-static const struct hda_pcm_stream conexant_pcm_analog_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0, /* fill later */
-	.ops = {
-		.open = conexant_playback_pcm_open,
-		.prepare = conexant_playback_pcm_prepare,
-		.cleanup = conexant_playback_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream conexant_pcm_analog_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0, /* fill later */
-	.ops = {
-		.prepare = conexant_capture_pcm_prepare,
-		.cleanup = conexant_capture_pcm_cleanup
-	},
-};
-
-
-static const struct hda_pcm_stream conexant_pcm_digital_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0, /* fill later */
-	.ops = {
-		.open = conexant_dig_playback_pcm_open,
-		.close = conexant_dig_playback_pcm_close,
-		.prepare = conexant_dig_playback_pcm_prepare
-	},
-};
-
-static const struct hda_pcm_stream conexant_pcm_digital_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in alc_build_pcms */
-};
-
-static int cx5051_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      unsigned int stream_tag,
-				      unsigned int format,
-				      struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	spec->cur_adc = spec->adc_nids[spec->cur_adc_idx];
-	spec->cur_adc_stream_tag = stream_tag;
-	spec->cur_adc_format = format;
-	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
-	return 0;
-}
-
-static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
-	spec->cur_adc = 0;
-	return 0;
-}
-
-static const struct hda_pcm_stream cx5051_pcm_analog_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0, /* fill later */
-	.ops = {
-		.prepare = cx5051_capture_pcm_prepare,
-		.cleanup = cx5051_capture_pcm_cleanup
-	},
-};
-
-static int conexant_build_pcms(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	struct hda_pcm *info = spec->pcm_rec;
-
-	codec->num_pcms = 1;
-	codec->pcm_info = info;
-
-	info->name = "CONEXANT Analog";
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback;
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
-		spec->multiout.max_channels;
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
-		spec->multiout.dac_nids[0];
-	if (spec->capture_stream)
-		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *spec->capture_stream;
-	else {
-		if (codec->vendor_id == 0x14f15051)
-			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
-				cx5051_pcm_analog_capture;
-		else {
-			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
-				conexant_pcm_analog_capture;
-			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
-				spec->num_adc_nids;
-		}
-	}
-	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
-
-	if (spec->multiout.dig_out_nid) {
-		info++;
-		codec->num_pcms++;
-		info->name = "Conexant Digital";
-		info->pcm_type = HDA_PCM_TYPE_SPDIF;
-		info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
-			conexant_pcm_digital_playback;
-		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
-			spec->multiout.dig_out_nid;
-		if (spec->dig_in_nid) {
-			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
-				conexant_pcm_digital_capture;
-			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
-				spec->dig_in_nid;
-		}
-	}
-
-	return 0;
-}
-
-static int conexant_mux_enum_info(struct snd_kcontrol *kcontrol,
-	       			  struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-
-	return snd_hda_input_mux_info(spec->input_mux, uinfo);
-}
-
-static int conexant_mux_enum_get(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
-	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
-	return 0;
-}
-
-static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
-	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
-				     spec->capsrc_nids[adc_idx],
-				     &spec->cur_mux[adc_idx]);
-}
-
-static void conexant_set_power(struct hda_codec *codec, hda_nid_t fg,
-			       unsigned int power_state)
-{
-	if (power_state == AC_PWRST_D3)
-		msleep(100);
-	snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
-			    power_state);
-	/* partial workaround for "azx_get_response timeout" */
-	if (power_state == AC_PWRST_D0)
-		msleep(10);
-	snd_hda_codec_set_power_to_all(codec, fg, power_state);
-}
-
-static int conexant_init(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	int i;
-
-	for (i = 0; i < spec->num_init_verbs; i++)
-		snd_hda_sequence_write(codec, spec->init_verbs[i]);
-	return 0;
-}
-
-static void conexant_free(struct hda_codec *codec)
-{
-	kfree(codec->spec);
-}
-
-static const struct snd_kcontrol_new cxt_capture_mixers[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.info = conexant_mux_enum_info,
-		.get = conexant_mux_enum_get,
-		.put = conexant_mux_enum_put
-	},
-	{}
-};
-
-static const char * const slave_pfxs[] = {
-	"Headphone", "Speaker", "Bass Speaker", "Front", "Surround", "CLFE",
-	NULL
-};
-
-static int conexant_build_controls(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int i;
-	int err;
-
-	for (i = 0; i < spec->num_mixers; i++) {
-		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
-		if (err < 0)
-			return err;
-	}
-	if (spec->multiout.dig_out_nid) {
-		err = snd_hda_create_spdif_out_ctls(codec,
-						    spec->multiout.dig_out_nid,
-						    spec->multiout.dig_out_nid);
-		if (err < 0)
-			return err;
-		err = snd_hda_create_spdif_share_sw(codec,
-						    &spec->multiout);
-		if (err < 0)
-			return err;
-		spec->multiout.share_spdif = 1;
-	} 
-	if (spec->dig_in_nid) {
-		err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid);
-		if (err < 0)
-			return err;
-	}
-
-	/* if we have no master control, let's create it */
-	if (spec->vmaster_nid &&
-	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
-		unsigned int vmaster_tlv[4];
-		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
-					HDA_OUTPUT, vmaster_tlv);
-		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
-					  vmaster_tlv, slave_pfxs,
-					  "Playback Volume");
-		if (err < 0)
-			return err;
-	}
-	if (spec->vmaster_nid &&
-	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
-		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
-					  NULL, slave_pfxs,
-					  "Playback Switch");
-		if (err < 0)
-			return err;
-	}
-
-	if (spec->input_mux) {
-		err = snd_hda_add_new_ctls(codec, cxt_capture_mixers);
-		if (err < 0)
-			return err;
-	}
-
-	err = add_beep_ctls(codec);
-	if (err < 0)
-		return err;
-
-	return 0;
-}
-
-static const struct hda_codec_ops conexant_patch_ops = {
-	.build_controls = conexant_build_controls,
-	.build_pcms = conexant_build_pcms,
-	.init = conexant_init,
-	.free = conexant_free,
-	.set_power_state = conexant_set_power,
-};
-
-static int patch_conexant_auto(struct hda_codec *codec);
-/*
- * EAPD control
- * the private value = nid | (invert << 8)
- */
-
-#define cxt_eapd_info		snd_ctl_boolean_mono_info
-
-static int cxt_eapd_get(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	int invert = (kcontrol->private_value >> 8) & 1;
-	if (invert)
-		ucontrol->value.integer.value[0] = !spec->cur_eapd;
-	else
-		ucontrol->value.integer.value[0] = spec->cur_eapd;
-	return 0;
-
-}
-
-static int cxt_eapd_put(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	int invert = (kcontrol->private_value >> 8) & 1;
-	hda_nid_t nid = kcontrol->private_value & 0xff;
-	unsigned int eapd;
-
-	eapd = !!ucontrol->value.integer.value[0];
-	if (invert)
-		eapd = !eapd;
-	if (eapd == spec->cur_eapd)
-		return 0;
-	
-	spec->cur_eapd = eapd;
-	snd_hda_codec_write_cache(codec, nid,
-				  0, AC_VERB_SET_EAPD_BTLENABLE,
-				  eapd ? 0x02 : 0x00);
-	return 1;
-}
-
-/* controls for test mode */
-#ifdef CONFIG_SND_DEBUG
-
-#define CXT_EAPD_SWITCH(xname, nid, mask) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .info = cxt_eapd_info, \
-	  .get = cxt_eapd_get, \
-	  .put = cxt_eapd_put, \
-	  .private_value = nid | (mask<<16) }
-
-
-
-static int conexant_ch_mode_info(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
-				    spec->num_channel_mode);
-}
-
-static int conexant_ch_mode_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
-				   spec->num_channel_mode,
-				   spec->multiout.max_channels);
-}
-
-static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
-				      spec->num_channel_mode,
-				      &spec->multiout.max_channels);
-	return err;
-}
-
-#define CXT_PIN_MODE(xname, nid, dir) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .info = conexant_ch_mode_info, \
-	  .get = conexant_ch_mode_get, \
-	  .put = conexant_ch_mode_put, \
-	  .private_value = nid | (dir<<16) }
-
-#endif /* CONFIG_SND_DEBUG */
-
-/* Conexant 5045 specific */
-
-static const hda_nid_t cxt5045_dac_nids[1] = { 0x19 };
-static const hda_nid_t cxt5045_adc_nids[1] = { 0x1a };
-static const hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a };
-#define CXT5045_SPDIF_OUT	0x18
-
-static const struct hda_channel_mode cxt5045_modes[1] = {
-	{ 2, NULL },
-};
-
-static const struct hda_input_mux cxt5045_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Internal Mic", 0x1 },
-		{ "Mic",          0x2 },
-	}
-};
-
-static const struct hda_input_mux cxt5045_capture_source_benq = {
-	.num_items = 4,
-	.items = {
-		{ "Internal Mic", 0x1 },
-		{ "Mic",          0x2 },
-		{ "Line",         0x3 },
-		{ "Mixer",        0x0 },
-	}
-};
-
-/* turn on/off EAPD (+ mute HP) as a master switch */
-static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	unsigned int bits;
-
-	if (!cxt_eapd_put(kcontrol, ucontrol))
-		return 0;
-
-	/* toggle internal speakers mute depending of presence of
-	 * the headphone jack
-	 */
-	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
-	snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-
-	bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
-	snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	return 1;
-}
-
-/* bind volumes of both NID 0x10 and 0x11 */
-static const struct hda_bind_ctls cxt5045_hp_bind_master_vol = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
-
-/* toggle input of built-in and mic jack appropriately */
-static void cxt5045_hp_automic(struct hda_codec *codec)
-{
-	static const struct hda_verb mic_jack_on[] = {
-		{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-		{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-		{}
-	};
-	static const struct hda_verb mic_jack_off[] = {
-		{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-		{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-		{}
-	};
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x12);
-	if (present)
-		snd_hda_sequence_write(codec, mic_jack_on);
-	else
-		snd_hda_sequence_write(codec, mic_jack_off);
-}
-
-
-/* mute internal speaker if HP is plugged */
-static void cxt5045_hp_automute(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int bits;
-
-	spec->hp_present = snd_hda_jack_detect(codec, 0x11);
-
-	bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 
-	snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-}
-
-/* unsolicited event for HP jack sensing */
-static void cxt5045_hp_unsol_event(struct hda_codec *codec,
-				   unsigned int res)
-{
-	res >>= 26;
-	switch (res) {
-	case CONEXANT_HP_EVENT:
-		cxt5045_hp_automute(codec);
-		break;
-	case CONEXANT_MIC_EVENT:
-		cxt5045_hp_automic(codec);
-		break;
-
-	}
-}
-
-static const struct snd_kcontrol_new cxt5045_mixers[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
-	HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = cxt_eapd_info,
-		.get = cxt_eapd_get,
-		.put = cxt5045_hp_master_sw_put,
-		.private_value = 0x10,
-	},
-
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5045_benq_mixers[] = {
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x3, HDA_INPUT),
-
-	{}
-};
-
-static const struct hda_verb cxt5045_init_verbs[] = {
-	/* Line in, Mic */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
-	/* HP, Amp  */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Record selector: Internal mic */
-	{0x1a, AC_VERB_SET_CONNECT_SEL,0x1},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
-	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
-	/* SPDIF route: PCM */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{ 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	/* EAPD */
-	{0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ 
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5045_benq_init_verbs[] = {
-	/* Internal Mic, Mic */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
-	/* Line In,HP, Amp  */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Record selector: Internal mic */
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
-	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
-	/* SPDIF route: PCM */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* EAPD */
-	{0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5045_hp_sense_init_verbs[] = {
-	/* pin sensing on HP jack */
-	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5045_mic_sense_init_verbs[] = {
-	/* pin sensing on HP jack */
-	{0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	{ } /* end */
-};
-
-#ifdef CONFIG_SND_DEBUG
-/* Test configuration for debugging, modelled after the ALC260 test
- * configuration.
- */
-static const struct hda_input_mux cxt5045_test_capture_source = {
-	.num_items = 5,
-	.items = {
-		{ "MIXER", 0x0 },
-		{ "MIC1 pin", 0x1 },
-		{ "LINE1 pin", 0x2 },
-		{ "HP-OUT pin", 0x3 },
-		{ "CD pin", 0x4 },
-        },
-};
-
-static const struct snd_kcontrol_new cxt5045_test_mixer[] = {
-
-	/* Output controls */
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("HP-OUT Playback Volume", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("HP-OUT Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("LINE1 Playback Switch", 0x12, 0x0, HDA_OUTPUT),
-	
-	/* Modes for retasking pin widgets */
-	CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT),
-	CXT_PIN_MODE("LINE1 pin mode", 0x12, CXT_PIN_DIR_INOUT),
-
-	/* EAPD Switch Control */
-	CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0),
-
-	/* Loopback mixer controls */
-
-	HDA_CODEC_VOLUME("PCM Volume", 0x17, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("PCM Switch", 0x17, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("MIC1 pin Volume", 0x17, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("MIC1 pin Switch", 0x17, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("LINE1 pin Volume", 0x17, 0x2, HDA_INPUT),
-	HDA_CODEC_MUTE("LINE1 pin Switch", 0x17, 0x2, HDA_INPUT),
-	HDA_CODEC_VOLUME("HP-OUT pin Volume", 0x17, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("HP-OUT pin Switch", 0x17, 0x3, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD pin Volume", 0x17, 0x4, HDA_INPUT),
-	HDA_CODEC_MUTE("CD pin Switch", 0x17, 0x4, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Input Source",
-		.info = conexant_mux_enum_info,
-		.get = conexant_mux_enum_get,
-		.put = conexant_mux_enum_put,
-	},
-	/* Audio input controls */
-	HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5045_test_init_verbs[] = {
-	/* Set connections */
-	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	{ 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	{ 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	/* Enable retasking pins as output, initially without power amp */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* Disable digital (SPDIF) pins initially, but users can enable
-	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
-	 * payload also sets the generation to 0, output to be in "consumer"
-	 * PCM format, copyright asserted, no pre-emphasis and no validity
-	 * control.
-	 */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x18, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
-	/* Unmute retasking pin widget output buffers since the default
-	 * state appears to be output.  As the pin mode is changed by the
-	 * user the pin mode control will take care of enabling the pin's
-	 * input/output buffers as needed.
-	 */
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Mute capture amp left and right */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-
-	/* Set ADC connection select to match default mixer setting (mic1
-	 * pin)
-	 */
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x01},
-
-	/* Mute all inputs to mixer widget (even unconnected ones) */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Mic1 pin */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* Line pin */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* HP pin */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
-
-	{ }
-};
-#endif
-
-
-/* initialize jack-sensing, too */
-static int cxt5045_init(struct hda_codec *codec)
-{
-	conexant_init(codec);
-	cxt5045_hp_automute(codec);
-	return 0;
-}
-
-
-enum {
-	CXT5045_LAPTOP_HPSENSE,
-	CXT5045_LAPTOP_MICSENSE,
-	CXT5045_LAPTOP_HPMICSENSE,
-	CXT5045_BENQ,
-#ifdef CONFIG_SND_DEBUG
-	CXT5045_TEST,
-#endif
-	CXT5045_AUTO,
-	CXT5045_MODELS
-};
-
-static const char * const cxt5045_models[CXT5045_MODELS] = {
-	[CXT5045_LAPTOP_HPSENSE]	= "laptop-hpsense",
-	[CXT5045_LAPTOP_MICSENSE]	= "laptop-micsense",
-	[CXT5045_LAPTOP_HPMICSENSE]	= "laptop-hpmicsense",
-	[CXT5045_BENQ]			= "benq",
-#ifdef CONFIG_SND_DEBUG
-	[CXT5045_TEST]		= "test",
-#endif
-	[CXT5045_AUTO]			= "auto",
-};
-
-static const struct snd_pci_quirk cxt5045_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
-	SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
-	SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505",
-		      CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell",
-			   CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE),
-	{}
-};
-
-static int patch_cxt5045(struct hda_codec *codec)
-{
-	struct conexant_spec *spec;
-	int board_config;
-
-	board_config = snd_hda_check_board_config(codec, CXT5045_MODELS,
-						  cxt5045_models,
-						  cxt5045_cfg_tbl);
-	if (board_config < 0)
-		board_config = CXT5045_AUTO; /* model=auto as default */
-	if (board_config == CXT5045_AUTO)
-		return patch_conexant_auto(codec);
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (!spec)
-		return -ENOMEM;
-	codec->spec = spec;
-	codec->single_adc_amp = 1;
-
-	spec->multiout.max_channels = 2;
-	spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids);
-	spec->multiout.dac_nids = cxt5045_dac_nids;
-	spec->multiout.dig_out_nid = CXT5045_SPDIF_OUT;
-	spec->num_adc_nids = 1;
-	spec->adc_nids = cxt5045_adc_nids;
-	spec->capsrc_nids = cxt5045_capsrc_nids;
-	spec->input_mux = &cxt5045_capture_source;
-	spec->num_mixers = 1;
-	spec->mixers[0] = cxt5045_mixers;
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = cxt5045_init_verbs;
-	spec->spdif_route = 0;
-	spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes);
-	spec->channel_mode = cxt5045_modes;
-
-	set_beep_amp(spec, 0x16, 0, 1);
-
-	codec->patch_ops = conexant_patch_ops;
-
-	switch (board_config) {
-	case CXT5045_LAPTOP_HPSENSE:
-		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
-		spec->input_mux = &cxt5045_capture_source;
-		spec->num_init_verbs = 2;
-		spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
-		spec->mixers[0] = cxt5045_mixers;
-		codec->patch_ops.init = cxt5045_init;
-		break;
-	case CXT5045_LAPTOP_MICSENSE:
-		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
-		spec->input_mux = &cxt5045_capture_source;
-		spec->num_init_verbs = 2;
-		spec->init_verbs[1] = cxt5045_mic_sense_init_verbs;
-		spec->mixers[0] = cxt5045_mixers;
-		codec->patch_ops.init = cxt5045_init;
-		break;
-	default:
-	case CXT5045_LAPTOP_HPMICSENSE:
-		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
-		spec->input_mux = &cxt5045_capture_source;
-		spec->num_init_verbs = 3;
-		spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
-		spec->init_verbs[2] = cxt5045_mic_sense_init_verbs;
-		spec->mixers[0] = cxt5045_mixers;
-		codec->patch_ops.init = cxt5045_init;
-		break;
-	case CXT5045_BENQ:
-		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
-		spec->input_mux = &cxt5045_capture_source_benq;
-		spec->num_init_verbs = 1;
-		spec->init_verbs[0] = cxt5045_benq_init_verbs;
-		spec->mixers[0] = cxt5045_mixers;
-		spec->mixers[1] = cxt5045_benq_mixers;
-		spec->num_mixers = 2;
-		codec->patch_ops.init = cxt5045_init;
-		break;
-#ifdef CONFIG_SND_DEBUG
-	case CXT5045_TEST:
-		spec->input_mux = &cxt5045_test_capture_source;
-		spec->mixers[0] = cxt5045_test_mixer;
-		spec->init_verbs[0] = cxt5045_test_init_verbs;
-		break;
-		
-#endif	
-	}
-
-	switch (codec->subsystem_id >> 16) {
-	case 0x103c:
-	case 0x1631:
-	case 0x1734:
-	case 0x17aa:
-		/* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have
-		 * really bad sound over 0dB on NID 0x17. Fix max PCM level to
-		 * 0 dB (originally it has 0x2b steps with 0dB offset 0x14)
-		 */
-		snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
-					  (0x14 << AC_AMPCAP_OFFSET_SHIFT) |
-					  (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) |
-					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
-					  (1 << AC_AMPCAP_MUTE_SHIFT));
-		break;
-	}
-
-	if (spec->beep_amp)
-		snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
-
-	return 0;
-}
-
-
-/* Conexant 5047 specific */
-#define CXT5047_SPDIF_OUT	0x11
-
-static const hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */
-static const hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
-static const hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
-
-static const struct hda_channel_mode cxt5047_modes[1] = {
-	{ 2, NULL },
-};
-
-static const struct hda_input_mux cxt5047_toshiba_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "ExtMic", 0x2 },
-		{ "Line-In", 0x1 },
-	}
-};
-
-/* turn on/off EAPD (+ mute HP) as a master switch */
-static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	unsigned int bits;
-
-	if (!cxt_eapd_put(kcontrol, ucontrol))
-		return 0;
-
-	/* toggle internal speakers mute depending of presence of
-	 * the headphone jack
-	 */
-	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
-	/* NOTE: Conexat codec needs the index for *OUTPUT* amp of
-	 * pin widgets unlike other codecs.  In this case, we need to
-	 * set index 0x01 for the volume from the mixer amp 0x19.
-	 */
-	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01,
-				 HDA_AMP_MUTE, bits);
-	bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
-	snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	return 1;
-}
-
-/* mute internal speaker if HP is plugged */
-static void cxt5047_hp_automute(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int bits;
-
-	spec->hp_present = snd_hda_jack_detect(codec, 0x13);
-
-	bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
-	/* See the note in cxt5047_hp_master_sw_put */
-	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01,
-				 HDA_AMP_MUTE, bits);
-}
-
-/* toggle input of built-in and mic jack appropriately */
-static void cxt5047_hp_automic(struct hda_codec *codec)
-{
-	static const struct hda_verb mic_jack_on[] = {
-		{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-		{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-		{}
-	};
-	static const struct hda_verb mic_jack_off[] = {
-		{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-		{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-		{}
-	};
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x15);
-	if (present)
-		snd_hda_sequence_write(codec, mic_jack_on);
-	else
-		snd_hda_sequence_write(codec, mic_jack_off);
-}
-
-/* unsolicited event for HP jack sensing */
-static void cxt5047_hp_unsol_event(struct hda_codec *codec,
-				  unsigned int res)
-{
-	switch (res >> 26) {
-	case CONEXANT_HP_EVENT:
-		cxt5047_hp_automute(codec);
-		break;
-	case CONEXANT_MIC_EVENT:
-		cxt5047_hp_automic(codec);
-		break;
-	}
-}
-
-static const struct snd_kcontrol_new cxt5047_base_mixers[] = {
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
-	HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = cxt_eapd_info,
-		.get = cxt_eapd_get,
-		.put = cxt5047_hp_master_sw_put,
-		.private_value = 0x13,
-	},
-
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = {
-	/* See the note in cxt5047_hp_master_sw_put */
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5047_hp_only_mixers[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5047_init_verbs[] = {
-	/* Line in, Mic, Built-in Mic */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
-	/* HP, Speaker  */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */
-	{0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */
-	/* Record selector: Mic */
-	{0x12, AC_VERB_SET_CONNECT_SEL,0x03},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE,
-	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
-	{0x1A, AC_VERB_SET_CONNECT_SEL,0x02},
-	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
-	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00},
-	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
-	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
-	/* SPDIF route: PCM */
-	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	/* Enable unsolicited events */
-	{0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	{ } /* end */
-};
-
-/* configuration for Toshiba Laptops */
-static const struct hda_verb cxt5047_toshiba_init_verbs[] = {
-	{0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */
-	{}
-};
-
-/* Test configuration for debugging, modelled after the ALC260 test
- * configuration.
- */
-#ifdef CONFIG_SND_DEBUG
-static const struct hda_input_mux cxt5047_test_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "LINE1 pin", 0x0 },
-		{ "MIC1 pin", 0x1 },
-		{ "MIC2 pin", 0x2 },
-		{ "CD pin", 0x3 },
-        },
-};
-
-static const struct snd_kcontrol_new cxt5047_test_mixer[] = {
-
-	/* Output only controls */
-	HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("HeadPhone Playback Volume", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("HeadPhone Playback Switch", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line1-Out Playback Volume", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Line1-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line2-Out Playback Volume", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Line2-Out Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-
-	/* Modes for retasking pin widgets */
-	CXT_PIN_MODE("LINE1 pin mode", 0x14, CXT_PIN_DIR_INOUT),
-	CXT_PIN_MODE("MIC1 pin mode", 0x15, CXT_PIN_DIR_INOUT),
-
-	/* EAPD Switch Control */
-	CXT_EAPD_SWITCH("External Amplifier", 0x13, 0x0),
-
-	/* Loopback mixer controls */
-	HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x12, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("MIC1 Playback Switch", 0x12, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x12, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("MIC2 Playback Switch", 0x12, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("LINE Playback Volume", 0x12, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("LINE Playback Switch", 0x12, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x12, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x12, 0x04, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Capture-1 Volume", 0x19, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture-1 Switch", 0x19, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture-2 Volume", 0x19, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture-2 Switch", 0x19, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture-3 Volume", 0x19, 0x2, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture-3 Switch", 0x19, 0x2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture-4 Volume", 0x19, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture-4 Switch", 0x19, 0x3, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Input Source",
-		.info = conexant_mux_enum_info,
-		.get = conexant_mux_enum_get,
-		.put = conexant_mux_enum_put,
-	},
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT),
-
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5047_test_init_verbs[] = {
-	/* Enable retasking pins as output, initially without power amp */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* Disable digital (SPDIF) pins initially, but users can enable
-	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
-	 * payload also sets the generation to 0, output to be in "consumer"
-	 * PCM format, copyright asserted, no pre-emphasis and no validity
-	 * control.
-	 */
-	{0x18, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
-	/* Ensure mic1, mic2, line1 pin widgets take input from the 
-	 * OUT1 sum bus when acting as an output.
-	 */
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* Start with output sum widgets muted and their output gains at min */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
-	/* Unmute retasking pin widget output buffers since the default
-	 * state appears to be output.  As the pin mode is changed by the
-	 * user the pin mode control will take care of enabling the pin's
-	 * input/output buffers as needed.
-	 */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Mute capture amp left and right */
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-
-	/* Set ADC connection select to match default mixer setting (mic1
-	 * pin)
-	 */
-	{0x12, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Mute all inputs to mixer widget (even unconnected ones) */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
-	{ }
-};
-#endif
-
-
-/* initialize jack-sensing, too */
-static int cxt5047_hp_init(struct hda_codec *codec)
-{
-	conexant_init(codec);
-	cxt5047_hp_automute(codec);
-	return 0;
-}
-
-
-enum {
-	CXT5047_LAPTOP,		/* Laptops w/o EAPD support */
-	CXT5047_LAPTOP_HP,	/* Some HP laptops */
-	CXT5047_LAPTOP_EAPD,	/* Laptops with EAPD support */
-#ifdef CONFIG_SND_DEBUG
-	CXT5047_TEST,
-#endif
-	CXT5047_AUTO,
-	CXT5047_MODELS
-};
-
-static const char * const cxt5047_models[CXT5047_MODELS] = {
-	[CXT5047_LAPTOP]	= "laptop",
-	[CXT5047_LAPTOP_HP]	= "laptop-hp",
-	[CXT5047_LAPTOP_EAPD]	= "laptop-eapd",
-#ifdef CONFIG_SND_DEBUG
-	[CXT5047_TEST]		= "test",
-#endif
-	[CXT5047_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk cxt5047_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP),
-	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
-			   CXT5047_LAPTOP),
-	SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD),
-	{}
-};
-
-static int patch_cxt5047(struct hda_codec *codec)
-{
-	struct conexant_spec *spec;
-	int board_config;
-
-	board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
-						  cxt5047_models,
-						  cxt5047_cfg_tbl);
-	if (board_config < 0)
-		board_config = CXT5047_AUTO; /* model=auto as default */
-	if (board_config == CXT5047_AUTO)
-		return patch_conexant_auto(codec);
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (!spec)
-		return -ENOMEM;
-	codec->spec = spec;
-	codec->pin_amp_workaround = 1;
-
-	spec->multiout.max_channels = 2;
-	spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids);
-	spec->multiout.dac_nids = cxt5047_dac_nids;
-	spec->multiout.dig_out_nid = CXT5047_SPDIF_OUT;
-	spec->num_adc_nids = 1;
-	spec->adc_nids = cxt5047_adc_nids;
-	spec->capsrc_nids = cxt5047_capsrc_nids;
-	spec->num_mixers = 1;
-	spec->mixers[0] = cxt5047_base_mixers;
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = cxt5047_init_verbs;
-	spec->spdif_route = 0;
-	spec->num_channel_mode = ARRAY_SIZE(cxt5047_modes),
-	spec->channel_mode = cxt5047_modes,
-
-	codec->patch_ops = conexant_patch_ops;
-
-	switch (board_config) {
-	case CXT5047_LAPTOP:
-		spec->num_mixers = 2;
-		spec->mixers[1] = cxt5047_hp_spk_mixers;
-		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
-		break;
-	case CXT5047_LAPTOP_HP:
-		spec->num_mixers = 2;
-		spec->mixers[1] = cxt5047_hp_only_mixers;
-		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
-		codec->patch_ops.init = cxt5047_hp_init;
-		break;
-	case CXT5047_LAPTOP_EAPD:
-		spec->input_mux = &cxt5047_toshiba_capture_source;
-		spec->num_mixers = 2;
-		spec->mixers[1] = cxt5047_hp_spk_mixers;
-		spec->num_init_verbs = 2;
-		spec->init_verbs[1] = cxt5047_toshiba_init_verbs;
-		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
-		break;
-#ifdef CONFIG_SND_DEBUG
-	case CXT5047_TEST:
-		spec->input_mux = &cxt5047_test_capture_source;
-		spec->mixers[0] = cxt5047_test_mixer;
-		spec->init_verbs[0] = cxt5047_test_init_verbs;
-		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
-#endif	
-	}
-	spec->vmaster_nid = 0x13;
-
-	switch (codec->subsystem_id >> 16) {
-	case 0x103c:
-		/* HP laptops have really bad sound over 0 dB on NID 0x10.
-		 * Fix max PCM level to 0 dB (originally it has 0x1e steps
-		 * with 0 dB offset 0x17)
-		 */
-		snd_hda_override_amp_caps(codec, 0x10, HDA_INPUT,
-					  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
-					  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
-					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
-					  (1 << AC_AMPCAP_MUTE_SHIFT));
-		break;
-	}
-
-	return 0;
-}
-
-/* Conexant 5051 specific */
-static const hda_nid_t cxt5051_dac_nids[1] = { 0x10 };
-static const hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 };
-
-static const struct hda_channel_mode cxt5051_modes[1] = {
-	{ 2, NULL },
-};
-
-static void cxt5051_update_speaker(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int pinctl;
-	/* headphone pin */
-	pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0;
-	snd_hda_set_pin_ctl(codec, 0x16, pinctl);
-	/* speaker pin */
-	pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
-	snd_hda_set_pin_ctl(codec, 0x1a, pinctl);
-	/* on ideapad there is an additional speaker (subwoofer) to mute */
-	if (spec->ideapad)
-		snd_hda_set_pin_ctl(codec, 0x1b, pinctl);
-}
-
-/* turn on/off EAPD (+ mute HP) as a master switch */
-static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-
-	if (!cxt_eapd_put(kcontrol, ucontrol))
-		return 0;
-	cxt5051_update_speaker(codec);
-	return 1;
-}
-
-/* toggle input of built-in and mic jack appropriately */
-static void cxt5051_portb_automic(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int present;
-
-	if (!(spec->auto_mic & AUTO_MIC_PORTB))
-		return;
-	present = snd_hda_jack_detect(codec, 0x17);
-	snd_hda_codec_write(codec, 0x14, 0,
-			    AC_VERB_SET_CONNECT_SEL,
-			    present ? 0x01 : 0x00);
-}
-
-/* switch the current ADC according to the jack state */
-static void cxt5051_portc_automic(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int present;
-	hda_nid_t new_adc;
-
-	if (!(spec->auto_mic & AUTO_MIC_PORTC))
-		return;
-	present = snd_hda_jack_detect(codec, 0x18);
-	if (present)
-		spec->cur_adc_idx = 1;
-	else
-		spec->cur_adc_idx = 0;
-	new_adc = spec->adc_nids[spec->cur_adc_idx];
-	if (spec->cur_adc && spec->cur_adc != new_adc) {
-		/* stream is running, let's swap the current ADC */
-		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
-		spec->cur_adc = new_adc;
-		snd_hda_codec_setup_stream(codec, new_adc,
-					   spec->cur_adc_stream_tag, 0,
-					   spec->cur_adc_format);
-	}
-}
-
-/* mute internal speaker if HP is plugged */
-static void cxt5051_hp_automute(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-
-	spec->hp_present = snd_hda_jack_detect(codec, 0x16);
-	cxt5051_update_speaker(codec);
-}
-
-/* unsolicited event for HP jack sensing */
-static void cxt5051_hp_unsol_event(struct hda_codec *codec,
-				   unsigned int res)
-{
-	switch (res >> 26) {
-	case CONEXANT_HP_EVENT:
-		cxt5051_hp_automute(codec);
-		break;
-	case CXT5051_PORTB_EVENT:
-		cxt5051_portb_automic(codec);
-		break;
-	case CXT5051_PORTC_EVENT:
-		cxt5051_portc_automic(codec);
-		break;
-	}
-}
-
-static const struct snd_kcontrol_new cxt5051_playback_mixers[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = cxt_eapd_info,
-		.get = cxt_eapd_get,
-		.put = cxt5051_hp_master_sw_put,
-		.private_value = 0x1a,
-	},
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5051_capture_mixers[] = {
-	HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Dock Mic Volume", 0x15, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Dock Mic Switch", 0x15, 0x00, HDA_INPUT),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5051_hp_mixers[] = {
-	HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Volume", 0x15, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Switch", 0x15, 0x00, HDA_INPUT),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x14, 0x00, HDA_INPUT),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5051_f700_mixers[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x14, 0x01, HDA_INPUT),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5051_toshiba_mixers[] = {
-	HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT),
-	{}
-};
-
-static const struct hda_verb cxt5051_init_verbs[] = {
-	/* Line in, Mic */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-	/* SPK  */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* HP, Amp  */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* DAC1 */	
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Record selector: Internal mic */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
-	/* SPDIF route: PCM */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* EAPD */
-	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 
-	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
-	/* Line in, Mic */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
-	/* SPK  */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* HP, Amp  */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* DAC1 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Record selector: Internal mic */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
-	/* SPDIF route: PCM */
-	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* EAPD */
-	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5051_f700_init_verbs[] = {
-	/* Line in, Mic */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
-	/* SPK  */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* HP, Amp  */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* DAC1 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Record selector: Internal mic */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
-	/* SPDIF route: PCM */
-	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* EAPD */
-	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
-	{ } /* end */
-};
-
-static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
-				 unsigned int event)
-{
-	snd_hda_codec_write(codec, nid, 0,
-			    AC_VERB_SET_UNSOLICITED_ENABLE,
-			    AC_USRSP_EN | event);
-}
-
-static const struct hda_verb cxt5051_ideapad_init_verbs[] = {
-	/* Subwoofer */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{ } /* end */
-};
-
-/* initialize jack-sensing, too */
-static int cxt5051_init(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-
-	conexant_init(codec);
-
-	if (spec->auto_mic & AUTO_MIC_PORTB)
-		cxt5051_init_mic_port(codec, 0x17, CXT5051_PORTB_EVENT);
-	if (spec->auto_mic & AUTO_MIC_PORTC)
-		cxt5051_init_mic_port(codec, 0x18, CXT5051_PORTC_EVENT);
-
-	if (codec->patch_ops.unsol_event) {
-		cxt5051_hp_automute(codec);
-		cxt5051_portb_automic(codec);
-		cxt5051_portc_automic(codec);
-	}
-	return 0;
-}
-
-
-enum {
-	CXT5051_LAPTOP,	 /* Laptops w/ EAPD support */
-	CXT5051_HP,	/* no docking */
-	CXT5051_HP_DV6736,	/* HP without mic switch */
-	CXT5051_F700,       /* HP Compaq Presario F700 */
-	CXT5051_TOSHIBA,	/* Toshiba M300 & co */
-	CXT5051_IDEAPAD,	/* Lenovo IdeaPad Y430 */
-	CXT5051_AUTO,		/* auto-parser */
-	CXT5051_MODELS
-};
-
-static const char *const cxt5051_models[CXT5051_MODELS] = {
-	[CXT5051_LAPTOP]	= "laptop",
-	[CXT5051_HP]		= "hp",
-	[CXT5051_HP_DV6736]	= "hp-dv6736",
-	[CXT5051_F700]          = "hp-700",
-	[CXT5051_TOSHIBA]	= "toshiba",
-	[CXT5051_IDEAPAD]	= "ideapad",
-	[CXT5051_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk cxt5051_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736),
-	SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP),
-	SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700),
-	SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba M30x", CXT5051_TOSHIBA),
-	SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
-		      CXT5051_LAPTOP),
-	SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
-	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD),
-	{}
-};
-
-static int patch_cxt5051(struct hda_codec *codec)
-{
-	struct conexant_spec *spec;
-	int board_config;
-
-	board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
-						  cxt5051_models,
-						  cxt5051_cfg_tbl);
-	if (board_config < 0)
-		board_config = CXT5051_AUTO; /* model=auto as default */
-	if (board_config == CXT5051_AUTO)
-		return patch_conexant_auto(codec);
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (!spec)
-		return -ENOMEM;
-	codec->spec = spec;
-	codec->pin_amp_workaround = 1;
-
-	codec->patch_ops = conexant_patch_ops;
-	codec->patch_ops.init = cxt5051_init;
-
-	spec->multiout.max_channels = 2;
-	spec->multiout.num_dacs = ARRAY_SIZE(cxt5051_dac_nids);
-	spec->multiout.dac_nids = cxt5051_dac_nids;
-	spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT;
-	spec->num_adc_nids = 1; /* not 2; via auto-mic switch */
-	spec->adc_nids = cxt5051_adc_nids;
-	spec->num_mixers = 2;
-	spec->mixers[0] = cxt5051_capture_mixers;
-	spec->mixers[1] = cxt5051_playback_mixers;
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = cxt5051_init_verbs;
-	spec->spdif_route = 0;
-	spec->num_channel_mode = ARRAY_SIZE(cxt5051_modes);
-	spec->channel_mode = cxt5051_modes;
-	spec->cur_adc = 0;
-	spec->cur_adc_idx = 0;
-
-	set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
-
-	codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
-
-	spec->auto_mic = AUTO_MIC_PORTB | AUTO_MIC_PORTC;
-	switch (board_config) {
-	case CXT5051_HP:
-		spec->mixers[0] = cxt5051_hp_mixers;
-		break;
-	case CXT5051_HP_DV6736:
-		spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs;
-		spec->mixers[0] = cxt5051_hp_dv6736_mixers;
-		spec->auto_mic = 0;
-		break;
-	case CXT5051_F700:
-		spec->init_verbs[0] = cxt5051_f700_init_verbs;
-		spec->mixers[0] = cxt5051_f700_mixers;
-		spec->auto_mic = 0;
-		break;
-	case CXT5051_TOSHIBA:
-		spec->mixers[0] = cxt5051_toshiba_mixers;
-		spec->auto_mic = AUTO_MIC_PORTB;
-		break;
-	case CXT5051_IDEAPAD:
-		spec->init_verbs[spec->num_init_verbs++] =
-			cxt5051_ideapad_init_verbs;
-		spec->ideapad = 1;
-		break;
-	}
-
-	if (spec->beep_amp)
-		snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
-
-	return 0;
-}
-
-/* Conexant 5066 specific */
-
-static const hda_nid_t cxt5066_dac_nids[1] = { 0x10 };
-static const hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 };
-static const hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 };
-static const hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 };
-
-static const struct hda_channel_mode cxt5066_modes[1] = {
-	{ 2, NULL },
-};
-
-#define HP_PRESENT_PORT_A	(1 << 0)
-#define HP_PRESENT_PORT_D	(1 << 1)
-#define hp_port_a_present(spec)	((spec)->hp_present & HP_PRESENT_PORT_A)
-#define hp_port_d_present(spec)	((spec)->hp_present & HP_PRESENT_PORT_D)
-
-static void cxt5066_update_speaker(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int pinctl;
-
-	codec_dbg(codec,
-		  "CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n",
-		    spec->hp_present, spec->cur_eapd);
-
-	/* Port A (HP) */
-	pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0;
-	snd_hda_set_pin_ctl(codec, 0x19, pinctl);
-
-	/* Port D (HP/LO) */
-	pinctl = spec->cur_eapd ? spec->port_d_mode : 0;
-	if (spec->dell_automute || spec->thinkpad) {
-		/* Mute if Port A is connected */
-		if (hp_port_a_present(spec))
-			pinctl = 0;
-	} else {
-		/* Thinkpad/Dell doesn't give pin-D status */
-		if (!hp_port_d_present(spec))
-			pinctl = 0;
-	}
-	snd_hda_set_pin_ctl(codec, 0x1c, pinctl);
-
-	/* CLASS_D AMP */
-	pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
-	snd_hda_set_pin_ctl(codec, 0x1f, pinctl);
-}
-
-/* turn on/off EAPD (+ mute HP) as a master switch */
-static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-
-	if (!cxt_eapd_put(kcontrol, ucontrol))
-		return 0;
-
-	cxt5066_update_speaker(codec);
-	return 1;
-}
-
-/* toggle input of built-in digital mic and mic jack appropriately */
-static void cxt5066_vostro_automic(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	struct hda_verb ext_mic_present[] = {
-		/* enable external mic, port B */
-		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-
-		/* switch to external mic input */
-		{0x17, AC_VERB_SET_CONNECT_SEL, 0},
-		{0x14, AC_VERB_SET_CONNECT_SEL, 0},
-
-		/* disable internal digital mic */
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-	static const struct hda_verb ext_mic_absent[] = {
-		/* enable internal mic, port C */
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-		/* switch to internal mic input */
-		{0x14, AC_VERB_SET_CONNECT_SEL, 2},
-
-		/* disable external mic, port B */
-		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-
-	present = snd_hda_jack_detect(codec, 0x1a);
-	if (present) {
-		codec_dbg(codec, "CXT5066: external microphone detected\n");
-		snd_hda_sequence_write(codec, ext_mic_present);
-	} else {
-		codec_dbg(codec, "CXT5066: external microphone absent\n");
-		snd_hda_sequence_write(codec, ext_mic_absent);
-	}
-}
-
-/* toggle input of built-in digital mic and mic jack appropriately */
-static void cxt5066_ideapad_automic(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	struct hda_verb ext_mic_present[] = {
-		{0x14, AC_VERB_SET_CONNECT_SEL, 0},
-		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-	static const struct hda_verb ext_mic_absent[] = {
-		{0x14, AC_VERB_SET_CONNECT_SEL, 2},
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-
-	present = snd_hda_jack_detect(codec, 0x1b);
-	if (present) {
-		codec_dbg(codec, "CXT5066: external microphone detected\n");
-		snd_hda_sequence_write(codec, ext_mic_present);
-	} else {
-		codec_dbg(codec, "CXT5066: external microphone absent\n");
-		snd_hda_sequence_write(codec, ext_mic_absent);
-	}
-}
-
-
-/* toggle input of built-in digital mic and mic jack appropriately */
-static void cxt5066_asus_automic(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x1b);
-	codec_dbg(codec, "CXT5066: external microphone present=%d\n", present);
-	snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL,
-			    present ? 1 : 0);
-}
-
-
-/* toggle input of built-in digital mic and mic jack appropriately */
-static void cxt5066_hp_laptop_automic(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x1b);
-	codec_dbg(codec, "CXT5066: external microphone present=%d\n", present);
-	snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL,
-			    present ? 1 : 3);
-}
-
-
-/* toggle input of built-in digital mic and mic jack appropriately
-   order is: external mic -> dock mic -> interal mic */
-static void cxt5066_thinkpad_automic(struct hda_codec *codec)
-{
-	unsigned int ext_present, dock_present;
-
-	static const struct hda_verb ext_mic_present[] = {
-		{0x14, AC_VERB_SET_CONNECT_SEL, 0},
-		{0x17, AC_VERB_SET_CONNECT_SEL, 1},
-		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-	static const struct hda_verb dock_mic_present[] = {
-		{0x14, AC_VERB_SET_CONNECT_SEL, 0},
-		{0x17, AC_VERB_SET_CONNECT_SEL, 0},
-		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-	static const struct hda_verb ext_mic_absent[] = {
-		{0x14, AC_VERB_SET_CONNECT_SEL, 2},
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-
-	ext_present = snd_hda_jack_detect(codec, 0x1b);
-	dock_present = snd_hda_jack_detect(codec, 0x1a);
-	if (ext_present) {
-		codec_dbg(codec, "CXT5066: external microphone detected\n");
-		snd_hda_sequence_write(codec, ext_mic_present);
-	} else if (dock_present) {
-		codec_dbg(codec, "CXT5066: dock microphone detected\n");
-		snd_hda_sequence_write(codec, dock_mic_present);
-	} else {
-		codec_dbg(codec, "CXT5066: external microphone absent\n");
-		snd_hda_sequence_write(codec, ext_mic_absent);
-	}
-}
-
-/* mute internal speaker if HP is plugged */
-static void cxt5066_hp_automute(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int portA, portD;
-
-	/* Port A */
-	portA = snd_hda_jack_detect(codec, 0x19);
-
-	/* Port D */
-	portD = snd_hda_jack_detect(codec, 0x1c);
-
-	spec->hp_present = portA ? HP_PRESENT_PORT_A : 0;
-	spec->hp_present |= portD ? HP_PRESENT_PORT_D : 0;
-	codec_dbg(codec, "CXT5066: hp automute portA=%x portD=%x present=%d\n",
-		portA, portD, spec->hp_present);
-	cxt5066_update_speaker(codec);
-}
-
-/* Dispatch the right mic autoswitch function */
-static void cxt5066_automic(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-
-	if (spec->dell_vostro)
-		cxt5066_vostro_automic(codec);
-	else if (spec->ideapad)
-		cxt5066_ideapad_automic(codec);
-	else if (spec->thinkpad)
-		cxt5066_thinkpad_automic(codec);
-	else if (spec->hp_laptop)
-		cxt5066_hp_laptop_automic(codec);
-	else if (spec->asus)
-		cxt5066_asus_automic(codec);
-}
-
-/* unsolicited event for jack sensing */
-static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	codec_dbg(codec, "CXT5066: unsol event %x (%x)\n", res, res >> 26);
-	switch (res >> 26) {
-	case CONEXANT_HP_EVENT:
-		cxt5066_hp_automute(codec);
-		break;
-	case CONEXANT_MIC_EVENT:
-		cxt5066_automic(codec);
-		break;
-	}
-}
-
-
-static const struct hda_input_mux cxt5066_analog_mic_boost = {
-	.num_items = 5,
-	.items = {
-		{ "0dB",  0 },
-		{ "10dB", 1 },
-		{ "20dB", 2 },
-		{ "30dB", 3 },
-		{ "40dB", 4 },
-	},
-};
-
-static void cxt5066_set_mic_boost(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	snd_hda_codec_write_cache(codec, 0x17, 0,
-		AC_VERB_SET_AMP_GAIN_MUTE,
-		AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT |
-			cxt5066_analog_mic_boost.items[spec->mic_boost].index);
-	if (spec->ideapad || spec->thinkpad) {
-		/* adjust the internal mic as well...it is not through 0x17 */
-		snd_hda_codec_write_cache(codec, 0x23, 0,
-			AC_VERB_SET_AMP_GAIN_MUTE,
-			AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_INPUT |
-				cxt5066_analog_mic_boost.
-					items[spec->mic_boost].index);
-	}
-}
-
-static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol,
-					   struct snd_ctl_elem_info *uinfo)
-{
-	return snd_hda_input_mux_info(&cxt5066_analog_mic_boost, uinfo);
-}
-
-static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol,
-					  struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	ucontrol->value.enumerated.item[0] = spec->mic_boost;
-	return 0;
-}
-
-static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
-					  struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
-	unsigned int idx;
-	idx = ucontrol->value.enumerated.item[0];
-	if (idx >= imux->num_items)
-		idx = imux->num_items - 1;
-
-	spec->mic_boost = idx;
-	cxt5066_set_mic_boost(codec);
-	return 1;
-}
-
-static void conexant_check_dig_outs(struct hda_codec *codec,
-				    const hda_nid_t *dig_pins,
-				    int num_pins)
-{
-	struct conexant_spec *spec = codec->spec;
-	hda_nid_t *nid_loc = &spec->multiout.dig_out_nid;
-	int i;
-
-	for (i = 0; i < num_pins; i++, dig_pins++) {
-		unsigned int cfg = snd_hda_codec_get_pincfg(codec, *dig_pins);
-		if (get_defcfg_connect(cfg) == AC_JACK_PORT_NONE)
-			continue;
-		if (snd_hda_get_connections(codec, *dig_pins, nid_loc, 1) != 1)
-			continue;
-	}
-}
-
-static const struct hda_input_mux cxt5066_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic B", 0 },
-		{ "Mic C", 1 },
-		{ "Mic E", 2 },
-		{ "Mic F", 3 },
-	},
-};
-
-static const struct hda_bind_ctls cxt5066_bind_capture_vol_others = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT),
-		0
-	},
-};
-
-static const struct hda_bind_ctls cxt5066_bind_capture_sw_others = {
-	.ops = &snd_hda_bind_sw,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT),
-		0
-	},
-};
-
-static const struct snd_kcontrol_new cxt5066_mixer_master[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5066_mixers[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = cxt_eapd_info,
-		.get = cxt_eapd_get,
-		.put = cxt5066_hp_master_sw_put,
-		.private_value = 0x1d,
-	},
-
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Analog Mic Boost Capture Enum",
-		.info = cxt5066_mic_boost_mux_enum_info,
-		.get = cxt5066_mic_boost_mux_enum_get,
-		.put = cxt5066_mic_boost_mux_enum_put,
-	},
-
-	HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others),
-	HDA_BIND_SW("Capture Switch", &cxt5066_bind_capture_sw_others),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Internal Mic Boost Capture Enum",
-		.info = cxt5066_mic_boost_mux_enum_info,
-		.get = cxt5066_mic_boost_mux_enum_get,
-		.put = cxt5066_mic_boost_mux_enum_put,
-		.private_value = 0x23 | 0x100,
-	},
-	{}
-};
-
-static const struct hda_verb cxt5066_init_verbs[] = {
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
-	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
-
-	/* Speakers  */
-	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* HP, Amp  */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* DAC1 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-	/* no digital microphone support yet */
-	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Audio input selector */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
-
-	/* SPDIF route: PCM */
-	{0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
-
-	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* EAPD */
-	{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-
-	/* not handling these yet */
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x20, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x22, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5066_init_verbs_vostro[] = {
-	/* Port A: headphones */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* Port B: external microphone */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Port C: unused */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Port D: unused */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Port E: unused, but has primary EAPD */
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-
-	/* Port F: unused */
-	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Port G: internal speakers */
-	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* DAC1 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* DAC2: unused */
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-
-	/* Digital microphone port */
-	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	/* Audio input selectors */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-
-	/* Disable SPDIF */
-	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* enable unsolicited events for Port A and B */
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5066_init_verbs_ideapad[] = {
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
-	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
-
-	/* Speakers  */
-	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* HP, Amp  */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* DAC1 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 2},	/* default to internal mic */
-
-	/* Audio input selector */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2},
-	{0x17, AC_VERB_SET_CONNECT_SEL, 1},	/* route ext mic */
-
-	/* SPDIF route: PCM */
-	{0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
-
-	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* internal microphone */
-	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */
-
-	/* EAPD */
-	{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5066_init_verbs_thinkpad[] = {
-	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
-
-	/* Port G: internal speakers  */
-	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* Port A: HP, Amp  */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* Port B: Mic Dock */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Port C: Mic */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Port D: HP Dock, Amp */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* DAC1 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 2},	/* default to internal mic */
-
-	/* Audio input selector */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2},
-	{0x17, AC_VERB_SET_CONNECT_SEL, 1},	/* route ext mic */
-
-	/* SPDIF route: PCM */
-	{0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
-
-	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* internal microphone */
-	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */
-
-	/* EAPD */
-	{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-
-	/* enable unsolicited events for Port A, B, C and D */
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5066_init_verbs_portd_lo[] = {
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{ } /* end */
-};
-
-
-static const struct hda_verb cxt5066_init_verbs_hp_laptop[] = {
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	{ } /* end */
-};
-
-/* initialize jack-sensing, too */
-static int cxt5066_init(struct hda_codec *codec)
-{
-	codec_dbg(codec, "CXT5066: init\n");
-	conexant_init(codec);
-	if (codec->patch_ops.unsol_event) {
-		cxt5066_hp_automute(codec);
-		cxt5066_automic(codec);
-	}
-	cxt5066_set_mic_boost(codec);
-	return 0;
-}
-
-enum {
-	CXT5066_LAPTOP,		/* Laptops w/ EAPD support */
-	CXT5066_DELL_LAPTOP,	/* Dell Laptop */
-	CXT5066_DELL_VOSTRO,	/* Dell Vostro 1015i */
-	CXT5066_IDEAPAD,	/* Lenovo IdeaPad U150 */
-	CXT5066_THINKPAD,	/* Lenovo ThinkPad T410s, others? */
-	CXT5066_ASUS,		/* Asus K52JU, Lenovo G560 - Int mic at 0x1a and Ext mic at 0x1b */
-	CXT5066_HP_LAPTOP,      /* HP Laptop */
-	CXT5066_AUTO,		/* BIOS auto-parser */
-	CXT5066_MODELS
-};
-
-static const char * const cxt5066_models[CXT5066_MODELS] = {
-	[CXT5066_LAPTOP]	= "laptop",
-	[CXT5066_DELL_LAPTOP]	= "dell-laptop",
-	[CXT5066_DELL_VOSTRO]	= "dell-vostro",
-	[CXT5066_IDEAPAD]	= "ideapad",
-	[CXT5066_THINKPAD]	= "thinkpad",
-	[CXT5066_ASUS]		= "asus",
-	[CXT5066_HP_LAPTOP]	= "hp-laptop",
-	[CXT5066_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
-	SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD),
-	SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO),
-	SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD),
-	SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO),
-	SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
-	SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD),
-	SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
-	SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS),
-	SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS),
-	SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS),
-	SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD),
-	SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
-		      CXT5066_LAPTOP),
-	SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
-	SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
-	SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
-	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),
-	SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
-	{}
-};
-
-static int patch_cxt5066(struct hda_codec *codec)
-{
-	struct conexant_spec *spec;
-	int board_config;
-
-	board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
-						  cxt5066_models, cxt5066_cfg_tbl);
-	if (board_config < 0)
-		board_config = CXT5066_AUTO; /* model=auto as default */
-	if (board_config == CXT5066_AUTO)
-		return patch_conexant_auto(codec);
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (!spec)
-		return -ENOMEM;
-	codec->spec = spec;
-
-	codec->patch_ops = conexant_patch_ops;
-	codec->patch_ops.init = conexant_init;
-
-	spec->dell_automute = 0;
-	spec->multiout.max_channels = 2;
-	spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids);
-	spec->multiout.dac_nids = cxt5066_dac_nids;
-	conexant_check_dig_outs(codec, cxt5066_digout_pin_nids,
-	    ARRAY_SIZE(cxt5066_digout_pin_nids));
-	spec->num_adc_nids = 1;
-	spec->adc_nids = cxt5066_adc_nids;
-	spec->capsrc_nids = cxt5066_capsrc_nids;
-	spec->input_mux = &cxt5066_capture_source;
-
-	spec->port_d_mode = PIN_HP;
-
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = cxt5066_init_verbs;
-	spec->num_channel_mode = ARRAY_SIZE(cxt5066_modes);
-	spec->channel_mode = cxt5066_modes;
-	spec->cur_adc = 0;
-	spec->cur_adc_idx = 0;
-
-	set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
-
-	switch (board_config) {
-	default:
-	case CXT5066_LAPTOP:
-		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
-		break;
-	case CXT5066_DELL_LAPTOP:
-		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
-
-		spec->port_d_mode = PIN_OUT;
-		spec->init_verbs[spec->num_init_verbs] = cxt5066_init_verbs_portd_lo;
-		spec->num_init_verbs++;
-		spec->dell_automute = 1;
-		break;
-	case CXT5066_ASUS:
-	case CXT5066_HP_LAPTOP:
-		codec->patch_ops.init = cxt5066_init;
-		codec->patch_ops.unsol_event = cxt5066_unsol_event;
-		spec->init_verbs[spec->num_init_verbs] =
-			cxt5066_init_verbs_hp_laptop;
-		spec->num_init_verbs++;
-		spec->hp_laptop = board_config == CXT5066_HP_LAPTOP;
-		spec->asus = board_config == CXT5066_ASUS;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
-		/* no S/PDIF out */
-		if (board_config == CXT5066_HP_LAPTOP)
-			spec->multiout.dig_out_nid = 0;
-		/* input source automatically selected */
-		spec->input_mux = NULL;
-		spec->port_d_mode = 0;
-		spec->mic_boost = 3; /* default 30dB gain */
-		break;
-
-	case CXT5066_DELL_VOSTRO:
-		codec->patch_ops.init = cxt5066_init;
-		codec->patch_ops.unsol_event = cxt5066_unsol_event;
-		spec->init_verbs[0] = cxt5066_init_verbs_vostro;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
-		spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers;
-		spec->port_d_mode = 0;
-		spec->dell_vostro = 1;
-		spec->mic_boost = 3; /* default 30dB gain */
-
-		/* no S/PDIF out */
-		spec->multiout.dig_out_nid = 0;
-
-		/* input source automatically selected */
-		spec->input_mux = NULL;
-		break;
-	case CXT5066_IDEAPAD:
-		codec->patch_ops.init = cxt5066_init;
-		codec->patch_ops.unsol_event = cxt5066_unsol_event;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
-		spec->init_verbs[0] = cxt5066_init_verbs_ideapad;
-		spec->port_d_mode = 0;
-		spec->ideapad = 1;
-		spec->mic_boost = 2;	/* default 20dB gain */
-
-		/* no S/PDIF out */
-		spec->multiout.dig_out_nid = 0;
-
-		/* input source automatically selected */
-		spec->input_mux = NULL;
-		break;
-	case CXT5066_THINKPAD:
-		codec->patch_ops.init = cxt5066_init;
-		codec->patch_ops.unsol_event = cxt5066_unsol_event;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
-		spec->init_verbs[0] = cxt5066_init_verbs_thinkpad;
-		spec->thinkpad = 1;
-		spec->port_d_mode = PIN_OUT;
-		spec->mic_boost = 2;	/* default 20dB gain */
-
-		/* no S/PDIF out */
-		spec->multiout.dig_out_nid = 0;
-
-		/* input source automatically selected */
-		spec->input_mux = NULL;
-		break;
-	}
-
-	if (spec->beep_amp)
-		snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
-
-	return 0;
-}
-
-#endif /* ENABLE_CXT_STATIC_QUIRKS */
-
-
 /*
  * Automatic parser for CX20641 & co
  */
@@ -3487,35 +881,28 @@ static int patch_conexant_auto(struct hda_codec *codec)
 	return err;
 }
 
-#ifndef ENABLE_CXT_STATIC_QUIRKS
-#define patch_cxt5045	patch_conexant_auto
-#define patch_cxt5047	patch_conexant_auto
-#define patch_cxt5051	patch_conexant_auto
-#define patch_cxt5066	patch_conexant_auto
-#endif
-
 /*
  */
 
 static const struct hda_codec_preset snd_hda_preset_conexant[] = {
 	{ .id = 0x14f15045, .name = "CX20549 (Venice)",
-	  .patch = patch_cxt5045 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15047, .name = "CX20551 (Waikiki)",
-	  .patch = patch_cxt5047 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15051, .name = "CX20561 (Hermosa)",
-	  .patch = patch_cxt5051 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15066, .name = "CX20582 (Pebble)",
-	  .patch = patch_cxt5066 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15067, .name = "CX20583 (Pebble HSF)",
-	  .patch = patch_cxt5066 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15068, .name = "CX20584",
-	  .patch = patch_cxt5066 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15069, .name = "CX20585",
-	  .patch = patch_cxt5066 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f1506c, .name = "CX20588",
-	  .patch = patch_cxt5066 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f1506e, .name = "CX20590",
-	  .patch = patch_cxt5066 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15097, .name = "CX20631",
 	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15098, .name = "CX20632",
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index ba4ca52072ff..36badba2dcec 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -648,7 +648,8 @@ static int get_channel_allocation_order(int ca)
  *
  * TODO: it could select the wrong CA from multiple candidates.
 */
-static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels)
+static int hdmi_channel_allocation(struct hda_codec *codec,
+				   struct hdmi_eld *eld, int channels)
 {
 	int i;
 	int ca = 0;
@@ -694,7 +695,7 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels)
 	}
 
 	snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf));
-	snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
+	codec_dbg(codec, "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
 		    ca, channels, buf);
 
 	return ca;
@@ -1131,7 +1132,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
 	if (!non_pcm && per_pin->chmap_set)
 		ca = hdmi_manual_channel_allocation(channels, per_pin->chmap);
 	else
-		ca = hdmi_channel_allocation(eld, channels);
+		ca = hdmi_channel_allocation(codec, eld, channels);
 	if (ca < 0)
 		ca = 0;
 
@@ -1557,13 +1558,13 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
 			eld->eld_valid = false;
 		else {
 			memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld));
-			if (snd_hdmi_parse_eld(&eld->info, eld->eld_buffer,
+			if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer,
 						    eld->eld_size) < 0)
 				eld->eld_valid = false;
 		}
 
 		if (eld->eld_valid) {
-			snd_hdmi_show_eld(&eld->info);
+			snd_hdmi_show_eld(codec, &eld->info);
 			update_eld = true;
 		}
 		else if (repoll) {
@@ -3355,6 +3356,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
 { .id = 0x80862808, .name = "Broadwell HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x80862880, .name = "CedarTrail HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x80862882, .name = "Valleyview2 HDMI",	.patch = patch_generic_hdmi },
+{ .id = 0x80862883, .name = "Braswell HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x808629fb, .name = "Crestline HDMI",	.patch = patch_generic_hdmi },
 {} /* terminator */
 };
@@ -3414,6 +3416,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862807");
 MODULE_ALIAS("snd-hda-codec-id:80862808");
 MODULE_ALIAS("snd-hda-codec-id:80862880");
 MODULE_ALIAS("snd-hda-codec-id:80862882");
+MODULE_ALIAS("snd-hda-codec-id:80862883");
 MODULE_ALIAS("snd-hda-codec-id:808629fb");
 
 MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index b60824e90408..654c8f16d150 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -101,6 +101,7 @@ struct alc_spec {
 	/* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */
 	int mute_led_polarity;
 	hda_nid_t mute_led_nid;
+	hda_nid_t cap_mute_led_nid;
 
 	unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */
 
@@ -3402,7 +3403,8 @@ static unsigned int led_power_filter(struct hda_codec *codec,
 {
 	struct alc_spec *spec = codec->spec;
 
-	if (power_state != AC_PWRST_D3 || nid != spec->mute_led_nid)
+	if (power_state != AC_PWRST_D3 || nid == 0 ||
+	    (nid != spec->mute_led_nid && nid != spec->cap_mute_led_nid))
 		return power_state;
 
 	/* Set pin ctl again, it might have just been set to 0 */
@@ -3520,6 +3522,68 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
 	}
 }
 
+/* turn on/off mic-mute LED per capture hook */
+static void alc269_fixup_hp_cap_mic_mute_hook(struct hda_codec *codec,
+					       struct snd_kcontrol *kcontrol,
+					       struct snd_ctl_elem_value *ucontrol)
+{
+	struct alc_spec *spec = codec->spec;
+	unsigned int pinval, enable, disable;
+
+	pinval = snd_hda_codec_get_pin_target(codec, spec->cap_mute_led_nid);
+	pinval &= ~AC_PINCTL_VREFEN;
+	enable  = pinval | AC_PINCTL_VREF_80;
+	disable = pinval | AC_PINCTL_VREF_HIZ;
+
+	if (!ucontrol)
+		return;
+
+	if (ucontrol->value.integer.value[0] ||
+	    ucontrol->value.integer.value[1])
+		pinval = disable;
+	else
+		pinval = enable;
+
+	if (spec->cap_mute_led_nid)
+		snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval);
+}
+
+static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
+				const struct hda_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	static const struct hda_verb gpio_init[] = {
+		{ 0x01, AC_VERB_SET_GPIO_MASK, 0x08 },
+		{ 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x08 },
+		{}
+	};
+
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+		spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook;
+		spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
+		spec->gpio_led = 0;
+		spec->cap_mute_led_nid = 0x18;
+		snd_hda_add_verbs(codec, gpio_init);
+		codec->power_filter = led_power_filter;
+	}
+}
+
+static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
+				const struct hda_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+		spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
+		spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
+		spec->mute_led_polarity = 0;
+		spec->mute_led_nid = 0x1a;
+		spec->cap_mute_led_nid = 0x18;
+		spec->gen.vmaster_mute_enum = 1;
+		codec->power_filter = led_power_filter;
+	}
+}
+
 static void alc_headset_mode_unplugged(struct hda_codec *codec)
 {
 	int val;
@@ -4231,6 +4295,9 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec,
 /* for hda_fixup_thinkpad_acpi() */
 #include "thinkpad_helper.c"
 
+/* for dell wmi mic mute led */
+#include "dell_wmi_helper.c"
+
 enum {
 	ALC269_FIXUP_SONY_VAIO,
 	ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -4255,6 +4322,8 @@ enum {
 	ALC269_FIXUP_HP_MUTE_LED_MIC1,
 	ALC269_FIXUP_HP_MUTE_LED_MIC2,
 	ALC269_FIXUP_HP_GPIO_LED,
+	ALC269_FIXUP_HP_GPIO_MIC1_LED,
+	ALC269_FIXUP_HP_LINE1_MIC1_LED,
 	ALC269_FIXUP_INV_DMIC,
 	ALC269_FIXUP_LENOVO_DOCK,
 	ALC269_FIXUP_NO_SHUTUP,
@@ -4292,6 +4361,8 @@ enum {
 	ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
 	ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
 	ALC292_FIXUP_TPT440_DOCK,
+	ALC283_FIXUP_BXBT2807_MIC,
+	ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -4447,6 +4518,14 @@ static const struct hda_fixup alc269_fixups[] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc269_fixup_hp_gpio_led,
 	},
+	[ALC269_FIXUP_HP_GPIO_MIC1_LED] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc269_fixup_hp_gpio_mic1_led,
+	},
+	[ALC269_FIXUP_HP_LINE1_MIC1_LED] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc269_fixup_hp_line1_mic1_led,
+	},
 	[ALC269_FIXUP_INV_DMIC] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc_fixup_inv_dmic_0x12,
@@ -4718,6 +4797,20 @@ static const struct hda_fixup alc269_fixups[] = {
 		.chained = true,
 		.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
 	},
+	[ALC283_FIXUP_BXBT2807_MIC] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x19, 0x04a110f0 },
+			{ },
+		},
+	},
+	[ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc_fixup_dell_wmi,
+		.chained_before = true,
+		.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
+	},
+
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -4727,7 +4820,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
 	SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
 	SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
-	SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
 	SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
 	SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
 	SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
@@ -4761,10 +4853,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+	SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
 	SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
 	SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
+	SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
 	SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
 	SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -4782,6 +4876,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
 	/* ALC282 */
+	SND_PCI_QUIRK(0x103c, 0x21f8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x21f9, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x220d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x220e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -4790,6 +4886,20 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x2212, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2234, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2235, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2237, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2238, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2239, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x224a, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x224b, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x224c, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x224d, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
 	SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -4814,13 +4924,43 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22da, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x8004, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
 	/* ALC290 */
+	SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x221c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x221d, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2220, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2222, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2223, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2224, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2256, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2258, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
 	SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2277, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
 	SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -4843,7 +4983,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
-	SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
 	SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
 	SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
 	SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -4864,9 +5003,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
 	SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
 	SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX),
-	SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
 	SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
 	SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
+	SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_BXBT2807_MIC),
 	SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
@@ -4891,7 +5030,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
 	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
 	SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
-	SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI),
 	SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
 
 #if 0
@@ -4945,6 +5083,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	{}
 };
 
+static const struct snd_pci_quirk alc269_fixup_vendor_tbl[] = {
+	SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
+	SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
+	SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
+	SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI),
+	{}
+};
+
 static const struct hda_model_fixup alc269_fixup_models[] = {
 	{.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"},
 	{.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"},
@@ -5040,6 +5186,17 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
 		{0x1d, 0x40700001},
 		{0x1e, 0x411111f0},
 		{0x21, 0x02211040}),
+	SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP 15 Touchsmart", ALC269_FIXUP_HP_MUTE_LED_MIC1,
+		{0x12, 0x99a30130},
+		{0x14, 0x90170110},
+		{0x17, 0x40000000},
+		{0x18, 0x411111f0},
+		{0x19, 0x03a11020},
+		{0x1a, 0x411111f0},
+		{0x1b, 0x411111f0},
+		{0x1d, 0x40f41905},
+		{0x1e, 0x411111f0},
+		{0x21, 0x0321101f}),
 	SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
 		{0x12, 0x90a60130},
 		{0x14, 0x90170110},
@@ -5162,6 +5319,8 @@ static int patch_alc269(struct hda_codec *codec)
 	snd_hda_pick_fixup(codec, alc269_fixup_models,
 		       alc269_fixup_tbl, alc269_fixups);
 	snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups);
+	snd_hda_pick_fixup(codec, NULL,	alc269_fixup_vendor_tbl,
+			   alc269_fixups);
 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
 	alc_auto_parse_customize_define(codec);
@@ -5858,6 +6017,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
 	SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+	SND_PCI_QUIRK(0x1028, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13),
 	SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13),
 	SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 3744ea4e843d..ea823e1100da 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -84,6 +84,7 @@ enum {
 	STAC_DELL_EQ,
 	STAC_ALIENWARE_M17X,
 	STAC_92HD89XX_HP_FRONT_JACK,
+	STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK,
 	STAC_92HD73XX_MODELS
 };
 
@@ -103,6 +104,7 @@ enum {
 	STAC_92HD83XXX_HP,
 	STAC_HP_ENVY_BASS,
 	STAC_HP_BNB13_EQ,
+	STAC_HP_ENVY_TS_BASS,
 	STAC_92HD83XXX_MODELS
 };
 
@@ -1017,7 +1019,7 @@ static int stac_create_spdif_mux_ctls(struct hda_codec *codec)
 	for (i = 0; i < num_cons; i++) {
 		if (snd_BUG_ON(!labels[i]))
 			return -EINVAL;
-		snd_hda_add_imux_item(&spec->spdif_mux, labels[i], i, NULL);
+		snd_hda_add_imux_item(codec, &spec->spdif_mux, labels[i], i, NULL);
 	}
 
 	kctl = snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_smux_mixer);
@@ -1809,6 +1811,11 @@ static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = {
 	{}
 };
 
+static const struct hda_pintbl stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs[] = {
+	{ 0x0e, 0x400000f0 },
+	{}
+};
+
 static void stac92hd73xx_fixup_ref(struct hda_codec *codec,
 				   const struct hda_fixup *fix, int action)
 {
@@ -1931,6 +1938,10 @@ static const struct hda_fixup stac92hd73xx_fixups[] = {
 	[STAC_92HD89XX_HP_FRONT_JACK] = {
 		.type = HDA_FIXUP_PINS,
 		.v.pins = stac92hd89xx_hp_front_jack_pin_configs,
+	},
+	[STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs,
 	}
 };
 
@@ -1991,6 +2002,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = {
 		      "Alienware M17x", STAC_ALIENWARE_M17X),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490,
 		      "Alienware M17x R3", STAC_DELL_EQ),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1927,
+				"HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17,
 				"unknown HP", STAC_92HD89XX_HP_FRONT_JACK),
 	{} /* terminator */
@@ -2668,6 +2681,13 @@ static const struct hda_fixup stac92hd83xxx_fixups[] = {
 		.chained = true,
 		.chain_id = STAC_92HD83XXX_HP_MIC_LED,
 	},
+	[STAC_HP_ENVY_TS_BASS] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x10, 0x92170111 },
+			{}
+		},
+	},
 };
 
 static const struct hda_model_fixup stac92hd83xxx_models[] = {
@@ -2684,6 +2704,7 @@ static const struct hda_model_fixup stac92hd83xxx_models[] = {
 	{ .id = STAC_92HD83XXX_HEADSET_JACK, .name = "headset-jack" },
 	{ .id = STAC_HP_ENVY_BASS, .name = "hp-envy-bass" },
 	{ .id = STAC_HP_BNB13_EQ, .name = "hp-bnb13-eq" },
+	{ .id = STAC_HP_ENVY_TS_BASS, .name = "hp-envy-ts-bass" },
 	{}
 };
 
@@ -2739,6 +2760,8 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = {
 			  "HP bNB13", STAC_HP_BNB13_EQ),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190A,
 			  "HP bNB13", STAC_HP_BNB13_EQ),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190e,
+			  "HP ENVY TS", STAC_HP_ENVY_TS_BASS),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1940,
 			  "HP bNB13", STAC_HP_BNB13_EQ),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1941,
@@ -3438,9 +3461,11 @@ static void stac922x_fixup_intel_mac_auto(struct hda_codec *codec,
 {
 	if (action != HDA_FIXUP_ACT_PRE_PROBE)
 		return;
+
+	codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
 	snd_hda_pick_fixup(codec, NULL, stac922x_intel_mac_fixup_tbl,
 			   stac922x_fixups);
-	if (codec->fixup_id != STAC_INTEL_MAC_AUTO)
+	if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
 		snd_hda_apply_fixup(codec, action);
 }
 
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index b209fc30b334..58f8f2ae758d 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -41,14 +41,17 @@
 #define ICEREG(ice, x) ((ice)->port + ICE1712_REG_##x)
 
 #define ICE1712_REG_CONTROL		0x00	/* byte */
-#define   ICE1712_RESET			0x80	/* reset whole chip */
-#define   ICE1712_SERR_LEVEL		0x04	/* SERR# level otherwise edge */
+#define   ICE1712_RESET			0x80	/* soft reset whole chip */
+#define   ICE1712_SERR_ASSERT_DS_DMA	0x40    /* disabled SERR# assertion for the DS DMA Ch-C irq otherwise enabled */
+#define   ICE1712_DOS_VOL		0x10    /* DOS WT/FM volume control */
+#define   ICE1712_SERR_LEVEL		0x08	/* SERR# level otherwise edge */
+#define   ICE1712_SERR_ASSERT_SB	0x02	/* disabled SERR# assertion for SB irq otherwise enabled */
 #define   ICE1712_NATIVE		0x01	/* native mode otherwise SB */
 #define ICE1712_REG_IRQMASK		0x01	/* byte */
-#define   ICE1712_IRQ_MPU1		0x80
-#define   ICE1712_IRQ_TIMER		0x40
-#define   ICE1712_IRQ_MPU2		0x20
-#define   ICE1712_IRQ_PROPCM		0x10
+#define   ICE1712_IRQ_MPU1		0x80	/* MIDI irq mask */
+#define   ICE1712_IRQ_TIMER		0x40	/* Timer mask */
+#define   ICE1712_IRQ_MPU2		0x20	/* Secondary MIDI irq mask */
+#define   ICE1712_IRQ_PROPCM		0x10	/* professional multi-track */
 #define   ICE1712_IRQ_FM		0x08	/* FM/MIDI - legacy */
 #define   ICE1712_IRQ_PBKDS		0x04	/* playback DS channels */
 #define   ICE1712_IRQ_CONCAP		0x02	/* consumer capture */
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c
index 71f4bdcc4055..84f67450924e 100644
--- a/sound/pci/mixart/mixart_core.c
+++ b/sound/pci/mixart/mixart_core.c
@@ -151,13 +151,11 @@ static int send_msg( struct mixart_mgr *mgr,
 {
 	u32 headptr, tailptr;
 	u32 msg_frame_address;
-	int err, i;
+	int i;
 
 	if (snd_BUG_ON(msg->size % 4))
 		return -EINVAL;
 
-	err = 0;
-
 	/* get message frame address */
 	tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL));
 	headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD));
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 64b9fda5f04a..dbbbacfd535e 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -53,6 +53,7 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = {
 	{ OXYGEN_PCI_SUBID(0x1043, 0x835e) },
 	{ OXYGEN_PCI_SUBID(0x1043, 0x838e) },
 	{ OXYGEN_PCI_SUBID(0x1043, 0x8522) },
+	{ OXYGEN_PCI_SUBID(0x1043, 0x85f4) },
 	{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
 	{ }
 };
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c
index c8c7f2c9b355..e02605931669 100644
--- a/sound/pci/oxygen/xonar_pcm179x.c
+++ b/sound/pci/oxygen/xonar_pcm179x.c
@@ -100,8 +100,8 @@
  */
 
 /*
- * Xonar Essence ST (Deluxe)/STX
- * -----------------------------
+ * Xonar Essence ST (Deluxe)/STX (II)
+ * ----------------------------------
  *
  * CMI8788:
  *
@@ -1138,6 +1138,14 @@ int get_xonar_pcm179x_model(struct oxygen *chip,
 		chip->model.resume = xonar_stx_resume;
 		chip->model.set_dac_params = set_pcm1796_params;
 		break;
+	case 0x85f4:
+		chip->model = model_xonar_st;
+		/* TODO: daughterboard support */
+		chip->model.shortname = "Xonar STX II";
+		chip->model.init = xonar_stx_init;
+		chip->model.resume = xonar_stx_resume;
+		chip->model.set_dac_params = set_pcm1796_params;
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index b4a8278241b1..f0315c3f7de4 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -941,7 +941,7 @@ setmixer(struct cmdif *cif, short num, unsigned short rval, unsigned short lval)
 	union cmdret rptr = CMDRET_ZERO;
 	int i = 0;
 
-	snd_printdd("sent mixer %d: 0x%d 0x%d\n", num, rval, lval);
+	snd_printdd("sent mixer %d: 0x%x 0x%x\n", num, rval, lval);
 	do {
 		SEND_SDGV(cif, num, num, rval, lval);
 		SEND_RDGV(cif, num, num, &rptr);
@@ -1080,7 +1080,7 @@ getmixer(struct cmdif *cif, short num, unsigned short *rval,
 		return -EIO;
 	*rval = rptr.retwords[0];
 	*lval = rptr.retwords[1];
-	snd_printdd("got mixer %d: 0x%d 0x%d\n", num, *rval, *lval);
+	snd_printdd("got mixer %d: 0x%x 0x%x\n", num, *rval, *lval);
 	return 0;
 }
 
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 1272c18a2544..da875dced2ef 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -3880,14 +3880,12 @@ void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voi
 {
 	unsigned long flags;
 	void (*private_free)(struct snd_trident_voice *);
-	void *private_data;
 
 	if (voice == NULL || !voice->use)
 		return;
 	snd_trident_clear_voices(trident, voice->number, voice->number);
 	spin_lock_irqsave(&trident->voice_alloc, flags);
 	private_free = voice->private_free;
-	private_data = voice->private_data;
 	voice->private_free = NULL;
 	voice->private_data = NULL;
 	if (voice->pcm)
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
index 3102a579660b..04c474658e3c 100644
--- a/sound/pci/trident/trident_memory.c
+++ b/sound/pci/trident/trident_memory.c
@@ -139,12 +139,11 @@ static inline void *offset_ptr(struct snd_trident *trident, int offset)
 static struct snd_util_memblk *
 search_empty(struct snd_util_memhdr *hdr, int size)
 {
-	struct snd_util_memblk *blk, *prev;
+	struct snd_util_memblk *blk;
 	int page, psize;
 	struct list_head *p;
 
 	psize = get_aligned_page(size + ALIGN_PAGE_SIZE -1);
-	prev = NULL;
 	page = 0;
 	list_for_each(p, &hdr->block) {
 		blk = list_entry(p, struct snd_util_memblk, list);
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 0060b31cc3f3..0e9623368ab0 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -47,6 +47,7 @@ source "sound/soc/kirkwood/Kconfig"
 source "sound/soc/intel/Kconfig"
 source "sound/soc/mxs/Kconfig"
 source "sound/soc/pxa/Kconfig"
+source "sound/soc/rockchip/Kconfig"
 source "sound/soc/samsung/Kconfig"
 source "sound/soc/s6000/Kconfig"
 source "sound/soc/sh/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 5f1df02984f8..534714a1ca44 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_SND_SOC)	+= nuc900/
 obj-$(CONFIG_SND_SOC)	+= omap/
 obj-$(CONFIG_SND_SOC)	+= kirkwood/
 obj-$(CONFIG_SND_SOC)	+= pxa/
+obj-$(CONFIG_SND_SOC)	+= rockchip/
 obj-$(CONFIG_SND_SOC)	+= samsung/
 obj-$(CONFIG_SND_SOC)	+= s6000/
 obj-$(CONFIG_SND_SOC)	+= sh/
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index de433cfd044c..f403f399808a 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -347,6 +347,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 	u32 tfmr, rfmr, tcmr, rcmr;
 	int start_event;
 	int ret;
+	int fslen, fslen_ext;
 
 	/*
 	 * Currently, there is only one set of dma params for
@@ -388,18 +389,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	/*
-	 * The SSC only supports up to 16-bit samples in I2S format, due
-	 * to the size of the Frame Mode Register FSLEN field.
-	 */
-	if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
-		&& bits > 16) {
-		printk(KERN_WARNING
-				"atmel_ssc_dai: sample size %d "
-				"is too large for I2S\n", bits);
-		return -EINVAL;
-	}
-
-	/*
 	 * Compute SSC register settings.
 	 */
 	switch (ssc_p->daifmt
@@ -413,6 +402,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 		 * from the MCK divider, and the BCLK signal
 		 * is output on the SSC TK line.
 		 */
+
+		if (bits > 16 && !ssc->pdata->has_fslen_ext) {
+			dev_err(dai->dev,
+				"sample size %d is too large for SSC device\n",
+				bits);
+			return -EINVAL;
+		}
+
+		fslen_ext = (bits - 1) / 16;
+		fslen = (bits - 1) % 16;
+
 		rcmr =	  SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
 			| SSC_BF(RCMR_STTDLY, START_DELAY)
 			| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
@@ -420,9 +420,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 			| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
 			| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
 
-		rfmr =	  SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+		rfmr =    SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
+			| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
 			| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
-			| SSC_BF(RFMR_FSLEN, (bits - 1))
+			| SSC_BF(RFMR_FSLEN, fslen)
 			| SSC_BF(RFMR_DATNB, (channels - 1))
 			| SSC_BIT(RFMR_MSBF)
 			| SSC_BF(RFMR_LOOP, 0)
@@ -435,10 +436,11 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 			| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
 			| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
 
-		tfmr =	  SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+		tfmr =    SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
+			| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
 			| SSC_BF(TFMR_FSDEN, 0)
 			| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
-			| SSC_BF(TFMR_FSLEN, (bits - 1))
+			| SSC_BF(TFMR_FSLEN, fslen)
 			| SSC_BF(TFMR_DATNB, (channels - 1))
 			| SSC_BIT(TFMR_MSBF)
 			| SSC_BF(TFMR_DATDEF, 0)
diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c
index b4e36901a40b..4052268ce462 100644
--- a/sound/soc/atmel/atmel_wm8904.c
+++ b/sound/soc/atmel/atmel_wm8904.c
@@ -18,10 +18,6 @@
 #include "../codecs/wm8904.h"
 #include "atmel_ssc_dai.h"
 
-#define MCLK_RATE 32768
-
-static struct clk *mclk;
-
 static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = {
 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
 	SND_SOC_DAPM_MIC("Mic", NULL),
@@ -61,26 +57,6 @@ static struct snd_soc_ops atmel_asoc_wm8904_ops = {
 	.hw_params = atmel_asoc_wm8904_hw_params,
 };
 
-static int atmel_set_bias_level(struct snd_soc_card *card,
-		struct snd_soc_dapm_context *dapm,
-		enum snd_soc_bias_level level)
-{
-	if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
-		switch (level) {
-		case SND_SOC_BIAS_PREPARE:
-			clk_prepare_enable(mclk);
-			break;
-		case SND_SOC_BIAS_OFF:
-			clk_disable_unprepare(mclk);
-			break;
-		default:
-			break;
-		}
-	}
-
-	return 0;
-};
-
 static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = {
 	.name = "WM8904",
 	.stream_name = "WM8904 PCM",
@@ -94,7 +70,6 @@ static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = {
 static struct snd_soc_card atmel_asoc_wm8904_card = {
 	.name = "atmel_asoc_wm8904",
 	.owner = THIS_MODULE,
-	.set_bias_level = atmel_set_bias_level,
 	.dai_link = &atmel_asoc_wm8904_dailink,
 	.num_links = 1,
 	.dapm_widgets = atmel_asoc_wm8904_dapm_widgets,
@@ -153,7 +128,6 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev)
 {
 	struct snd_soc_card *card = &atmel_asoc_wm8904_card;
 	struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
-	struct clk *clk_src;
 	int id, ret;
 
 	card->dev = &pdev->dev;
@@ -170,30 +144,6 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	mclk = clk_get(NULL, "pck0");
-	if (IS_ERR(mclk)) {
-		dev_err(&pdev->dev, "failed to get pck0\n");
-		ret = PTR_ERR(mclk);
-		goto err_set_audio;
-	}
-
-	clk_src = clk_get(NULL, "clk32k");
-	if (IS_ERR(clk_src)) {
-		dev_err(&pdev->dev, "failed to get clk32k\n");
-		ret = PTR_ERR(clk_src);
-		goto err_set_audio;
-	}
-
-	ret = clk_set_parent(mclk, clk_src);
-	clk_put(clk_src);
-	if (ret != 0) {
-		dev_err(&pdev->dev, "failed to set MCLK parent\n");
-		goto err_set_audio;
-	}
-
-	dev_info(&pdev->dev, "setting pck0 to %dHz\n", MCLK_RATE);
-	clk_set_rate(mclk, MCLK_RATE);
-
 	ret = snd_soc_register_card(card);
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed\n");
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index a3881c4381c9..bcf591373a7a 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -290,19 +290,19 @@ static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
 	unsigned int sample_size = runtime->sample_bits / 8;
 	void *buf = runtime->dma_area;
 	struct bf5xx_i2s_pcm_data *dma_data;
-	unsigned int offset, size;
+	unsigned int offset, samples;
 
 	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
 	if (dma_data->tdm_mode) {
 		offset = pos * 8 * sample_size;
-		size = count * 8 * sample_size;
+		samples = count * 8;
 	} else {
 		offset = frames_to_bytes(runtime, pos);
-		size = frames_to_bytes(runtime, count);
+		samples = count * runtime->channels;
 	}
 
-	snd_pcm_format_set_silence(runtime->format, buf + offset, size);
+	snd_pcm_format_set_silence(runtime->format, buf + offset, samples);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index 3c4b10ff48c1..922006dd0583 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -945,11 +945,11 @@ static int pm860x_pcm_hw_params(struct snd_pcm_substream *substream,
 	unsigned char inf = 0, mask = 0;
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		inf &= ~PCM_INF2_18WL;
 		break;
-	case SNDRV_PCM_FORMAT_S18_3LE:
+	case 18:
 		inf |= PCM_INF2_18WL;
 		break;
 	default:
@@ -1044,11 +1044,11 @@ static int pm860x_i2s_hw_params(struct snd_pcm_substream *substream,
 	unsigned char inf;
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		inf = 0;
 		break;
-	case SNDRV_PCM_FORMAT_S18_3LE:
+	case 18:
 		inf = PCM_INF2_18WL;
 		break;
 	default:
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 0b9571c858f8..8838838e25ed 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -47,6 +47,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_CS42L52 if I2C && INPUT
 	select SND_SOC_CS42L56 if I2C && INPUT
 	select SND_SOC_CS42L73 if I2C
+	select SND_SOC_CS4265 if I2C
 	select SND_SOC_CS4270 if I2C
 	select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_CS42XX8_I2C if I2C
@@ -74,10 +75,12 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_PCM3008
 	select SND_SOC_PCM512x_I2C if I2C
 	select SND_SOC_PCM512x_SPI if SPI_MASTER
+	select SND_SOC_RT286 if I2C
 	select SND_SOC_RT5631 if I2C
 	select SND_SOC_RT5640 if I2C
 	select SND_SOC_RT5645 if I2C
 	select SND_SOC_RT5651 if I2C
+	select SND_SOC_RT5670 if I2C
 	select SND_SOC_RT5677 if I2C
 	select SND_SOC_SGTL5000 if I2C
 	select SND_SOC_SI476X if MFD_SI476X_CORE
@@ -91,6 +94,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_STA350 if I2C
 	select SND_SOC_STA529 if I2C
 	select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
+	select SND_SOC_TAS2552 if I2C
 	select SND_SOC_TAS5086 if I2C
 	select SND_SOC_TLV320AIC23_I2C if I2C
 	select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
@@ -338,6 +342,11 @@ config SND_SOC_CS42L73
 	tristate "Cirrus Logic CS42L73 CODEC"
 	depends on I2C
 
+config SND_SOC_CS4265
+	tristate "Cirrus Logic CS4265 CODEC"
+	depends on I2C
+	select REGMAP_I2C
+
 # Cirrus Logic CS4270 Codec
 config SND_SOC_CS4270
 	tristate "Cirrus Logic CS4270 CODEC"
@@ -445,9 +454,16 @@ config SND_SOC_RL6231
 	default y if SND_SOC_RT5640=y
 	default y if SND_SOC_RT5645=y
 	default y if SND_SOC_RT5651=y
+	default y if SND_SOC_RT5670=y
+	default y if SND_SOC_RT5677=y
 	default m if SND_SOC_RT5640=m
 	default m if SND_SOC_RT5645=m
 	default m if SND_SOC_RT5651=m
+	default m if SND_SOC_RT5670=m
+	default m if SND_SOC_RT5677=m
+
+config SND_SOC_RT286
+	tristate
 
 config SND_SOC_RT5631
 	tristate
@@ -461,6 +477,9 @@ config SND_SOC_RT5645
 config SND_SOC_RT5651
 	tristate
 
+config SND_SOC_RT5670
+	tristate
+
 config SND_SOC_RT5677
 	tristate
 
@@ -521,6 +540,10 @@ config SND_SOC_STA529
 config SND_SOC_STAC9766
 	tristate
 
+config SND_SOC_TAS2552
+	tristate "Texas Instruments TAS2552 Mono Audio amplifier"
+	depends on I2C
+
 config SND_SOC_TAS5086
 	tristate "Texas Instruments TAS5086 speaker amplifier"
 	depends on I2C
@@ -541,7 +564,9 @@ config SND_SOC_TLV320AIC26
 	depends on SPI
 
 config SND_SOC_TLV320AIC31XX
-        tristate
+	tristate "Texas Instruments TLV320AIC31xx CODECs"
+	depends on I2C
+	select REGMAP_I2C
 
 config SND_SOC_TLV320AIC32X4
 	tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 1bd6e1cf6f82..20afe0f0c5be 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -37,6 +37,7 @@ snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
 snd-soc-cs42l52-objs := cs42l52.o
 snd-soc-cs42l56-objs := cs42l56.o
 snd-soc-cs42l73-objs := cs42l73.o
+snd-soc-cs4265-objs := cs4265.o
 snd-soc-cs4270-objs := cs4270.o
 snd-soc-cs4271-objs := cs4271.o
 snd-soc-cs42xx8-objs := cs42xx8.o
@@ -68,10 +69,12 @@ snd-soc-pcm512x-objs := pcm512x.o
 snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
 snd-soc-pcm512x-spi-objs := pcm512x-spi.o
 snd-soc-rl6231-objs := rl6231.o
+snd-soc-rt286-objs := rt286.o
 snd-soc-rt5631-objs := rt5631.o
 snd-soc-rt5640-objs := rt5640.o
 snd-soc-rt5645-objs := rt5645.o
 snd-soc-rt5651-objs := rt5651.o
+snd-soc-rt5670-objs := rt5670.o
 snd-soc-rt5677-objs := rt5677.o
 snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
@@ -162,6 +165,7 @@ snd-soc-wm-hubs-objs := wm_hubs.o
 # Amp
 snd-soc-max9877-objs := max9877.o
 snd-soc-tpa6130a2-objs := tpa6130a2.o
+snd-soc-tas2552-objs := tas2552.o
 
 obj-$(CONFIG_SND_SOC_88PM860X)	+= snd-soc-88pm860x.o
 obj-$(CONFIG_SND_SOC_AB8500_CODEC)	+= snd-soc-ab8500-codec.o
@@ -204,6 +208,7 @@ obj-$(CONFIG_SND_SOC_CS42L51_I2C)	+= snd-soc-cs42l51-i2c.o
 obj-$(CONFIG_SND_SOC_CS42L52)	+= snd-soc-cs42l52.o
 obj-$(CONFIG_SND_SOC_CS42L56)	+= snd-soc-cs42l56.o
 obj-$(CONFIG_SND_SOC_CS42L73)	+= snd-soc-cs42l73.o
+obj-$(CONFIG_SND_SOC_CS4265)	+= snd-soc-cs4265.o
 obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
 obj-$(CONFIG_SND_SOC_CS4271)	+= snd-soc-cs4271.o
 obj-$(CONFIG_SND_SOC_CS42XX8)	+= snd-soc-cs42xx8.o
@@ -235,10 +240,12 @@ obj-$(CONFIG_SND_SOC_PCM512x)	+= snd-soc-pcm512x.o
 obj-$(CONFIG_SND_SOC_PCM512x_I2C)	+= snd-soc-pcm512x-i2c.o
 obj-$(CONFIG_SND_SOC_PCM512x_SPI)	+= snd-soc-pcm512x-spi.o
 obj-$(CONFIG_SND_SOC_RL6231)	+= snd-soc-rl6231.o
+obj-$(CONFIG_SND_SOC_RT286)	+= snd-soc-rt286.o
 obj-$(CONFIG_SND_SOC_RT5631)	+= snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_RT5640)	+= snd-soc-rt5640.o
 obj-$(CONFIG_SND_SOC_RT5645)	+= snd-soc-rt5645.o
 obj-$(CONFIG_SND_SOC_RT5651)	+= snd-soc-rt5651.o
+obj-$(CONFIG_SND_SOC_RT5670)	+= snd-soc-rt5670.o
 obj-$(CONFIG_SND_SOC_RT5677)	+= snd-soc-rt5677.o
 obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
 obj-$(CONFIG_SND_SOC_SIGMADSP)	+= snd-soc-sigmadsp.o
@@ -255,6 +262,7 @@ obj-$(CONFIG_SND_SOC_STA32X)   += snd-soc-sta32x.o
 obj-$(CONFIG_SND_SOC_STA350)   += snd-soc-sta350.o
 obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766)	+= snd-soc-stac9766.o
+obj-$(CONFIG_SND_SOC_TAS2552)	+= snd-soc-tas2552.o
 obj-$(CONFIG_SND_SOC_TAS5086)	+= snd-soc-tas5086.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)	+= snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C)	+= snd-soc-tlv320aic23-i2c.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 8d9ba4ba4bfe..e889e1b84192 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -89,8 +89,8 @@ static int ac97_soc_probe(struct snd_soc_codec *codec)
 	int ret;
 
 	/* add codec as bus device for standard ac97 */
-	ret = snd_ac97_bus(codec->card->snd_card, 0, soc_ac97_ops, NULL,
-			   &ac97_bus);
+	ret = snd_ac97_bus(codec->component.card->snd_card, 0, soc_ac97_ops,
+			   NULL, &ac97_bus);
 	if (ret < 0)
 		return ret;
 
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index d71c59cf7bdd..370b742117ef 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -230,8 +230,10 @@ static int adau1701_reg_read(void *context, unsigned int reg,
 
 	*value = 0;
 
-	for (i = 0; i < size; i++)
-		*value |= recv_buf[i] << (i * 8);
+	for (i = 0; i < size; i++) {
+		*value <<= 8;
+		*value |= recv_buf[i];
+	}
 
 	return 0;
 }
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c
index 2961fae9670a..0b659704e60c 100644
--- a/sound/soc/codecs/adau17x1.c
+++ b/sound/soc/codecs/adau17x1.c
@@ -359,14 +359,14 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
 	if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J)
 		return 0;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		val = ADAU17X1_SERIAL_PORT1_DELAY16;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		val = ADAU17X1_SERIAL_PORT1_DELAY8;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		val = ADAU17X1_SERIAL_PORT1_DELAY0;
 		break;
 	default:
diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c
index fd55da7cb9d4..70ab35744aba 100644
--- a/sound/soc/codecs/adau1977.c
+++ b/sound/soc/codecs/adau1977.c
@@ -968,7 +968,7 @@ int adau1977_probe(struct device *dev, struct regmap *regmap,
 	if (adau1977->dvdd_reg)
 		power_off_mask = ~0;
 	else
-		power_off_mask = ~ADAU1977_BLOCK_POWER_SAI_LDO_EN;
+		power_off_mask = (unsigned int)~ADAU1977_BLOCK_POWER_SAI_LDO_EN;
 
 	ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI,
 				power_off_mask, 0x00);
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 3ba4c0f11418..041712592e29 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -547,7 +547,7 @@ static const struct ak4642_drvdata ak4648_drvdata = {
 	.extended_frequencies = 1,
 };
 
-static struct of_device_id ak4642_of_match[];
+static const struct of_device_id ak4642_of_match[];
 static int ak4642_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
@@ -593,7 +593,7 @@ static int ak4642_i2c_remove(struct i2c_client *client)
 	return 0;
 }
 
-static struct of_device_id ak4642_of_match[] = {
+static const struct of_device_id ak4642_of_match[] = {
 	{ .compatible = "asahi-kasei,ak4642",	.data = &ak4642_drvdata},
 	{ .compatible = "asahi-kasei,ak4643",	.data = &ak4643_drvdata},
 	{ .compatible = "asahi-kasei,ak4648",	.data = &ak4648_drvdata},
diff --git a/sound/soc/codecs/ak5386.c b/sound/soc/codecs/ak5386.c
index 72e953b2cb41..8107a1cac876 100644
--- a/sound/soc/codecs/ak5386.c
+++ b/sound/soc/codecs/ak5386.c
@@ -14,12 +14,18 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
 #include <sound/soc.h>
 #include <sound/pcm.h>
 #include <sound/initval.h>
 
+static const char * const supply_names[] = {
+	"va", "vd"
+};
+
 struct ak5386_priv {
 	int reset_gpio;
+	struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
 };
 
 static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = {
@@ -32,7 +38,42 @@ static const struct snd_soc_dapm_route ak5386_dapm_routes[] = {
 	{ "Capture", NULL, "AINR" },
 };
 
+static int ak5386_soc_probe(struct snd_soc_codec *codec)
+{
+	struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+	return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
+}
+
+static int ak5386_soc_remove(struct snd_soc_codec *codec)
+{
+	struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+	regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ak5386_soc_suspend(struct snd_soc_codec *codec)
+{
+	struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+	regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
+	return 0;
+}
+
+static int ak5386_soc_resume(struct snd_soc_codec *codec)
+{
+	struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+	return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
+}
+#else
+#define ak5386_soc_suspend	NULL
+#define ak5386_soc_resume	NULL
+#endif /* CONFIG_PM */
+
 static struct snd_soc_codec_driver soc_codec_ak5386 = {
+	.probe = ak5386_soc_probe,
+	.remove = ak5386_soc_remove,
+	.suspend = ak5386_soc_suspend,
+	.resume = ak5386_soc_resume,
 	.dapm_widgets = ak5386_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets),
 	.dapm_routes = ak5386_dapm_routes,
@@ -122,6 +163,7 @@ static int ak5386_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct ak5386_priv *priv;
+	int ret, i;
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
@@ -130,6 +172,14 @@ static int ak5386_probe(struct platform_device *pdev)
 	priv->reset_gpio = -EINVAL;
 	dev_set_drvdata(dev, priv);
 
+	for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+		priv->supplies[i].supply = supply_names[i];
+
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
+				      priv->supplies);
+	if (ret < 0)
+		return ret;
+
 	if (of_match_device(of_match_ptr(ak5386_dt_ids), dev))
 		priv->reset_gpio = of_get_named_gpio(dev->of_node,
 						      "reset-gpio", 0);
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 29e198f57d4c..2f2e91ac690f 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -243,6 +243,31 @@ int arizona_init_spk(struct snd_soc_codec *codec)
 }
 EXPORT_SYMBOL_GPL(arizona_init_spk);
 
+static const struct snd_soc_dapm_route arizona_mono_routes[] = {
+	{ "OUT1R", NULL, "OUT1L" },
+	{ "OUT2R", NULL, "OUT2L" },
+	{ "OUT3R", NULL, "OUT3L" },
+	{ "OUT4R", NULL, "OUT4L" },
+	{ "OUT5R", NULL, "OUT5L" },
+	{ "OUT6R", NULL, "OUT6L" },
+};
+
+int arizona_init_mono(struct snd_soc_codec *codec)
+{
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona *arizona = priv->arizona;
+	int i;
+
+	for (i = 0; i < ARIZONA_MAX_OUTPUT; ++i) {
+		if (arizona->pdata.out_mono[i])
+			snd_soc_dapm_add_routes(&codec->dapm,
+						&arizona_mono_routes[i], 1);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(arizona_init_mono);
+
 int arizona_init_gpio(struct snd_soc_codec *codec)
 {
 	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
@@ -1127,6 +1152,31 @@ static int arizona_startup(struct snd_pcm_substream *substream,
 					  constraint);
 }
 
+static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
+					unsigned int rate)
+{
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona *arizona = priv->arizona;
+	struct reg_default dac_comp[] = {
+		{ 0x80, 0x3 },
+		{ ARIZONA_DAC_COMP_1, 0 },
+		{ ARIZONA_DAC_COMP_2, 0 },
+		{ 0x80, 0x0 },
+	};
+
+	mutex_lock(&codec->mutex);
+
+	dac_comp[1].def = arizona->dac_comp_coeff;
+	if (rate >= 176400)
+		dac_comp[2].def = arizona->dac_comp_enabled;
+
+	mutex_unlock(&codec->mutex);
+
+	regmap_multi_reg_write(arizona->regmap,
+			       dac_comp,
+			       ARRAY_SIZE(dac_comp));
+}
+
 static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
 				  struct snd_pcm_hw_params *params,
 				  struct snd_soc_dai *dai)
@@ -1153,6 +1203,15 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
 
 	switch (dai_priv->clk) {
 	case ARIZONA_CLK_SYSCLK:
+		switch (priv->arizona->type) {
+		case WM5102:
+			arizona_wm5102_set_dac_comp(codec,
+						    params_rate(params));
+			break;
+		default:
+			break;
+		}
+
 		snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
 				    ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
 		if (base)
@@ -1175,6 +1234,27 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
 	return 0;
 }
 
+static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec,
+				    int base, int bclk, int lrclk, int frame)
+{
+	int val;
+
+	val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL);
+	if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK))
+		return true;
+
+	val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE);
+	if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK))
+		return true;
+
+	val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1);
+	if (frame != (val & (ARIZONA_AIF1TX_WL_MASK |
+			     ARIZONA_AIF1TX_SLOT_LEN_MASK)))
+		return true;
+
+	return false;
+}
+
 static int arizona_hw_params(struct snd_pcm_substream *substream,
 			     struct snd_pcm_hw_params *params,
 			     struct snd_soc_dai *dai)
@@ -1185,26 +1265,40 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
 	int base = dai->driver->base;
 	const int *rates;
 	int i, ret, val;
+	int channels = params_channels(params);
 	int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
+	int tdm_width = arizona->tdm_width[dai->id - 1];
+	int tdm_slots = arizona->tdm_slots[dai->id - 1];
 	int bclk, lrclk, wl, frame, bclk_target;
+	bool reconfig;
+	unsigned int aif_tx_state, aif_rx_state;
 
 	if (params_rate(params) % 8000)
 		rates = &arizona_44k1_bclk_rates[0];
 	else
 		rates = &arizona_48k_bclk_rates[0];
 
-	bclk_target = snd_soc_params_to_bclk(params);
-	if (chan_limit && chan_limit < params_channels(params)) {
+	if (tdm_slots) {
+		arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
+				tdm_slots, tdm_width);
+		bclk_target = tdm_slots * tdm_width * params_rate(params);
+		channels = tdm_slots;
+	} else {
+		bclk_target = snd_soc_params_to_bclk(params);
+	}
+
+	if (chan_limit && chan_limit < channels) {
 		arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
-		bclk_target /= params_channels(params);
+		bclk_target /= channels;
 		bclk_target *= chan_limit;
 	}
 
-	/* Force stereo for I2S mode */
+	/* Force multiple of 2 channels for I2S mode */
 	val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
-	if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) {
+	if ((channels & 1) && (val & ARIZONA_AIF1_FMT_MASK)) {
 		arizona_aif_dbg(dai, "Forcing stereo mode\n");
-		bclk_target *= 2;
+		bclk_target /= channels;
+		bclk_target *= channels + 1;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
@@ -1228,28 +1322,56 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
 	wl = snd_pcm_format_width(params_format(params));
 	frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
 
+	reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame);
+
+	if (reconfig) {
+		/* Save AIF TX/RX state */
+		aif_tx_state = snd_soc_read(codec,
+					    base + ARIZONA_AIF_TX_ENABLES);
+		aif_rx_state = snd_soc_read(codec,
+					    base + ARIZONA_AIF_RX_ENABLES);
+		/* Disable AIF TX/RX before reconfiguring it */
+		regmap_update_bits_async(arizona->regmap,
+				    base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0);
+		regmap_update_bits(arizona->regmap,
+				    base + ARIZONA_AIF_RX_ENABLES, 0xff, 0x0);
+	}
+
 	ret = arizona_hw_params_rate(substream, params, dai);
 	if (ret != 0)
-		return ret;
+		goto restore_aif;
 
-	regmap_update_bits_async(arizona->regmap,
-				 base + ARIZONA_AIF_BCLK_CTRL,
-				 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
-	regmap_update_bits_async(arizona->regmap,
-				 base + ARIZONA_AIF_TX_BCLK_RATE,
-				 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
-	regmap_update_bits_async(arizona->regmap,
-				 base + ARIZONA_AIF_RX_BCLK_RATE,
-				 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
-	regmap_update_bits_async(arizona->regmap,
-				 base + ARIZONA_AIF_FRAME_CTRL_1,
-				 ARIZONA_AIF1TX_WL_MASK |
-				 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
-	regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2,
-			   ARIZONA_AIF1RX_WL_MASK |
-			   ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
+	if (reconfig) {
+		regmap_update_bits_async(arizona->regmap,
+					 base + ARIZONA_AIF_BCLK_CTRL,
+					 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
+		regmap_update_bits_async(arizona->regmap,
+					 base + ARIZONA_AIF_TX_BCLK_RATE,
+					 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
+		regmap_update_bits_async(arizona->regmap,
+					 base + ARIZONA_AIF_RX_BCLK_RATE,
+					 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
+		regmap_update_bits_async(arizona->regmap,
+					 base + ARIZONA_AIF_FRAME_CTRL_1,
+					 ARIZONA_AIF1TX_WL_MASK |
+					 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
+		regmap_update_bits(arizona->regmap,
+				   base + ARIZONA_AIF_FRAME_CTRL_2,
+				   ARIZONA_AIF1RX_WL_MASK |
+				   ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
+	}
 
-	return 0;
+restore_aif:
+	if (reconfig) {
+		/* Restore AIF TX/RX state */
+		regmap_update_bits_async(arizona->regmap,
+					 base + ARIZONA_AIF_TX_ENABLES,
+					 0xff, aif_tx_state);
+		regmap_update_bits(arizona->regmap,
+				   base + ARIZONA_AIF_RX_ENABLES,
+				   0xff, aif_rx_state);
+	}
+	return ret;
 }
 
 static const char *arizona_dai_clk_str(int clk_id)
@@ -1324,9 +1446,63 @@ static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
 				   ARIZONA_AIF1_TRI, reg);
 }
 
+static void arizona_set_channels_to_mask(struct snd_soc_dai *dai,
+					 unsigned int base,
+					 int channels, unsigned int mask)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona *arizona = priv->arizona;
+	int slot, i;
+
+	for (i = 0; i < channels; ++i) {
+		slot = ffs(mask) - 1;
+		if (slot < 0)
+			return;
+
+		regmap_write(arizona->regmap, base + i, slot);
+
+		mask &= ~(1 << slot);
+	}
+
+	if (mask)
+		arizona_aif_warn(dai, "Too many channels in TDM mask\n");
+}
+
+static int arizona_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+				unsigned int rx_mask, int slots, int slot_width)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona *arizona = priv->arizona;
+	int base = dai->driver->base;
+	int rx_max_chan = dai->driver->playback.channels_max;
+	int tx_max_chan = dai->driver->capture.channels_max;
+
+	/* Only support TDM for the physical AIFs */
+	if (dai->id > ARIZONA_MAX_AIF)
+		return -ENOTSUPP;
+
+	if (slots == 0) {
+		tx_mask = (1 << tx_max_chan) - 1;
+		rx_mask = (1 << rx_max_chan) - 1;
+	}
+
+	arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_3,
+				     tx_max_chan, tx_mask);
+	arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_11,
+				     rx_max_chan, rx_mask);
+
+	arizona->tdm_width[dai->id - 1] = slot_width;
+	arizona->tdm_slots[dai->id - 1] = slots;
+
+	return 0;
+}
+
 const struct snd_soc_dai_ops arizona_dai_ops = {
 	.startup = arizona_startup,
 	.set_fmt = arizona_set_fmt,
+	.set_tdm_slot = arizona_set_tdm_slot,
 	.hw_params = arizona_hw_params,
 	.set_sysclk = arizona_dai_set_sysclk,
 	.set_tristate = arizona_set_tristate,
@@ -1400,6 +1576,12 @@ static int arizona_validate_fll(struct arizona_fll *fll,
 {
 	unsigned int Fvco_min;
 
+	if (fll->fout && Fout != fll->fout) {
+		arizona_fll_err(fll,
+				"Can't change output on active FLL\n");
+		return -EINVAL;
+	}
+
 	if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
 		arizona_fll_err(fll,
 				"Can't scale %dMHz in to <=13.5MHz\n",
@@ -1478,6 +1660,10 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
 	while (div <= ARIZONA_FLL_MAX_REFDIV) {
 		for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO;
 		     ratio++) {
+			if ((ARIZONA_FLL_VCO_CORNER / 2) /
+			    (fll->vco_mult * ratio) < Fref)
+				break;
+
 			if (target % (ratio * Fref)) {
 				cfg->refdiv = refdiv;
 				cfg->fratio = ratio - 1;
@@ -1485,11 +1671,7 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
 			}
 		}
 
-		for (ratio = init_ratio - 1; ratio >= 0; ratio--) {
-			if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) <
-			    Fref)
-				break;
-
+		for (ratio = init_ratio - 1; ratio > 0; ratio--) {
 			if (target % (ratio * Fref)) {
 				cfg->refdiv = refdiv;
 				cfg->fratio = ratio - 1;
@@ -1616,7 +1798,7 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
 				 ARIZONA_FLL1_CTRL_UPD | cfg->n);
 }
 
-static bool arizona_is_enabled_fll(struct arizona_fll *fll)
+static int arizona_is_enabled_fll(struct arizona_fll *fll)
 {
 	struct arizona *arizona = fll->arizona;
 	unsigned int reg;
@@ -1632,13 +1814,26 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll)
 	return reg & ARIZONA_FLL1_ENA;
 }
 
-static void arizona_enable_fll(struct arizona_fll *fll)
+static int arizona_enable_fll(struct arizona_fll *fll)
 {
 	struct arizona *arizona = fll->arizona;
 	int ret;
 	bool use_sync = false;
+	int already_enabled = arizona_is_enabled_fll(fll);
 	struct arizona_fll_cfg cfg;
 
+	if (already_enabled < 0)
+		return already_enabled;
+
+	if (already_enabled) {
+		/* Facilitate smooth refclk across the transition */
+		regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x7,
+					 ARIZONA_FLL1_GAIN_MASK, 0);
+		regmap_update_bits_async(fll->arizona->regmap, fll->base + 1,
+					 ARIZONA_FLL1_FREERUN,
+					 ARIZONA_FLL1_FREERUN);
+	}
+
 	/*
 	 * If we have both REFCLK and SYNCCLK then enable both,
 	 * otherwise apply the SYNCCLK settings to REFCLK.
@@ -1666,7 +1861,7 @@ static void arizona_enable_fll(struct arizona_fll *fll)
 					 ARIZONA_FLL1_SYNC_ENA, 0);
 	} else {
 		arizona_fll_err(fll, "No clocks provided\n");
-		return;
+		return -EINVAL;
 	}
 
 	/*
@@ -1681,25 +1876,29 @@ static void arizona_enable_fll(struct arizona_fll *fll)
 					 ARIZONA_FLL1_SYNC_BW,
 					 ARIZONA_FLL1_SYNC_BW);
 
-	if (!arizona_is_enabled_fll(fll))
+	if (!already_enabled)
 		pm_runtime_get(arizona->dev);
 
 	/* Clear any pending completions */
 	try_wait_for_completion(&fll->ok);
 
 	regmap_update_bits_async(arizona->regmap, fll->base + 1,
-				 ARIZONA_FLL1_FREERUN, 0);
-	regmap_update_bits_async(arizona->regmap, fll->base + 1,
 				 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
 	if (use_sync)
 		regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
 					 ARIZONA_FLL1_SYNC_ENA,
 					 ARIZONA_FLL1_SYNC_ENA);
 
+	if (already_enabled)
+		regmap_update_bits_async(arizona->regmap, fll->base + 1,
+					 ARIZONA_FLL1_FREERUN, 0);
+
 	ret = wait_for_completion_timeout(&fll->ok,
 					  msecs_to_jiffies(250));
 	if (ret == 0)
 		arizona_fll_warn(fll, "Timed out waiting for lock\n");
+
+	return 0;
 }
 
 static void arizona_disable_fll(struct arizona_fll *fll)
@@ -1713,6 +1912,8 @@ static void arizona_disable_fll(struct arizona_fll *fll)
 				 ARIZONA_FLL1_ENA, 0, &change);
 	regmap_update_bits(arizona->regmap, fll->base + 0x11,
 			   ARIZONA_FLL1_SYNC_ENA, 0);
+	regmap_update_bits_async(arizona->regmap, fll->base + 1,
+				 ARIZONA_FLL1_FREERUN, 0);
 
 	if (change)
 		pm_runtime_put_autosuspend(arizona->dev);
@@ -1721,7 +1922,7 @@ static void arizona_disable_fll(struct arizona_fll *fll)
 int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
 			   unsigned int Fref, unsigned int Fout)
 {
-	int ret;
+	int ret = 0;
 
 	if (fll->ref_src == source && fll->ref_freq == Fref)
 		return 0;
@@ -1736,17 +1937,17 @@ int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
 	fll->ref_freq = Fref;
 
 	if (fll->fout && Fref > 0) {
-		arizona_enable_fll(fll);
+		ret = arizona_enable_fll(fll);
 	}
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
 
 int arizona_set_fll(struct arizona_fll *fll, int source,
 		    unsigned int Fref, unsigned int Fout)
 {
-	int ret;
+	int ret = 0;
 
 	if (fll->sync_src == source &&
 	    fll->sync_freq == Fref && fll->fout == Fout)
@@ -1768,13 +1969,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
 	fll->sync_freq = Fref;
 	fll->fout = Fout;
 
-	if (Fout) {
-		arizona_enable_fll(fll);
-	} else {
+	if (Fout)
+		ret = arizona_enable_fll(fll);
+	else
 		arizona_disable_fll(fll);
-	}
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(arizona_set_fll);
 
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index 05ae17f5bca3..942cfb197b6d 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -249,6 +249,7 @@ extern int arizona_set_fll(struct arizona_fll *fll, int source,
 
 extern int arizona_init_spk(struct snd_soc_codec *codec);
 extern int arizona_init_gpio(struct snd_soc_codec *codec);
+extern int arizona_init_mono(struct snd_soc_codec *codec);
 
 extern int arizona_init_dai(struct arizona_priv *priv, int dai);
 
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c
new file mode 100644
index 000000000000..a20b30ca52c0
--- /dev/null
+++ b/sound/soc/codecs/cs4265.c
@@ -0,0 +1,682 @@
+/*
+ * cs4265.c -- CS4265 ALSA SoC audio driver
+ *
+ * Copyright 2014 Cirrus Logic, Inc.
+ *
+ * Author: Paul Handrigan <paul.handrigan@cirrus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/gpio/consumer.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include "cs4265.h"
+
+struct cs4265_private {
+	struct device *dev;
+	struct regmap *regmap;
+	struct gpio_desc *reset_gpio;
+	u8 format;
+	u32 sysclk;
+};
+
+static const struct reg_default cs4265_reg_defaults[] = {
+	{ CS4265_PWRCTL, 0x0F },
+	{ CS4265_DAC_CTL, 0x08 },
+	{ CS4265_ADC_CTL, 0x00 },
+	{ CS4265_MCLK_FREQ, 0x00 },
+	{ CS4265_SIG_SEL, 0x40 },
+	{ CS4265_CHB_PGA_CTL, 0x00 },
+	{ CS4265_CHA_PGA_CTL, 0x00 },
+	{ CS4265_ADC_CTL2, 0x19 },
+	{ CS4265_DAC_CHA_VOL, 0x00 },
+	{ CS4265_DAC_CHB_VOL, 0x00 },
+	{ CS4265_DAC_CTL2, 0xC0 },
+	{ CS4265_SPDIF_CTL1, 0x00 },
+	{ CS4265_SPDIF_CTL2, 0x00 },
+	{ CS4265_INT_MASK, 0x00 },
+	{ CS4265_STATUS_MODE_MSB, 0x00 },
+	{ CS4265_STATUS_MODE_LSB, 0x00 },
+};
+
+static bool cs4265_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case CS4265_PWRCTL:
+	case CS4265_DAC_CTL:
+	case CS4265_ADC_CTL:
+	case CS4265_MCLK_FREQ:
+	case CS4265_SIG_SEL:
+	case CS4265_CHB_PGA_CTL:
+	case CS4265_CHA_PGA_CTL:
+	case CS4265_ADC_CTL2:
+	case CS4265_DAC_CHA_VOL:
+	case CS4265_DAC_CHB_VOL:
+	case CS4265_DAC_CTL2:
+	case CS4265_SPDIF_CTL1:
+	case CS4265_SPDIF_CTL2:
+	case CS4265_INT_MASK:
+	case CS4265_STATUS_MODE_MSB:
+	case CS4265_STATUS_MODE_LSB:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool cs4265_volatile_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case CS4265_INT_STATUS:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static DECLARE_TLV_DB_SCALE(pga_tlv, -1200, 50, 0);
+
+static DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 0);
+
+static const char * const digital_input_mux_text[] = {
+	"SDIN1", "SDIN2"
+};
+
+static SOC_ENUM_SINGLE_DECL(digital_input_mux_enum, CS4265_SIG_SEL, 7,
+		digital_input_mux_text);
+
+static const struct snd_kcontrol_new digital_input_mux =
+	SOC_DAPM_ENUM("Digital Input Mux", digital_input_mux_enum);
+
+static const char * const mic_linein_text[] = {
+	"MIC", "LINEIN"
+};
+
+static SOC_ENUM_SINGLE_DECL(mic_linein_enum, CS4265_ADC_CTL2, 0,
+		mic_linein_text);
+
+static const char * const cam_mode_text[] = {
+	"One Byte", "Two Byte"
+};
+
+static SOC_ENUM_SINGLE_DECL(cam_mode_enum, CS4265_SPDIF_CTL1, 5,
+		cam_mode_text);
+
+static const char * const cam_mono_stereo_text[] = {
+	"Stereo", "Mono"
+};
+
+static SOC_ENUM_SINGLE_DECL(spdif_mono_stereo_enum, CS4265_SPDIF_CTL2, 2,
+		cam_mono_stereo_text);
+
+static const char * const mono_select_text[] = {
+	"Channel A", "Channel B"
+};
+
+static SOC_ENUM_SINGLE_DECL(spdif_mono_select_enum, CS4265_SPDIF_CTL2, 0,
+		mono_select_text);
+
+static const struct snd_kcontrol_new mic_linein_mux =
+	SOC_DAPM_ENUM("ADC Input Capture Mux", mic_linein_enum);
+
+static const struct snd_kcontrol_new loopback_ctl =
+	SOC_DAPM_SINGLE("Switch", CS4265_SIG_SEL, 1, 1, 0);
+
+static const struct snd_kcontrol_new spdif_switch =
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 0, 0);
+
+static const struct snd_kcontrol_new dac_switch =
+	SOC_DAPM_SINGLE("Switch", CS4265_PWRCTL, 1, 1, 0);
+
+static const struct snd_kcontrol_new cs4265_snd_controls[] = {
+
+	SOC_DOUBLE_R_SX_TLV("PGA Volume", CS4265_CHA_PGA_CTL,
+			      CS4265_CHB_PGA_CTL, 0, 0x28, 0x30, pga_tlv),
+	SOC_DOUBLE_R_TLV("DAC Volume", CS4265_DAC_CHA_VOL,
+		      CS4265_DAC_CHB_VOL, 0, 0xFF, 1, dac_tlv),
+	SOC_SINGLE("De-emp 44.1kHz Switch", CS4265_DAC_CTL, 1,
+				1, 0),
+	SOC_SINGLE("DAC INV Switch", CS4265_DAC_CTL2, 5,
+				1, 0),
+	SOC_SINGLE("DAC Zero Cross Switch", CS4265_DAC_CTL2, 6,
+				1, 0),
+	SOC_SINGLE("DAC Soft Ramp Switch", CS4265_DAC_CTL2, 7,
+				1, 0),
+	SOC_SINGLE("ADC HPF Switch", CS4265_ADC_CTL, 1,
+				1, 0),
+	SOC_SINGLE("ADC Zero Cross Switch", CS4265_ADC_CTL2, 3,
+				1, 1),
+	SOC_SINGLE("ADC Soft Ramp Switch", CS4265_ADC_CTL2, 7,
+				1, 0),
+	SOC_SINGLE("E to F Buffer Disable Switch", CS4265_SPDIF_CTL1,
+				6, 1, 0),
+	SOC_ENUM("C Data Access", cam_mode_enum),
+	SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2,
+				3, 1, 0),
+	SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum),
+	SOC_SINGLE("MMTLR Data Switch", 0,
+				1, 1, 0),
+	SOC_ENUM("Mono Channel Select", spdif_mono_select_enum),
+	SND_SOC_BYTES("C Data Buffer", CS4265_C_DATA_BUFF, 24),
+};
+
+static const struct snd_soc_dapm_widget cs4265_dapm_widgets[] = {
+
+	SND_SOC_DAPM_INPUT("LINEINL"),
+	SND_SOC_DAPM_INPUT("LINEINR"),
+	SND_SOC_DAPM_INPUT("MICL"),
+	SND_SOC_DAPM_INPUT("MICR"),
+
+	SND_SOC_DAPM_AIF_OUT("DOUT", NULL,  0,
+			SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("SPDIFOUT", NULL,  0,
+			SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_MUX("ADC Mux", SND_SOC_NOPM, 0, 0, &mic_linein_mux),
+
+	SND_SOC_DAPM_ADC("ADC", NULL, CS4265_PWRCTL, 2, 1),
+	SND_SOC_DAPM_PGA("Pre-amp MIC", CS4265_PWRCTL, 3,
+			1, NULL, 0),
+
+	SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM,
+			 0, 0, &digital_input_mux),
+
+	SND_SOC_DAPM_MIXER("SDIN1 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("SDIN2 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("SPDIF Transmitter", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_SWITCH("Loopback", SND_SOC_NOPM, 0, 0,
+			&loopback_ctl),
+	SND_SOC_DAPM_SWITCH("SPDIF", SND_SOC_NOPM, 0, 0,
+			&spdif_switch),
+	SND_SOC_DAPM_SWITCH("DAC", CS4265_PWRCTL, 1, 1,
+			&dac_switch),
+
+	SND_SOC_DAPM_AIF_IN("DIN1", NULL,  0,
+			SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("DIN2", NULL,  0,
+			SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("TXIN", NULL,  0,
+			CS4265_SPDIF_CTL2, 5, 1),
+
+	SND_SOC_DAPM_OUTPUT("LINEOUTL"),
+	SND_SOC_DAPM_OUTPUT("LINEOUTR"),
+
+};
+
+static const struct snd_soc_dapm_route cs4265_audio_map[] = {
+
+	{"DIN1", NULL, "DAI1 Playback"},
+	{"DIN2", NULL, "DAI2 Playback"},
+	{"SDIN1 Input Mixer", NULL, "DIN1"},
+	{"SDIN2 Input Mixer", NULL, "DIN2"},
+	{"Input Mux", "SDIN1", "SDIN1 Input Mixer"},
+	{"Input Mux", "SDIN2", "SDIN2 Input Mixer"},
+	{"DAC", "Switch", "Input Mux"},
+	{"SPDIF", "Switch", "Input Mux"},
+	{"LINEOUTL", NULL, "DAC"},
+	{"LINEOUTR", NULL, "DAC"},
+	{"SPDIFOUT", NULL, "SPDIF"},
+
+	{"ADC Mux", "LINEIN", "LINEINL"},
+	{"ADC Mux", "LINEIN", "LINEINR"},
+	{"ADC Mux", "MIC", "MICL"},
+	{"ADC Mux", "MIC", "MICR"},
+	{"ADC", NULL, "ADC Mux"},
+	{"DOUT", NULL, "ADC"},
+	{"DAI1 Capture", NULL, "DOUT"},
+	{"DAI2 Capture", NULL, "DOUT"},
+
+	/* Loopback */
+	{"Loopback", "Switch", "ADC"},
+	{"DAC", NULL, "Loopback"},
+};
+
+struct cs4265_clk_para {
+	u32 mclk;
+	u32 rate;
+	u8 fm_mode; /* values 1, 2, or 4 */
+	u8 mclkdiv;
+};
+
+static const struct cs4265_clk_para clk_map_table[] = {
+	/*32k*/
+	{8192000, 32000, 0, 0},
+	{12288000, 32000, 0, 1},
+	{16384000, 32000, 0, 2},
+	{24576000, 32000, 0, 3},
+	{32768000, 32000, 0, 4},
+
+	/*44.1k*/
+	{11289600, 44100, 0, 0},
+	{16934400, 44100, 0, 1},
+	{22579200, 44100, 0, 2},
+	{33868000, 44100, 0, 3},
+	{45158400, 44100, 0, 4},
+
+	/*48k*/
+	{12288000, 48000, 0, 0},
+	{18432000, 48000, 0, 1},
+	{24576000, 48000, 0, 2},
+	{36864000, 48000, 0, 3},
+	{49152000, 48000, 0, 4},
+
+	/*64k*/
+	{8192000, 64000, 1, 0},
+	{1228800, 64000, 1, 1},
+	{1693440, 64000, 1, 2},
+	{2457600, 64000, 1, 3},
+	{3276800, 64000, 1, 4},
+
+	/* 88.2k */
+	{11289600, 88200, 1, 0},
+	{16934400, 88200, 1, 1},
+	{22579200, 88200, 1, 2},
+	{33868000, 88200, 1, 3},
+	{45158400, 88200, 1, 4},
+
+	/* 96k */
+	{12288000, 96000, 1, 0},
+	{18432000, 96000, 1, 1},
+	{24576000, 96000, 1, 2},
+	{36864000, 96000, 1, 3},
+	{49152000, 96000, 1, 4},
+
+	/* 128k */
+	{8192000, 128000, 2, 0},
+	{12288000, 128000, 2, 1},
+	{16934400, 128000, 2, 2},
+	{24576000, 128000, 2, 3},
+	{32768000, 128000, 2, 4},
+
+	/* 176.4k */
+	{11289600, 176400, 2, 0},
+	{16934400, 176400, 2, 1},
+	{22579200, 176400, 2, 2},
+	{33868000, 176400, 2, 3},
+	{49152000, 176400, 2, 4},
+
+	/* 192k */
+	{12288000, 192000, 2, 0},
+	{18432000, 192000, 2, 1},
+	{24576000, 192000, 2, 2},
+	{36864000, 192000, 2, 3},
+	{49152000, 192000, 2, 4},
+};
+
+static int cs4265_get_clk_index(int mclk, int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
+		if (clk_map_table[i].rate == rate &&
+				clk_map_table[i].mclk == mclk)
+			return i;
+	}
+	return -EINVAL;
+}
+
+static int cs4265_set_sysclk(struct snd_soc_dai *codec_dai, int clk_id,
+			unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
+	int i;
+
+	if (clk_id != 0) {
+		dev_err(codec->dev, "Invalid clk_id %d\n", clk_id);
+		return -EINVAL;
+	}
+	for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
+		if (clk_map_table[i].mclk == freq) {
+			cs4265->sysclk = freq;
+			return 0;
+		}
+	}
+	cs4265->sysclk = 0;
+	dev_err(codec->dev, "Invalid freq parameter %d\n", freq);
+	return -EINVAL;
+}
+
+static int cs4265_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
+	u8 iface = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		snd_soc_update_bits(codec, CS4265_ADC_CTL,
+				CS4265_ADC_MASTER,
+				CS4265_ADC_MASTER);
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		snd_soc_update_bits(codec, CS4265_ADC_CTL,
+				CS4265_ADC_MASTER,
+				0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	 /* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		iface |= SND_SOC_DAIFMT_I2S;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		iface |= SND_SOC_DAIFMT_RIGHT_J;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		iface |= SND_SOC_DAIFMT_LEFT_J;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cs4265->format = iface;
+	return 0;
+}
+
+static int cs4265_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+
+	if (mute) {
+		snd_soc_update_bits(codec, CS4265_DAC_CTL,
+			CS4265_DAC_CTL_MUTE,
+			CS4265_DAC_CTL_MUTE);
+		snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
+			CS4265_SPDIF_CTL2_MUTE,
+			CS4265_SPDIF_CTL2_MUTE);
+	} else {
+		snd_soc_update_bits(codec, CS4265_DAC_CTL,
+			CS4265_DAC_CTL_MUTE,
+			0);
+		snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
+			CS4265_SPDIF_CTL2_MUTE,
+			0);
+	}
+	return 0;
+}
+
+static int cs4265_pcm_hw_params(struct snd_pcm_substream *substream,
+				     struct snd_pcm_hw_params *params,
+				     struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
+	int index;
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
+		((cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK)
+		== SND_SOC_DAIFMT_RIGHT_J))
+		return -EINVAL;
+
+	index = cs4265_get_clk_index(cs4265->sysclk, params_rate(params));
+	if (index >= 0) {
+		snd_soc_update_bits(codec, CS4265_ADC_CTL,
+			CS4265_ADC_FM, clk_map_table[index].fm_mode);
+		snd_soc_update_bits(codec, CS4265_MCLK_FREQ,
+			CS4265_MCLK_FREQ_MASK,
+			clk_map_table[index].mclkdiv);
+
+	} else {
+		dev_err(codec->dev, "can't get correct mclk\n");
+		return -EINVAL;
+	}
+
+	switch (cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		snd_soc_update_bits(codec, CS4265_DAC_CTL,
+			CS4265_DAC_CTL_DIF, (1 << 4));
+		snd_soc_update_bits(codec, CS4265_ADC_CTL,
+			CS4265_ADC_DIF, (1 << 4));
+		snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
+			CS4265_SPDIF_CTL2_DIF, (1 << 6));
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		if (params_width(params) == 16) {
+			snd_soc_update_bits(codec, CS4265_DAC_CTL,
+				CS4265_DAC_CTL_DIF, (1 << 5));
+			snd_soc_update_bits(codec, CS4265_ADC_CTL,
+				CS4265_SPDIF_CTL2_DIF, (1 << 7));
+		} else {
+			snd_soc_update_bits(codec, CS4265_DAC_CTL,
+				CS4265_DAC_CTL_DIF, (3 << 5));
+			snd_soc_update_bits(codec, CS4265_ADC_CTL,
+				CS4265_SPDIF_CTL2_DIF, (1 << 7));
+		}
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		snd_soc_update_bits(codec, CS4265_DAC_CTL,
+			CS4265_DAC_CTL_DIF, 0);
+		snd_soc_update_bits(codec, CS4265_ADC_CTL,
+			CS4265_ADC_DIF, 0);
+		snd_soc_update_bits(codec, CS4265_ADC_CTL,
+			CS4265_SPDIF_CTL2_DIF, (1 << 6));
+
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int cs4265_set_bias_level(struct snd_soc_codec *codec,
+					enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+	case SND_SOC_BIAS_PREPARE:
+		snd_soc_update_bits(codec, CS4265_PWRCTL,
+			CS4265_PWRCTL_PDN, 0);
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		snd_soc_update_bits(codec, CS4265_PWRCTL,
+			CS4265_PWRCTL_PDN,
+			CS4265_PWRCTL_PDN);
+		break;
+	case SND_SOC_BIAS_OFF:
+		snd_soc_update_bits(codec, CS4265_PWRCTL,
+			CS4265_PWRCTL_PDN,
+			CS4265_PWRCTL_PDN);
+		break;
+	}
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+#define CS4265_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
+			SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
+			SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
+
+#define CS4265_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE)
+
+static const struct snd_soc_dai_ops cs4265_ops = {
+	.hw_params	= cs4265_pcm_hw_params,
+	.digital_mute	= cs4265_digital_mute,
+	.set_fmt	= cs4265_set_fmt,
+	.set_sysclk	= cs4265_set_sysclk,
+};
+
+static struct snd_soc_dai_driver cs4265_dai[] = {
+	{
+		.name = "cs4265-dai1",
+		.playback = {
+			.stream_name = "DAI1 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = CS4265_RATES,
+			.formats = CS4265_FORMATS,
+		},
+		.capture = {
+			.stream_name = "DAI1 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = CS4265_RATES,
+			.formats = CS4265_FORMATS,
+		},
+		.ops = &cs4265_ops,
+	},
+	{
+		.name = "cs4265-dai2",
+		.playback = {
+			.stream_name = "DAI2 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = CS4265_RATES,
+			.formats = CS4265_FORMATS,
+		},
+		.capture = {
+			.stream_name = "DAI2 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = CS4265_RATES,
+			.formats = CS4265_FORMATS,
+		},
+		.ops = &cs4265_ops,
+	},
+};
+
+static const struct snd_soc_codec_driver soc_codec_cs4265 = {
+	.set_bias_level = cs4265_set_bias_level,
+
+	.dapm_widgets = cs4265_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(cs4265_dapm_widgets),
+	.dapm_routes = cs4265_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(cs4265_audio_map),
+
+	.controls = cs4265_snd_controls,
+	.num_controls = ARRAY_SIZE(cs4265_snd_controls),
+};
+
+static const struct regmap_config cs4265_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = CS4265_MAX_REGISTER,
+	.reg_defaults = cs4265_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(cs4265_reg_defaults),
+	.readable_reg = cs4265_readable_register,
+	.volatile_reg = cs4265_volatile_register,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static int cs4265_i2c_probe(struct i2c_client *i2c_client,
+			     const struct i2c_device_id *id)
+{
+	struct cs4265_private *cs4265;
+	int ret = 0;
+	unsigned int devid = 0;
+	unsigned int reg;
+
+	cs4265 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4265_private),
+			       GFP_KERNEL);
+	if (cs4265 == NULL)
+		return -ENOMEM;
+	cs4265->dev = &i2c_client->dev;
+
+	cs4265->regmap = devm_regmap_init_i2c(i2c_client, &cs4265_regmap);
+	if (IS_ERR(cs4265->regmap)) {
+		ret = PTR_ERR(cs4265->regmap);
+		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	cs4265->reset_gpio = devm_gpiod_get(&i2c_client->dev,
+		"reset-gpios");
+	if (IS_ERR(cs4265->reset_gpio)) {
+		ret = PTR_ERR(cs4265->reset_gpio);
+		if (ret != -ENOENT && ret != -ENOSYS)
+			return ret;
+
+		cs4265->reset_gpio = NULL;
+	} else {
+		ret = gpiod_direction_output(cs4265->reset_gpio, 0);
+		if (ret)
+			return ret;
+		mdelay(1);
+		gpiod_set_value_cansleep(cs4265->reset_gpio, 1);
+
+	}
+
+	i2c_set_clientdata(i2c_client, cs4265);
+
+	ret = regmap_read(cs4265->regmap, CS4265_CHIP_ID, &reg);
+	devid = reg & CS4265_CHIP_ID_MASK;
+	if (devid != CS4265_CHIP_ID_VAL) {
+		ret = -ENODEV;
+		dev_err(&i2c_client->dev,
+			"CS4265 Device ID (%X). Expected %X\n",
+			devid, CS4265_CHIP_ID);
+		return ret;
+	}
+	dev_info(&i2c_client->dev,
+		"CS4265 Version %x\n",
+			reg & CS4265_REV_ID_MASK);
+
+	regmap_write(cs4265->regmap, CS4265_PWRCTL, 0x0F);
+
+	ret =  snd_soc_register_codec(&i2c_client->dev,
+			&soc_codec_cs4265, cs4265_dai,
+			ARRAY_SIZE(cs4265_dai));
+	return ret;
+}
+
+static int cs4265_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	return 0;
+}
+
+static const struct of_device_id cs4265_of_match[] = {
+	{ .compatible = "cirrus,cs4265", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, cs4265_of_match);
+
+static const struct i2c_device_id cs4265_id[] = {
+	{ "cs4265", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cs4265_id);
+
+static struct i2c_driver cs4265_i2c_driver = {
+	.driver = {
+		.name = "cs4265",
+		.owner = THIS_MODULE,
+		.of_match_table = cs4265_of_match,
+	},
+	.id_table = cs4265_id,
+	.probe =    cs4265_i2c_probe,
+	.remove =   cs4265_i2c_remove,
+};
+
+module_i2c_driver(cs4265_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC CS4265 driver");
+MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <paul.handrigan@cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs4265.h b/sound/soc/codecs/cs4265.h
new file mode 100644
index 000000000000..0a80a8dcec67
--- /dev/null
+++ b/sound/soc/codecs/cs4265.h
@@ -0,0 +1,64 @@
+/*
+ * cs4265.h -- CS4265 ALSA SoC audio driver
+ *
+ * Copyright 2014 Cirrus Logic, Inc.
+ *
+ * Author: Paul Handrigan <paul.handrigan@cirrus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __CS4265_H__
+#define __CS4265_H__
+
+#define CS4265_CHIP_ID				0x1
+#define CS4265_CHIP_ID_VAL			0xD0
+#define CS4265_CHIP_ID_MASK			0xF0
+#define CS4265_REV_ID_MASK			0x0F
+
+#define CS4265_PWRCTL				0x02
+#define CS4265_PWRCTL_PDN			1
+
+#define CS4265_DAC_CTL				0x3
+#define CS4265_DAC_CTL_MUTE			(1 << 2)
+#define CS4265_DAC_CTL_DIF			(3 << 4)
+
+#define CS4265_ADC_CTL				0x4
+#define CS4265_ADC_MASTER			1
+#define CS4265_ADC_DIF				(1 << 4)
+#define CS4265_ADC_FM				(3 << 6)
+
+#define CS4265_MCLK_FREQ			0x5
+#define CS4265_MCLK_FREQ_MASK			(7 << 4)
+
+#define CS4265_SIG_SEL				0x6
+#define CS4265_SIG_SEL_LOOP			(1 << 1)
+
+#define CS4265_CHB_PGA_CTL			0x7
+#define CS4265_CHA_PGA_CTL			0x8
+
+#define CS4265_ADC_CTL2				0x9
+
+#define CS4265_DAC_CHA_VOL			0xA
+#define CS4265_DAC_CHB_VOL			0xB
+
+#define CS4265_DAC_CTL2				0xC
+
+#define CS4265_INT_STATUS			0xD
+#define CS4265_INT_MASK				0xE
+#define CS4265_STATUS_MODE_MSB			0xF
+#define CS4265_STATUS_MODE_LSB			0x10
+
+#define CS4265_SPDIF_CTL1			0x11
+
+#define CS4265_SPDIF_CTL2			0x12
+#define CS4265_SPDIF_CTL2_MUTE			(1 << 4)
+#define CS4265_SPDIF_CTL2_DIF			(3 << 6)
+
+#define CS4265_C_DATA_BUFF			0x13
+#define CS4265_MAX_REGISTER			0x2A
+
+#endif
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 9947a9583679..e6d4ff9fd992 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -664,10 +664,8 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
 
 	cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private),
 			      GFP_KERNEL);
-	if (!cs4270) {
-		dev_err(&i2c_client->dev, "could not allocate codec\n");
+	if (!cs4270)
 		return -ENOMEM;
-	}
 
 	/* get the power supply regulators */
 	for (i = 0; i < ARRAY_SIZE(supply_names); i++)
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index 071fc77f2f06..969167d8b71e 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -399,15 +399,15 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
 			      CS42L52_MASTERB_VOL, 0, 0x34, 0xE4, hl_tlv),
 
 	SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L52_HPA_VOL,
-			      CS42L52_HPB_VOL, 0, 0x34, 0xCC, hpd_tlv),
+			      CS42L52_HPB_VOL, 0, 0x34, 0xC0, hpd_tlv),
 
 	SOC_ENUM("Headphone Analog Gain", hp_gain_enum),
 
 	SOC_DOUBLE_R_SX_TLV("Speaker Volume", CS42L52_SPKA_VOL,
-			      CS42L52_SPKB_VOL, 0, 0x1, 0xff, hl_tlv),
+			      CS42L52_SPKB_VOL, 0, 0x40, 0xC0, hl_tlv),
 
 	SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL,
-			      CS42L52_PASSTHRUB_VOL, 6, 0x18, 0x90, pga_tlv),
+			      CS42L52_PASSTHRUB_VOL, 0, 0x88, 0x90, pga_tlv),
 
 	SOC_DOUBLE("Bypass Mute", CS42L52_MISC_CTL, 4, 5, 1, 0),
 
@@ -417,10 +417,10 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
 	SOC_ENUM("MIC Bias Level", mic_bias_level_enum),
 
 	SOC_DOUBLE_R_SX_TLV("ADC Volume", CS42L52_ADCA_VOL,
-			      CS42L52_ADCB_VOL, 7, 0x80, 0xA0, ipd_tlv),
+			      CS42L52_ADCB_VOL, 0, 0xA0, 0x78, ipd_tlv),
 	SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
 			     CS42L52_ADCA_MIXER_VOL, CS42L52_ADCB_MIXER_VOL,
-				6, 0x7f, 0x19, ipd_tlv),
+				0, 0x19, 0x7F, ipd_tlv),
 
 	SOC_DOUBLE("ADC Switch", CS42L52_ADC_MISC_CTL, 0, 1, 1, 0),
 
@@ -428,11 +428,11 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
 		     CS42L52_ADCB_MIXER_VOL, 7, 1, 1),
 
 	SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L52_PGAA_CTL,
-			    CS42L52_PGAB_CTL, 0, 0x28, 0x30, pga_tlv),
+			    CS42L52_PGAB_CTL, 0, 0x28, 0x24, pga_tlv),
 
 	SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume",
 			    CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL,
-				0, 0x7f, 0x19, mix_tlv),
+				0, 0x19, 0x7f, mix_tlv),
 	SOC_DOUBLE_R("PCM Mixer Switch",
 		     CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, 7, 1, 1),
 
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c
index fdc4bd27b0df..c766a5a9ce80 100644
--- a/sound/soc/codecs/cs42l56.c
+++ b/sound/soc/codecs/cs42l56.c
@@ -318,24 +318,32 @@ static const struct soc_enum adca_swap_enum =
 			      ARRAY_SIZE(left_swap_text),
 			      left_swap_text,
 			      swap_values);
+static const struct snd_kcontrol_new adca_swap_mux =
+	SOC_DAPM_ENUM("Route", adca_swap_enum);
 
 static const struct soc_enum pcma_swap_enum =
 	SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 4, 3,
 			      ARRAY_SIZE(left_swap_text),
 			      left_swap_text,
 			      swap_values);
+static const struct snd_kcontrol_new pcma_swap_mux =
+	SOC_DAPM_ENUM("Route", pcma_swap_enum);
 
 static const struct soc_enum adcb_swap_enum =
 	SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 2, 3,
 			      ARRAY_SIZE(right_swap_text),
 			      right_swap_text,
 			      swap_values);
+static const struct snd_kcontrol_new adcb_swap_mux =
+	SOC_DAPM_ENUM("Route", adcb_swap_enum);
 
 static const struct soc_enum pcmb_swap_enum =
 	SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 6, 3,
 			      ARRAY_SIZE(right_swap_text),
 			      right_swap_text,
 			      swap_values);
+static const struct snd_kcontrol_new pcmb_swap_mux =
+	SOC_DAPM_ENUM("Route", pcmb_swap_enum);
 
 static const struct snd_kcontrol_new hpa_switch =
 	SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 6, 1, 1);
@@ -421,15 +429,15 @@ static const struct soc_enum ng_delay_enum =
 static const struct snd_kcontrol_new cs42l56_snd_controls[] = {
 
 	SOC_DOUBLE_R_SX_TLV("Master Volume", CS42L56_MASTER_A_VOLUME,
-			      CS42L56_MASTER_B_VOLUME, 0, 0x34, 0xfd, adv_tlv),
+			      CS42L56_MASTER_B_VOLUME, 0, 0x34, 0xE4, adv_tlv),
 	SOC_DOUBLE("Master Mute Switch", CS42L56_DSP_MUTE_CTL, 0, 1, 1, 1),
 
 	SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", CS42L56_ADCA_MIX_VOLUME,
-			      CS42L56_ADCB_MIX_VOLUME, 0, 0x88, 0xa9, hl_tlv),
+			      CS42L56_ADCB_MIX_VOLUME, 0, 0x88, 0x90, hl_tlv),
 	SOC_DOUBLE("ADC Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 6, 7, 1, 1),
 
 	SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", CS42L56_PCMA_MIX_VOLUME,
-			      CS42L56_PCMB_MIX_VOLUME, 0, 0x88, 0xa9, hl_tlv),
+			      CS42L56_PCMB_MIX_VOLUME, 0, 0x88, 0x90, hl_tlv),
 	SOC_DOUBLE("PCM Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 4, 5, 1, 1),
 
 	SOC_SINGLE_TLV("Analog Advisory Volume",
@@ -438,16 +446,16 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = {
 			  CS42L56_DIGINPUT_ADV_VOLUME, 0, 0x00, 1, adv_tlv),
 
 	SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L56_PGAA_MUX_VOLUME,
-			      CS42L56_PGAB_MUX_VOLUME, 0, 0x34, 0xfd, pga_tlv),
+			      CS42L56_PGAB_MUX_VOLUME, 0, 0x34, 0x24, pga_tlv),
 	SOC_DOUBLE_R_TLV("ADC Volume", CS42L56_ADCA_ATTENUATOR,
 			      CS42L56_ADCB_ATTENUATOR, 0, 0x00, 1, adc_tlv),
 	SOC_DOUBLE("ADC Mute Switch", CS42L56_MISC_ADC_CTL, 2, 3, 1, 1),
 	SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1),
 
 	SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME,
-			      CS42L56_HPA_VOLUME, 0, 0x44, 0x55, hl_tlv),
+			      CS42L56_HPB_VOLUME, 0, 0x84, 0x48, hl_tlv),
 	SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME,
-			      CS42L56_LOA_VOLUME, 0, 0x44, 0x55, hl_tlv),
+			      CS42L56_LOB_VOLUME, 0, 0x84, 0x48, hl_tlv),
 
 	SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL,
 			0, 0x00, 1, tone_tlv),
@@ -467,11 +475,6 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = {
 	SOC_SINGLE("ADCA Invert", CS42L56_MISC_ADC_CTL, 2, 1, 1),
 	SOC_SINGLE("ADCB Invert", CS42L56_MISC_ADC_CTL, 3, 1, 1),
 
-	SOC_ENUM("PCMA Swap", pcma_swap_enum),
-	SOC_ENUM("PCMB Swap", pcmb_swap_enum),
-	SOC_ENUM("ADCA Swap", adca_swap_enum),
-	SOC_ENUM("ADCB Swap", adcb_swap_enum),
-
 	SOC_DOUBLE("HPF Switch", CS42L56_HPF_CTL, 5, 7, 1, 1),
 	SOC_DOUBLE("HPF Freeze Switch", CS42L56_HPF_CTL, 4, 6, 1, 1),
 	SOC_ENUM("HPFA Corner Freq", hpfa_freq_enum),
@@ -570,6 +573,16 @@ static const struct snd_soc_dapm_widget cs42l56_dapm_widgets[] = {
 	SND_SOC_DAPM_ADC("ADCA", NULL, CS42L56_PWRCTL_1, 1, 1),
 	SND_SOC_DAPM_ADC("ADCB", NULL, CS42L56_PWRCTL_1, 2, 1),
 
+	SND_SOC_DAPM_MUX("ADCA Swap Mux", SND_SOC_NOPM, 0, 0,
+		&adca_swap_mux),
+	SND_SOC_DAPM_MUX("ADCB Swap Mux", SND_SOC_NOPM, 0, 0,
+		&adcb_swap_mux),
+
+	SND_SOC_DAPM_MUX("PCMA Swap Mux", SND_SOC_NOPM, 0, 0,
+		&pcma_swap_mux),
+	SND_SOC_DAPM_MUX("PCMB Swap Mux", SND_SOC_NOPM, 0, 0,
+		&pcmb_swap_mux),
+
 	SND_SOC_DAPM_DAC("DACA", NULL, SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_DAC("DACB", NULL, SND_SOC_NOPM, 0, 0),
 
@@ -607,8 +620,19 @@ static const struct snd_soc_dapm_route cs42l56_audio_map[] = {
 	{"Digital Output Mux", NULL, "ADCA"},
 	{"Digital Output Mux", NULL, "ADCB"},
 
-	{"ADCB", NULL, "ADCB Mux"},
-	{"ADCA", NULL, "ADCA Mux"},
+	{"ADCB", NULL, "ADCB Swap Mux"},
+	{"ADCA", NULL, "ADCA Swap Mux"},
+
+	{"ADCA Swap Mux", NULL, "ADCA"},
+	{"ADCB Swap Mux", NULL, "ADCB"},
+
+	{"DACA", "Left", "ADCA Swap Mux"},
+	{"DACA", "LR 2", "ADCA Swap Mux"},
+	{"DACA", "Right", "ADCA Swap Mux"},
+
+	{"DACB", "Left", "ADCB Swap Mux"},
+	{"DACB", "LR 2", "ADCB Swap Mux"},
+	{"DACB", "Right", "ADCB Swap Mux"},
 
 	{"ADCA Mux", NULL, "AIN3A"},
 	{"ADCA Mux", NULL, "AIN2A"},
@@ -633,30 +657,32 @@ static const struct snd_soc_dapm_route cs42l56_audio_map[] = {
 	{"PGAB Input Mux", NULL, "AIN2B"},
 	{"PGAB Input Mux", NULL, "AIN3B"},
 
-	{"LOB", NULL, "Lineout Right"},
-	{"LOA", NULL, "Lineout Left"},
-
-	{"Lineout Right", "Switch", "LINEOUTB Input Mux"},
-	{"Lineout Left", "Switch", "LINEOUTA Input Mux"},
+	{"LOB", "Switch", "LINEOUTB Input Mux"},
+	{"LOA", "Switch", "LINEOUTA Input Mux"},
 
 	{"LINEOUTA Input Mux", "PGAA", "PGAA"},
 	{"LINEOUTB Input Mux", "PGAB", "PGAB"},
 	{"LINEOUTA Input Mux", "DACA", "DACA"},
 	{"LINEOUTB Input Mux", "DACB", "DACB"},
 
-	{"HPA", NULL, "Headphone Left"},
-	{"HPB", NULL, "Headphone Right"},
-
-	{"Headphone Right", "Switch", "HPB Input Mux"},
-	{"Headphone Left", "Switch", "HPA Input Mux"},
+	{"HPA", "Switch", "HPB Input Mux"},
+	{"HPB", "Switch", "HPA Input Mux"},
 
 	{"HPA Input Mux", "PGAA", "PGAA"},
 	{"HPB Input Mux", "PGAB", "PGAB"},
 	{"HPA Input Mux", "DACA", "DACA"},
 	{"HPB Input Mux", "DACB", "DACB"},
 
-	{"DACB", NULL, "HiFi Playback"},
-	{"DACA", NULL, "HiFi Playback"},
+	{"DACA", NULL, "PCMA Swap Mux"},
+	{"DACB", NULL, "PCMB Swap Mux"},
+
+	{"PCMB Swap Mux", "Left", "HiFi Playback"},
+	{"PCMB Swap Mux", "LR 2", "HiFi Playback"},
+	{"PCMB Swap Mux", "Right", "HiFi Playback"},
+
+	{"PCMA Swap Mux", "Left", "HiFi Playback"},
+	{"PCMA Swap Mux", "LR 2", "HiFi Playback"},
+	{"PCMA Swap Mux", "Right", "HiFi Playback"},
 
 };
 
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index ae3717992d56..0e7b9eb2ba61 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -401,7 +401,7 @@ static const struct snd_kcontrol_new cs42l73_snd_controls[] = {
 			CS42L73_LOBAVOL, 0, 0x41, 0x4B, hpaloa_tlv),
 
 	SOC_DOUBLE_R_SX_TLV("Input PGA Analog Volume", CS42L73_MICAPREPGAAVOL,
-			CS42L73_MICBPREPGABVOL, 5, 0x34,
+			CS42L73_MICBPREPGABVOL, 0, 0x34,
 			0x24, micpga_tlv),
 
 	SOC_DOUBLE_R("MIC Preamp Switch", CS42L73_MICAPREPGAAVOL,
@@ -1408,10 +1408,8 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
 
 	cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private),
 			       GFP_KERNEL);
-	if (!cs42l73) {
-		dev_err(&i2c_client->dev, "could not allocate codec\n");
+	if (!cs42l73)
 		return -ENOMEM;
-	}
 
 	cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap);
 	if (IS_ERR(cs42l73->regmap)) {
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c
index a25bc6061a30..02b1520ae0bc 100644
--- a/sound/soc/codecs/cs42xx8.c
+++ b/sound/soc/codecs/cs42xx8.c
@@ -219,6 +219,9 @@ static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	case SND_SOC_DAIFMT_RIGHT_J:
 		val = CS42XX8_INTF_DAC_DIF_RIGHTJ | CS42XX8_INTF_ADC_DIF_RIGHTJ;
 		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		val = CS42XX8_INTF_DAC_DIF_TDM | CS42XX8_INTF_ADC_DIF_TDM;
+		break;
 	default:
 		dev_err(codec->dev, "unsupported dai format\n");
 		return -EINVAL;
@@ -422,7 +425,7 @@ const struct cs42xx8_driver_data cs42888_data = {
 };
 EXPORT_SYMBOL_GPL(cs42888_data);
 
-const struct of_device_id cs42xx8_of_match[] = {
+static const struct of_device_id cs42xx8_of_match[] = {
 	{ .compatible = "cirrus,cs42448", .data = &cs42448_data, },
 	{ .compatible = "cirrus,cs42888", .data = &cs42888_data, },
 	{ /* sentinel */ }
diff --git a/sound/soc/codecs/cs42xx8.h b/sound/soc/codecs/cs42xx8.h
index da0b94aee419..b2c10e537ef6 100644
--- a/sound/soc/codecs/cs42xx8.h
+++ b/sound/soc/codecs/cs42xx8.h
@@ -128,8 +128,8 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap);
 #define CS42XX8_INTF_DAC_DIF_RIGHTJ		(2 << CS42XX8_INTF_DAC_DIF_SHIFT)
 #define CS42XX8_INTF_DAC_DIF_RIGHTJ_16		(3 << CS42XX8_INTF_DAC_DIF_SHIFT)
 #define CS42XX8_INTF_DAC_DIF_ONELINE_20		(4 << CS42XX8_INTF_DAC_DIF_SHIFT)
-#define CS42XX8_INTF_DAC_DIF_ONELINE_24		(6 << CS42XX8_INTF_DAC_DIF_SHIFT)
-#define CS42XX8_INTF_DAC_DIF_TDM		(7 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_ONELINE_24		(5 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_TDM		(6 << CS42XX8_INTF_DAC_DIF_SHIFT)
 #define CS42XX8_INTF_ADC_DIF_SHIFT		0
 #define CS42XX8_INTF_ADC_DIF_WIDTH		3
 #define CS42XX8_INTF_ADC_DIF_MASK		(((1 << CS42XX8_INTF_ADC_DIF_WIDTH) - 1) << CS42XX8_INTF_ADC_DIF_SHIFT)
@@ -138,8 +138,8 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap);
 #define CS42XX8_INTF_ADC_DIF_RIGHTJ		(2 << CS42XX8_INTF_ADC_DIF_SHIFT)
 #define CS42XX8_INTF_ADC_DIF_RIGHTJ_16		(3 << CS42XX8_INTF_ADC_DIF_SHIFT)
 #define CS42XX8_INTF_ADC_DIF_ONELINE_20		(4 << CS42XX8_INTF_ADC_DIF_SHIFT)
-#define CS42XX8_INTF_ADC_DIF_ONELINE_24		(6 << CS42XX8_INTF_ADC_DIF_SHIFT)
-#define CS42XX8_INTF_ADC_DIF_TDM		(7 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_ONELINE_24		(5 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_TDM		(6 << CS42XX8_INTF_ADC_DIF_SHIFT)
 
 /* ADC Control & DAC De-Emphasis (Address 05h) */
 #define CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT	7
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index d5fd00a64748..8f95b0300f1a 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -253,7 +253,7 @@ static void v253_close(struct tty_struct *tty)
 	/* Prevent the codec driver from further accessing the modem */
 	codec->hw_write = NULL;
 	cx20442->control_data = NULL;
-	codec->card->pop_time = 0;
+	codec->component.card->pop_time = 0;
 }
 
 /* Line discipline .hangup() */
@@ -281,7 +281,7 @@ static void v253_receive(struct tty_struct *tty,
 		/* Set up codec driver access to modem controls */
 		cx20442->control_data = tty;
 		codec->hw_write = (hw_write_t)tty->ops->write;
-		codec->card->pop_time = 1;
+		codec->component.card->pop_time = 1;
 	}
 }
 
@@ -372,7 +372,7 @@ static int cx20442_codec_probe(struct snd_soc_codec *codec)
 
 	snd_soc_codec_set_drvdata(codec, cx20442);
 	codec->hw_write = NULL;
-	codec->card->pop_time = 0;
+	codec->component.card->pop_time = 0;
 
 	return 0;
 }
@@ -383,8 +383,8 @@ static int cx20442_codec_remove(struct snd_soc_codec *codec)
 	struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
 
 	if (cx20442->control_data) {
-			struct tty_struct *tty = cx20442->control_data;
-			tty_hangup(tty);
+		struct tty_struct *tty = cx20442->control_data;
+		tty_hangup(tty);
 	}
 
 	if (!IS_ERR(cx20442->por)) {
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 9134982807b5..2cd3e5427441 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -1299,12 +1299,12 @@ static int max98088_dai2_hw_params(struct snd_pcm_substream *substream,
 
        rate = params_rate(params);
 
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT,
                        M98088_DAI_WS, 0);
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT,
                        M98088_DAI_WS, M98088_DAI_WS);
                break;
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index f5fccc7a8e89..4a063fa88526 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -26,10 +26,6 @@
 #include <sound/max98090.h>
 #include "max98090.h"
 
-#define DEBUG
-#define EXTMIC_METHOD
-#define EXTMIC_METHOD_TEST
-
 /* Allows for sparsely populated register maps */
 static struct reg_default max98090_reg[] = {
 	{ 0x00, 0x00 }, /* 00 Software Reset */
@@ -820,7 +816,6 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w,
 	else
 		val = (val & M98090_MIC_PA2EN_MASK) >> M98090_MIC_PA2EN_SHIFT;
 
-
 	if (val >= 1) {
 		if (w->reg == M98090_REG_MIC1_INPUT_LEVEL) {
 			max98090->pa1en = val - 1; /* Update for volatile */
@@ -1140,7 +1135,6 @@ static const struct snd_kcontrol_new max98090_mixhprsel_mux =
 	SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum);
 
 static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
-
 	SND_SOC_DAPM_INPUT("MIC1"),
 	SND_SOC_DAPM_INPUT("MIC2"),
 	SND_SOC_DAPM_INPUT("DMICL"),
@@ -1304,7 +1298,6 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
 };
 
 static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
-
 	SND_SOC_DAPM_INPUT("DMIC3"),
 	SND_SOC_DAPM_INPUT("DMIC4"),
 
@@ -1315,7 +1308,6 @@ static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
 };
 
 static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
-
 	{"MIC1 Input", NULL, "MIC1"},
 	{"MIC2 Input", NULL, "MIC2"},
 
@@ -1493,17 +1485,14 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
 	{"SPKR", NULL, "SPK Right Out"},
 	{"RCVL", NULL, "RCV Left Out"},
 	{"RCVR", NULL, "RCV Right Out"},
-
 };
 
 static const struct snd_soc_dapm_route max98091_dapm_routes[] = {
-
 	/* DMIC inputs */
 	{"DMIC3", NULL, "DMIC3_ENA"},
 	{"DMIC4", NULL, "DMIC4_ENA"},
 	{"DMIC3", NULL, "AHPF"},
 	{"DMIC4", NULL, "AHPF"},
-
 };
 
 static int max98090_add_widgets(struct snd_soc_codec *codec)
@@ -1531,7 +1520,6 @@ static int max98090_add_widgets(struct snd_soc_codec *codec)
 
 		snd_soc_dapm_add_routes(dapm, max98091_dapm_routes,
 			ARRAY_SIZE(max98091_dapm_routes));
-
 	}
 
 	return 0;
@@ -2212,22 +2200,11 @@ static struct snd_soc_dai_driver max98090_dai[] = {
 }
 };
 
-static void max98090_handle_pdata(struct snd_soc_codec *codec)
-{
-	struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
-	struct max98090_pdata *pdata = max98090->pdata;
-
-	if (!pdata) {
-		dev_err(codec->dev, "No platform data\n");
-		return;
-	}
-
-}
-
 static int max98090_probe(struct snd_soc_codec *codec)
 {
 	struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
 	struct max98090_cdata *cdata;
+	enum max98090_type devtype;
 	int ret = 0;
 
 	dev_dbg(codec->dev, "max98090_probe\n");
@@ -2263,16 +2240,21 @@ static int max98090_probe(struct snd_soc_codec *codec)
 	}
 
 	if ((ret >= M98090_REVA) && (ret <= M98090_REVA + 0x0f)) {
-		max98090->devtype = MAX98090;
+		devtype = MAX98090;
 		dev_info(codec->dev, "MAX98090 REVID=0x%02x\n", ret);
 	} else if ((ret >= M98091_REVA) && (ret <= M98091_REVA + 0x0f)) {
-		max98090->devtype = MAX98091;
+		devtype = MAX98091;
 		dev_info(codec->dev, "MAX98091 REVID=0x%02x\n", ret);
 	} else {
-		max98090->devtype = MAX98090;
+		devtype = MAX98090;
 		dev_err(codec->dev, "Unrecognized revision 0x%02x\n", ret);
 	}
 
+	if (max98090->devtype != devtype) {
+		dev_warn(codec->dev, "Mismatch in DT specified CODEC type.\n");
+		max98090->devtype = devtype;
+	}
+
 	max98090->jack_state = M98090_JACK_STATE_NO_HEADSET;
 
 	INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work);
@@ -2284,7 +2266,7 @@ static int max98090_probe(struct snd_soc_codec *codec)
 	/* Register for interrupts */
 	dev_dbg(codec->dev, "irq = %d\n", max98090->irq);
 
-	ret = request_threaded_irq(max98090->irq, NULL,
+	ret = devm_request_threaded_irq(codec->dev, max98090->irq, NULL,
 		max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 		"max98090_interrupt", codec);
 	if (ret < 0) {
@@ -2317,8 +2299,6 @@ static int max98090_probe(struct snd_soc_codec *codec)
 	snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE,
 		M98090_MBVSEL_MASK, M98090_MBVSEL_2V8);
 
-	max98090_handle_pdata(codec);
-
 	max98090_add_widgets(codec);
 
 err_access:
@@ -2428,7 +2408,7 @@ static int max98090_runtime_suspend(struct device *dev)
 }
 #endif
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int max98090_resume(struct device *dev)
 {
 	struct max98090_priv *max98090 = dev_get_drvdata(dev);
@@ -2460,12 +2440,14 @@ static const struct dev_pm_ops max98090_pm = {
 
 static const struct i2c_device_id max98090_i2c_id[] = {
 	{ "max98090", MAX98090 },
+	{ "max98091", MAX98091 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, max98090_i2c_id);
 
 static const struct of_device_id max98090_of_match[] = {
 	{ .compatible = "maxim,max98090", },
+	{ .compatible = "maxim,max98091", },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, max98090_of_match);
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 89ec00424880..0ee6797d5083 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -1280,12 +1280,12 @@ static int max98095_dai2_hw_params(struct snd_pcm_substream *substream,
 
 	rate = params_rate(params);
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT,
 			M98095_DAI_WS, 0);
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT,
 			M98095_DAI_WS, M98095_DAI_WS);
 		break;
@@ -1341,12 +1341,12 @@ static int max98095_dai3_hw_params(struct snd_pcm_substream *substream,
 
 	rate = params_rate(params);
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT,
 			M98095_DAI_WS, 0);
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT,
 			M98095_DAI_WS, M98095_DAI_WS);
 		break;
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index 9965277b595a..388f90a597fa 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -766,11 +766,11 @@ static int __init mc13783_codec_probe(struct platform_device *pdev)
 
 		ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port);
 		if (ret)
-			return ret;
+			goto out;
 
 		ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port);
 		if (ret)
-			return ret;
+			goto out;
 	}
 
 	dev_set_drvdata(&pdev->dev, priv);
@@ -783,6 +783,8 @@ static int __init mc13783_codec_probe(struct platform_device *pdev)
 		ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783,
 			mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async));
 
+out:
+	of_node_put(np);
 	return ret;
 }
 
diff --git a/sound/soc/codecs/pcm1792a.c b/sound/soc/codecs/pcm1792a.c
index 3a80ba4452df..57b0c94a710b 100644
--- a/sound/soc/codecs/pcm1792a.c
+++ b/sound/soc/codecs/pcm1792a.c
@@ -36,6 +36,7 @@
 #define PCM1792A_DAC_VOL_LEFT	0x10
 #define PCM1792A_DAC_VOL_RIGHT	0x11
 #define PCM1792A_FMT_CONTROL	0x12
+#define PCM1792A_MODE_CONTROL	0x13
 #define PCM1792A_SOFT_MUTE	PCM1792A_FMT_CONTROL
 
 #define PCM1792A_FMT_MASK	0x70
@@ -164,6 +165,8 @@ static const struct snd_kcontrol_new pcm1792a_controls[] = {
 	SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM1792A_DAC_VOL_LEFT,
 			 PCM1792A_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0,
 			 pcm1792a_dac_tlv),
+	SOC_SINGLE("DAC Invert Output Switch", PCM1792A_MODE_CONTROL, 7, 1, 0),
+	SOC_SINGLE("DAC Rolloff Filter Switch", PCM1792A_MODE_CONTROL, 1, 1, 0),
 };
 
 static const struct snd_soc_dapm_widget pcm1792a_dapm_widgets[] = {
diff --git a/sound/soc/codecs/pcm1792a.h b/sound/soc/codecs/pcm1792a.h
index 7a83d1fc102a..51d5470fee16 100644
--- a/sound/soc/codecs/pcm1792a.h
+++ b/sound/soc/codecs/pcm1792a.h
@@ -18,7 +18,8 @@
 #define __PCM1792A_H__
 
 #define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \
-			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+			SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
+			SNDRV_PCM_RATE_192000)
 
 #define PCM1792A_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \
 			  SNDRV_PCM_FMTBIT_S16_LE)
diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c
index 7b82fbe0d14c..56650d6c2f53 100644
--- a/sound/soc/codecs/rl6231.c
+++ b/sound/soc/codecs/rl6231.c
@@ -11,25 +11,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/regmap.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/acpi.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <sound/initval.h>
-#include <sound/tlv.h>
 
 #include "rl6231.h"
 
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
new file mode 100644
index 000000000000..e4f6102efc1a
--- /dev/null
+++ b/sound/soc/codecs/rt286.c
@@ -0,0 +1,1222 @@
+/*
+ * rt286.c  --  RT286 ALSA SoC audio codec driver
+ *
+ * Copyright 2013 Realtek Semiconductor Corp.
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/acpi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/jack.h>
+#include <linux/workqueue.h>
+#include <sound/rt286.h>
+#include <sound/hda_verbs.h>
+
+#include "rt286.h"
+
+#define RT286_VENDOR_ID 0x10ec0286
+
+struct rt286_priv {
+	struct regmap *regmap;
+	struct rt286_platform_data pdata;
+	struct i2c_client *i2c;
+	struct snd_soc_jack *jack;
+	struct delayed_work jack_detect_work;
+	int sys_clk;
+	struct reg_default *index_cache;
+};
+
+static struct reg_default rt286_index_def[] = {
+	{ 0x01, 0xaaaa },
+	{ 0x02, 0x8aaa },
+	{ 0x03, 0x0002 },
+	{ 0x04, 0xaf01 },
+	{ 0x08, 0x000d },
+	{ 0x09, 0xd810 },
+	{ 0x0a, 0x0060 },
+	{ 0x0b, 0x0000 },
+	{ 0x0d, 0x2800 },
+	{ 0x0f, 0x0000 },
+	{ 0x19, 0x0a17 },
+	{ 0x20, 0x0020 },
+	{ 0x33, 0x0208 },
+	{ 0x49, 0x0004 },
+	{ 0x4f, 0x50e9 },
+	{ 0x50, 0x2c00 },
+	{ 0x63, 0x2902 },
+	{ 0x67, 0x1111 },
+	{ 0x68, 0x1016 },
+	{ 0x69, 0x273f },
+};
+#define INDEX_CACHE_SIZE ARRAY_SIZE(rt286_index_def)
+
+static const struct reg_default rt286_reg[] = {
+	{ 0x00170500, 0x00000400 },
+	{ 0x00220000, 0x00000031 },
+	{ 0x00239000, 0x0000007f },
+	{ 0x0023a000, 0x0000007f },
+	{ 0x00270500, 0x00000400 },
+	{ 0x00370500, 0x00000400 },
+	{ 0x00870500, 0x00000400 },
+	{ 0x00920000, 0x00000031 },
+	{ 0x00935000, 0x000000c3 },
+	{ 0x00936000, 0x000000c3 },
+	{ 0x00970500, 0x00000400 },
+	{ 0x00b37000, 0x00000097 },
+	{ 0x00b37200, 0x00000097 },
+	{ 0x00b37300, 0x00000097 },
+	{ 0x00c37000, 0x00000000 },
+	{ 0x00c37100, 0x00000080 },
+	{ 0x01270500, 0x00000400 },
+	{ 0x01370500, 0x00000400 },
+	{ 0x01371f00, 0x411111f0 },
+	{ 0x01439000, 0x00000080 },
+	{ 0x0143a000, 0x00000080 },
+	{ 0x01470700, 0x00000000 },
+	{ 0x01470500, 0x00000400 },
+	{ 0x01470c00, 0x00000000 },
+	{ 0x01470100, 0x00000000 },
+	{ 0x01837000, 0x00000000 },
+	{ 0x01870500, 0x00000400 },
+	{ 0x02050000, 0x00000000 },
+	{ 0x02139000, 0x00000080 },
+	{ 0x0213a000, 0x00000080 },
+	{ 0x02170100, 0x00000000 },
+	{ 0x02170500, 0x00000400 },
+	{ 0x02170700, 0x00000000 },
+	{ 0x02270100, 0x00000000 },
+	{ 0x02370100, 0x00000000 },
+	{ 0x02040000, 0x00004002 },
+	{ 0x01870700, 0x00000020 },
+	{ 0x00830000, 0x000000c3 },
+	{ 0x00930000, 0x000000c3 },
+	{ 0x01270700, 0x00000000 },
+};
+
+static bool rt286_volatile_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case 0 ... 0xff:
+	case RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID):
+	case RT286_GET_HP_SENSE:
+	case RT286_GET_MIC1_SENSE:
+	case RT286_PROC_COEF:
+		return true;
+	default:
+		return false;
+	}
+
+
+}
+
+static bool rt286_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case 0 ... 0xff:
+	case RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID):
+	case RT286_GET_HP_SENSE:
+	case RT286_GET_MIC1_SENSE:
+	case RT286_SET_AUDIO_POWER:
+	case RT286_SET_HPO_POWER:
+	case RT286_SET_SPK_POWER:
+	case RT286_SET_DMIC1_POWER:
+	case RT286_SPK_MUX:
+	case RT286_HPO_MUX:
+	case RT286_ADC0_MUX:
+	case RT286_ADC1_MUX:
+	case RT286_SET_MIC1:
+	case RT286_SET_PIN_HPO:
+	case RT286_SET_PIN_SPK:
+	case RT286_SET_PIN_DMIC1:
+	case RT286_SPK_EAPD:
+	case RT286_SET_AMP_GAIN_HPO:
+	case RT286_SET_DMIC2_DEFAULT:
+	case RT286_DACL_GAIN:
+	case RT286_DACR_GAIN:
+	case RT286_ADCL_GAIN:
+	case RT286_ADCR_GAIN:
+	case RT286_MIC_GAIN:
+	case RT286_SPOL_GAIN:
+	case RT286_SPOR_GAIN:
+	case RT286_HPOL_GAIN:
+	case RT286_HPOR_GAIN:
+	case RT286_F_DAC_SWITCH:
+	case RT286_F_RECMIX_SWITCH:
+	case RT286_REC_MIC_SWITCH:
+	case RT286_REC_I2S_SWITCH:
+	case RT286_REC_LINE_SWITCH:
+	case RT286_REC_BEEP_SWITCH:
+	case RT286_DAC_FORMAT:
+	case RT286_ADC_FORMAT:
+	case RT286_COEF_INDEX:
+	case RT286_PROC_COEF:
+	case RT286_SET_AMP_GAIN_ADC_IN1:
+	case RT286_SET_AMP_GAIN_ADC_IN2:
+	case RT286_SET_POWER(RT286_DAC_OUT1):
+	case RT286_SET_POWER(RT286_DAC_OUT2):
+	case RT286_SET_POWER(RT286_ADC_IN1):
+	case RT286_SET_POWER(RT286_ADC_IN2):
+	case RT286_SET_POWER(RT286_DMIC2):
+	case RT286_SET_POWER(RT286_MIC1):
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int rt286_hw_write(void *context, unsigned int reg, unsigned int value)
+{
+	struct i2c_client *client = context;
+	struct rt286_priv *rt286 = i2c_get_clientdata(client);
+	u8 data[4];
+	int ret, i;
+
+	/*handle index registers*/
+	if (reg <= 0xff) {
+		rt286_hw_write(client, RT286_COEF_INDEX, reg);
+		reg = RT286_PROC_COEF;
+		for (i = 0; i < INDEX_CACHE_SIZE; i++) {
+			if (reg == rt286->index_cache[i].reg) {
+				rt286->index_cache[i].def = value;
+				break;
+			}
+
+		}
+	}
+
+	data[0] = (reg >> 24) & 0xff;
+	data[1] = (reg >> 16) & 0xff;
+	/*
+	 * 4 bit VID: reg should be 0
+	 * 12 bit VID: value should be 0
+	 * So we use an OR operator to handle it rather than use if condition.
+	 */
+	data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff);
+	data[3] = value & 0xff;
+
+	ret = i2c_master_send(client, data, 4);
+
+	if (ret == 4)
+		return 0;
+	else
+		pr_err("ret=%d\n", ret);
+	if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static int rt286_hw_read(void *context, unsigned int reg, unsigned int *value)
+{
+	struct i2c_client *client = context;
+	struct i2c_msg xfer[2];
+	int ret;
+	__be32 be_reg;
+	unsigned int index, vid, buf = 0x0;
+
+	/*handle index registers*/
+	if (reg <= 0xff) {
+		rt286_hw_write(client, RT286_COEF_INDEX, reg);
+		reg = RT286_PROC_COEF;
+	}
+
+	reg = reg | 0x80000;
+	vid = (reg >> 8) & 0xfff;
+
+	if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) {
+		index = (reg >> 8) & 0xf;
+		reg = (reg & ~0xf0f) | index;
+	}
+	be_reg = cpu_to_be32(reg);
+
+	/* Write register */
+	xfer[0].addr = client->addr;
+	xfer[0].flags = 0;
+	xfer[0].len = 4;
+	xfer[0].buf = (u8 *)&be_reg;
+
+	/* Read data */
+	xfer[1].addr = client->addr;
+	xfer[1].flags = I2C_M_RD;
+	xfer[1].len = 4;
+	xfer[1].buf = (u8 *)&buf;
+
+	ret = i2c_transfer(client->adapter, xfer, 2);
+	if (ret < 0)
+		return ret;
+	else if (ret != 2)
+		return -EIO;
+
+	*value = be32_to_cpu(buf);
+
+	return 0;
+}
+
+static void rt286_index_sync(struct snd_soc_codec *codec)
+{
+	struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
+	int i;
+
+	for (i = 0; i < INDEX_CACHE_SIZE; i++) {
+		snd_soc_write(codec, rt286->index_cache[i].reg,
+				  rt286->index_cache[i].def);
+	}
+}
+
+static int rt286_support_power_controls[] = {
+	RT286_DAC_OUT1,
+	RT286_DAC_OUT2,
+	RT286_ADC_IN1,
+	RT286_ADC_IN2,
+	RT286_MIC1,
+	RT286_DMIC1,
+	RT286_DMIC2,
+	RT286_SPK_OUT,
+	RT286_HP_OUT,
+};
+#define RT286_POWER_REG_LEN ARRAY_SIZE(rt286_support_power_controls)
+
+static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic)
+{
+	unsigned int val, buf;
+	int i;
+
+	*hp = false;
+	*mic = false;
+
+	if (rt286->pdata.cbj_en) {
+		regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf);
+		*hp = buf & 0x80000000;
+		if (*hp) {
+			/* power on HV,VERF */
+			regmap_update_bits(rt286->regmap,
+				RT286_POWER_CTRL1, 0x1001, 0x0);
+			/* power LDO1 */
+			regmap_update_bits(rt286->regmap,
+				RT286_POWER_CTRL2, 0x4, 0x4);
+			regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24);
+			regmap_read(rt286->regmap, RT286_CBJ_CTRL2, &val);
+
+			msleep(200);
+			i = 40;
+			while (((val & 0x0800) == 0) && (i > 0)) {
+				regmap_read(rt286->regmap,
+					RT286_CBJ_CTRL2, &val);
+				i--;
+				msleep(20);
+			}
+
+			if (0x0400 == (val & 0x0700)) {
+				*mic = false;
+
+				regmap_write(rt286->regmap,
+					RT286_SET_MIC1, 0x20);
+				/* power off HV,VERF */
+				regmap_update_bits(rt286->regmap,
+					RT286_POWER_CTRL1, 0x1001, 0x1001);
+				regmap_update_bits(rt286->regmap,
+					RT286_A_BIAS_CTRL3, 0xc000, 0x0000);
+				regmap_update_bits(rt286->regmap,
+					RT286_CBJ_CTRL1, 0x0030, 0x0000);
+				regmap_update_bits(rt286->regmap,
+					RT286_A_BIAS_CTRL2, 0xc000, 0x0000);
+			} else if ((0x0200 == (val & 0x0700)) ||
+				(0x0100 == (val & 0x0700))) {
+				*mic = true;
+				regmap_update_bits(rt286->regmap,
+					RT286_A_BIAS_CTRL3, 0xc000, 0x8000);
+				regmap_update_bits(rt286->regmap,
+					RT286_CBJ_CTRL1, 0x0030, 0x0020);
+				regmap_update_bits(rt286->regmap,
+					RT286_A_BIAS_CTRL2, 0xc000, 0x8000);
+			} else {
+				*mic = false;
+			}
+
+			regmap_update_bits(rt286->regmap,
+						RT286_MISC_CTRL1,
+						0x0060, 0x0000);
+		} else {
+			regmap_update_bits(rt286->regmap,
+						RT286_MISC_CTRL1,
+						0x0060, 0x0020);
+			regmap_update_bits(rt286->regmap,
+						RT286_A_BIAS_CTRL3,
+						0xc000, 0x8000);
+			regmap_update_bits(rt286->regmap,
+						RT286_CBJ_CTRL1,
+						0x0030, 0x0020);
+			regmap_update_bits(rt286->regmap,
+						RT286_A_BIAS_CTRL2,
+						0xc000, 0x8000);
+
+			*mic = false;
+		}
+	} else {
+		regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf);
+		*hp = buf & 0x80000000;
+		regmap_read(rt286->regmap, RT286_GET_MIC1_SENSE, &buf);
+		*mic = buf & 0x80000000;
+	}
+
+	return 0;
+}
+
+static void rt286_jack_detect_work(struct work_struct *work)
+{
+	struct rt286_priv *rt286 =
+		container_of(work, struct rt286_priv, jack_detect_work.work);
+	int status = 0;
+	bool hp = false;
+	bool mic = false;
+
+	rt286_jack_detect(rt286, &hp, &mic);
+
+	if (hp == true)
+		status |= SND_JACK_HEADPHONE;
+
+	if (mic == true)
+		status |= SND_JACK_MICROPHONE;
+
+	snd_soc_jack_report(rt286->jack, status,
+		SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
+}
+
+int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
+{
+	struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
+
+	rt286->jack = jack;
+
+	/* Send an initial empty report */
+	snd_soc_jack_report(rt286->jack, 0,
+		SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt286_mic_detect);
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0);
+static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
+
+static const struct snd_kcontrol_new rt286_snd_controls[] = {
+	SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT286_DACL_GAIN,
+			    RT286_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv),
+	SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT286_ADCL_GAIN,
+			    RT286_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv),
+	SOC_SINGLE_TLV("AMIC Volume", RT286_MIC_GAIN,
+			    0, 0x3, 0, mic_vol_tlv),
+	SOC_DOUBLE_R("Speaker Playback Switch", RT286_SPOL_GAIN,
+			    RT286_SPOR_GAIN, RT286_MUTE_SFT, 1, 1),
+};
+
+/* Digital Mixer */
+static const struct snd_kcontrol_new rt286_front_mix[] = {
+	SOC_DAPM_SINGLE("DAC Switch",  RT286_F_DAC_SWITCH,
+			RT286_MUTE_SFT, 1, 1),
+	SOC_DAPM_SINGLE("RECMIX Switch", RT286_F_RECMIX_SWITCH,
+			RT286_MUTE_SFT, 1, 1),
+};
+
+/* Analog Input Mixer */
+static const struct snd_kcontrol_new rt286_rec_mix[] = {
+	SOC_DAPM_SINGLE("Mic1 Switch", RT286_REC_MIC_SWITCH,
+			RT286_MUTE_SFT, 1, 1),
+	SOC_DAPM_SINGLE("I2S Switch", RT286_REC_I2S_SWITCH,
+			RT286_MUTE_SFT, 1, 1),
+	SOC_DAPM_SINGLE("Line1 Switch", RT286_REC_LINE_SWITCH,
+			RT286_MUTE_SFT, 1, 1),
+	SOC_DAPM_SINGLE("Beep Switch", RT286_REC_BEEP_SWITCH,
+			RT286_MUTE_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new spo_enable_control =
+	SOC_DAPM_SINGLE("Switch", RT286_SET_PIN_SPK,
+			RT286_SET_PIN_SFT, 1, 0);
+
+static const struct snd_kcontrol_new hpol_enable_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT286_HPOL_GAIN,
+			RT286_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hpor_enable_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT286_HPOR_GAIN,
+			RT286_MUTE_SFT, 1, 1);
+
+/* ADC0 source */
+static const char * const rt286_adc_src[] = {
+	"Mic", "RECMIX", "Dmic"
+};
+
+static const int rt286_adc_values[] = {
+	0, 4, 5,
+};
+
+static SOC_VALUE_ENUM_SINGLE_DECL(
+	rt286_adc0_enum, RT286_ADC0_MUX, RT286_ADC_SEL_SFT,
+	RT286_ADC_SEL_MASK, rt286_adc_src, rt286_adc_values);
+
+static const struct snd_kcontrol_new rt286_adc0_mux =
+	SOC_DAPM_ENUM("ADC 0 source", rt286_adc0_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(
+	rt286_adc1_enum, RT286_ADC1_MUX, RT286_ADC_SEL_SFT,
+	RT286_ADC_SEL_MASK, rt286_adc_src, rt286_adc_values);
+
+static const struct snd_kcontrol_new rt286_adc1_mux =
+	SOC_DAPM_ENUM("ADC 1 source", rt286_adc1_enum);
+
+static const char * const rt286_dac_src[] = {
+	"Front", "Surround"
+};
+/* HP-OUT source */
+static SOC_ENUM_SINGLE_DECL(rt286_hpo_enum, RT286_HPO_MUX,
+				0, rt286_dac_src);
+
+static const struct snd_kcontrol_new rt286_hpo_mux =
+SOC_DAPM_ENUM("HPO source", rt286_hpo_enum);
+
+/* SPK-OUT source */
+static SOC_ENUM_SINGLE_DECL(rt286_spo_enum, RT286_SPK_MUX,
+				0, rt286_dac_src);
+
+static const struct snd_kcontrol_new rt286_spo_mux =
+SOC_DAPM_ENUM("SPO source", rt286_spo_enum);
+
+static int rt286_spk_event(struct snd_soc_dapm_widget *w,
+			    struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_write(codec,
+			RT286_SPK_EAPD, RT286_SET_EAPD_HIGH);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_write(codec,
+			RT286_SPK_EAPD, RT286_SET_EAPD_LOW);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w,
+				  struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_write(codec, RT286_SET_PIN_DMIC1, 0x20);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_write(codec, RT286_SET_PIN_DMIC1, 0);
+		break;
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt286_adc_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	unsigned int nid;
+
+	nid = (w->reg >> 20) & 0xff;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec,
+			VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0),
+			0x7080, 0x7000);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec,
+			VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0),
+			0x7080, 0x7080);
+		break;
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = {
+	/* Input Lines */
+	SND_SOC_DAPM_INPUT("DMIC1 Pin"),
+	SND_SOC_DAPM_INPUT("DMIC2 Pin"),
+	SND_SOC_DAPM_INPUT("MIC1"),
+	SND_SOC_DAPM_INPUT("LINE1"),
+	SND_SOC_DAPM_INPUT("Beep"),
+
+	/* DMIC */
+	SND_SOC_DAPM_PGA_E("DMIC1", RT286_SET_POWER(RT286_DMIC1), 0, 1,
+		NULL, 0, rt286_set_dmic1_event,
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_PGA("DMIC2", RT286_SET_POWER(RT286_DMIC2), 0, 1,
+		NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DMIC Receiver", SND_SOC_NOPM,
+		0, 0, NULL, 0),
+
+	/* REC Mixer */
+	SND_SOC_DAPM_MIXER("RECMIX", SND_SOC_NOPM, 0, 0,
+		rt286_rec_mix, ARRAY_SIZE(rt286_rec_mix)),
+
+	/* ADCs */
+	SND_SOC_DAPM_ADC("ADC 0", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0),
+
+	/* ADC Mux */
+	SND_SOC_DAPM_MUX_E("ADC 0 Mux", RT286_SET_POWER(RT286_ADC_IN1), 0, 1,
+		&rt286_adc0_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_MUX_E("ADC 1 Mux", RT286_SET_POWER(RT286_ADC_IN2), 0, 1,
+		&rt286_adc1_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_POST_PMU),
+
+	/* Audio Interface */
+	SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+
+	/* Output Side */
+	/* DACs */
+	SND_SOC_DAPM_DAC("DAC 0", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_DAC("DAC 1", NULL, SND_SOC_NOPM, 0, 0),
+
+	/* Output Mux */
+	SND_SOC_DAPM_MUX("SPK Mux", SND_SOC_NOPM, 0, 0, &rt286_spo_mux),
+	SND_SOC_DAPM_MUX("HPO Mux", SND_SOC_NOPM, 0, 0, &rt286_hpo_mux),
+
+	SND_SOC_DAPM_SUPPLY("HP Power", RT286_SET_PIN_HPO,
+		RT286_SET_PIN_SFT, 0, NULL, 0),
+
+	/* Output Mixer */
+	SND_SOC_DAPM_MIXER("Front", RT286_SET_POWER(RT286_DAC_OUT1), 0, 1,
+			rt286_front_mix, ARRAY_SIZE(rt286_front_mix)),
+	SND_SOC_DAPM_PGA("Surround", RT286_SET_POWER(RT286_DAC_OUT2), 0, 1,
+			NULL, 0),
+
+	/* Output Pga */
+	SND_SOC_DAPM_SWITCH_E("SPO", SND_SOC_NOPM, 0, 0,
+		&spo_enable_control, rt286_spk_event,
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_SWITCH("HPO L", SND_SOC_NOPM, 0, 0,
+		&hpol_enable_control),
+	SND_SOC_DAPM_SWITCH("HPO R", SND_SOC_NOPM, 0, 0,
+		&hpor_enable_control),
+
+	/* Output Lines */
+	SND_SOC_DAPM_OUTPUT("SPOL"),
+	SND_SOC_DAPM_OUTPUT("SPOR"),
+	SND_SOC_DAPM_OUTPUT("HPO Pin"),
+	SND_SOC_DAPM_OUTPUT("SPDIF"),
+};
+
+static const struct snd_soc_dapm_route rt286_dapm_routes[] = {
+	{"DMIC1", NULL, "DMIC1 Pin"},
+	{"DMIC2", NULL, "DMIC2 Pin"},
+	{"DMIC1", NULL, "DMIC Receiver"},
+	{"DMIC2", NULL, "DMIC Receiver"},
+
+	{"RECMIX", "Beep Switch", "Beep"},
+	{"RECMIX", "Line1 Switch", "LINE1"},
+	{"RECMIX", "Mic1 Switch", "MIC1"},
+
+	{"ADC 0 Mux", "Dmic", "DMIC1"},
+	{"ADC 0 Mux", "RECMIX", "RECMIX"},
+	{"ADC 0 Mux", "Mic", "MIC1"},
+	{"ADC 1 Mux", "Dmic", "DMIC2"},
+	{"ADC 1 Mux", "RECMIX", "RECMIX"},
+	{"ADC 1 Mux", "Mic", "MIC1"},
+
+	{"ADC 0", NULL, "ADC 0 Mux"},
+	{"ADC 1", NULL, "ADC 1 Mux"},
+
+	{"AIF1TX", NULL, "ADC 0"},
+	{"AIF2TX", NULL, "ADC 1"},
+
+	{"DAC 0", NULL, "AIF1RX"},
+	{"DAC 1", NULL, "AIF2RX"},
+
+	{"Front", "DAC Switch", "DAC 0"},
+	{"Front", "RECMIX Switch", "RECMIX"},
+
+	{"Surround", NULL, "DAC 1"},
+
+	{"SPK Mux", "Front", "Front"},
+	{"SPK Mux", "Surround", "Surround"},
+
+	{"HPO Mux", "Front", "Front"},
+	{"HPO Mux", "Surround", "Surround"},
+
+	{"SPO", "Switch", "SPK Mux"},
+	{"HPO L", "Switch", "HPO Mux"},
+	{"HPO R", "Switch", "HPO Mux"},
+	{"HPO L", NULL, "HP Power"},
+	{"HPO R", NULL, "HP Power"},
+
+	{"SPOL", NULL, "SPO"},
+	{"SPOR", NULL, "SPO"},
+	{"HPO Pin", NULL, "HPO L"},
+	{"HPO Pin", NULL, "HPO R"},
+};
+
+static int rt286_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
+	unsigned int val = 0;
+	int d_len_code;
+
+	switch (params_rate(params)) {
+	/* bit 14 0:48K 1:44.1K */
+	case 44100:
+		val |= 0x4000;
+		break;
+	case 48000:
+		break;
+	default:
+		dev_err(codec->dev, "Unsupported sample rate %d\n",
+					params_rate(params));
+		return -EINVAL;
+	}
+	switch (rt286->sys_clk) {
+	case 12288000:
+	case 24576000:
+		if (params_rate(params) != 48000) {
+			dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n",
+					params_rate(params), rt286->sys_clk);
+			return -EINVAL;
+		}
+		break;
+	case 11289600:
+	case 22579200:
+		if (params_rate(params) != 44100) {
+			dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n",
+					params_rate(params), rt286->sys_clk);
+			return -EINVAL;
+		}
+		break;
+	}
+
+	if (params_channels(params) <= 16) {
+		/* bit 3:0 Number of Channel */
+		val |= (params_channels(params) - 1);
+	} else {
+		dev_err(codec->dev, "Unsupported channels %d\n",
+					params_channels(params));
+		return -EINVAL;
+	}
+
+	d_len_code = 0;
+	switch (params_width(params)) {
+	/* bit 6:4 Bits per Sample */
+	case 16:
+		d_len_code = 0;
+		val |= (0x1 << 4);
+		break;
+	case 32:
+		d_len_code = 2;
+		val |= (0x4 << 4);
+		break;
+	case 20:
+		d_len_code = 1;
+		val |= (0x2 << 4);
+		break;
+	case 24:
+		d_len_code = 2;
+		val |= (0x3 << 4);
+		break;
+	case 8:
+		d_len_code = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec,
+		RT286_I2S_CTRL1, 0x0018, d_len_code << 3);
+	dev_dbg(codec->dev, "format val = 0x%x\n", val);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		snd_soc_update_bits(codec, RT286_DAC_FORMAT, 0x407f, val);
+	else
+		snd_soc_update_bits(codec, RT286_ADC_FORMAT, 0x407f, val);
+
+	return 0;
+}
+
+static int rt286_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = dai->codec;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL1, 0x800, 0x800);
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL1, 0x800, 0x0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL1, 0x300, 0x0);
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL1, 0x300, 0x1 << 8);
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL1, 0x300, 0x2 << 8);
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL1, 0x300, 0x3 << 8);
+		break;
+	default:
+		return -EINVAL;
+	}
+	/* bit 15 Stream Type 0:PCM 1:Non-PCM */
+	snd_soc_update_bits(codec, RT286_DAC_FORMAT, 0x8000, 0);
+	snd_soc_update_bits(codec, RT286_ADC_FORMAT, 0x8000, 0);
+
+	return 0;
+}
+
+static int rt286_set_dai_sysclk(struct snd_soc_dai *dai,
+				int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
+
+	dev_dbg(codec->dev, "%s freq=%d\n", __func__, freq);
+
+	if (RT286_SCLK_S_MCLK == clk_id) {
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL2, 0x0100, 0x0);
+		snd_soc_update_bits(codec,
+			RT286_PLL_CTRL1, 0x20, 0x20);
+	} else {
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL2, 0x0100, 0x0100);
+		snd_soc_update_bits(codec,
+			RT286_PLL_CTRL, 0x4, 0x4);
+		snd_soc_update_bits(codec,
+			RT286_PLL_CTRL1, 0x20, 0x0);
+	}
+
+	switch (freq) {
+	case 19200000:
+		if (RT286_SCLK_S_MCLK == clk_id) {
+			dev_err(codec->dev, "Should not use MCLK\n");
+			return -EINVAL;
+		}
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL2, 0x40, 0x40);
+		break;
+	case 24000000:
+		if (RT286_SCLK_S_MCLK == clk_id) {
+			dev_err(codec->dev, "Should not use MCLK\n");
+			return -EINVAL;
+		}
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL2, 0x40, 0x0);
+		break;
+	case 12288000:
+	case 11289600:
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL2, 0x8, 0x0);
+		snd_soc_update_bits(codec,
+			RT286_CLK_DIV, 0xfc1e, 0x0004);
+		break;
+	case 24576000:
+	case 22579200:
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL2, 0x8, 0x8);
+		snd_soc_update_bits(codec,
+			RT286_CLK_DIV, 0xfc1e, 0x5406);
+		break;
+	default:
+		dev_err(codec->dev, "Unsupported system clock\n");
+		return -EINVAL;
+	}
+
+	rt286->sys_clk = freq;
+
+	return 0;
+}
+
+static int rt286_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
+{
+	struct snd_soc_codec *codec = dai->codec;
+
+	dev_dbg(codec->dev, "%s ratio=%d\n", __func__, ratio);
+	if (50 == ratio)
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL1, 0x1000, 0x1000);
+	else
+		snd_soc_update_bits(codec,
+			RT286_I2S_CTRL1, 0x1000, 0x0);
+
+
+	return 0;
+}
+
+static int rt286_set_bias_level(struct snd_soc_codec *codec,
+				 enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_PREPARE:
+		if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) {
+			snd_soc_write(codec,
+				RT286_SET_AUDIO_POWER, AC_PWRST_D0);
+			snd_soc_update_bits(codec,
+				RT286_DC_GAIN, 0x200, 0x200);
+		}
+		break;
+
+	case SND_SOC_BIAS_ON:
+		mdelay(10);
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		snd_soc_write(codec,
+			RT286_SET_AUDIO_POWER, AC_PWRST_D3);
+		snd_soc_update_bits(codec,
+			RT286_DC_GAIN, 0x200, 0x0);
+		break;
+
+	default:
+		break;
+	}
+	codec->dapm.bias_level = level;
+
+	return 0;
+}
+
+static irqreturn_t rt286_irq(int irq, void *data)
+{
+	struct rt286_priv *rt286 = data;
+	bool hp = false;
+	bool mic = false;
+	int status = 0;
+
+	rt286_jack_detect(rt286, &hp, &mic);
+
+	/* Clear IRQ */
+	regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x1, 0x1);
+
+	if (hp == true)
+		status |= SND_JACK_HEADPHONE;
+
+	if (mic == true)
+		status |= SND_JACK_MICROPHONE;
+
+	snd_soc_jack_report(rt286->jack, status,
+		SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
+
+	pm_wakeup_event(&rt286->i2c->dev, 300);
+
+	return IRQ_HANDLED;
+}
+
+static int rt286_probe(struct snd_soc_codec *codec)
+{
+	struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
+
+	codec->dapm.bias_level = SND_SOC_BIAS_OFF;
+
+	if (rt286->i2c->irq) {
+		regmap_update_bits(rt286->regmap,
+					RT286_IRQ_CTRL, 0x2, 0x2);
+
+		INIT_DELAYED_WORK(&rt286->jack_detect_work,
+					rt286_jack_detect_work);
+		schedule_delayed_work(&rt286->jack_detect_work,
+					msecs_to_jiffies(1250));
+	}
+
+	return 0;
+}
+
+static int rt286_remove(struct snd_soc_codec *codec)
+{
+	struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
+
+	cancel_delayed_work_sync(&rt286->jack_detect_work);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt286_suspend(struct snd_soc_codec *codec)
+{
+	struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
+
+	regcache_cache_only(rt286->regmap, true);
+	regcache_mark_dirty(rt286->regmap);
+
+	return 0;
+}
+
+static int rt286_resume(struct snd_soc_codec *codec)
+{
+	struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
+
+	regcache_cache_only(rt286->regmap, false);
+	rt286_index_sync(codec);
+	regcache_sync(rt286->regmap);
+
+	return 0;
+}
+#else
+#define rt286_suspend NULL
+#define rt286_resume NULL
+#endif
+
+#define RT286_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+#define RT286_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
+
+static const struct snd_soc_dai_ops rt286_aif_dai_ops = {
+	.hw_params = rt286_hw_params,
+	.set_fmt = rt286_set_dai_fmt,
+	.set_sysclk = rt286_set_dai_sysclk,
+	.set_bclk_ratio = rt286_set_bclk_ratio,
+};
+
+static struct snd_soc_dai_driver rt286_dai[] = {
+	{
+		.name = "rt286-aif1",
+		.id = RT286_AIF1,
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT286_STEREO_RATES,
+			.formats = RT286_FORMATS,
+		},
+		.capture = {
+			.stream_name = "AIF1 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT286_STEREO_RATES,
+			.formats = RT286_FORMATS,
+		},
+		.ops = &rt286_aif_dai_ops,
+		.symmetric_rates = 1,
+	},
+	{
+		.name = "rt286-aif2",
+		.id = RT286_AIF2,
+		.playback = {
+			.stream_name = "AIF2 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT286_STEREO_RATES,
+			.formats = RT286_FORMATS,
+		},
+		.capture = {
+			.stream_name = "AIF2 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT286_STEREO_RATES,
+			.formats = RT286_FORMATS,
+		},
+		.ops = &rt286_aif_dai_ops,
+		.symmetric_rates = 1,
+	},
+
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt286 = {
+	.probe = rt286_probe,
+	.remove = rt286_remove,
+	.suspend = rt286_suspend,
+	.resume = rt286_resume,
+	.set_bias_level = rt286_set_bias_level,
+	.idle_bias_off = true,
+	.controls = rt286_snd_controls,
+	.num_controls = ARRAY_SIZE(rt286_snd_controls),
+	.dapm_widgets = rt286_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(rt286_dapm_widgets),
+	.dapm_routes = rt286_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(rt286_dapm_routes),
+};
+
+static const struct regmap_config rt286_regmap = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.max_register = 0x02370100,
+	.volatile_reg = rt286_volatile_register,
+	.readable_reg = rt286_readable_register,
+	.reg_write = rt286_hw_write,
+	.reg_read = rt286_hw_read,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = rt286_reg,
+	.num_reg_defaults = ARRAY_SIZE(rt286_reg),
+};
+
+static const struct i2c_device_id rt286_i2c_id[] = {
+	{"rt286", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, rt286_i2c_id);
+
+static const struct acpi_device_id rt286_acpi_match[] = {
+	{ "INT343A", 0 },
+	{},
+};
+MODULE_DEVICE_TABLE(acpi, rt286_acpi_match);
+
+static int rt286_i2c_probe(struct i2c_client *i2c,
+			   const struct i2c_device_id *id)
+{
+	struct rt286_platform_data *pdata = dev_get_platdata(&i2c->dev);
+	struct rt286_priv *rt286;
+	int i, ret;
+
+	rt286 = devm_kzalloc(&i2c->dev,	sizeof(*rt286),
+				GFP_KERNEL);
+	if (NULL == rt286)
+		return -ENOMEM;
+
+	rt286->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt286_regmap);
+	if (IS_ERR(rt286->regmap)) {
+		ret = PTR_ERR(rt286->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	regmap_read(rt286->regmap,
+		RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret);
+	if (ret != RT286_VENDOR_ID) {
+		dev_err(&i2c->dev,
+			"Device with ID register %x is not rt286\n", ret);
+		return -ENODEV;
+	}
+
+	rt286->index_cache = rt286_index_def;
+	rt286->i2c = i2c;
+	i2c_set_clientdata(i2c, rt286);
+
+	if (pdata)
+		rt286->pdata = *pdata;
+
+	regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3);
+
+	for (i = 0; i < RT286_POWER_REG_LEN; i++)
+		regmap_write(rt286->regmap,
+			RT286_SET_POWER(rt286_support_power_controls[i]),
+			AC_PWRST_D1);
+
+	if (!rt286->pdata.cbj_en) {
+		regmap_write(rt286->regmap, RT286_CBJ_CTRL2, 0x0000);
+		regmap_write(rt286->regmap, RT286_MIC1_DET_CTRL, 0x0816);
+		regmap_write(rt286->regmap, RT286_MISC_CTRL1, 0x0000);
+		regmap_update_bits(rt286->regmap,
+					RT286_CBJ_CTRL1, 0xf000, 0xb000);
+	} else {
+		regmap_update_bits(rt286->regmap,
+					RT286_CBJ_CTRL1, 0xf000, 0x5000);
+	}
+
+	mdelay(10);
+
+	if (!rt286->pdata.gpio2_en)
+		regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0x4000);
+	else
+		regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0);
+
+	mdelay(10);
+
+	/*Power down LDO2*/
+	regmap_update_bits(rt286->regmap, RT286_POWER_CTRL2, 0x8, 0x0);
+
+	/*Set depop parameter*/
+	regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL2, 0x403a, 0x401a);
+	regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737);
+	regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f);
+
+	if (rt286->i2c->irq) {
+		ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq,
+			IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286);
+		if (ret != 0) {
+			dev_err(&i2c->dev,
+				"Failed to reguest IRQ: %d\n", ret);
+			return ret;
+		}
+	}
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt286,
+				     rt286_dai, ARRAY_SIZE(rt286_dai));
+
+	return ret;
+}
+
+static int rt286_i2c_remove(struct i2c_client *i2c)
+{
+	struct rt286_priv *rt286 = i2c_get_clientdata(i2c);
+
+	if (i2c->irq)
+		free_irq(i2c->irq, rt286);
+	snd_soc_unregister_codec(&i2c->dev);
+
+	return 0;
+}
+
+
+static struct i2c_driver rt286_i2c_driver = {
+	.driver = {
+		   .name = "rt286",
+		   .owner = THIS_MODULE,
+		   .acpi_match_table = ACPI_PTR(rt286_acpi_match),
+		   },
+	.probe = rt286_i2c_probe,
+	.remove = rt286_i2c_remove,
+	.id_table = rt286_i2c_id,
+};
+
+module_i2c_driver(rt286_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC RT286 driver");
+MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt286.h b/sound/soc/codecs/rt286.h
new file mode 100644
index 000000000000..b539b7320a79
--- /dev/null
+++ b/sound/soc/codecs/rt286.h
@@ -0,0 +1,198 @@
+/*
+ * rt286.h  --  RT286 ALSA SoC audio driver
+ *
+ * Copyright 2011 Realtek Microelectronics
+ * Author: Johnny Hsu <johnnyhsu@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __RT286_H__
+#define __RT286_H__
+
+#define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D)
+
+#define RT286_AUDIO_FUNCTION_GROUP			0x01
+#define RT286_DAC_OUT1					0x02
+#define RT286_DAC_OUT2					0x03
+#define RT286_ADC_IN1					0x09
+#define RT286_ADC_IN2					0x08
+#define RT286_MIXER_IN					0x0b
+#define RT286_MIXER_OUT1				0x0c
+#define RT286_MIXER_OUT2				0x0d
+#define RT286_DMIC1					0x12
+#define RT286_DMIC2					0x13
+#define RT286_SPK_OUT					0x14
+#define RT286_MIC1					0x18
+#define RT286_LINE1					0x1a
+#define RT286_BEEP					0x1d
+#define RT286_SPDIF					0x1e
+#define RT286_VENDOR_REGISTERS				0x20
+#define RT286_HP_OUT					0x21
+#define RT286_MIXER_IN1					0x22
+#define RT286_MIXER_IN2					0x23
+
+#define RT286_SET_PIN_SFT				6
+#define RT286_SET_PIN_ENABLE				0x40
+#define RT286_SET_PIN_DISABLE				0
+#define RT286_SET_EAPD_HIGH				0x2
+#define RT286_SET_EAPD_LOW				0
+
+#define RT286_MUTE_SFT					7
+
+/* Verb commands */
+#define RT286_GET_PARAM(NID, PARAM) VERB_CMD(AC_VERB_PARAMETERS, NID, PARAM)
+#define RT286_SET_POWER(NID) VERB_CMD(AC_VERB_SET_POWER_STATE, NID, 0)
+#define RT286_SET_AUDIO_POWER RT286_SET_POWER(RT286_AUDIO_FUNCTION_GROUP)
+#define RT286_SET_HPO_POWER RT286_SET_POWER(RT286_HP_OUT)
+#define RT286_SET_SPK_POWER RT286_SET_POWER(RT286_SPK_OUT)
+#define RT286_SET_DMIC1_POWER RT286_SET_POWER(RT286_DMIC1)
+#define RT286_SPK_MUX\
+	VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_SPK_OUT, 0)
+#define RT286_HPO_MUX\
+	VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_HP_OUT, 0)
+#define RT286_ADC0_MUX\
+	VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_MIXER_IN1, 0)
+#define RT286_ADC1_MUX\
+	VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_MIXER_IN2, 0)
+#define RT286_SET_MIC1\
+	VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_MIC1, 0)
+#define RT286_SET_PIN_HPO\
+	VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_HP_OUT, 0)
+#define RT286_SET_PIN_SPK\
+	VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_SPK_OUT, 0)
+#define RT286_SET_PIN_DMIC1\
+	VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_DMIC1, 0)
+#define RT286_SPK_EAPD\
+	VERB_CMD(AC_VERB_SET_EAPD_BTLENABLE, RT286_SPK_OUT, 0)
+#define RT286_SET_AMP_GAIN_HPO\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0)
+#define RT286_SET_AMP_GAIN_ADC_IN1\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0)
+#define RT286_SET_AMP_GAIN_ADC_IN2\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN2, 0)
+#define RT286_GET_HP_SENSE\
+	VERB_CMD(AC_VERB_GET_PIN_SENSE, RT286_HP_OUT, 0)
+#define RT286_GET_MIC1_SENSE\
+	VERB_CMD(AC_VERB_GET_PIN_SENSE, RT286_MIC1, 0)
+#define RT286_SET_DMIC2_DEFAULT\
+	VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT286_DMIC2, 0)
+#define RT286_DACL_GAIN\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_DAC_OUT1, 0xa000)
+#define RT286_DACR_GAIN\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_DAC_OUT1, 0x9000)
+#define RT286_ADCL_GAIN\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0x6000)
+#define RT286_ADCR_GAIN\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0x5000)
+#define RT286_MIC_GAIN\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIC1, 0x7000)
+#define RT286_SPOL_GAIN\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_SPK_OUT, 0xa000)
+#define RT286_SPOR_GAIN\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_SPK_OUT, 0x9000)
+#define RT286_HPOL_GAIN\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0xa000)
+#define RT286_HPOR_GAIN\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0x9000)
+#define RT286_F_DAC_SWITCH\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_OUT1, 0x7000)
+#define RT286_F_RECMIX_SWITCH\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_OUT1, 0x7100)
+#define RT286_REC_MIC_SWITCH\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7000)
+#define RT286_REC_I2S_SWITCH\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7100)
+#define RT286_REC_LINE_SWITCH\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7200)
+#define RT286_REC_BEEP_SWITCH\
+	VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7300)
+#define RT286_DAC_FORMAT\
+	VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT286_DAC_OUT1, 0)
+#define RT286_ADC_FORMAT\
+	VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT286_ADC_IN1, 0)
+#define RT286_COEF_INDEX\
+	VERB_CMD(AC_VERB_SET_COEF_INDEX, RT286_VENDOR_REGISTERS, 0)
+#define RT286_PROC_COEF\
+	VERB_CMD(AC_VERB_SET_PROC_COEF, RT286_VENDOR_REGISTERS, 0)
+
+/* Index registers */
+#define RT286_A_BIAS_CTRL1	0x01
+#define RT286_A_BIAS_CTRL2	0x02
+#define RT286_POWER_CTRL1	0x03
+#define RT286_A_BIAS_CTRL3	0x04
+#define RT286_POWER_CTRL2	0x08
+#define RT286_I2S_CTRL1		0x09
+#define RT286_I2S_CTRL2		0x0a
+#define RT286_CLK_DIV		0x0b
+#define RT286_DC_GAIN		0x0d
+#define RT286_POWER_CTRL3	0x0f
+#define RT286_MIC1_DET_CTRL	0x19
+#define RT286_MISC_CTRL1	0x20
+#define RT286_IRQ_CTRL		0x33
+#define RT286_PLL_CTRL1		0x49
+#define RT286_CBJ_CTRL1		0x4f
+#define RT286_CBJ_CTRL2		0x50
+#define RT286_PLL_CTRL		0x63
+#define RT286_DEPOP_CTRL1	0x66
+#define RT286_DEPOP_CTRL2	0x67
+#define RT286_DEPOP_CTRL3	0x68
+#define RT286_DEPOP_CTRL4	0x69
+
+/* SPDIF (0x06) */
+#define RT286_SPDIF_SEL_SFT	0
+#define RT286_SPDIF_SEL_PCM0	0
+#define RT286_SPDIF_SEL_PCM1	1
+#define RT286_SPDIF_SEL_SPOUT	2
+#define RT286_SPDIF_SEL_PP	3
+
+/* RECMIX (0x0b) */
+#define RT286_M_REC_BEEP_SFT	0
+#define RT286_M_REC_LINE1_SFT	1
+#define RT286_M_REC_MIC1_SFT	2
+#define RT286_M_REC_I2S_SFT	3
+
+/* Front (0x0c) */
+#define RT286_M_FRONT_DAC_SFT	0
+#define RT286_M_FRONT_REC_SFT	1
+
+/* SPK-OUT (0x14) */
+#define RT286_M_SPK_MUX_SFT	14
+#define RT286_SPK_SEL_MASK	0x1
+#define RT286_SPK_SEL_SFT	0
+#define RT286_SPK_SEL_F		0
+#define RT286_SPK_SEL_S		1
+
+/* HP-OUT (0x21) */
+#define RT286_M_HP_MUX_SFT	14
+#define RT286_HP_SEL_MASK	0x1
+#define RT286_HP_SEL_SFT	0
+#define RT286_HP_SEL_F		0
+#define RT286_HP_SEL_S		1
+
+/* ADC (0x22) (0x23) */
+#define RT286_ADC_SEL_MASK	0x7
+#define RT286_ADC_SEL_SFT	0
+#define RT286_ADC_SEL_SURR	0
+#define RT286_ADC_SEL_FRONT	1
+#define RT286_ADC_SEL_DMIC	2
+#define RT286_ADC_SEL_BEEP	4
+#define RT286_ADC_SEL_LINE1	5
+#define RT286_ADC_SEL_I2S	6
+#define RT286_ADC_SEL_MIC1	7
+
+#define RT286_SCLK_S_MCLK	0
+#define RT286_SCLK_S_PLL	1
+
+enum {
+	RT286_AIF1,
+	RT286_AIF2,
+	RT286_AIFS,
+};
+
+int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
+
+#endif /* __RT286_H__ */
+
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
index 30e234708579..1ba27db660a6 100644
--- a/sound/soc/codecs/rt5631.c
+++ b/sound/soc/codecs/rt5631.c
@@ -1370,16 +1370,16 @@ static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream,
 		return coeff;
 	}
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface |= RT5631_SDP_I2S_DL_20;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface |= RT5631_SDP_I2S_DL_24;
 		break;
-	case SNDRV_PCM_FORMAT_S8:
+	case 8:
 		iface |= RT5631_SDP_I2S_DL_8;
 		break;
 	default:
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index de80e89b5fd8..6bc6efdec550 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -2215,14 +2215,8 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
 
 	rt5640->hp_mute = 1;
 
-	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640,
-			rt5640_dai, ARRAY_SIZE(rt5640_dai));
-	if (ret < 0)
-		goto err;
-
-	return 0;
-err:
-	return ret;
+	return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640,
+				      rt5640_dai, ARRAY_SIZE(rt5640_dai));
 }
 
 static int rt5640_i2c_remove(struct i2c_client *i2c)
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 02147be2b302..a7762d0a623e 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -2345,14 +2345,8 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
 
 	}
 
-	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645,
-			rt5645_dai, ARRAY_SIZE(rt5645_dai));
-	if (ret < 0)
-		goto err;
-
-	return 0;
-err:
-	return ret;
+	return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645,
+				      rt5645_dai, ARRAY_SIZE(rt5645_dai));
 }
 
 static int rt5645_i2c_remove(struct i2c_client *i2c)
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index ea4b1c652a26..bb0a3ab5416c 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -1366,16 +1366,16 @@ static int rt5651_hw_params(struct snd_pcm_substream *substream,
 	dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
 				bclk_ms, pre_div, dai->id);
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		val_len |= RT5651_I2S_DL_20;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		val_len |= RT5651_I2S_DL_24;
 		break;
-	case SNDRV_PCM_FORMAT_S8:
+	case 8:
 		val_len |= RT5651_I2S_DL_8;
 		break;
 	default:
diff --git a/sound/soc/codecs/rt5670-dsp.h b/sound/soc/codecs/rt5670-dsp.h
new file mode 100644
index 000000000000..a34d0cdb8198
--- /dev/null
+++ b/sound/soc/codecs/rt5670-dsp.h
@@ -0,0 +1,54 @@
+/*
+ * rt5670-dsp.h  --  RT5670 ALSA SoC DSP driver
+ *
+ * Copyright 2014 Realtek Microelectronics
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __RT5670_DSP_H__
+#define __RT5670_DSP_H__
+
+#define RT5670_DSP_CTRL1		0xe0
+#define RT5670_DSP_CTRL2		0xe1
+#define RT5670_DSP_CTRL3		0xe2
+#define RT5670_DSP_CTRL4		0xe3
+#define RT5670_DSP_CTRL5		0xe4
+
+/* DSP Control 1 (0xe0) */
+#define RT5670_DSP_CMD_MASK		(0xff << 8)
+#define RT5670_DSP_CMD_PE		(0x0d << 8)	/* Patch Entry */
+#define RT5670_DSP_CMD_MW		(0x3b << 8)	/* Memory Write */
+#define RT5670_DSP_CMD_MR		(0x37 << 8)	/* Memory Read */
+#define RT5670_DSP_CMD_RR		(0x60 << 8)	/* Register Read */
+#define RT5670_DSP_CMD_RW		(0x68 << 8)	/* Register Write */
+#define RT5670_DSP_REG_DATHI		(0x26 << 8)	/* High Data Addr */
+#define RT5670_DSP_REG_DATLO		(0x25 << 8)	/* Low Data Addr */
+#define RT5670_DSP_CLK_MASK		(0x3 << 6)
+#define RT5670_DSP_CLK_SFT		6
+#define RT5670_DSP_CLK_768K		(0x0 << 6)
+#define RT5670_DSP_CLK_384K		(0x1 << 6)
+#define RT5670_DSP_CLK_192K		(0x2 << 6)
+#define RT5670_DSP_CLK_96K		(0x3 << 6)
+#define RT5670_DSP_BUSY_MASK		(0x1 << 5)
+#define RT5670_DSP_RW_MASK		(0x1 << 4)
+#define RT5670_DSP_DL_MASK		(0x3 << 2)
+#define RT5670_DSP_DL_0			(0x0 << 2)
+#define RT5670_DSP_DL_1			(0x1 << 2)
+#define RT5670_DSP_DL_2			(0x2 << 2)
+#define RT5670_DSP_DL_3			(0x3 << 2)
+#define RT5670_DSP_I2C_AL_16		(0x1 << 1)
+#define RT5670_DSP_CMD_EN		(0x1)
+
+struct rt5670_dsp_param {
+	u16 cmd_fmt;
+	u16 addr;
+	u16 data;
+	u8 cmd;
+};
+
+#endif /* __RT5670_DSP_H__ */
+
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
new file mode 100644
index 000000000000..ba9d9b4d4857
--- /dev/null
+++ b/sound/soc/codecs/rt5670.c
@@ -0,0 +1,2657 @@
+/*
+ * rt5670.c  --  RT5670 ALSA SoC audio codec driver
+ *
+ * Copyright 2014 Realtek Semiconductor Corp.
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/jack.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/rt5670.h>
+
+#include "rl6231.h"
+#include "rt5670.h"
+#include "rt5670-dsp.h"
+
+#define RT5670_DEVICE_ID 0x6271
+
+#define RT5670_PR_RANGE_BASE (0xff + 1)
+#define RT5670_PR_SPACING 0x100
+
+#define RT5670_PR_BASE (RT5670_PR_RANGE_BASE + (0 * RT5670_PR_SPACING))
+
+static const struct regmap_range_cfg rt5670_ranges[] = {
+	{ .name = "PR", .range_min = RT5670_PR_BASE,
+	  .range_max = RT5670_PR_BASE + 0xf8,
+	  .selector_reg = RT5670_PRIV_INDEX,
+	  .selector_mask = 0xff,
+	  .selector_shift = 0x0,
+	  .window_start = RT5670_PRIV_DATA,
+	  .window_len = 0x1, },
+};
+
+static struct reg_default init_list[] = {
+	{ RT5670_PR_BASE + 0x14, 0x9a8a },
+	{ RT5670_PR_BASE + 0x38, 0x3ba1 },
+	{ RT5670_PR_BASE + 0x3d, 0x3640 },
+};
+#define RT5670_INIT_REG_LEN ARRAY_SIZE(init_list)
+
+static const struct reg_default rt5670_reg[] = {
+	{ 0x00, 0x0000 },
+	{ 0x02, 0x8888 },
+	{ 0x03, 0x8888 },
+	{ 0x0a, 0x0001 },
+	{ 0x0b, 0x0827 },
+	{ 0x0c, 0x0000 },
+	{ 0x0d, 0x0008 },
+	{ 0x0e, 0x0000 },
+	{ 0x0f, 0x0808 },
+	{ 0x19, 0xafaf },
+	{ 0x1a, 0xafaf },
+	{ 0x1b, 0x0011 },
+	{ 0x1c, 0x2f2f },
+	{ 0x1d, 0x2f2f },
+	{ 0x1e, 0x0000 },
+	{ 0x1f, 0x2f2f },
+	{ 0x20, 0x0000 },
+	{ 0x26, 0x7860 },
+	{ 0x27, 0x7860 },
+	{ 0x28, 0x7871 },
+	{ 0x29, 0x8080 },
+	{ 0x2a, 0x5656 },
+	{ 0x2b, 0x5454 },
+	{ 0x2c, 0xaaa0 },
+	{ 0x2d, 0x0000 },
+	{ 0x2e, 0x2f2f },
+	{ 0x2f, 0x1002 },
+	{ 0x30, 0x0000 },
+	{ 0x31, 0x5f00 },
+	{ 0x32, 0x0000 },
+	{ 0x33, 0x0000 },
+	{ 0x34, 0x0000 },
+	{ 0x35, 0x0000 },
+	{ 0x36, 0x0000 },
+	{ 0x37, 0x0000 },
+	{ 0x38, 0x0000 },
+	{ 0x3b, 0x0000 },
+	{ 0x3c, 0x007f },
+	{ 0x3d, 0x0000 },
+	{ 0x3e, 0x007f },
+	{ 0x45, 0xe00f },
+	{ 0x4c, 0x5380 },
+	{ 0x4f, 0x0073 },
+	{ 0x52, 0x00d3 },
+	{ 0x53, 0xf0f0 },
+	{ 0x61, 0x0000 },
+	{ 0x62, 0x0001 },
+	{ 0x63, 0x00c3 },
+	{ 0x64, 0x0000 },
+	{ 0x65, 0x0000 },
+	{ 0x66, 0x0000 },
+	{ 0x6f, 0x8000 },
+	{ 0x70, 0x8000 },
+	{ 0x71, 0x8000 },
+	{ 0x72, 0x8000 },
+	{ 0x73, 0x1110 },
+	{ 0x74, 0x0e00 },
+	{ 0x75, 0x1505 },
+	{ 0x76, 0x0015 },
+	{ 0x77, 0x0c00 },
+	{ 0x78, 0x4000 },
+	{ 0x79, 0x0123 },
+	{ 0x7f, 0x1100 },
+	{ 0x80, 0x0000 },
+	{ 0x81, 0x0000 },
+	{ 0x82, 0x0000 },
+	{ 0x83, 0x0000 },
+	{ 0x84, 0x0000 },
+	{ 0x85, 0x0000 },
+	{ 0x86, 0x0008 },
+	{ 0x87, 0x0000 },
+	{ 0x88, 0x0000 },
+	{ 0x89, 0x0000 },
+	{ 0x8a, 0x0000 },
+	{ 0x8b, 0x0000 },
+	{ 0x8c, 0x0007 },
+	{ 0x8d, 0x0000 },
+	{ 0x8e, 0x0004 },
+	{ 0x8f, 0x1100 },
+	{ 0x90, 0x0646 },
+	{ 0x91, 0x0c06 },
+	{ 0x93, 0x0000 },
+	{ 0x94, 0x0000 },
+	{ 0x95, 0x0000 },
+	{ 0x97, 0x0000 },
+	{ 0x98, 0x0000 },
+	{ 0x99, 0x0000 },
+	{ 0x9a, 0x2184 },
+	{ 0x9b, 0x010a },
+	{ 0x9c, 0x0aea },
+	{ 0x9d, 0x000c },
+	{ 0x9e, 0x0400 },
+	{ 0xae, 0x7000 },
+	{ 0xaf, 0x0000 },
+	{ 0xb0, 0x6000 },
+	{ 0xb1, 0x0000 },
+	{ 0xb2, 0x0000 },
+	{ 0xb3, 0x001f },
+	{ 0xb4, 0x2206 },
+	{ 0xb5, 0x1f00 },
+	{ 0xb6, 0x0000 },
+	{ 0xb7, 0x0000 },
+	{ 0xbb, 0x0000 },
+	{ 0xbc, 0x0000 },
+	{ 0xbd, 0x0000 },
+	{ 0xbe, 0x0000 },
+	{ 0xbf, 0x0000 },
+	{ 0xc0, 0x0000 },
+	{ 0xc1, 0x0000 },
+	{ 0xc2, 0x0000 },
+	{ 0xcd, 0x0000 },
+	{ 0xce, 0x0000 },
+	{ 0xcf, 0x1813 },
+	{ 0xd0, 0x0690 },
+	{ 0xd1, 0x1c17 },
+	{ 0xd3, 0xb320 },
+	{ 0xd4, 0x0000 },
+	{ 0xd6, 0x0400 },
+	{ 0xd9, 0x0809 },
+	{ 0xda, 0x0000 },
+	{ 0xdb, 0x0001 },
+	{ 0xdc, 0x0049 },
+	{ 0xdd, 0x0009 },
+	{ 0xe6, 0x8000 },
+	{ 0xe7, 0x0000 },
+	{ 0xec, 0xb300 },
+	{ 0xed, 0x0000 },
+	{ 0xee, 0xb300 },
+	{ 0xef, 0x0000 },
+	{ 0xf8, 0x0000 },
+	{ 0xf9, 0x0000 },
+	{ 0xfa, 0x8010 },
+	{ 0xfb, 0x0033 },
+	{ 0xfc, 0x0080 },
+};
+
+static bool rt5670_volatile_register(struct device *dev, unsigned int reg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rt5670_ranges); i++) {
+		if ((reg >= rt5670_ranges[i].window_start &&
+		     reg <= rt5670_ranges[i].window_start +
+		     rt5670_ranges[i].window_len) ||
+		    (reg >= rt5670_ranges[i].range_min &&
+		     reg <= rt5670_ranges[i].range_max)) {
+			return true;
+		}
+	}
+
+	switch (reg) {
+	case RT5670_RESET:
+	case RT5670_PDM_DATA_CTRL1:
+	case RT5670_PDM1_DATA_CTRL4:
+	case RT5670_PDM2_DATA_CTRL4:
+	case RT5670_PRIV_DATA:
+	case RT5670_ASRC_5:
+	case RT5670_CJ_CTRL1:
+	case RT5670_CJ_CTRL2:
+	case RT5670_CJ_CTRL3:
+	case RT5670_A_JD_CTRL1:
+	case RT5670_A_JD_CTRL2:
+	case RT5670_VAD_CTRL5:
+	case RT5670_ADC_EQ_CTRL1:
+	case RT5670_EQ_CTRL1:
+	case RT5670_ALC_CTRL_1:
+	case RT5670_IRQ_CTRL1:
+	case RT5670_IRQ_CTRL2:
+	case RT5670_INT_IRQ_ST:
+	case RT5670_IL_CMD:
+	case RT5670_DSP_CTRL1:
+	case RT5670_DSP_CTRL2:
+	case RT5670_DSP_CTRL3:
+	case RT5670_DSP_CTRL4:
+	case RT5670_DSP_CTRL5:
+	case RT5670_VENDOR_ID:
+	case RT5670_VENDOR_ID1:
+	case RT5670_VENDOR_ID2:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rt5670_readable_register(struct device *dev, unsigned int reg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rt5670_ranges); i++) {
+		if ((reg >= rt5670_ranges[i].window_start &&
+		     reg <= rt5670_ranges[i].window_start +
+		     rt5670_ranges[i].window_len) ||
+		    (reg >= rt5670_ranges[i].range_min &&
+		     reg <= rt5670_ranges[i].range_max)) {
+			return true;
+		}
+	}
+
+	switch (reg) {
+	case RT5670_RESET:
+	case RT5670_HP_VOL:
+	case RT5670_LOUT1:
+	case RT5670_CJ_CTRL1:
+	case RT5670_CJ_CTRL2:
+	case RT5670_CJ_CTRL3:
+	case RT5670_IN2:
+	case RT5670_INL1_INR1_VOL:
+	case RT5670_DAC1_DIG_VOL:
+	case RT5670_DAC2_DIG_VOL:
+	case RT5670_DAC_CTRL:
+	case RT5670_STO1_ADC_DIG_VOL:
+	case RT5670_MONO_ADC_DIG_VOL:
+	case RT5670_STO2_ADC_DIG_VOL:
+	case RT5670_ADC_BST_VOL1:
+	case RT5670_ADC_BST_VOL2:
+	case RT5670_STO2_ADC_MIXER:
+	case RT5670_STO1_ADC_MIXER:
+	case RT5670_MONO_ADC_MIXER:
+	case RT5670_AD_DA_MIXER:
+	case RT5670_STO_DAC_MIXER:
+	case RT5670_DD_MIXER:
+	case RT5670_DIG_MIXER:
+	case RT5670_DSP_PATH1:
+	case RT5670_DSP_PATH2:
+	case RT5670_DIG_INF1_DATA:
+	case RT5670_DIG_INF2_DATA:
+	case RT5670_PDM_OUT_CTRL:
+	case RT5670_PDM_DATA_CTRL1:
+	case RT5670_PDM1_DATA_CTRL2:
+	case RT5670_PDM1_DATA_CTRL3:
+	case RT5670_PDM1_DATA_CTRL4:
+	case RT5670_PDM2_DATA_CTRL2:
+	case RT5670_PDM2_DATA_CTRL3:
+	case RT5670_PDM2_DATA_CTRL4:
+	case RT5670_REC_L1_MIXER:
+	case RT5670_REC_L2_MIXER:
+	case RT5670_REC_R1_MIXER:
+	case RT5670_REC_R2_MIXER:
+	case RT5670_HPO_MIXER:
+	case RT5670_MONO_MIXER:
+	case RT5670_OUT_L1_MIXER:
+	case RT5670_OUT_R1_MIXER:
+	case RT5670_LOUT_MIXER:
+	case RT5670_PWR_DIG1:
+	case RT5670_PWR_DIG2:
+	case RT5670_PWR_ANLG1:
+	case RT5670_PWR_ANLG2:
+	case RT5670_PWR_MIXER:
+	case RT5670_PWR_VOL:
+	case RT5670_PRIV_INDEX:
+	case RT5670_PRIV_DATA:
+	case RT5670_I2S4_SDP:
+	case RT5670_I2S1_SDP:
+	case RT5670_I2S2_SDP:
+	case RT5670_I2S3_SDP:
+	case RT5670_ADDA_CLK1:
+	case RT5670_ADDA_CLK2:
+	case RT5670_DMIC_CTRL1:
+	case RT5670_DMIC_CTRL2:
+	case RT5670_TDM_CTRL_1:
+	case RT5670_TDM_CTRL_2:
+	case RT5670_TDM_CTRL_3:
+	case RT5670_DSP_CLK:
+	case RT5670_GLB_CLK:
+	case RT5670_PLL_CTRL1:
+	case RT5670_PLL_CTRL2:
+	case RT5670_ASRC_1:
+	case RT5670_ASRC_2:
+	case RT5670_ASRC_3:
+	case RT5670_ASRC_4:
+	case RT5670_ASRC_5:
+	case RT5670_ASRC_7:
+	case RT5670_ASRC_8:
+	case RT5670_ASRC_9:
+	case RT5670_ASRC_10:
+	case RT5670_ASRC_11:
+	case RT5670_ASRC_12:
+	case RT5670_ASRC_13:
+	case RT5670_ASRC_14:
+	case RT5670_DEPOP_M1:
+	case RT5670_DEPOP_M2:
+	case RT5670_DEPOP_M3:
+	case RT5670_CHARGE_PUMP:
+	case RT5670_MICBIAS:
+	case RT5670_A_JD_CTRL1:
+	case RT5670_A_JD_CTRL2:
+	case RT5670_VAD_CTRL1:
+	case RT5670_VAD_CTRL2:
+	case RT5670_VAD_CTRL3:
+	case RT5670_VAD_CTRL4:
+	case RT5670_VAD_CTRL5:
+	case RT5670_ADC_EQ_CTRL1:
+	case RT5670_ADC_EQ_CTRL2:
+	case RT5670_EQ_CTRL1:
+	case RT5670_EQ_CTRL2:
+	case RT5670_ALC_DRC_CTRL1:
+	case RT5670_ALC_DRC_CTRL2:
+	case RT5670_ALC_CTRL_1:
+	case RT5670_ALC_CTRL_2:
+	case RT5670_ALC_CTRL_3:
+	case RT5670_JD_CTRL:
+	case RT5670_IRQ_CTRL1:
+	case RT5670_IRQ_CTRL2:
+	case RT5670_INT_IRQ_ST:
+	case RT5670_GPIO_CTRL1:
+	case RT5670_GPIO_CTRL2:
+	case RT5670_GPIO_CTRL3:
+	case RT5670_SCRABBLE_FUN:
+	case RT5670_SCRABBLE_CTRL:
+	case RT5670_BASE_BACK:
+	case RT5670_MP3_PLUS1:
+	case RT5670_MP3_PLUS2:
+	case RT5670_ADJ_HPF1:
+	case RT5670_ADJ_HPF2:
+	case RT5670_HP_CALIB_AMP_DET:
+	case RT5670_SV_ZCD1:
+	case RT5670_SV_ZCD2:
+	case RT5670_IL_CMD:
+	case RT5670_IL_CMD2:
+	case RT5670_IL_CMD3:
+	case RT5670_DRC_HL_CTRL1:
+	case RT5670_DRC_HL_CTRL2:
+	case RT5670_ADC_MONO_HP_CTRL1:
+	case RT5670_ADC_MONO_HP_CTRL2:
+	case RT5670_ADC_STO2_HP_CTRL1:
+	case RT5670_ADC_STO2_HP_CTRL2:
+	case RT5670_JD_CTRL3:
+	case RT5670_JD_CTRL4:
+	case RT5670_DIG_MISC:
+	case RT5670_DSP_CTRL1:
+	case RT5670_DSP_CTRL2:
+	case RT5670_DSP_CTRL3:
+	case RT5670_DSP_CTRL4:
+	case RT5670_DSP_CTRL5:
+	case RT5670_GEN_CTRL2:
+	case RT5670_GEN_CTRL3:
+	case RT5670_VENDOR_ID:
+	case RT5670_VENDOR_ID1:
+	case RT5670_VENDOR_ID2:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
+
+/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
+static unsigned int bst_tlv[] = {
+	TLV_DB_RANGE_HEAD(7),
+	0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+	1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
+	2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
+	3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
+	6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
+	7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
+	8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
+};
+
+/* Interface data select */
+static const char * const rt5670_data_select[] = {
+	"Normal", "Swap", "left copy to right", "right copy to left"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_if2_dac_enum, RT5670_DIG_INF1_DATA,
+				RT5670_IF2_DAC_SEL_SFT, rt5670_data_select);
+
+static SOC_ENUM_SINGLE_DECL(rt5670_if2_adc_enum, RT5670_DIG_INF1_DATA,
+				RT5670_IF2_ADC_SEL_SFT, rt5670_data_select);
+
+static const struct snd_kcontrol_new rt5670_snd_controls[] = {
+	/* Headphone Output Volume */
+	SOC_DOUBLE("HP Playback Switch", RT5670_HP_VOL,
+		RT5670_L_MUTE_SFT, RT5670_R_MUTE_SFT, 1, 1),
+	SOC_DOUBLE_TLV("HP Playback Volume", RT5670_HP_VOL,
+		RT5670_L_VOL_SFT, RT5670_R_VOL_SFT,
+		39, 0, out_vol_tlv),
+	/* OUTPUT Control */
+	SOC_DOUBLE("OUT Channel Switch", RT5670_LOUT1,
+		RT5670_VOL_L_SFT, RT5670_VOL_R_SFT, 1, 1),
+	SOC_DOUBLE_TLV("OUT Playback Volume", RT5670_LOUT1,
+		RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, 39, 1, out_vol_tlv),
+	/* DAC Digital Volume */
+	SOC_DOUBLE("DAC2 Playback Switch", RT5670_DAC_CTRL,
+		RT5670_M_DAC_L2_VOL_SFT, RT5670_M_DAC_R2_VOL_SFT, 1, 1),
+	SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5670_DAC1_DIG_VOL,
+			RT5670_L_VOL_SFT, RT5670_R_VOL_SFT,
+			175, 0, dac_vol_tlv),
+	SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5670_DAC2_DIG_VOL,
+			RT5670_L_VOL_SFT, RT5670_R_VOL_SFT,
+			175, 0, dac_vol_tlv),
+	/* IN1/IN2 Control */
+	SOC_SINGLE_TLV("IN1 Boost Volume", RT5670_CJ_CTRL1,
+		RT5670_BST_SFT1, 8, 0, bst_tlv),
+	SOC_SINGLE_TLV("IN2 Boost Volume", RT5670_IN2,
+		RT5670_BST_SFT1, 8, 0, bst_tlv),
+	/* INL/INR Volume Control */
+	SOC_DOUBLE_TLV("IN Capture Volume", RT5670_INL1_INR1_VOL,
+			RT5670_INL_VOL_SFT, RT5670_INR_VOL_SFT,
+			31, 1, in_vol_tlv),
+	/* ADC Digital Volume Control */
+	SOC_DOUBLE("ADC Capture Switch", RT5670_STO1_ADC_DIG_VOL,
+		RT5670_L_MUTE_SFT, RT5670_R_MUTE_SFT, 1, 1),
+	SOC_DOUBLE_TLV("ADC Capture Volume", RT5670_STO1_ADC_DIG_VOL,
+			RT5670_L_VOL_SFT, RT5670_R_VOL_SFT,
+			127, 0, adc_vol_tlv),
+
+	SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5670_MONO_ADC_DIG_VOL,
+			RT5670_L_VOL_SFT, RT5670_R_VOL_SFT,
+			127, 0, adc_vol_tlv),
+
+	/* ADC Boost Volume Control */
+	SOC_DOUBLE_TLV("STO1 ADC Boost Gain Volume", RT5670_ADC_BST_VOL1,
+			RT5670_STO1_ADC_L_BST_SFT, RT5670_STO1_ADC_R_BST_SFT,
+			3, 0, adc_bst_tlv),
+
+	SOC_DOUBLE_TLV("STO2 ADC Boost Gain Volume", RT5670_ADC_BST_VOL1,
+			RT5670_STO2_ADC_L_BST_SFT, RT5670_STO2_ADC_R_BST_SFT,
+			3, 0, adc_bst_tlv),
+
+	SOC_ENUM("ADC IF2 Data Switch", rt5670_if2_adc_enum),
+	SOC_ENUM("DAC IF2 Data Switch", rt5670_if2_dac_enum),
+};
+
+/**
+ * set_dmic_clk - Set parameter of dmic.
+ *
+ * @w: DAPM widget.
+ * @kcontrol: The kcontrol of this widget.
+ * @event: Event id.
+ *
+ * Choose dmic clock between 1MHz and 3MHz.
+ * It is better for clock to approximate 3MHz.
+ */
+static int set_dmic_clk(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
+	int idx = -EINVAL;
+
+	idx = rl6231_calc_dmic_clk(rt5670->sysclk);
+
+	if (idx < 0)
+		dev_err(codec->dev, "Failed to set DMIC clock\n");
+	else
+		snd_soc_update_bits(codec, RT5670_DMIC_CTRL1,
+			RT5670_DMIC_CLK_MASK, idx << RT5670_DMIC_CLK_SFT);
+	return idx;
+}
+
+static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	unsigned int val;
+
+	val = snd_soc_read(source->codec, RT5670_GLB_CLK);
+	val &= RT5670_SCLK_SRC_MASK;
+	if (val == RT5670_SCLK_SRC_PLL1)
+		return 1;
+	else
+		return 0;
+}
+
+static int is_using_asrc(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	unsigned int reg, shift, val;
+
+	switch (source->shift) {
+	case 0:
+		reg = RT5670_ASRC_3;
+		shift = 0;
+		break;
+	case 1:
+		reg = RT5670_ASRC_3;
+		shift = 4;
+		break;
+	case 2:
+		reg = RT5670_ASRC_5;
+		shift = 12;
+		break;
+	case 3:
+		reg = RT5670_ASRC_2;
+		shift = 0;
+		break;
+	case 8:
+		reg = RT5670_ASRC_2;
+		shift = 4;
+		break;
+	case 9:
+		reg = RT5670_ASRC_2;
+		shift = 8;
+		break;
+	case 10:
+		reg = RT5670_ASRC_2;
+		shift = 12;
+		break;
+	default:
+		return 0;
+	}
+
+	val = (snd_soc_read(source->codec, reg) >> shift) & 0xf;
+	switch (val) {
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+		return 1;
+	default:
+		return 0;
+	}
+
+}
+
+/* Digital Mixer */
+static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER,
+			RT5670_M_ADC_L1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5670_STO1_ADC_MIXER,
+			RT5670_M_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_sto1_adc_r_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER,
+			RT5670_M_ADC_R1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5670_STO1_ADC_MIXER,
+			RT5670_M_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_sto2_adc_l_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO2_ADC_MIXER,
+			RT5670_M_ADC_L1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5670_STO2_ADC_MIXER,
+			RT5670_M_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_sto2_adc_r_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO2_ADC_MIXER,
+			RT5670_M_ADC_R1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5670_STO2_ADC_MIXER,
+			RT5670_M_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_mono_adc_l_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5670_MONO_ADC_MIXER,
+			RT5670_M_MONO_ADC_L1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5670_MONO_ADC_MIXER,
+			RT5670_M_MONO_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_mono_adc_r_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5670_MONO_ADC_MIXER,
+			RT5670_M_MONO_ADC_R1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5670_MONO_ADC_MIXER,
+			RT5670_M_MONO_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_dac_l_mix[] = {
+	SOC_DAPM_SINGLE("Stereo ADC Switch", RT5670_AD_DA_MIXER,
+			RT5670_M_ADCMIX_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC1 Switch", RT5670_AD_DA_MIXER,
+			RT5670_M_DAC1_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_dac_r_mix[] = {
+	SOC_DAPM_SINGLE("Stereo ADC Switch", RT5670_AD_DA_MIXER,
+			RT5670_M_ADCMIX_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC1 Switch", RT5670_AD_DA_MIXER,
+			RT5670_M_DAC1_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_sto_dac_l_mix[] = {
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_STO_DAC_MIXER,
+			RT5670_M_DAC_L1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_STO_DAC_MIXER,
+			RT5670_M_DAC_L2_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_STO_DAC_MIXER,
+			RT5670_M_DAC_R1_STO_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_sto_dac_r_mix[] = {
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_STO_DAC_MIXER,
+			RT5670_M_DAC_R1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_STO_DAC_MIXER,
+			RT5670_M_DAC_R2_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_STO_DAC_MIXER,
+			RT5670_M_DAC_L1_STO_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_mono_dac_l_mix[] = {
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_DD_MIXER,
+			RT5670_M_DAC_L1_MONO_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_DD_MIXER,
+			RT5670_M_DAC_L2_MONO_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_DD_MIXER,
+			RT5670_M_DAC_R2_MONO_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_mono_dac_r_mix[] = {
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_DD_MIXER,
+			RT5670_M_DAC_R1_MONO_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_DD_MIXER,
+			RT5670_M_DAC_R2_MONO_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_DD_MIXER,
+			RT5670_M_DAC_L2_MONO_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_dig_l_mix[] = {
+	SOC_DAPM_SINGLE("Sto DAC Mix L Switch", RT5670_DIG_MIXER,
+			RT5670_M_STO_L_DAC_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_DIG_MIXER,
+			RT5670_M_DAC_L2_DAC_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_DIG_MIXER,
+			RT5670_M_DAC_R2_DAC_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_dig_r_mix[] = {
+	SOC_DAPM_SINGLE("Sto DAC Mix R Switch", RT5670_DIG_MIXER,
+			RT5670_M_STO_R_DAC_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_DIG_MIXER,
+			RT5670_M_DAC_R2_DAC_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_DIG_MIXER,
+			RT5670_M_DAC_L2_DAC_R_SFT, 1, 1),
+};
+
+/* Analog Input Mixer */
+static const struct snd_kcontrol_new rt5670_rec_l_mix[] = {
+	SOC_DAPM_SINGLE("INL Switch", RT5670_REC_L2_MIXER,
+			RT5670_M_IN_L_RM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST2 Switch", RT5670_REC_L2_MIXER,
+			RT5670_M_BST2_RM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST1 Switch", RT5670_REC_L2_MIXER,
+			RT5670_M_BST1_RM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_rec_r_mix[] = {
+	SOC_DAPM_SINGLE("INR Switch", RT5670_REC_R2_MIXER,
+			RT5670_M_IN_R_RM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST2 Switch", RT5670_REC_R2_MIXER,
+			RT5670_M_BST2_RM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST1 Switch", RT5670_REC_R2_MIXER,
+			RT5670_M_BST1_RM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_out_l_mix[] = {
+	SOC_DAPM_SINGLE("BST1 Switch", RT5670_OUT_L1_MIXER,
+			RT5670_M_BST1_OM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INL Switch", RT5670_OUT_L1_MIXER,
+			RT5670_M_IN_L_OM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_OUT_L1_MIXER,
+			RT5670_M_DAC_L2_OM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_OUT_L1_MIXER,
+			RT5670_M_DAC_L1_OM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_out_r_mix[] = {
+	SOC_DAPM_SINGLE("BST2 Switch", RT5670_OUT_R1_MIXER,
+			RT5670_M_BST2_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INR Switch", RT5670_OUT_R1_MIXER,
+			RT5670_M_IN_R_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_OUT_R1_MIXER,
+			RT5670_M_DAC_R2_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_OUT_R1_MIXER,
+			RT5670_M_DAC_R1_OM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_hpo_mix[] = {
+	SOC_DAPM_SINGLE("DAC1 Switch", RT5670_HPO_MIXER,
+			RT5670_M_DAC1_HM_SFT, 1, 1),
+	SOC_DAPM_SINGLE("HPVOL Switch", RT5670_HPO_MIXER,
+			RT5670_M_HPVOL_HM_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_hpvoll_mix[] = {
+	SOC_DAPM_SINGLE("DAC1 Switch", RT5670_HPO_MIXER,
+			RT5670_M_DACL1_HML_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INL Switch", RT5670_HPO_MIXER,
+			RT5670_M_INL1_HML_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_hpvolr_mix[] = {
+	SOC_DAPM_SINGLE("DAC1 Switch", RT5670_HPO_MIXER,
+			RT5670_M_DACR1_HMR_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INR Switch", RT5670_HPO_MIXER,
+			RT5670_M_INR1_HMR_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_lout_mix[] = {
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_LOUT_MIXER,
+			RT5670_M_DAC_L1_LM_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_LOUT_MIXER,
+			RT5670_M_DAC_R1_LM_SFT, 1, 1),
+	SOC_DAPM_SINGLE("OUTMIX L Switch", RT5670_LOUT_MIXER,
+			RT5670_M_OV_L_LM_SFT, 1, 1),
+	SOC_DAPM_SINGLE("OUTMIX R Switch", RT5670_LOUT_MIXER,
+			RT5670_M_OV_R_LM_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_hpl_mix[] = {
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_HPO_MIXER,
+			RT5670_M_DACL1_HML_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INL1 Switch", RT5670_HPO_MIXER,
+			RT5670_M_INL1_HML_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5670_hpr_mix[] = {
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_HPO_MIXER,
+			RT5670_M_DACR1_HMR_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INR1 Switch", RT5670_HPO_MIXER,
+			RT5670_M_INR1_HMR_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new lout_l_enable_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5670_LOUT1,
+		RT5670_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new lout_r_enable_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5670_LOUT1,
+		RT5670_R_MUTE_SFT, 1, 1);
+
+/* DAC1 L/R source */ /* MX-29 [9:8] [11:10] */
+static const char * const rt5670_dac1_src[] = {
+	"IF1 DAC", "IF2 DAC"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_dac1l_enum, RT5670_AD_DA_MIXER,
+	RT5670_DAC1_L_SEL_SFT, rt5670_dac1_src);
+
+static const struct snd_kcontrol_new rt5670_dac1l_mux =
+	SOC_DAPM_ENUM("DAC1 L source", rt5670_dac1l_enum);
+
+static SOC_ENUM_SINGLE_DECL(rt5670_dac1r_enum, RT5670_AD_DA_MIXER,
+	RT5670_DAC1_R_SEL_SFT, rt5670_dac1_src);
+
+static const struct snd_kcontrol_new rt5670_dac1r_mux =
+	SOC_DAPM_ENUM("DAC1 R source", rt5670_dac1r_enum);
+
+/*DAC2 L/R source*/ /* MX-1B [6:4] [2:0] */
+/* TODO Use SOC_VALUE_ENUM_SINGLE_DECL */
+static const char * const rt5670_dac12_src[] = {
+	"IF1 DAC", "IF2 DAC", "IF3 DAC", "TxDC DAC",
+	"Bass", "VAD_ADC", "IF4 DAC"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_dac2l_enum, RT5670_DAC_CTRL,
+	RT5670_DAC2_L_SEL_SFT, rt5670_dac12_src);
+
+static const struct snd_kcontrol_new rt5670_dac_l2_mux =
+	SOC_DAPM_ENUM("DAC2 L source", rt5670_dac2l_enum);
+
+static const char * const rt5670_dacr2_src[] = {
+	"IF1 DAC", "IF2 DAC", "IF3 DAC", "TxDC DAC", "TxDP ADC", "IF4 DAC"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_dac2r_enum, RT5670_DAC_CTRL,
+	RT5670_DAC2_R_SEL_SFT, rt5670_dacr2_src);
+
+static const struct snd_kcontrol_new rt5670_dac_r2_mux =
+	SOC_DAPM_ENUM("DAC2 R source", rt5670_dac2r_enum);
+
+/*RxDP source*/ /* MX-2D [15:13] */
+static const char * const rt5670_rxdp_src[] = {
+	"IF2 DAC", "IF1 DAC", "STO1 ADC Mixer", "STO2 ADC Mixer",
+	"Mono ADC Mixer L", "Mono ADC Mixer R", "DAC1"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_rxdp_enum, RT5670_DSP_PATH1,
+	RT5670_RXDP_SEL_SFT, rt5670_rxdp_src);
+
+static const struct snd_kcontrol_new rt5670_rxdp_mux =
+	SOC_DAPM_ENUM("DAC2 L source", rt5670_rxdp_enum);
+
+/* MX-2D [1] [0] */
+static const char * const rt5670_dsp_bypass_src[] = {
+	"DSP", "Bypass"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_dsp_ul_enum, RT5670_DSP_PATH1,
+	RT5670_DSP_UL_SFT, rt5670_dsp_bypass_src);
+
+static const struct snd_kcontrol_new rt5670_dsp_ul_mux =
+	SOC_DAPM_ENUM("DSP UL source", rt5670_dsp_ul_enum);
+
+static SOC_ENUM_SINGLE_DECL(rt5670_dsp_dl_enum, RT5670_DSP_PATH1,
+	RT5670_DSP_DL_SFT, rt5670_dsp_bypass_src);
+
+static const struct snd_kcontrol_new rt5670_dsp_dl_mux =
+	SOC_DAPM_ENUM("DSP DL source", rt5670_dsp_dl_enum);
+
+/* Stereo2 ADC source */
+/* MX-26 [15] */
+static const char * const rt5670_stereo2_adc_lr_src[] = {
+	"L", "LR"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc_lr_enum, RT5670_STO2_ADC_MIXER,
+	RT5670_STO2_ADC_SRC_SFT, rt5670_stereo2_adc_lr_src);
+
+static const struct snd_kcontrol_new rt5670_sto2_adc_lr_mux =
+	SOC_DAPM_ENUM("Stereo2 ADC LR source", rt5670_stereo2_adc_lr_enum);
+
+/* Stereo1 ADC source */
+/* MX-27 MX-26 [12] */
+static const char * const rt5670_stereo_adc1_src[] = {
+	"DAC MIX", "ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc1_enum, RT5670_STO1_ADC_MIXER,
+	RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src);
+
+static const struct snd_kcontrol_new rt5670_sto_adc_l1_mux =
+	SOC_DAPM_ENUM("Stereo1 ADC L1 source", rt5670_stereo1_adc1_enum);
+
+static const struct snd_kcontrol_new rt5670_sto_adc_r1_mux =
+	SOC_DAPM_ENUM("Stereo1 ADC R1 source", rt5670_stereo1_adc1_enum);
+
+static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc1_enum, RT5670_STO2_ADC_MIXER,
+	RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src);
+
+static const struct snd_kcontrol_new rt5670_sto2_adc_l1_mux =
+	SOC_DAPM_ENUM("Stereo2 ADC L1 source", rt5670_stereo2_adc1_enum);
+
+static const struct snd_kcontrol_new rt5670_sto2_adc_r1_mux =
+	SOC_DAPM_ENUM("Stereo2 ADC R1 source", rt5670_stereo2_adc1_enum);
+
+/* MX-27 MX-26 [11] */
+static const char * const rt5670_stereo_adc2_src[] = {
+	"DAC MIX", "DMIC"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc2_enum, RT5670_STO1_ADC_MIXER,
+	RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src);
+
+static const struct snd_kcontrol_new rt5670_sto_adc_l2_mux =
+	SOC_DAPM_ENUM("Stereo1 ADC L2 source", rt5670_stereo1_adc2_enum);
+
+static const struct snd_kcontrol_new rt5670_sto_adc_r2_mux =
+	SOC_DAPM_ENUM("Stereo1 ADC R2 source", rt5670_stereo1_adc2_enum);
+
+static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc2_enum, RT5670_STO2_ADC_MIXER,
+	RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src);
+
+static const struct snd_kcontrol_new rt5670_sto2_adc_l2_mux =
+	SOC_DAPM_ENUM("Stereo2 ADC L2 source", rt5670_stereo2_adc2_enum);
+
+static const struct snd_kcontrol_new rt5670_sto2_adc_r2_mux =
+	SOC_DAPM_ENUM("Stereo2 ADC R2 source", rt5670_stereo2_adc2_enum);
+
+/* MX-27 MX26 [10] */
+static const char * const rt5670_stereo_adc_src[] = {
+	"ADC1L ADC2R", "ADC3"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc_enum, RT5670_STO1_ADC_MIXER,
+	RT5670_ADC_SRC_SFT, rt5670_stereo_adc_src);
+
+static const struct snd_kcontrol_new rt5670_sto_adc_mux =
+	SOC_DAPM_ENUM("Stereo1 ADC source", rt5670_stereo1_adc_enum);
+
+static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc_enum, RT5670_STO2_ADC_MIXER,
+	RT5670_ADC_SRC_SFT, rt5670_stereo_adc_src);
+
+static const struct snd_kcontrol_new rt5670_sto2_adc_mux =
+	SOC_DAPM_ENUM("Stereo2 ADC source", rt5670_stereo2_adc_enum);
+
+/* MX-27 MX-26 [9:8] */
+static const char * const rt5670_stereo_dmic_src[] = {
+	"DMIC1", "DMIC2", "DMIC3"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_dmic_enum, RT5670_STO1_ADC_MIXER,
+	RT5670_DMIC_SRC_SFT, rt5670_stereo_dmic_src);
+
+static const struct snd_kcontrol_new rt5670_sto1_dmic_mux =
+	SOC_DAPM_ENUM("Stereo1 DMIC source", rt5670_stereo1_dmic_enum);
+
+static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_dmic_enum, RT5670_STO2_ADC_MIXER,
+	RT5670_DMIC_SRC_SFT, rt5670_stereo_dmic_src);
+
+static const struct snd_kcontrol_new rt5670_sto2_dmic_mux =
+	SOC_DAPM_ENUM("Stereo2 DMIC source", rt5670_stereo2_dmic_enum);
+
+/* MX-27 [0] */
+static const char * const rt5670_stereo_dmic3_src[] = {
+	"DMIC3", "PDM ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_stereo_dmic3_enum, RT5670_STO1_ADC_MIXER,
+	RT5670_DMIC3_SRC_SFT, rt5670_stereo_dmic3_src);
+
+static const struct snd_kcontrol_new rt5670_sto_dmic3_mux =
+	SOC_DAPM_ENUM("Stereo DMIC3 source", rt5670_stereo_dmic3_enum);
+
+/* Mono ADC source */
+/* MX-28 [12] */
+static const char * const rt5670_mono_adc_l1_src[] = {
+	"Mono DAC MIXL", "ADC1"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_l1_enum, RT5670_MONO_ADC_MIXER,
+	RT5670_MONO_ADC_L1_SRC_SFT, rt5670_mono_adc_l1_src);
+
+static const struct snd_kcontrol_new rt5670_mono_adc_l1_mux =
+	SOC_DAPM_ENUM("Mono ADC1 left source", rt5670_mono_adc_l1_enum);
+/* MX-28 [11] */
+static const char * const rt5670_mono_adc_l2_src[] = {
+	"Mono DAC MIXL", "DMIC"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_l2_enum, RT5670_MONO_ADC_MIXER,
+	RT5670_MONO_ADC_L2_SRC_SFT, rt5670_mono_adc_l2_src);
+
+static const struct snd_kcontrol_new rt5670_mono_adc_l2_mux =
+	SOC_DAPM_ENUM("Mono ADC2 left source", rt5670_mono_adc_l2_enum);
+
+/* MX-28 [9:8] */
+static const char * const rt5670_mono_dmic_src[] = {
+	"DMIC1", "DMIC2", "DMIC3"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_mono_dmic_l_enum, RT5670_MONO_ADC_MIXER,
+	RT5670_MONO_DMIC_L_SRC_SFT, rt5670_mono_dmic_src);
+
+static const struct snd_kcontrol_new rt5670_mono_dmic_l_mux =
+	SOC_DAPM_ENUM("Mono DMIC left source", rt5670_mono_dmic_l_enum);
+/* MX-28 [1:0] */
+static SOC_ENUM_SINGLE_DECL(rt5670_mono_dmic_r_enum, RT5670_MONO_ADC_MIXER,
+	RT5670_MONO_DMIC_R_SRC_SFT, rt5670_mono_dmic_src);
+
+static const struct snd_kcontrol_new rt5670_mono_dmic_r_mux =
+	SOC_DAPM_ENUM("Mono DMIC Right source", rt5670_mono_dmic_r_enum);
+/* MX-28 [4] */
+static const char * const rt5670_mono_adc_r1_src[] = {
+	"Mono DAC MIXR", "ADC2"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_r1_enum, RT5670_MONO_ADC_MIXER,
+	RT5670_MONO_ADC_R1_SRC_SFT, rt5670_mono_adc_r1_src);
+
+static const struct snd_kcontrol_new rt5670_mono_adc_r1_mux =
+	SOC_DAPM_ENUM("Mono ADC1 right source", rt5670_mono_adc_r1_enum);
+/* MX-28 [3] */
+static const char * const rt5670_mono_adc_r2_src[] = {
+	"Mono DAC MIXR", "DMIC"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_r2_enum, RT5670_MONO_ADC_MIXER,
+	RT5670_MONO_ADC_R2_SRC_SFT, rt5670_mono_adc_r2_src);
+
+static const struct snd_kcontrol_new rt5670_mono_adc_r2_mux =
+	SOC_DAPM_ENUM("Mono ADC2 right source", rt5670_mono_adc_r2_enum);
+
+/* MX-2D [3:2] */
+static const char * const rt5670_txdp_slot_src[] = {
+	"Slot 0-1", "Slot 2-3", "Slot 4-5", "Slot 6-7"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_txdp_slot_enum, RT5670_DSP_PATH1,
+	RT5670_TXDP_SLOT_SEL_SFT, rt5670_txdp_slot_src);
+
+static const struct snd_kcontrol_new rt5670_txdp_slot_mux =
+	SOC_DAPM_ENUM("TxDP Slot source", rt5670_txdp_slot_enum);
+
+/* MX-2F [15] */
+static const char * const rt5670_if1_adc2_in_src[] = {
+	"IF_ADC2", "VAD_ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc2_in_enum, RT5670_DIG_INF1_DATA,
+	RT5670_IF1_ADC2_IN_SFT, rt5670_if1_adc2_in_src);
+
+static const struct snd_kcontrol_new rt5670_if1_adc2_in_mux =
+	SOC_DAPM_ENUM("IF1 ADC2 IN source", rt5670_if1_adc2_in_enum);
+
+/* MX-2F [14:12] */
+static const char * const rt5670_if2_adc_in_src[] = {
+	"IF_ADC1", "IF_ADC2", "IF_ADC3", "TxDC_DAC", "TxDP_ADC", "VAD_ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_if2_adc_in_enum, RT5670_DIG_INF1_DATA,
+	RT5670_IF2_ADC_IN_SFT, rt5670_if2_adc_in_src);
+
+static const struct snd_kcontrol_new rt5670_if2_adc_in_mux =
+	SOC_DAPM_ENUM("IF2 ADC IN source", rt5670_if2_adc_in_enum);
+
+/* MX-30 [5:4] */
+static const char * const rt5670_if4_adc_in_src[] = {
+	"IF_ADC1", "IF_ADC2", "IF_ADC3"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_if4_adc_in_enum, RT5670_DIG_INF2_DATA,
+	RT5670_IF4_ADC_IN_SFT, rt5670_if4_adc_in_src);
+
+static const struct snd_kcontrol_new rt5670_if4_adc_in_mux =
+	SOC_DAPM_ENUM("IF4 ADC IN source", rt5670_if4_adc_in_enum);
+
+/* MX-31 [15] [13] [11] [9] */
+static const char * const rt5670_pdm_src[] = {
+	"Mono DAC", "Stereo DAC"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_pdm1_l_enum, RT5670_PDM_OUT_CTRL,
+	RT5670_PDM1_L_SFT, rt5670_pdm_src);
+
+static const struct snd_kcontrol_new rt5670_pdm1_l_mux =
+	SOC_DAPM_ENUM("PDM1 L source", rt5670_pdm1_l_enum);
+
+static SOC_ENUM_SINGLE_DECL(rt5670_pdm1_r_enum, RT5670_PDM_OUT_CTRL,
+	RT5670_PDM1_R_SFT, rt5670_pdm_src);
+
+static const struct snd_kcontrol_new rt5670_pdm1_r_mux =
+	SOC_DAPM_ENUM("PDM1 R source", rt5670_pdm1_r_enum);
+
+static SOC_ENUM_SINGLE_DECL(rt5670_pdm2_l_enum, RT5670_PDM_OUT_CTRL,
+	RT5670_PDM2_L_SFT, rt5670_pdm_src);
+
+static const struct snd_kcontrol_new rt5670_pdm2_l_mux =
+	SOC_DAPM_ENUM("PDM2 L source", rt5670_pdm2_l_enum);
+
+static SOC_ENUM_SINGLE_DECL(rt5670_pdm2_r_enum, RT5670_PDM_OUT_CTRL,
+	RT5670_PDM2_R_SFT, rt5670_pdm_src);
+
+static const struct snd_kcontrol_new rt5670_pdm2_r_mux =
+	SOC_DAPM_ENUM("PDM2 R source", rt5670_pdm2_r_enum);
+
+/* MX-FA [12] */
+static const char * const rt5670_if1_adc1_in1_src[] = {
+	"IF_ADC1", "IF1_ADC3"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc1_in1_enum, RT5670_DIG_MISC,
+	RT5670_IF1_ADC1_IN1_SFT, rt5670_if1_adc1_in1_src);
+
+static const struct snd_kcontrol_new rt5670_if1_adc1_in1_mux =
+	SOC_DAPM_ENUM("IF1 ADC1 IN1 source", rt5670_if1_adc1_in1_enum);
+
+/* MX-FA [11] */
+static const char * const rt5670_if1_adc1_in2_src[] = {
+	"IF1_ADC1_IN1", "IF1_ADC4"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc1_in2_enum, RT5670_DIG_MISC,
+	RT5670_IF1_ADC1_IN2_SFT, rt5670_if1_adc1_in2_src);
+
+static const struct snd_kcontrol_new rt5670_if1_adc1_in2_mux =
+	SOC_DAPM_ENUM("IF1 ADC1 IN2 source", rt5670_if1_adc1_in2_enum);
+
+/* MX-FA [10] */
+static const char * const rt5670_if1_adc2_in1_src[] = {
+	"IF1_ADC2_IN", "IF1_ADC4"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc2_in1_enum, RT5670_DIG_MISC,
+	RT5670_IF1_ADC2_IN1_SFT, rt5670_if1_adc2_in1_src);
+
+static const struct snd_kcontrol_new rt5670_if1_adc2_in1_mux =
+	SOC_DAPM_ENUM("IF1 ADC2 IN1 source", rt5670_if1_adc2_in1_enum);
+
+/* MX-9D [9:8] */
+static const char * const rt5670_vad_adc_src[] = {
+	"Sto1 ADC L", "Mono ADC L", "Mono ADC R", "Sto2 ADC L"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5670_vad_adc_enum, RT5670_VAD_CTRL4,
+	RT5670_VAD_SEL_SFT, rt5670_vad_adc_src);
+
+static const struct snd_kcontrol_new rt5670_vad_adc_mux =
+	SOC_DAPM_ENUM("VAD ADC source", rt5670_vad_adc_enum);
+
+static int rt5670_hp_power_event(struct snd_soc_dapm_widget *w,
+			   struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		regmap_update_bits(rt5670->regmap, RT5670_CHARGE_PUMP,
+			RT5670_PM_HP_MASK, RT5670_PM_HP_HV);
+		regmap_update_bits(rt5670->regmap, RT5670_GEN_CTRL2,
+			0x0400, 0x0400);
+		/* headphone amp power on */
+		regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1,
+			RT5670_PWR_HA |	RT5670_PWR_FV1 |
+			RT5670_PWR_FV2,	RT5670_PWR_HA |
+			RT5670_PWR_FV1 | RT5670_PWR_FV2);
+		/* depop parameters */
+		regmap_write(rt5670->regmap, RT5670_DEPOP_M2, 0x3100);
+		regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x8009);
+		regmap_write(rt5670->regmap, RT5670_PR_BASE +
+			RT5670_HP_DCC_INT1, 0x9f00);
+		mdelay(20);
+		regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x8019);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x0004);
+		msleep(30);
+		break;
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5670_hp_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		/* headphone unmute sequence */
+		regmap_write(rt5670->regmap, RT5670_PR_BASE +
+				RT5670_MAMP_INT_REG2, 0xb400);
+		regmap_write(rt5670->regmap, RT5670_DEPOP_M3, 0x0772);
+		regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x805d);
+		regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x831d);
+		regmap_update_bits(rt5670->regmap, RT5670_GEN_CTRL2,
+				0x0300, 0x0300);
+		regmap_update_bits(rt5670->regmap, RT5670_HP_VOL,
+			RT5670_L_MUTE | RT5670_R_MUTE, 0);
+		msleep(80);
+		regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x8019);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		/* headphone mute sequence */
+		regmap_write(rt5670->regmap, RT5670_PR_BASE +
+				RT5670_MAMP_INT_REG2, 0xb400);
+		regmap_write(rt5670->regmap, RT5670_DEPOP_M3, 0x0772);
+		regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x803d);
+		mdelay(10);
+		regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x831d);
+		mdelay(10);
+		regmap_update_bits(rt5670->regmap, RT5670_HP_VOL,
+				   RT5670_L_MUTE | RT5670_R_MUTE,
+				   RT5670_L_MUTE | RT5670_R_MUTE);
+		msleep(20);
+		regmap_update_bits(rt5670->regmap,
+				   RT5670_GEN_CTRL2, 0x0300, 0x0);
+		regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x8019);
+		regmap_write(rt5670->regmap, RT5670_DEPOP_M3, 0x0707);
+		regmap_write(rt5670->regmap, RT5670_PR_BASE +
+				RT5670_MAMP_INT_REG2, 0xfc00);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5670_bst1_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, RT5670_PWR_ANLG2,
+				    RT5670_PWR_BST1_P, RT5670_PWR_BST1_P);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, RT5670_PWR_ANLG2,
+				    RT5670_PWR_BST1_P, 0);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5670_bst2_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, RT5670_PWR_ANLG2,
+				    RT5670_PWR_BST2_P, RT5670_PWR_BST2_P);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, RT5670_PWR_ANLG2,
+				    RT5670_PWR_BST2_P, 0);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget rt5670_dapm_widgets[] = {
+	SND_SOC_DAPM_SUPPLY("PLL1", RT5670_PWR_ANLG2,
+			    RT5670_PWR_PLL_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("I2S DSP", RT5670_PWR_DIG2,
+			    RT5670_PWR_I2S_DSP_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5670_PWR_VOL,
+			    RT5670_PWR_MIC_DET_BIT, 0, NULL, 0),
+
+	/* ASRC */
+	SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5670_ASRC_1,
+			      11, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5670_ASRC_1,
+			      12, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("DAC STO ASRC", 1, RT5670_ASRC_1,
+			      10, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("DAC MONO L ASRC", 1, RT5670_ASRC_1,
+			      9, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("DAC MONO R ASRC", 1, RT5670_ASRC_1,
+			      8, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("ADC STO1 ASRC", 1, RT5670_ASRC_1,
+			      3, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("ADC STO2 ASRC", 1, RT5670_ASRC_1,
+			      2, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("ADC MONO L ASRC", 1, RT5670_ASRC_1,
+			      1, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("ADC MONO R ASRC", 1, RT5670_ASRC_1,
+			      0, 0, NULL, 0),
+
+	/* Input Side */
+	/* micbias */
+	SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5670_PWR_ANLG2,
+			     RT5670_PWR_MB1_BIT, 0, NULL, 0),
+
+	/* Input Lines */
+	SND_SOC_DAPM_INPUT("DMIC L1"),
+	SND_SOC_DAPM_INPUT("DMIC R1"),
+	SND_SOC_DAPM_INPUT("DMIC L2"),
+	SND_SOC_DAPM_INPUT("DMIC R2"),
+	SND_SOC_DAPM_INPUT("DMIC L3"),
+	SND_SOC_DAPM_INPUT("DMIC R3"),
+
+	SND_SOC_DAPM_INPUT("IN1P"),
+	SND_SOC_DAPM_INPUT("IN1N"),
+	SND_SOC_DAPM_INPUT("IN2P"),
+	SND_SOC_DAPM_INPUT("IN2N"),
+
+	SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DMIC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0,
+			    set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5670_DMIC_CTRL1,
+			    RT5670_DMIC_1_EN_SFT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5670_DMIC_CTRL1,
+			    RT5670_DMIC_2_EN_SFT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DMIC3 Power", RT5670_DMIC_CTRL1,
+			    RT5670_DMIC_3_EN_SFT, 0, NULL, 0),
+	/* Boost */
+	SND_SOC_DAPM_PGA_E("BST1", RT5670_PWR_ANLG2, RT5670_PWR_BST1_BIT,
+			   0, NULL, 0, rt5670_bst1_event,
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_PGA_E("BST2", RT5670_PWR_ANLG2, RT5670_PWR_BST2_BIT,
+			   0, NULL, 0, rt5670_bst2_event,
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	/* Input Volume */
+	SND_SOC_DAPM_PGA("INL VOL", RT5670_PWR_VOL,
+			 RT5670_PWR_IN_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("INR VOL", RT5670_PWR_VOL,
+			 RT5670_PWR_IN_R_BIT, 0, NULL, 0),
+
+	/* REC Mixer */
+	SND_SOC_DAPM_MIXER("RECMIXL", RT5670_PWR_MIXER, RT5670_PWR_RM_L_BIT, 0,
+			   rt5670_rec_l_mix, ARRAY_SIZE(rt5670_rec_l_mix)),
+	SND_SOC_DAPM_MIXER("RECMIXR", RT5670_PWR_MIXER, RT5670_PWR_RM_R_BIT, 0,
+			   rt5670_rec_r_mix, ARRAY_SIZE(rt5670_rec_r_mix)),
+	/* ADCs */
+	SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_ADC("ADC 2", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_PGA("ADC 1_2", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_SUPPLY("ADC 1 power", RT5670_PWR_DIG1,
+			    RT5670_PWR_ADC_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("ADC 2 power", RT5670_PWR_DIG1,
+			    RT5670_PWR_ADC_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("ADC clock", RT5670_PR_BASE +
+			    RT5670_CHOP_DAC_ADC, 12, 0, NULL, 0),
+	/* ADC Mux */
+	SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_sto1_dmic_mux),
+	SND_SOC_DAPM_MUX("Stereo1 ADC L2 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_sto_adc_l2_mux),
+	SND_SOC_DAPM_MUX("Stereo1 ADC R2 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_sto_adc_r2_mux),
+	SND_SOC_DAPM_MUX("Stereo1 ADC L1 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_sto_adc_l1_mux),
+	SND_SOC_DAPM_MUX("Stereo1 ADC R1 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_sto_adc_r1_mux),
+	SND_SOC_DAPM_MUX("Stereo2 DMIC Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_sto2_dmic_mux),
+	SND_SOC_DAPM_MUX("Stereo2 ADC L2 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_sto2_adc_l2_mux),
+	SND_SOC_DAPM_MUX("Stereo2 ADC R2 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_sto2_adc_r2_mux),
+	SND_SOC_DAPM_MUX("Stereo2 ADC L1 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_sto2_adc_l1_mux),
+	SND_SOC_DAPM_MUX("Stereo2 ADC R1 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_sto2_adc_r1_mux),
+	SND_SOC_DAPM_MUX("Stereo2 ADC LR Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_sto2_adc_lr_mux),
+	SND_SOC_DAPM_MUX("Mono DMIC L Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_mono_dmic_l_mux),
+	SND_SOC_DAPM_MUX("Mono DMIC R Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_mono_dmic_r_mux),
+	SND_SOC_DAPM_MUX("Mono ADC L2 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_mono_adc_l2_mux),
+	SND_SOC_DAPM_MUX("Mono ADC L1 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_mono_adc_l1_mux),
+	SND_SOC_DAPM_MUX("Mono ADC R1 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_mono_adc_r1_mux),
+	SND_SOC_DAPM_MUX("Mono ADC R2 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_mono_adc_r2_mux),
+	/* ADC Mixer */
+	SND_SOC_DAPM_SUPPLY("ADC Stereo1 Filter", RT5670_PWR_DIG2,
+			    RT5670_PWR_ADC_S1F_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("ADC Stereo2 Filter", RT5670_PWR_DIG2,
+			    RT5670_PWR_ADC_S2F_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", RT5670_STO1_ADC_DIG_VOL,
+			   RT5670_L_MUTE_SFT, 1, rt5670_sto1_adc_l_mix,
+			   ARRAY_SIZE(rt5670_sto1_adc_l_mix)),
+	SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", RT5670_STO1_ADC_DIG_VOL,
+			   RT5670_R_MUTE_SFT, 1, rt5670_sto1_adc_r_mix,
+			   ARRAY_SIZE(rt5670_sto1_adc_r_mix)),
+	SND_SOC_DAPM_MIXER("Sto2 ADC MIXL", SND_SOC_NOPM, 0, 0,
+			   rt5670_sto2_adc_l_mix,
+			   ARRAY_SIZE(rt5670_sto2_adc_l_mix)),
+	SND_SOC_DAPM_MIXER("Sto2 ADC MIXR", SND_SOC_NOPM, 0, 0,
+			   rt5670_sto2_adc_r_mix,
+			   ARRAY_SIZE(rt5670_sto2_adc_r_mix)),
+	SND_SOC_DAPM_SUPPLY("ADC Mono Left Filter", RT5670_PWR_DIG2,
+			    RT5670_PWR_ADC_MF_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("Mono ADC MIXL", RT5670_MONO_ADC_DIG_VOL,
+			   RT5670_L_MUTE_SFT, 1, rt5670_mono_adc_l_mix,
+			   ARRAY_SIZE(rt5670_mono_adc_l_mix)),
+	SND_SOC_DAPM_SUPPLY("ADC Mono Right Filter", RT5670_PWR_DIG2,
+			    RT5670_PWR_ADC_MF_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("Mono ADC MIXR", RT5670_MONO_ADC_DIG_VOL,
+			   RT5670_R_MUTE_SFT, 1, rt5670_mono_adc_r_mix,
+			   ARRAY_SIZE(rt5670_mono_adc_r_mix)),
+
+	/* ADC PGA */
+	SND_SOC_DAPM_PGA("Stereo1 ADC MIXL", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Stereo1 ADC MIXR", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Stereo2 ADC MIXL", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Stereo2 ADC MIXR", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Sto2 ADC LR MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Stereo2 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Mono ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("VAD_ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* DSP */
+	SND_SOC_DAPM_PGA("TxDP_ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("TxDP_ADC_L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("TxDP_ADC_R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("TxDC_DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("TDM Data Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_txdp_slot_mux),
+
+	SND_SOC_DAPM_MUX("DSP UL Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_dsp_ul_mux),
+	SND_SOC_DAPM_MUX("DSP DL Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_dsp_dl_mux),
+
+	SND_SOC_DAPM_MUX("RxDP Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_rxdp_mux),
+
+	/* IF2 Mux */
+	SND_SOC_DAPM_MUX("IF2 ADC Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_if2_adc_in_mux),
+
+	/* Digital Interface */
+	SND_SOC_DAPM_SUPPLY("I2S1", RT5670_PWR_DIG1,
+			    RT5670_PWR_I2S1_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC2 L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC2 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("I2S2", RT5670_PWR_DIG1,
+			    RT5670_PWR_I2S2_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF2 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF2 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF2 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF2 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF2 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF2 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* Digital Interface Select */
+	SND_SOC_DAPM_MUX("IF1 ADC1 IN1 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_if1_adc1_in1_mux),
+	SND_SOC_DAPM_MUX("IF1 ADC1 IN2 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_if1_adc1_in2_mux),
+	SND_SOC_DAPM_MUX("IF1 ADC2 IN Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_if1_adc2_in_mux),
+	SND_SOC_DAPM_MUX("IF1 ADC2 IN1 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_if1_adc2_in1_mux),
+	SND_SOC_DAPM_MUX("VAD ADC Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_vad_adc_mux),
+
+	/* Audio Interface */
+	SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0,
+			     RT5670_GPIO_CTRL1, RT5670_I2S2_PIN_SFT, 1),
+
+	/* Audio DSP */
+	SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* Output Side */
+	/* DAC mixer before sound effect  */
+	SND_SOC_DAPM_MIXER("DAC1 MIXL", SND_SOC_NOPM, 0, 0,
+			   rt5670_dac_l_mix, ARRAY_SIZE(rt5670_dac_l_mix)),
+	SND_SOC_DAPM_MIXER("DAC1 MIXR", SND_SOC_NOPM, 0, 0,
+			   rt5670_dac_r_mix, ARRAY_SIZE(rt5670_dac_r_mix)),
+	SND_SOC_DAPM_PGA("DAC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* DAC2 channel Mux */
+	SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_dac_l2_mux),
+	SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5670_dac_r2_mux),
+	SND_SOC_DAPM_PGA("DAC L2 Volume", RT5670_PWR_DIG1,
+			 RT5670_PWR_DAC_L2_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DAC R2 Volume", RT5670_PWR_DIG1,
+			 RT5670_PWR_DAC_R2_BIT, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("DAC1 L Mux", SND_SOC_NOPM, 0, 0, &rt5670_dac1l_mux),
+	SND_SOC_DAPM_MUX("DAC1 R Mux", SND_SOC_NOPM, 0, 0, &rt5670_dac1r_mux),
+
+	/* DAC Mixer */
+	SND_SOC_DAPM_SUPPLY("DAC Stereo1 Filter", RT5670_PWR_DIG2,
+			    RT5670_PWR_DAC_S1F_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DAC Mono Left Filter", RT5670_PWR_DIG2,
+			    RT5670_PWR_DAC_MF_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DAC Mono Right Filter", RT5670_PWR_DIG2,
+			    RT5670_PWR_DAC_MF_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+			   rt5670_sto_dac_l_mix,
+			   ARRAY_SIZE(rt5670_sto_dac_l_mix)),
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+			   rt5670_sto_dac_r_mix,
+			   ARRAY_SIZE(rt5670_sto_dac_r_mix)),
+	SND_SOC_DAPM_MIXER("Mono DAC MIXL", SND_SOC_NOPM, 0, 0,
+			   rt5670_mono_dac_l_mix,
+			   ARRAY_SIZE(rt5670_mono_dac_l_mix)),
+	SND_SOC_DAPM_MIXER("Mono DAC MIXR", SND_SOC_NOPM, 0, 0,
+			   rt5670_mono_dac_r_mix,
+			   ARRAY_SIZE(rt5670_mono_dac_r_mix)),
+	SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0,
+			   rt5670_dig_l_mix,
+			   ARRAY_SIZE(rt5670_dig_l_mix)),
+	SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0,
+			   rt5670_dig_r_mix,
+			   ARRAY_SIZE(rt5670_dig_r_mix)),
+
+	/* DACs */
+	SND_SOC_DAPM_SUPPLY("DAC L1 Power", RT5670_PWR_DIG1,
+			    RT5670_PWR_DAC_L1_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DAC R1 Power", RT5670_PWR_DIG1,
+			    RT5670_PWR_DAC_R1_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_DAC("DAC L1", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_DAC("DAC R1", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_DAC("DAC L2", NULL, RT5670_PWR_DIG1,
+			 RT5670_PWR_DAC_L2_BIT, 0),
+
+	SND_SOC_DAPM_DAC("DAC R2", NULL, RT5670_PWR_DIG1,
+			 RT5670_PWR_DAC_R2_BIT, 0),
+	/* OUT Mixer */
+
+	SND_SOC_DAPM_MIXER("OUT MIXL", RT5670_PWR_MIXER, RT5670_PWR_OM_L_BIT,
+			   0, rt5670_out_l_mix, ARRAY_SIZE(rt5670_out_l_mix)),
+	SND_SOC_DAPM_MIXER("OUT MIXR", RT5670_PWR_MIXER, RT5670_PWR_OM_R_BIT,
+			   0, rt5670_out_r_mix, ARRAY_SIZE(rt5670_out_r_mix)),
+	/* Ouput Volume */
+	SND_SOC_DAPM_MIXER("HPOVOL MIXL", RT5670_PWR_VOL,
+			   RT5670_PWR_HV_L_BIT, 0,
+			   rt5670_hpvoll_mix, ARRAY_SIZE(rt5670_hpvoll_mix)),
+	SND_SOC_DAPM_MIXER("HPOVOL MIXR", RT5670_PWR_VOL,
+			   RT5670_PWR_HV_R_BIT, 0,
+			   rt5670_hpvolr_mix, ARRAY_SIZE(rt5670_hpvolr_mix)),
+	SND_SOC_DAPM_PGA("DAC 1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DAC 2", SND_SOC_NOPM,	0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("HPOVOL", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* HPO/LOUT/Mono Mixer */
+	SND_SOC_DAPM_MIXER("HPO MIX", SND_SOC_NOPM, 0, 0,
+			   rt5670_hpo_mix, ARRAY_SIZE(rt5670_hpo_mix)),
+	SND_SOC_DAPM_MIXER("LOUT MIX", RT5670_PWR_ANLG1, RT5670_PWR_LM_BIT,
+			   0, rt5670_lout_mix, ARRAY_SIZE(rt5670_lout_mix)),
+	SND_SOC_DAPM_SUPPLY_S("Improve HP Amp Drv", 1, SND_SOC_NOPM, 0, 0,
+			      rt5670_hp_power_event, SND_SOC_DAPM_POST_PMU |
+			      SND_SOC_DAPM_PRE_PMD),
+	SND_SOC_DAPM_SUPPLY("HP L Amp", RT5670_PWR_ANLG1,
+			    RT5670_PWR_HP_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("HP R Amp", RT5670_PWR_ANLG1,
+			    RT5670_PWR_HP_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0,
+			   rt5670_hp_event, SND_SOC_DAPM_PRE_PMD |
+			   SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_SWITCH("LOUT L Playback", SND_SOC_NOPM, 0, 0,
+			    &lout_l_enable_control),
+	SND_SOC_DAPM_SWITCH("LOUT R Playback", SND_SOC_NOPM, 0, 0,
+			    &lout_r_enable_control),
+	SND_SOC_DAPM_PGA("LOUT Amp", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* PDM */
+	SND_SOC_DAPM_SUPPLY("PDM1 Power", RT5670_PWR_DIG2,
+		RT5670_PWR_PDM1_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("PDM2 Power", RT5670_PWR_DIG2,
+		RT5670_PWR_PDM2_BIT, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("PDM1 L Mux", RT5670_PDM_OUT_CTRL,
+			 RT5670_M_PDM1_L_SFT, 1, &rt5670_pdm1_l_mux),
+	SND_SOC_DAPM_MUX("PDM1 R Mux", RT5670_PDM_OUT_CTRL,
+			 RT5670_M_PDM1_R_SFT, 1, &rt5670_pdm1_r_mux),
+	SND_SOC_DAPM_MUX("PDM2 L Mux", RT5670_PDM_OUT_CTRL,
+			 RT5670_M_PDM2_L_SFT, 1, &rt5670_pdm2_l_mux),
+	SND_SOC_DAPM_MUX("PDM2 R Mux", RT5670_PDM_OUT_CTRL,
+			 RT5670_M_PDM2_R_SFT, 1, &rt5670_pdm2_r_mux),
+
+	/* Output Lines */
+	SND_SOC_DAPM_OUTPUT("HPOL"),
+	SND_SOC_DAPM_OUTPUT("HPOR"),
+	SND_SOC_DAPM_OUTPUT("LOUTL"),
+	SND_SOC_DAPM_OUTPUT("LOUTR"),
+	SND_SOC_DAPM_OUTPUT("PDM1L"),
+	SND_SOC_DAPM_OUTPUT("PDM1R"),
+	SND_SOC_DAPM_OUTPUT("PDM2L"),
+	SND_SOC_DAPM_OUTPUT("PDM2R"),
+};
+
+static const struct snd_soc_dapm_route rt5670_dapm_routes[] = {
+	{ "ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc },
+	{ "ADC Stereo2 Filter", NULL, "ADC STO2 ASRC", is_using_asrc },
+	{ "ADC Mono Left Filter", NULL, "ADC MONO L ASRC", is_using_asrc },
+	{ "ADC Mono Right Filter", NULL, "ADC MONO R ASRC", is_using_asrc },
+	{ "DAC Mono Left Filter", NULL, "DAC MONO L ASRC", is_using_asrc },
+	{ "DAC Mono Right Filter", NULL, "DAC MONO R ASRC", is_using_asrc },
+	{ "DAC Stereo1 Filter", NULL, "DAC STO ASRC", is_using_asrc },
+
+	{ "I2S1", NULL, "I2S1 ASRC" },
+	{ "I2S2", NULL, "I2S2 ASRC" },
+
+	{ "DMIC1", NULL, "DMIC L1" },
+	{ "DMIC1", NULL, "DMIC R1" },
+	{ "DMIC2", NULL, "DMIC L2" },
+	{ "DMIC2", NULL, "DMIC R2" },
+	{ "DMIC3", NULL, "DMIC L3" },
+	{ "DMIC3", NULL, "DMIC R3" },
+
+	{ "BST1", NULL, "IN1P" },
+	{ "BST1", NULL, "IN1N" },
+	{ "BST1", NULL, "Mic Det Power" },
+	{ "BST2", NULL, "IN2P" },
+	{ "BST2", NULL, "IN2N" },
+
+	{ "INL VOL", NULL, "IN2P" },
+	{ "INR VOL", NULL, "IN2N" },
+
+	{ "RECMIXL", "INL Switch", "INL VOL" },
+	{ "RECMIXL", "BST2 Switch", "BST2" },
+	{ "RECMIXL", "BST1 Switch", "BST1" },
+
+	{ "RECMIXR", "INR Switch", "INR VOL" },
+	{ "RECMIXR", "BST2 Switch", "BST2" },
+	{ "RECMIXR", "BST1 Switch", "BST1" },
+
+	{ "ADC 1", NULL, "RECMIXL" },
+	{ "ADC 1", NULL, "ADC 1 power" },
+	{ "ADC 1", NULL, "ADC clock" },
+	{ "ADC 2", NULL, "RECMIXR" },
+	{ "ADC 2", NULL, "ADC 2 power" },
+	{ "ADC 2", NULL, "ADC clock" },
+
+	{ "DMIC L1", NULL, "DMIC CLK" },
+	{ "DMIC L1", NULL, "DMIC1 Power" },
+	{ "DMIC R1", NULL, "DMIC CLK" },
+	{ "DMIC R1", NULL, "DMIC1 Power" },
+	{ "DMIC L2", NULL, "DMIC CLK" },
+	{ "DMIC L2", NULL, "DMIC2 Power" },
+	{ "DMIC R2", NULL, "DMIC CLK" },
+	{ "DMIC R2", NULL, "DMIC2 Power" },
+	{ "DMIC L3", NULL, "DMIC CLK" },
+	{ "DMIC L3", NULL, "DMIC3 Power" },
+	{ "DMIC R3", NULL, "DMIC CLK" },
+	{ "DMIC R3", NULL, "DMIC3 Power" },
+
+	{ "Stereo1 DMIC Mux", "DMIC1", "DMIC1" },
+	{ "Stereo1 DMIC Mux", "DMIC2", "DMIC2" },
+	{ "Stereo1 DMIC Mux", "DMIC3", "DMIC3" },
+
+	{ "Stereo2 DMIC Mux", "DMIC1", "DMIC1" },
+	{ "Stereo2 DMIC Mux", "DMIC2", "DMIC2" },
+	{ "Stereo2 DMIC Mux", "DMIC3", "DMIC3" },
+
+	{ "Mono DMIC L Mux", "DMIC1", "DMIC L1" },
+	{ "Mono DMIC L Mux", "DMIC2", "DMIC L2" },
+	{ "Mono DMIC L Mux", "DMIC3", "DMIC L3" },
+
+	{ "Mono DMIC R Mux", "DMIC1", "DMIC R1" },
+	{ "Mono DMIC R Mux", "DMIC2", "DMIC R2" },
+	{ "Mono DMIC R Mux", "DMIC3", "DMIC R3" },
+
+	{ "ADC 1_2", NULL, "ADC 1" },
+	{ "ADC 1_2", NULL, "ADC 2" },
+
+	{ "Stereo1 ADC L2 Mux", "DMIC", "Stereo1 DMIC Mux" },
+	{ "Stereo1 ADC L2 Mux", "DAC MIX", "DAC MIXL" },
+	{ "Stereo1 ADC L1 Mux", "ADC", "ADC 1_2" },
+	{ "Stereo1 ADC L1 Mux", "DAC MIX", "DAC MIXL" },
+
+	{ "Stereo1 ADC R1 Mux", "ADC", "ADC 1_2" },
+	{ "Stereo1 ADC R1 Mux", "DAC MIX", "DAC MIXR" },
+	{ "Stereo1 ADC R2 Mux", "DMIC", "Stereo1 DMIC Mux" },
+	{ "Stereo1 ADC R2 Mux", "DAC MIX", "DAC MIXR" },
+
+	{ "Mono ADC L2 Mux", "DMIC", "Mono DMIC L Mux" },
+	{ "Mono ADC L2 Mux", "Mono DAC MIXL", "Mono DAC MIXL" },
+	{ "Mono ADC L1 Mux", "Mono DAC MIXL", "Mono DAC MIXL" },
+	{ "Mono ADC L1 Mux", "ADC1",  "ADC 1" },
+
+	{ "Mono ADC R1 Mux", "Mono DAC MIXR", "Mono DAC MIXR" },
+	{ "Mono ADC R1 Mux", "ADC2", "ADC 2" },
+	{ "Mono ADC R2 Mux", "DMIC", "Mono DMIC R Mux" },
+	{ "Mono ADC R2 Mux", "Mono DAC MIXR", "Mono DAC MIXR" },
+
+	{ "Sto1 ADC MIXL", "ADC1 Switch", "Stereo1 ADC L1 Mux" },
+	{ "Sto1 ADC MIXL", "ADC2 Switch", "Stereo1 ADC L2 Mux" },
+	{ "Sto1 ADC MIXR", "ADC1 Switch", "Stereo1 ADC R1 Mux" },
+	{ "Sto1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux" },
+
+	{ "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" },
+	{ "Stereo1 ADC MIXL", NULL, "ADC Stereo1 Filter" },
+	{ "ADC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+	{ "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" },
+	{ "Stereo1 ADC MIXR", NULL, "ADC Stereo1 Filter" },
+	{ "ADC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+	{ "Mono ADC MIXL", "ADC1 Switch", "Mono ADC L1 Mux" },
+	{ "Mono ADC MIXL", "ADC2 Switch", "Mono ADC L2 Mux" },
+	{ "Mono ADC MIXL", NULL, "ADC Mono Left Filter" },
+	{ "ADC Mono Left Filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+	{ "Mono ADC MIXR", "ADC1 Switch", "Mono ADC R1 Mux" },
+	{ "Mono ADC MIXR", "ADC2 Switch", "Mono ADC R2 Mux" },
+	{ "Mono ADC MIXR", NULL, "ADC Mono Right Filter" },
+	{ "ADC Mono Right Filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+	{ "Stereo2 ADC L2 Mux", "DMIC", "Stereo2 DMIC Mux" },
+	{ "Stereo2 ADC L2 Mux", "DAC MIX", "DAC MIXL" },
+	{ "Stereo2 ADC L1 Mux", "ADC", "ADC 1_2" },
+	{ "Stereo2 ADC L1 Mux", "DAC MIX", "DAC MIXL" },
+
+	{ "Stereo2 ADC R1 Mux", "ADC", "ADC 1_2" },
+	{ "Stereo2 ADC R1 Mux", "DAC MIX", "DAC MIXR" },
+	{ "Stereo2 ADC R2 Mux", "DMIC", "Stereo2 DMIC Mux" },
+	{ "Stereo2 ADC R2 Mux", "DAC MIX", "DAC MIXR" },
+
+	{ "Sto2 ADC MIXL", "ADC1 Switch", "Stereo2 ADC L1 Mux" },
+	{ "Sto2 ADC MIXL", "ADC2 Switch", "Stereo2 ADC L2 Mux" },
+	{ "Sto2 ADC MIXR", "ADC1 Switch", "Stereo2 ADC R1 Mux" },
+	{ "Sto2 ADC MIXR", "ADC2 Switch", "Stereo2 ADC R2 Mux" },
+
+	{ "Sto2 ADC LR MIX", NULL, "Sto2 ADC MIXL" },
+	{ "Sto2 ADC LR MIX", NULL, "Sto2 ADC MIXR" },
+
+	{ "Stereo2 ADC LR Mux", "L", "Sto2 ADC MIXL" },
+	{ "Stereo2 ADC LR Mux", "LR", "Sto2 ADC LR MIX" },
+
+	{ "Stereo2 ADC MIXL", NULL, "Stereo2 ADC LR Mux" },
+	{ "Stereo2 ADC MIXL", NULL, "ADC Stereo2 Filter" },
+	{ "ADC Stereo2 Filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+	{ "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" },
+	{ "Stereo2 ADC MIXR", NULL, "ADC Stereo2 Filter" },
+	{ "ADC Stereo2 Filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+	{ "VAD ADC Mux", "Sto1 ADC L", "Stereo1 ADC MIXL" },
+	{ "VAD ADC Mux", "Mono ADC L", "Mono ADC MIXL" },
+	{ "VAD ADC Mux", "Mono ADC R", "Mono ADC MIXR" },
+	{ "VAD ADC Mux", "Sto2 ADC L", "Sto2 ADC MIXL" },
+
+	{ "VAD_ADC", NULL, "VAD ADC Mux" },
+
+	{ "IF_ADC1", NULL, "Stereo1 ADC MIXL" },
+	{ "IF_ADC1", NULL, "Stereo1 ADC MIXR" },
+	{ "IF_ADC2", NULL, "Mono ADC MIXL" },
+	{ "IF_ADC2", NULL, "Mono ADC MIXR" },
+	{ "IF_ADC3", NULL, "Stereo2 ADC MIXL" },
+	{ "IF_ADC3", NULL, "Stereo2 ADC MIXR" },
+
+	{ "IF1 ADC1 IN1 Mux", "IF_ADC1", "IF_ADC1" },
+	{ "IF1 ADC1 IN1 Mux", "IF1_ADC3", "IF1_ADC3" },
+
+	{ "IF1 ADC1 IN2 Mux", "IF1_ADC1_IN1", "IF1 ADC1 IN1 Mux" },
+	{ "IF1 ADC1 IN2 Mux", "IF1_ADC4", "IF1_ADC4" },
+
+	{ "IF1 ADC2 IN Mux", "IF_ADC2", "IF_ADC2" },
+	{ "IF1 ADC2 IN Mux", "VAD_ADC", "VAD_ADC" },
+
+	{ "IF1 ADC2 IN1 Mux", "IF1_ADC2_IN", "IF1 ADC2 IN Mux" },
+	{ "IF1 ADC2 IN1 Mux", "IF1_ADC4", "IF1_ADC4" },
+
+	{ "IF1_ADC1" , NULL, "IF1 ADC1 IN2 Mux" },
+	{ "IF1_ADC2" , NULL, "IF1 ADC2 IN1 Mux" },
+
+	{ "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL" },
+	{ "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR" },
+	{ "Stereo2 ADC MIX", NULL, "Sto2 ADC MIXL" },
+	{ "Stereo2 ADC MIX", NULL, "Sto2 ADC MIXR" },
+	{ "Mono ADC MIX", NULL, "Mono ADC MIXL" },
+	{ "Mono ADC MIX", NULL, "Mono ADC MIXR" },
+
+	{ "RxDP Mux", "IF2 DAC", "IF2 DAC" },
+	{ "RxDP Mux", "IF1 DAC", "IF1 DAC2" },
+	{ "RxDP Mux", "STO1 ADC Mixer", "Stereo1 ADC MIX" },
+	{ "RxDP Mux", "STO2 ADC Mixer", "Stereo2 ADC MIX" },
+	{ "RxDP Mux", "Mono ADC Mixer L", "Mono ADC MIXL" },
+	{ "RxDP Mux", "Mono ADC Mixer R", "Mono ADC MIXR" },
+	{ "RxDP Mux", "DAC1", "DAC MIX" },
+
+	{ "TDM Data Mux", "Slot 0-1", "Stereo1 ADC MIX" },
+	{ "TDM Data Mux", "Slot 2-3", "Mono ADC MIX" },
+	{ "TDM Data Mux", "Slot 4-5", "Stereo2 ADC MIX" },
+	{ "TDM Data Mux", "Slot 6-7", "IF2 DAC" },
+
+	{ "DSP UL Mux", "Bypass", "TDM Data Mux" },
+	{ "DSP UL Mux", NULL, "I2S DSP" },
+	{ "DSP DL Mux", "Bypass", "RxDP Mux" },
+	{ "DSP DL Mux", NULL, "I2S DSP" },
+
+	{ "TxDP_ADC_L", NULL, "DSP UL Mux" },
+	{ "TxDP_ADC_R", NULL, "DSP UL Mux" },
+	{ "TxDC_DAC", NULL, "DSP DL Mux" },
+
+	{ "TxDP_ADC", NULL, "TxDP_ADC_L" },
+	{ "TxDP_ADC", NULL, "TxDP_ADC_R" },
+
+	{ "IF1 ADC", NULL, "I2S1" },
+	{ "IF1 ADC", NULL, "IF1_ADC1" },
+	{ "IF1 ADC", NULL, "IF1_ADC2" },
+	{ "IF1 ADC", NULL, "IF_ADC3" },
+	{ "IF1 ADC", NULL, "TxDP_ADC" },
+
+	{ "IF2 ADC Mux", "IF_ADC1", "IF_ADC1" },
+	{ "IF2 ADC Mux", "IF_ADC2", "IF_ADC2" },
+	{ "IF2 ADC Mux", "IF_ADC3", "IF_ADC3" },
+	{ "IF2 ADC Mux", "TxDC_DAC", "TxDC_DAC" },
+	{ "IF2 ADC Mux", "TxDP_ADC", "TxDP_ADC" },
+	{ "IF2 ADC Mux", "VAD_ADC", "VAD_ADC" },
+
+	{ "IF2 ADC L", NULL, "IF2 ADC Mux" },
+	{ "IF2 ADC R", NULL, "IF2 ADC Mux" },
+
+	{ "IF2 ADC", NULL, "I2S2" },
+	{ "IF2 ADC", NULL, "IF2 ADC L" },
+	{ "IF2 ADC", NULL, "IF2 ADC R" },
+
+	{ "AIF1TX", NULL, "IF1 ADC" },
+	{ "AIF2TX", NULL, "IF2 ADC" },
+
+	{ "IF1 DAC1", NULL, "AIF1RX" },
+	{ "IF1 DAC2", NULL, "AIF1RX" },
+	{ "IF2 DAC", NULL, "AIF2RX" },
+
+	{ "IF1 DAC1", NULL, "I2S1" },
+	{ "IF1 DAC2", NULL, "I2S1" },
+	{ "IF2 DAC", NULL, "I2S2" },
+
+	{ "IF1 DAC2 L", NULL, "IF1 DAC2" },
+	{ "IF1 DAC2 R", NULL, "IF1 DAC2" },
+	{ "IF1 DAC1 L", NULL, "IF1 DAC1" },
+	{ "IF1 DAC1 R", NULL, "IF1 DAC1" },
+	{ "IF2 DAC L", NULL, "IF2 DAC" },
+	{ "IF2 DAC R", NULL, "IF2 DAC" },
+
+	{ "DAC1 L Mux", "IF1 DAC", "IF1 DAC1 L" },
+	{ "DAC1 L Mux", "IF2 DAC", "IF2 DAC L" },
+
+	{ "DAC1 R Mux", "IF1 DAC", "IF1 DAC1 R" },
+	{ "DAC1 R Mux", "IF2 DAC", "IF2 DAC R" },
+
+	{ "DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL" },
+	{ "DAC1 MIXL", "DAC1 Switch", "DAC1 L Mux" },
+	{ "DAC1 MIXL", NULL, "DAC Stereo1 Filter" },
+	{ "DAC1 MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR" },
+	{ "DAC1 MIXR", "DAC1 Switch", "DAC1 R Mux" },
+	{ "DAC1 MIXR", NULL, "DAC Stereo1 Filter" },
+
+	{ "DAC MIX", NULL, "DAC1 MIXL" },
+	{ "DAC MIX", NULL, "DAC1 MIXR" },
+
+	{ "Audio DSP", NULL, "DAC1 MIXL" },
+	{ "Audio DSP", NULL, "DAC1 MIXR" },
+
+	{ "DAC L2 Mux", "IF1 DAC", "IF1 DAC2 L" },
+	{ "DAC L2 Mux", "IF2 DAC", "IF2 DAC L" },
+	{ "DAC L2 Mux", "TxDC DAC", "TxDC_DAC" },
+	{ "DAC L2 Mux", "VAD_ADC", "VAD_ADC" },
+	{ "DAC L2 Volume", NULL, "DAC L2 Mux" },
+	{ "DAC L2 Volume", NULL, "DAC Mono Left Filter" },
+
+	{ "DAC R2 Mux", "IF1 DAC", "IF1 DAC2 R" },
+	{ "DAC R2 Mux", "IF2 DAC", "IF2 DAC R" },
+	{ "DAC R2 Mux", "TxDC DAC", "TxDC_DAC" },
+	{ "DAC R2 Mux", "TxDP ADC", "TxDP_ADC" },
+	{ "DAC R2 Volume", NULL, "DAC R2 Mux" },
+	{ "DAC R2 Volume", NULL, "DAC Mono Right Filter" },
+
+	{ "Stereo DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" },
+	{ "Stereo DAC MIXL", "DAC R1 Switch", "DAC1 MIXR" },
+	{ "Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" },
+	{ "Stereo DAC MIXL", NULL, "DAC Stereo1 Filter" },
+	{ "Stereo DAC MIXL", NULL, "DAC L1 Power" },
+	{ "Stereo DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" },
+	{ "Stereo DAC MIXR", "DAC L1 Switch", "DAC1 MIXL" },
+	{ "Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" },
+	{ "Stereo DAC MIXR", NULL, "DAC Stereo1 Filter" },
+	{ "Stereo DAC MIXR", NULL, "DAC R1 Power" },
+
+	{ "Mono DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" },
+	{ "Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" },
+	{ "Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Volume" },
+	{ "Mono DAC MIXL", NULL, "DAC Mono Left Filter" },
+	{ "Mono DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" },
+	{ "Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" },
+	{ "Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" },
+	{ "Mono DAC MIXR", NULL, "DAC Mono Right Filter" },
+
+	{ "DAC MIXL", "Sto DAC Mix L Switch", "Stereo DAC MIXL" },
+	{ "DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" },
+	{ "DAC MIXL", "DAC R2 Switch", "DAC R2 Volume" },
+	{ "DAC MIXR", "Sto DAC Mix R Switch", "Stereo DAC MIXR" },
+	{ "DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" },
+	{ "DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" },
+
+	{ "DAC L1", NULL, "DAC L1 Power" },
+	{ "DAC L1", NULL, "Stereo DAC MIXL" },
+	{ "DAC L1", NULL, "PLL1", is_sys_clk_from_pll },
+	{ "DAC R1", NULL, "DAC R1 Power" },
+	{ "DAC R1", NULL, "Stereo DAC MIXR" },
+	{ "DAC R1", NULL, "PLL1", is_sys_clk_from_pll },
+	{ "DAC L2", NULL, "Mono DAC MIXL" },
+	{ "DAC L2", NULL, "PLL1", is_sys_clk_from_pll },
+	{ "DAC R2", NULL, "Mono DAC MIXR" },
+	{ "DAC R2", NULL, "PLL1", is_sys_clk_from_pll },
+
+	{ "OUT MIXL", "BST1 Switch", "BST1" },
+	{ "OUT MIXL", "INL Switch", "INL VOL" },
+	{ "OUT MIXL", "DAC L2 Switch", "DAC L2" },
+	{ "OUT MIXL", "DAC L1 Switch", "DAC L1" },
+
+	{ "OUT MIXR", "BST2 Switch", "BST2" },
+	{ "OUT MIXR", "INR Switch", "INR VOL" },
+	{ "OUT MIXR", "DAC R2 Switch", "DAC R2" },
+	{ "OUT MIXR", "DAC R1 Switch", "DAC R1" },
+
+	{ "HPOVOL MIXL", "DAC1 Switch", "DAC L1" },
+	{ "HPOVOL MIXL", "INL Switch", "INL VOL" },
+	{ "HPOVOL MIXR", "DAC1 Switch", "DAC R1" },
+	{ "HPOVOL MIXR", "INR Switch", "INR VOL" },
+
+	{ "DAC 2", NULL, "DAC L2" },
+	{ "DAC 2", NULL, "DAC R2" },
+	{ "DAC 1", NULL, "DAC L1" },
+	{ "DAC 1", NULL, "DAC R1" },
+	{ "HPOVOL", NULL, "HPOVOL MIXL" },
+	{ "HPOVOL", NULL, "HPOVOL MIXR" },
+	{ "HPO MIX", "DAC1 Switch", "DAC 1" },
+	{ "HPO MIX", "HPVOL Switch", "HPOVOL" },
+
+	{ "LOUT MIX", "DAC L1 Switch", "DAC L1" },
+	{ "LOUT MIX", "DAC R1 Switch", "DAC R1" },
+	{ "LOUT MIX", "OUTMIX L Switch", "OUT MIXL" },
+	{ "LOUT MIX", "OUTMIX R Switch", "OUT MIXR" },
+
+	{ "PDM1 L Mux", "Stereo DAC", "Stereo DAC MIXL" },
+	{ "PDM1 L Mux", "Mono DAC", "Mono DAC MIXL" },
+	{ "PDM1 L Mux", NULL, "PDM1 Power" },
+	{ "PDM1 R Mux", "Stereo DAC", "Stereo DAC MIXR" },
+	{ "PDM1 R Mux", "Mono DAC", "Mono DAC MIXR" },
+	{ "PDM1 R Mux", NULL, "PDM1 Power" },
+	{ "PDM2 L Mux", "Stereo DAC", "Stereo DAC MIXL" },
+	{ "PDM2 L Mux", "Mono DAC", "Mono DAC MIXL" },
+	{ "PDM2 L Mux", NULL, "PDM2 Power" },
+	{ "PDM2 R Mux", "Stereo DAC", "Stereo DAC MIXR" },
+	{ "PDM2 R Mux", "Mono DAC", "Mono DAC MIXR" },
+	{ "PDM2 R Mux", NULL, "PDM2 Power" },
+
+	{ "HP Amp", NULL, "HPO MIX" },
+	{ "HP Amp", NULL, "Mic Det Power" },
+	{ "HPOL", NULL, "HP Amp" },
+	{ "HPOL", NULL, "HP L Amp" },
+	{ "HPOL", NULL, "Improve HP Amp Drv" },
+	{ "HPOR", NULL, "HP Amp" },
+	{ "HPOR", NULL, "HP R Amp" },
+	{ "HPOR", NULL, "Improve HP Amp Drv" },
+
+	{ "LOUT Amp", NULL, "LOUT MIX" },
+	{ "LOUT L Playback", "Switch", "LOUT Amp" },
+	{ "LOUT R Playback", "Switch", "LOUT Amp" },
+	{ "LOUTL", NULL, "LOUT L Playback" },
+	{ "LOUTR", NULL, "LOUT R Playback" },
+	{ "LOUTL", NULL, "Improve HP Amp Drv" },
+	{ "LOUTR", NULL, "Improve HP Amp Drv" },
+
+	{ "PDM1L", NULL, "PDM1 L Mux" },
+	{ "PDM1R", NULL, "PDM1 R Mux" },
+	{ "PDM2L", NULL, "PDM2 L Mux" },
+	{ "PDM2R", NULL, "PDM2 R Mux" },
+};
+
+static int rt5670_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
+	unsigned int val_len = 0, val_clk, mask_clk;
+	int pre_div, bclk_ms, frame_size;
+
+	rt5670->lrck[dai->id] = params_rate(params);
+	pre_div = rl6231_get_clk_info(rt5670->sysclk, rt5670->lrck[dai->id]);
+	if (pre_div < 0) {
+		dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n",
+			rt5670->lrck[dai->id], dai->id);
+		return -EINVAL;
+	}
+	frame_size = snd_soc_params_to_frame_size(params);
+	if (frame_size < 0) {
+		dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size);
+		return -EINVAL;
+	}
+	bclk_ms = frame_size > 32;
+	rt5670->bclk[dai->id] = rt5670->lrck[dai->id] * (32 << bclk_ms);
+
+	dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n",
+		rt5670->bclk[dai->id], rt5670->lrck[dai->id]);
+	dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
+				bclk_ms, pre_div, dai->id);
+
+	switch (params_width(params)) {
+	case 16:
+		break;
+	case 20:
+		val_len |= RT5670_I2S_DL_20;
+		break;
+	case 24:
+		val_len |= RT5670_I2S_DL_24;
+		break;
+	case 8:
+		val_len |= RT5670_I2S_DL_8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (dai->id) {
+	case RT5670_AIF1:
+		mask_clk = RT5670_I2S_BCLK_MS1_MASK | RT5670_I2S_PD1_MASK;
+		val_clk = bclk_ms << RT5670_I2S_BCLK_MS1_SFT |
+			pre_div << RT5670_I2S_PD1_SFT;
+		snd_soc_update_bits(codec, RT5670_I2S1_SDP,
+			RT5670_I2S_DL_MASK, val_len);
+		snd_soc_update_bits(codec, RT5670_ADDA_CLK1, mask_clk, val_clk);
+		break;
+	case RT5670_AIF2:
+		mask_clk = RT5670_I2S_BCLK_MS2_MASK | RT5670_I2S_PD2_MASK;
+		val_clk = bclk_ms << RT5670_I2S_BCLK_MS2_SFT |
+			pre_div << RT5670_I2S_PD2_SFT;
+		snd_soc_update_bits(codec, RT5670_I2S2_SDP,
+			RT5670_I2S_DL_MASK, val_len);
+		snd_soc_update_bits(codec, RT5670_ADDA_CLK1, mask_clk, val_clk);
+		break;
+	default:
+		dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rt5670_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
+	unsigned int reg_val = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		rt5670->master[dai->id] = 1;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		reg_val |= RT5670_I2S_MS_S;
+		rt5670->master[dai->id] = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		reg_val |= RT5670_I2S_BP_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		reg_val |= RT5670_I2S_DF_LEFT;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		reg_val |= RT5670_I2S_DF_PCM_A;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		reg_val |= RT5670_I2S_DF_PCM_B;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (dai->id) {
+	case RT5670_AIF1:
+		snd_soc_update_bits(codec, RT5670_I2S1_SDP,
+			RT5670_I2S_MS_MASK | RT5670_I2S_BP_MASK |
+			RT5670_I2S_DF_MASK, reg_val);
+		break;
+	case RT5670_AIF2:
+		snd_soc_update_bits(codec, RT5670_I2S2_SDP,
+			RT5670_I2S_MS_MASK | RT5670_I2S_BP_MASK |
+			RT5670_I2S_DF_MASK, reg_val);
+		break;
+	default:
+		dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int rt5670_set_dai_sysclk(struct snd_soc_dai *dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
+	unsigned int reg_val = 0;
+
+	if (freq == rt5670->sysclk && clk_id == rt5670->sysclk_src)
+		return 0;
+
+	switch (clk_id) {
+	case RT5670_SCLK_S_MCLK:
+		reg_val |= RT5670_SCLK_SRC_MCLK;
+		break;
+	case RT5670_SCLK_S_PLL1:
+		reg_val |= RT5670_SCLK_SRC_PLL1;
+		break;
+	case RT5670_SCLK_S_RCCLK:
+		reg_val |= RT5670_SCLK_SRC_RCCLK;
+		break;
+	default:
+		dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
+		return -EINVAL;
+	}
+	snd_soc_update_bits(codec, RT5670_GLB_CLK,
+		RT5670_SCLK_SRC_MASK, reg_val);
+	rt5670->sysclk = freq;
+	rt5670->sysclk_src = clk_id;
+
+	dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
+
+	return 0;
+}
+
+static int rt5670_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
+			unsigned int freq_in, unsigned int freq_out)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
+	struct rl6231_pll_code pll_code;
+	int ret;
+
+	if (source == rt5670->pll_src && freq_in == rt5670->pll_in &&
+	    freq_out == rt5670->pll_out)
+		return 0;
+
+	if (!freq_in || !freq_out) {
+		dev_dbg(codec->dev, "PLL disabled\n");
+
+		rt5670->pll_in = 0;
+		rt5670->pll_out = 0;
+		snd_soc_update_bits(codec, RT5670_GLB_CLK,
+			RT5670_SCLK_SRC_MASK, RT5670_SCLK_SRC_MCLK);
+		return 0;
+	}
+
+	switch (source) {
+	case RT5670_PLL1_S_MCLK:
+		snd_soc_update_bits(codec, RT5670_GLB_CLK,
+			RT5670_PLL1_SRC_MASK, RT5670_PLL1_SRC_MCLK);
+		break;
+	case RT5670_PLL1_S_BCLK1:
+	case RT5670_PLL1_S_BCLK2:
+	case RT5670_PLL1_S_BCLK3:
+	case RT5670_PLL1_S_BCLK4:
+		switch (dai->id) {
+		case RT5670_AIF1:
+			snd_soc_update_bits(codec, RT5670_GLB_CLK,
+				RT5670_PLL1_SRC_MASK, RT5670_PLL1_SRC_BCLK1);
+			break;
+		case RT5670_AIF2:
+			snd_soc_update_bits(codec, RT5670_GLB_CLK,
+				RT5670_PLL1_SRC_MASK, RT5670_PLL1_SRC_BCLK2);
+			break;
+		default:
+			dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id);
+			return -EINVAL;
+		}
+		break;
+	default:
+		dev_err(codec->dev, "Unknown PLL source %d\n", source);
+		return -EINVAL;
+	}
+
+	ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
+	if (ret < 0) {
+		dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
+		return ret;
+	}
+
+	dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n",
+		pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
+		pll_code.n_code, pll_code.k_code);
+
+	snd_soc_write(codec, RT5670_PLL_CTRL1,
+		pll_code.n_code << RT5670_PLL_N_SFT | pll_code.k_code);
+	snd_soc_write(codec, RT5670_PLL_CTRL2,
+		(pll_code.m_bp ? 0 : pll_code.m_code) << RT5670_PLL_M_SFT |
+		pll_code.m_bp << RT5670_PLL_M_BP_SFT);
+
+	rt5670->pll_in = freq_in;
+	rt5670->pll_out = freq_out;
+	rt5670->pll_src = source;
+
+	return 0;
+}
+
+static int rt5670_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+			unsigned int rx_mask, int slots, int slot_width)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	unsigned int val = 0;
+
+	if (rx_mask || tx_mask)
+		val |= (1 << 14);
+
+	switch (slots) {
+	case 4:
+		val |= (1 << 12);
+		break;
+	case 6:
+		val |= (2 << 12);
+		break;
+	case 8:
+		val |= (3 << 12);
+		break;
+	case 2:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (slot_width) {
+	case 20:
+		val |= (1 << 10);
+		break;
+	case 24:
+		val |= (2 << 10);
+		break;
+	case 32:
+		val |= (3 << 10);
+		break;
+	case 16:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, RT5670_TDM_CTRL_1, 0x7c00, val);
+
+	return 0;
+}
+
+static int rt5670_set_bias_level(struct snd_soc_codec *codec,
+			enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_PREPARE:
+		if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) {
+			snd_soc_update_bits(codec, RT5670_PWR_ANLG1,
+				RT5670_PWR_VREF1 | RT5670_PWR_MB |
+				RT5670_PWR_BG | RT5670_PWR_VREF2,
+				RT5670_PWR_VREF1 | RT5670_PWR_MB |
+				RT5670_PWR_BG | RT5670_PWR_VREF2);
+			mdelay(10);
+			snd_soc_update_bits(codec, RT5670_PWR_ANLG1,
+				RT5670_PWR_FV1 | RT5670_PWR_FV2,
+				RT5670_PWR_FV1 | RT5670_PWR_FV2);
+			snd_soc_update_bits(codec, RT5670_CHARGE_PUMP,
+				RT5670_OSW_L_MASK | RT5670_OSW_R_MASK,
+				RT5670_OSW_L_DIS | RT5670_OSW_R_DIS);
+			snd_soc_update_bits(codec, RT5670_DIG_MISC, 0x1, 0x1);
+			snd_soc_update_bits(codec, RT5670_PWR_ANLG1,
+				RT5670_LDO_SEL_MASK, 0x3);
+		}
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		snd_soc_write(codec, RT5670_PWR_DIG1, 0x0000);
+		snd_soc_write(codec, RT5670_PWR_DIG2, 0x0001);
+		snd_soc_write(codec, RT5670_PWR_VOL, 0x0000);
+		snd_soc_write(codec, RT5670_PWR_MIXER, 0x0001);
+		snd_soc_write(codec, RT5670_PWR_ANLG1, 0x2800);
+		snd_soc_write(codec, RT5670_PWR_ANLG2, 0x0004);
+		snd_soc_update_bits(codec, RT5670_DIG_MISC, 0x1, 0x0);
+		snd_soc_update_bits(codec, RT5670_PWR_ANLG1,
+				RT5670_LDO_SEL_MASK, 0x1);
+		break;
+
+	default:
+		break;
+	}
+	codec->dapm.bias_level = level;
+
+	return 0;
+}
+
+static int rt5670_probe(struct snd_soc_codec *codec)
+{
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
+
+	rt5670->codec = codec;
+
+	return 0;
+}
+
+static int rt5670_remove(struct snd_soc_codec *codec)
+{
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
+
+	regmap_write(rt5670->regmap, RT5670_RESET, 0);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt5670_suspend(struct snd_soc_codec *codec)
+{
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
+
+	regcache_cache_only(rt5670->regmap, true);
+	regcache_mark_dirty(rt5670->regmap);
+	return 0;
+}
+
+static int rt5670_resume(struct snd_soc_codec *codec)
+{
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
+
+	regcache_cache_only(rt5670->regmap, false);
+	regcache_sync(rt5670->regmap);
+
+	return 0;
+}
+#else
+#define rt5670_suspend NULL
+#define rt5670_resume NULL
+#endif
+
+#define RT5670_STEREO_RATES SNDRV_PCM_RATE_8000_96000
+#define RT5670_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
+
+static struct snd_soc_dai_ops rt5670_aif_dai_ops = {
+	.hw_params = rt5670_hw_params,
+	.set_fmt = rt5670_set_dai_fmt,
+	.set_sysclk = rt5670_set_dai_sysclk,
+	.set_tdm_slot = rt5670_set_tdm_slot,
+	.set_pll = rt5670_set_dai_pll,
+};
+
+static struct snd_soc_dai_driver rt5670_dai[] = {
+	{
+		.name = "rt5670-aif1",
+		.id = RT5670_AIF1,
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5670_STEREO_RATES,
+			.formats = RT5670_FORMATS,
+		},
+		.capture = {
+			.stream_name = "AIF1 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5670_STEREO_RATES,
+			.formats = RT5670_FORMATS,
+		},
+		.ops = &rt5670_aif_dai_ops,
+	},
+	{
+		.name = "rt5670-aif2",
+		.id = RT5670_AIF2,
+		.playback = {
+			.stream_name = "AIF2 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5670_STEREO_RATES,
+			.formats = RT5670_FORMATS,
+		},
+		.capture = {
+			.stream_name = "AIF2 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5670_STEREO_RATES,
+			.formats = RT5670_FORMATS,
+		},
+		.ops = &rt5670_aif_dai_ops,
+	},
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt5670 = {
+	.probe = rt5670_probe,
+	.remove = rt5670_remove,
+	.suspend = rt5670_suspend,
+	.resume = rt5670_resume,
+	.set_bias_level = rt5670_set_bias_level,
+	.idle_bias_off = true,
+	.controls = rt5670_snd_controls,
+	.num_controls = ARRAY_SIZE(rt5670_snd_controls),
+	.dapm_widgets = rt5670_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(rt5670_dapm_widgets),
+	.dapm_routes = rt5670_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(rt5670_dapm_routes),
+};
+
+static const struct regmap_config rt5670_regmap = {
+	.reg_bits = 8,
+	.val_bits = 16,
+	.max_register = RT5670_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5670_ranges) *
+					       RT5670_PR_SPACING),
+	.volatile_reg = rt5670_volatile_register,
+	.readable_reg = rt5670_readable_register,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = rt5670_reg,
+	.num_reg_defaults = ARRAY_SIZE(rt5670_reg),
+	.ranges = rt5670_ranges,
+	.num_ranges = ARRAY_SIZE(rt5670_ranges),
+};
+
+static const struct i2c_device_id rt5670_i2c_id[] = {
+	{ "rt5670", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id);
+
+static int rt5670_i2c_probe(struct i2c_client *i2c,
+		    const struct i2c_device_id *id)
+{
+	struct rt5670_platform_data *pdata = dev_get_platdata(&i2c->dev);
+	struct rt5670_priv *rt5670;
+	int ret;
+	unsigned int val;
+
+	rt5670 = devm_kzalloc(&i2c->dev,
+				sizeof(struct rt5670_priv),
+				GFP_KERNEL);
+	if (NULL == rt5670)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, rt5670);
+
+	if (pdata)
+		rt5670->pdata = *pdata;
+
+	rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap);
+	if (IS_ERR(rt5670->regmap)) {
+		ret = PTR_ERR(rt5670->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	regmap_read(rt5670->regmap, RT5670_VENDOR_ID2, &val);
+	if (val != RT5670_DEVICE_ID) {
+		dev_err(&i2c->dev,
+			"Device with ID register %x is not rt5670/72\n", val);
+		return -ENODEV;
+	}
+
+	regmap_write(rt5670->regmap, RT5670_RESET, 0);
+	regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1,
+		RT5670_PWR_HP_L | RT5670_PWR_HP_R |
+		RT5670_PWR_VREF2, RT5670_PWR_VREF2);
+	msleep(100);
+
+	regmap_write(rt5670->regmap, RT5670_RESET, 0);
+
+	ret = regmap_register_patch(rt5670->regmap, init_list,
+				    ARRAY_SIZE(init_list));
+	if (ret != 0)
+		dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
+
+	if (rt5670->pdata.in2_diff)
+		regmap_update_bits(rt5670->regmap, RT5670_IN2,
+					RT5670_IN_DF2, RT5670_IN_DF2);
+
+	if (i2c->irq) {
+		regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1,
+				   RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_IRQ);
+		regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2,
+				   RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT);
+
+	}
+
+	if (rt5670->pdata.jd_mode) {
+		regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1,
+				   RT5670_PWR_MB, RT5670_PWR_MB);
+		regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG2,
+				   RT5670_PWR_JD1, RT5670_PWR_JD1);
+		regmap_update_bits(rt5670->regmap, RT5670_IRQ_CTRL1,
+				   RT5670_JD1_1_EN_MASK, RT5670_JD1_1_EN);
+		regmap_update_bits(rt5670->regmap, RT5670_JD_CTRL3,
+				   RT5670_JD_TRI_CBJ_SEL_MASK |
+				   RT5670_JD_TRI_HPO_SEL_MASK,
+				   RT5670_JD_CBJ_JD1_1 | RT5670_JD_HPO_JD1_1);
+		switch (rt5670->pdata.jd_mode) {
+		case 1:
+			regmap_update_bits(rt5670->regmap, RT5670_A_JD_CTRL1,
+					   RT5670_JD1_MODE_MASK,
+					   RT5670_JD1_MODE_0);
+			break;
+		case 2:
+			regmap_update_bits(rt5670->regmap, RT5670_A_JD_CTRL1,
+					   RT5670_JD1_MODE_MASK,
+					   RT5670_JD1_MODE_1);
+			break;
+		case 3:
+			regmap_update_bits(rt5670->regmap, RT5670_A_JD_CTRL1,
+					   RT5670_JD1_MODE_MASK,
+					   RT5670_JD1_MODE_2);
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (rt5670->pdata.dmic_en) {
+		regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1,
+				   RT5670_GP2_PIN_MASK,
+				   RT5670_GP2_PIN_DMIC1_SCL);
+
+		switch (rt5670->pdata.dmic1_data_pin) {
+		case RT5670_DMIC_DATA_IN2P:
+			regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1,
+					   RT5670_DMIC_1_DP_MASK,
+					   RT5670_DMIC_1_DP_IN2P);
+			break;
+
+		case RT5670_DMIC_DATA_GPIO6:
+			regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1,
+					   RT5670_DMIC_1_DP_MASK,
+					   RT5670_DMIC_1_DP_GPIO6);
+			regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1,
+					   RT5670_GP6_PIN_MASK,
+					   RT5670_GP6_PIN_DMIC1_SDA);
+			break;
+
+		case RT5670_DMIC_DATA_GPIO7:
+			regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1,
+					   RT5670_DMIC_1_DP_MASK,
+					   RT5670_DMIC_1_DP_GPIO7);
+			regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1,
+					   RT5670_GP7_PIN_MASK,
+					   RT5670_GP7_PIN_DMIC1_SDA);
+			break;
+
+		default:
+			break;
+		}
+
+		switch (rt5670->pdata.dmic2_data_pin) {
+		case RT5670_DMIC_DATA_IN3N:
+			regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1,
+					   RT5670_DMIC_2_DP_MASK,
+					   RT5670_DMIC_2_DP_IN3N);
+			break;
+
+		case RT5670_DMIC_DATA_GPIO8:
+			regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1,
+					   RT5670_DMIC_2_DP_MASK,
+					   RT5670_DMIC_2_DP_GPIO8);
+			regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1,
+					   RT5670_GP8_PIN_MASK,
+					   RT5670_GP8_PIN_DMIC2_SDA);
+			break;
+
+		default:
+			break;
+		}
+
+		switch (rt5670->pdata.dmic3_data_pin) {
+		case RT5670_DMIC_DATA_GPIO5:
+			regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL2,
+					   RT5670_DMIC_3_DP_MASK,
+					   RT5670_DMIC_3_DP_GPIO5);
+			regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1,
+					   RT5670_GP5_PIN_MASK,
+					   RT5670_GP5_PIN_DMIC3_SDA);
+			break;
+
+		case RT5670_DMIC_DATA_GPIO9:
+		case RT5670_DMIC_DATA_GPIO10:
+			dev_err(&i2c->dev,
+				"Always use GPIO5 as DMIC3 data pin\n");
+			break;
+
+		default:
+			break;
+		}
+
+	}
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5670,
+			rt5670_dai, ARRAY_SIZE(rt5670_dai));
+	if (ret < 0)
+		goto err;
+
+	return 0;
+err:
+	return ret;
+}
+
+static int rt5670_i2c_remove(struct i2c_client *i2c)
+{
+	snd_soc_unregister_codec(&i2c->dev);
+
+	return 0;
+}
+
+static struct i2c_driver rt5670_i2c_driver = {
+	.driver = {
+		.name = "rt5670",
+		.owner = THIS_MODULE,
+	},
+	.probe = rt5670_i2c_probe,
+	.remove   = rt5670_i2c_remove,
+	.id_table = rt5670_i2c_id,
+};
+
+module_i2c_driver(rt5670_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC RT5670 driver");
+MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h
new file mode 100644
index 000000000000..a0b5c855b492
--- /dev/null
+++ b/sound/soc/codecs/rt5670.h
@@ -0,0 +1,2000 @@
+/*
+ * rt5670.h  --  RT5670 ALSA SoC audio driver
+ *
+ * Copyright 2014 Realtek Microelectronics
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __RT5670_H__
+#define __RT5670_H__
+
+#include <sound/rt5670.h>
+
+/* Info */
+#define RT5670_RESET				0x00
+#define RT5670_VENDOR_ID			0xfd
+#define RT5670_VENDOR_ID1			0xfe
+#define RT5670_VENDOR_ID2			0xff
+/*  I/O - Output */
+#define RT5670_HP_VOL				0x02
+#define RT5670_LOUT1				0x03
+/* I/O - Input */
+#define RT5670_CJ_CTRL1				0x0a
+#define RT5670_CJ_CTRL2				0x0b
+#define RT5670_CJ_CTRL3				0x0c
+#define RT5670_IN2				0x0e
+#define RT5670_INL1_INR1_VOL			0x0f
+/* I/O - ADC/DAC/DMIC */
+#define RT5670_DAC1_DIG_VOL			0x19
+#define RT5670_DAC2_DIG_VOL			0x1a
+#define RT5670_DAC_CTRL				0x1b
+#define RT5670_STO1_ADC_DIG_VOL			0x1c
+#define RT5670_MONO_ADC_DIG_VOL			0x1d
+#define RT5670_ADC_BST_VOL1			0x1e
+#define RT5670_STO2_ADC_DIG_VOL			0x1f
+/* Mixer - D-D */
+#define RT5670_ADC_BST_VOL2			0x20
+#define RT5670_STO2_ADC_MIXER			0x26
+#define RT5670_STO1_ADC_MIXER			0x27
+#define RT5670_MONO_ADC_MIXER			0x28
+#define RT5670_AD_DA_MIXER			0x29
+#define RT5670_STO_DAC_MIXER			0x2a
+#define RT5670_DD_MIXER				0x2b
+#define RT5670_DIG_MIXER			0x2c
+#define RT5670_DSP_PATH1			0x2d
+#define RT5670_DSP_PATH2			0x2e
+#define RT5670_DIG_INF1_DATA			0x2f
+#define RT5670_DIG_INF2_DATA			0x30
+/* Mixer - PDM */
+#define RT5670_PDM_OUT_CTRL			0x31
+#define RT5670_PDM_DATA_CTRL1			0x32
+#define RT5670_PDM1_DATA_CTRL2			0x33
+#define RT5670_PDM1_DATA_CTRL3			0x34
+#define RT5670_PDM1_DATA_CTRL4			0x35
+#define RT5670_PDM2_DATA_CTRL2			0x36
+#define RT5670_PDM2_DATA_CTRL3			0x37
+#define RT5670_PDM2_DATA_CTRL4			0x38
+/* Mixer - ADC */
+#define RT5670_REC_L1_MIXER			0x3b
+#define RT5670_REC_L2_MIXER			0x3c
+#define RT5670_REC_R1_MIXER			0x3d
+#define RT5670_REC_R2_MIXER			0x3e
+/* Mixer - DAC */
+#define RT5670_HPO_MIXER			0x45
+#define RT5670_MONO_MIXER			0x4c
+#define RT5670_OUT_L1_MIXER			0x4f
+#define RT5670_OUT_R1_MIXER			0x52
+#define RT5670_LOUT_MIXER			0x53
+/* Power */
+#define RT5670_PWR_DIG1				0x61
+#define RT5670_PWR_DIG2				0x62
+#define RT5670_PWR_ANLG1			0x63
+#define RT5670_PWR_ANLG2			0x64
+#define RT5670_PWR_MIXER			0x65
+#define RT5670_PWR_VOL				0x66
+/* Private Register Control */
+#define RT5670_PRIV_INDEX			0x6a
+#define RT5670_PRIV_DATA			0x6c
+/* Format - ADC/DAC */
+#define RT5670_I2S4_SDP				0x6f
+#define RT5670_I2S1_SDP				0x70
+#define RT5670_I2S2_SDP				0x71
+#define RT5670_I2S3_SDP				0x72
+#define RT5670_ADDA_CLK1			0x73
+#define RT5670_ADDA_CLK2			0x74
+#define RT5670_DMIC_CTRL1			0x75
+#define RT5670_DMIC_CTRL2			0x76
+/* Format - TDM Control */
+#define RT5670_TDM_CTRL_1			0x77
+#define RT5670_TDM_CTRL_2			0x78
+#define RT5670_TDM_CTRL_3			0x79
+
+/* Function - Analog */
+#define RT5670_DSP_CLK				0x7f
+#define RT5670_GLB_CLK				0x80
+#define RT5670_PLL_CTRL1			0x81
+#define RT5670_PLL_CTRL2			0x82
+#define RT5670_ASRC_1				0x83
+#define RT5670_ASRC_2				0x84
+#define RT5670_ASRC_3				0x85
+#define RT5670_ASRC_4				0x86
+#define RT5670_ASRC_5				0x87
+#define RT5670_ASRC_7				0x89
+#define RT5670_ASRC_8				0x8a
+#define RT5670_ASRC_9				0x8b
+#define RT5670_ASRC_10				0x8c
+#define RT5670_ASRC_11				0x8d
+#define RT5670_DEPOP_M1				0x8e
+#define RT5670_DEPOP_M2				0x8f
+#define RT5670_DEPOP_M3				0x90
+#define RT5670_CHARGE_PUMP			0x91
+#define RT5670_MICBIAS				0x93
+#define RT5670_A_JD_CTRL1			0x94
+#define RT5670_A_JD_CTRL2			0x95
+#define RT5670_ASRC_12				0x97
+#define RT5670_ASRC_13				0x98
+#define RT5670_ASRC_14				0x99
+#define RT5670_VAD_CTRL1			0x9a
+#define RT5670_VAD_CTRL2			0x9b
+#define RT5670_VAD_CTRL3			0x9c
+#define RT5670_VAD_CTRL4			0x9d
+#define RT5670_VAD_CTRL5			0x9e
+/* Function - Digital */
+#define RT5670_ADC_EQ_CTRL1			0xae
+#define RT5670_ADC_EQ_CTRL2			0xaf
+#define RT5670_EQ_CTRL1				0xb0
+#define RT5670_EQ_CTRL2				0xb1
+#define RT5670_ALC_DRC_CTRL1			0xb2
+#define RT5670_ALC_DRC_CTRL2			0xb3
+#define RT5670_ALC_CTRL_1			0xb4
+#define RT5670_ALC_CTRL_2			0xb5
+#define RT5670_ALC_CTRL_3			0xb6
+#define RT5670_ALC_CTRL_4			0xb7
+#define RT5670_JD_CTRL				0xbb
+#define RT5670_IRQ_CTRL1			0xbd
+#define RT5670_IRQ_CTRL2			0xbe
+#define RT5670_INT_IRQ_ST			0xbf
+#define RT5670_GPIO_CTRL1			0xc0
+#define RT5670_GPIO_CTRL2			0xc1
+#define RT5670_GPIO_CTRL3			0xc2
+#define RT5670_SCRABBLE_FUN			0xcd
+#define RT5670_SCRABBLE_CTRL			0xce
+#define RT5670_BASE_BACK			0xcf
+#define RT5670_MP3_PLUS1			0xd0
+#define RT5670_MP3_PLUS2			0xd1
+#define RT5670_ADJ_HPF1				0xd3
+#define RT5670_ADJ_HPF2				0xd4
+#define RT5670_HP_CALIB_AMP_DET			0xd6
+#define RT5670_SV_ZCD1				0xd9
+#define RT5670_SV_ZCD2				0xda
+#define RT5670_IL_CMD				0xdb
+#define RT5670_IL_CMD2				0xdc
+#define RT5670_IL_CMD3				0xdd
+#define RT5670_DRC_HL_CTRL1			0xe6
+#define RT5670_DRC_HL_CTRL2			0xe7
+#define RT5670_ADC_MONO_HP_CTRL1		0xec
+#define RT5670_ADC_MONO_HP_CTRL2		0xed
+#define RT5670_ADC_STO2_HP_CTRL1		0xee
+#define RT5670_ADC_STO2_HP_CTRL2		0xef
+#define RT5670_JD_CTRL3				0xf8
+#define RT5670_JD_CTRL4				0xf9
+/* General Control */
+#define RT5670_DIG_MISC				0xfa
+#define RT5670_GEN_CTRL2			0xfb
+#define RT5670_GEN_CTRL3			0xfc
+
+
+/* Index of Codec Private Register definition */
+#define RT5670_DIG_VOL				0x00
+#define RT5670_PR_ALC_CTRL_1			0x01
+#define RT5670_PR_ALC_CTRL_2			0x02
+#define RT5670_PR_ALC_CTRL_3			0x03
+#define RT5670_PR_ALC_CTRL_4			0x04
+#define RT5670_PR_ALC_CTRL_5			0x05
+#define RT5670_PR_ALC_CTRL_6			0x06
+#define RT5670_BIAS_CUR1			0x12
+#define RT5670_BIAS_CUR3			0x14
+#define RT5670_CLSD_INT_REG1			0x1c
+#define RT5670_MAMP_INT_REG2			0x37
+#define RT5670_CHOP_DAC_ADC			0x3d
+#define RT5670_MIXER_INT_REG			0x3f
+#define RT5670_3D_SPK				0x63
+#define RT5670_WND_1				0x6c
+#define RT5670_WND_2				0x6d
+#define RT5670_WND_3				0x6e
+#define RT5670_WND_4				0x6f
+#define RT5670_WND_5				0x70
+#define RT5670_WND_8				0x73
+#define RT5670_DIP_SPK_INF			0x75
+#define RT5670_HP_DCC_INT1			0x77
+#define RT5670_EQ_BW_LOP			0xa0
+#define RT5670_EQ_GN_LOP			0xa1
+#define RT5670_EQ_FC_BP1			0xa2
+#define RT5670_EQ_BW_BP1			0xa3
+#define RT5670_EQ_GN_BP1			0xa4
+#define RT5670_EQ_FC_BP2			0xa5
+#define RT5670_EQ_BW_BP2			0xa6
+#define RT5670_EQ_GN_BP2			0xa7
+#define RT5670_EQ_FC_BP3			0xa8
+#define RT5670_EQ_BW_BP3			0xa9
+#define RT5670_EQ_GN_BP3			0xaa
+#define RT5670_EQ_FC_BP4			0xab
+#define RT5670_EQ_BW_BP4			0xac
+#define RT5670_EQ_GN_BP4			0xad
+#define RT5670_EQ_FC_HIP1			0xae
+#define RT5670_EQ_GN_HIP1			0xaf
+#define RT5670_EQ_FC_HIP2			0xb0
+#define RT5670_EQ_BW_HIP2			0xb1
+#define RT5670_EQ_GN_HIP2			0xb2
+#define RT5670_EQ_PRE_VOL			0xb3
+#define RT5670_EQ_PST_VOL			0xb4
+
+
+/* global definition */
+#define RT5670_L_MUTE				(0x1 << 15)
+#define RT5670_L_MUTE_SFT			15
+#define RT5670_VOL_L_MUTE			(0x1 << 14)
+#define RT5670_VOL_L_SFT			14
+#define RT5670_R_MUTE				(0x1 << 7)
+#define RT5670_R_MUTE_SFT			7
+#define RT5670_VOL_R_MUTE			(0x1 << 6)
+#define RT5670_VOL_R_SFT			6
+#define RT5670_L_VOL_MASK			(0x3f << 8)
+#define RT5670_L_VOL_SFT			8
+#define RT5670_R_VOL_MASK			(0x3f)
+#define RT5670_R_VOL_SFT			0
+
+/* Combo Jack Control 1 (0x0a) */
+#define RT5670_CBJ_BST1_MASK			(0xf << 12)
+#define RT5670_CBJ_BST1_SFT			(12)
+#define RT5670_CBJ_JD_HP_EN			(0x1 << 9)
+#define RT5670_CBJ_JD_MIC_EN			(0x1 << 8)
+#define RT5670_CBJ_BST1_EN			(0x1 << 2)
+
+/* Combo Jack Control 1 (0x0b) */
+#define RT5670_CBJ_MN_JD			(0x1 << 12)
+#define RT5670_CAPLESS_EN			(0x1 << 11)
+#define RT5670_CBJ_DET_MODE			(0x1 << 7)
+
+/* IN2 Control (0x0e) */
+#define RT5670_BST_MASK1			(0xf<<12)
+#define RT5670_BST_SFT1				12
+#define RT5670_BST_MASK2			(0xf<<8)
+#define RT5670_BST_SFT2				8
+#define RT5670_IN_DF1				(0x1 << 7)
+#define RT5670_IN_SFT1				7
+#define RT5670_IN_DF2				(0x1 << 6)
+#define RT5670_IN_SFT2				6
+
+/* INL and INR Volume Control (0x0f) */
+#define RT5670_INL_SEL_MASK			(0x1 << 15)
+#define RT5670_INL_SEL_SFT			15
+#define RT5670_INL_SEL_IN4P			(0x0 << 15)
+#define RT5670_INL_SEL_MONOP			(0x1 << 15)
+#define RT5670_INL_VOL_MASK			(0x1f << 8)
+#define RT5670_INL_VOL_SFT			8
+#define RT5670_INR_SEL_MASK			(0x1 << 7)
+#define RT5670_INR_SEL_SFT			7
+#define RT5670_INR_SEL_IN4N			(0x0 << 7)
+#define RT5670_INR_SEL_MONON			(0x1 << 7)
+#define RT5670_INR_VOL_MASK			(0x1f)
+#define RT5670_INR_VOL_SFT			0
+
+/* Sidetone Control (0x18) */
+#define RT5670_ST_SEL_MASK			(0x7 << 9)
+#define RT5670_ST_SEL_SFT			9
+#define RT5670_M_ST_DACR2			(0x1 << 8)
+#define RT5670_M_ST_DACR2_SFT			8
+#define RT5670_M_ST_DACL2			(0x1 << 7)
+#define RT5670_M_ST_DACL2_SFT			7
+#define RT5670_ST_EN				(0x1 << 6)
+#define RT5670_ST_EN_SFT			6
+
+/* DAC1 Digital Volume (0x19) */
+#define RT5670_DAC_L1_VOL_MASK			(0xff << 8)
+#define RT5670_DAC_L1_VOL_SFT			8
+#define RT5670_DAC_R1_VOL_MASK			(0xff)
+#define RT5670_DAC_R1_VOL_SFT			0
+
+/* DAC2 Digital Volume (0x1a) */
+#define RT5670_DAC_L2_VOL_MASK			(0xff << 8)
+#define RT5670_DAC_L2_VOL_SFT			8
+#define RT5670_DAC_R2_VOL_MASK			(0xff)
+#define RT5670_DAC_R2_VOL_SFT			0
+
+/* DAC2 Control (0x1b) */
+#define RT5670_M_DAC_L2_VOL			(0x1 << 13)
+#define RT5670_M_DAC_L2_VOL_SFT			13
+#define RT5670_M_DAC_R2_VOL			(0x1 << 12)
+#define RT5670_M_DAC_R2_VOL_SFT			12
+#define RT5670_DAC2_L_SEL_MASK			(0x7 << 4)
+#define RT5670_DAC2_L_SEL_SFT			4
+#define RT5670_DAC2_R_SEL_MASK			(0x7 << 0)
+#define RT5670_DAC2_R_SEL_SFT			0
+
+/* ADC Digital Volume Control (0x1c) */
+#define RT5670_ADC_L_VOL_MASK			(0x7f << 8)
+#define RT5670_ADC_L_VOL_SFT			8
+#define RT5670_ADC_R_VOL_MASK			(0x7f)
+#define RT5670_ADC_R_VOL_SFT			0
+
+/* Mono ADC Digital Volume Control (0x1d) */
+#define RT5670_MONO_ADC_L_VOL_MASK		(0x7f << 8)
+#define RT5670_MONO_ADC_L_VOL_SFT		8
+#define RT5670_MONO_ADC_R_VOL_MASK		(0x7f)
+#define RT5670_MONO_ADC_R_VOL_SFT		0
+
+/* ADC Boost Volume Control (0x1e) */
+#define RT5670_STO1_ADC_L_BST_MASK		(0x3 << 14)
+#define RT5670_STO1_ADC_L_BST_SFT		14
+#define RT5670_STO1_ADC_R_BST_MASK		(0x3 << 12)
+#define RT5670_STO1_ADC_R_BST_SFT		12
+#define RT5670_STO1_ADC_COMP_MASK		(0x3 << 10)
+#define RT5670_STO1_ADC_COMP_SFT		10
+#define RT5670_STO2_ADC_L_BST_MASK		(0x3 << 8)
+#define RT5670_STO2_ADC_L_BST_SFT		8
+#define RT5670_STO2_ADC_R_BST_MASK		(0x3 << 6)
+#define RT5670_STO2_ADC_R_BST_SFT		6
+#define RT5670_STO2_ADC_COMP_MASK		(0x3 << 4)
+#define RT5670_STO2_ADC_COMP_SFT		4
+
+/* Stereo2 ADC Mixer Control (0x26) */
+#define RT5670_STO2_ADC_SRC_MASK		(0x1 << 15)
+#define RT5670_STO2_ADC_SRC_SFT			15
+
+/* Stereo ADC Mixer Control (0x26 0x27) */
+#define RT5670_M_ADC_L1				(0x1 << 14)
+#define RT5670_M_ADC_L1_SFT			14
+#define RT5670_M_ADC_L2				(0x1 << 13)
+#define RT5670_M_ADC_L2_SFT			13
+#define RT5670_ADC_1_SRC_MASK			(0x1 << 12)
+#define RT5670_ADC_1_SRC_SFT			12
+#define RT5670_ADC_1_SRC_ADC			(0x1 << 12)
+#define RT5670_ADC_1_SRC_DACMIX			(0x0 << 12)
+#define RT5670_ADC_2_SRC_MASK			(0x1 << 11)
+#define RT5670_ADC_2_SRC_SFT			11
+#define RT5670_ADC_SRC_MASK			(0x1 << 10)
+#define RT5670_ADC_SRC_SFT			10
+#define RT5670_DMIC_SRC_MASK			(0x3 << 8)
+#define RT5670_DMIC_SRC_SFT			8
+#define RT5670_M_ADC_R1				(0x1 << 6)
+#define RT5670_M_ADC_R1_SFT			6
+#define RT5670_M_ADC_R2				(0x1 << 5)
+#define RT5670_M_ADC_R2_SFT			5
+#define RT5670_DMIC3_SRC_MASK			(0x1 << 1)
+#define RT5670_DMIC3_SRC_SFT			0
+
+/* Mono ADC Mixer Control (0x28) */
+#define RT5670_M_MONO_ADC_L1			(0x1 << 14)
+#define RT5670_M_MONO_ADC_L1_SFT		14
+#define RT5670_M_MONO_ADC_L2			(0x1 << 13)
+#define RT5670_M_MONO_ADC_L2_SFT		13
+#define RT5670_MONO_ADC_L1_SRC_MASK		(0x1 << 12)
+#define RT5670_MONO_ADC_L1_SRC_SFT		12
+#define RT5670_MONO_ADC_L1_SRC_DACMIXL		(0x0 << 12)
+#define RT5670_MONO_ADC_L1_SRC_ADCL		(0x1 << 12)
+#define RT5670_MONO_ADC_L2_SRC_MASK		(0x1 << 11)
+#define RT5670_MONO_ADC_L2_SRC_SFT		11
+#define RT5670_MONO_ADC_L_SRC_MASK		(0x1 << 10)
+#define RT5670_MONO_ADC_L_SRC_SFT		10
+#define RT5670_MONO_DMIC_L_SRC_MASK		(0x3 << 8)
+#define RT5670_MONO_DMIC_L_SRC_SFT		8
+#define RT5670_M_MONO_ADC_R1			(0x1 << 6)
+#define RT5670_M_MONO_ADC_R1_SFT		6
+#define RT5670_M_MONO_ADC_R2			(0x1 << 5)
+#define RT5670_M_MONO_ADC_R2_SFT		5
+#define RT5670_MONO_ADC_R1_SRC_MASK		(0x1 << 4)
+#define RT5670_MONO_ADC_R1_SRC_SFT		4
+#define RT5670_MONO_ADC_R1_SRC_ADCR		(0x1 << 4)
+#define RT5670_MONO_ADC_R1_SRC_DACMIXR		(0x0 << 4)
+#define RT5670_MONO_ADC_R2_SRC_MASK		(0x1 << 3)
+#define RT5670_MONO_ADC_R2_SRC_SFT		3
+#define RT5670_MONO_DMIC_R_SRC_MASK		(0x3)
+#define RT5670_MONO_DMIC_R_SRC_SFT		0
+
+/* ADC Mixer to DAC Mixer Control (0x29) */
+#define RT5670_M_ADCMIX_L			(0x1 << 15)
+#define RT5670_M_ADCMIX_L_SFT			15
+#define RT5670_M_DAC1_L				(0x1 << 14)
+#define RT5670_M_DAC1_L_SFT			14
+#define RT5670_DAC1_R_SEL_MASK			(0x3 << 10)
+#define RT5670_DAC1_R_SEL_SFT			10
+#define RT5670_DAC1_R_SEL_IF1			(0x0 << 10)
+#define RT5670_DAC1_R_SEL_IF2			(0x1 << 10)
+#define RT5670_DAC1_R_SEL_IF3			(0x2 << 10)
+#define RT5670_DAC1_R_SEL_IF4			(0x3 << 10)
+#define RT5670_DAC1_L_SEL_MASK			(0x3 << 8)
+#define RT5670_DAC1_L_SEL_SFT			8
+#define RT5670_DAC1_L_SEL_IF1			(0x0 << 8)
+#define RT5670_DAC1_L_SEL_IF2			(0x1 << 8)
+#define RT5670_DAC1_L_SEL_IF3			(0x2 << 8)
+#define RT5670_DAC1_L_SEL_IF4			(0x3 << 8)
+#define RT5670_M_ADCMIX_R			(0x1 << 7)
+#define RT5670_M_ADCMIX_R_SFT			7
+#define RT5670_M_DAC1_R				(0x1 << 6)
+#define RT5670_M_DAC1_R_SFT			6
+
+/* Stereo DAC Mixer Control (0x2a) */
+#define RT5670_M_DAC_L1				(0x1 << 14)
+#define RT5670_M_DAC_L1_SFT			14
+#define RT5670_DAC_L1_STO_L_VOL_MASK		(0x1 << 13)
+#define RT5670_DAC_L1_STO_L_VOL_SFT		13
+#define RT5670_M_DAC_L2				(0x1 << 12)
+#define RT5670_M_DAC_L2_SFT			12
+#define RT5670_DAC_L2_STO_L_VOL_MASK		(0x1 << 11)
+#define RT5670_DAC_L2_STO_L_VOL_SFT		11
+#define RT5670_M_DAC_R1_STO_L			(0x1 << 9)
+#define RT5670_M_DAC_R1_STO_L_SFT		9
+#define RT5670_DAC_R1_STO_L_VOL_MASK		(0x1 << 8)
+#define RT5670_DAC_R1_STO_L_VOL_SFT		8
+#define RT5670_M_DAC_R1				(0x1 << 6)
+#define RT5670_M_DAC_R1_SFT			6
+#define RT5670_DAC_R1_STO_R_VOL_MASK		(0x1 << 5)
+#define RT5670_DAC_R1_STO_R_VOL_SFT		5
+#define RT5670_M_DAC_R2				(0x1 << 4)
+#define RT5670_M_DAC_R2_SFT			4
+#define RT5670_DAC_R2_STO_R_VOL_MASK		(0x1 << 3)
+#define RT5670_DAC_R2_STO_R_VOL_SFT		3
+#define RT5670_M_DAC_L1_STO_R			(0x1 << 1)
+#define RT5670_M_DAC_L1_STO_R_SFT		1
+#define RT5670_DAC_L1_STO_R_VOL_MASK		(0x1)
+#define RT5670_DAC_L1_STO_R_VOL_SFT		0
+
+/* Mono DAC Mixer Control (0x2b) */
+#define RT5670_M_DAC_L1_MONO_L			(0x1 << 14)
+#define RT5670_M_DAC_L1_MONO_L_SFT		14
+#define RT5670_DAC_L1_MONO_L_VOL_MASK		(0x1 << 13)
+#define RT5670_DAC_L1_MONO_L_VOL_SFT		13
+#define RT5670_M_DAC_L2_MONO_L			(0x1 << 12)
+#define RT5670_M_DAC_L2_MONO_L_SFT		12
+#define RT5670_DAC_L2_MONO_L_VOL_MASK		(0x1 << 11)
+#define RT5670_DAC_L2_MONO_L_VOL_SFT		11
+#define RT5670_M_DAC_R2_MONO_L			(0x1 << 10)
+#define RT5670_M_DAC_R2_MONO_L_SFT		10
+#define RT5670_DAC_R2_MONO_L_VOL_MASK		(0x1 << 9)
+#define RT5670_DAC_R2_MONO_L_VOL_SFT		9
+#define RT5670_M_DAC_R1_MONO_R			(0x1 << 6)
+#define RT5670_M_DAC_R1_MONO_R_SFT		6
+#define RT5670_DAC_R1_MONO_R_VOL_MASK		(0x1 << 5)
+#define RT5670_DAC_R1_MONO_R_VOL_SFT		5
+#define RT5670_M_DAC_R2_MONO_R			(0x1 << 4)
+#define RT5670_M_DAC_R2_MONO_R_SFT		4
+#define RT5670_DAC_R2_MONO_R_VOL_MASK		(0x1 << 3)
+#define RT5670_DAC_R2_MONO_R_VOL_SFT		3
+#define RT5670_M_DAC_L2_MONO_R			(0x1 << 2)
+#define RT5670_M_DAC_L2_MONO_R_SFT		2
+#define RT5670_DAC_L2_MONO_R_VOL_MASK		(0x1 << 1)
+#define RT5670_DAC_L2_MONO_R_VOL_SFT		1
+
+/* Digital Mixer Control (0x2c) */
+#define RT5670_M_STO_L_DAC_L			(0x1 << 15)
+#define RT5670_M_STO_L_DAC_L_SFT		15
+#define RT5670_STO_L_DAC_L_VOL_MASK		(0x1 << 14)
+#define RT5670_STO_L_DAC_L_VOL_SFT		14
+#define RT5670_M_DAC_L2_DAC_L			(0x1 << 13)
+#define RT5670_M_DAC_L2_DAC_L_SFT		13
+#define RT5670_DAC_L2_DAC_L_VOL_MASK		(0x1 << 12)
+#define RT5670_DAC_L2_DAC_L_VOL_SFT		12
+#define RT5670_M_STO_R_DAC_R			(0x1 << 11)
+#define RT5670_M_STO_R_DAC_R_SFT		11
+#define RT5670_STO_R_DAC_R_VOL_MASK		(0x1 << 10)
+#define RT5670_STO_R_DAC_R_VOL_SFT		10
+#define RT5670_M_DAC_R2_DAC_R			(0x1 << 9)
+#define RT5670_M_DAC_R2_DAC_R_SFT		9
+#define RT5670_DAC_R2_DAC_R_VOL_MASK		(0x1 << 8)
+#define RT5670_DAC_R2_DAC_R_VOL_SFT		8
+#define RT5670_M_DAC_R2_DAC_L			(0x1 << 7)
+#define RT5670_M_DAC_R2_DAC_L_SFT		7
+#define RT5670_DAC_R2_DAC_L_VOL_MASK		(0x1 << 6)
+#define RT5670_DAC_R2_DAC_L_VOL_SFT		6
+#define RT5670_M_DAC_L2_DAC_R			(0x1 << 5)
+#define RT5670_M_DAC_L2_DAC_R_SFT		5
+#define RT5670_DAC_L2_DAC_R_VOL_MASK		(0x1 << 4)
+#define RT5670_DAC_L2_DAC_R_VOL_SFT		4
+
+/* DSP Path Control 1 (0x2d) */
+#define RT5670_RXDP_SEL_MASK			(0x7 << 13)
+#define RT5670_RXDP_SEL_SFT			13
+#define RT5670_RXDP_SRC_MASK			(0x3 << 11)
+#define RT5670_RXDP_SRC_SFT			11
+#define RT5670_RXDP_SRC_NOR			(0x0 << 11)
+#define RT5670_RXDP_SRC_DIV2			(0x1 << 11)
+#define RT5670_RXDP_SRC_DIV3			(0x2 << 11)
+#define RT5670_TXDP_SRC_MASK			(0x3 << 4)
+#define RT5670_TXDP_SRC_SFT			4
+#define RT5670_TXDP_SRC_NOR			(0x0 << 4)
+#define RT5670_TXDP_SRC_DIV2			(0x1 << 4)
+#define RT5670_TXDP_SRC_DIV3			(0x2 << 4)
+#define RT5670_TXDP_SLOT_SEL_MASK		(0x3 << 2)
+#define RT5670_TXDP_SLOT_SEL_SFT		2
+#define RT5670_DSP_UL_SEL			(0x1 << 1)
+#define RT5670_DSP_UL_SFT			1
+#define RT5670_DSP_DL_SEL			0x1
+#define RT5670_DSP_DL_SFT			0
+
+/* DSP Path Control 2 (0x2e) */
+#define RT5670_TXDP_L_VOL_MASK			(0x7f << 8)
+#define RT5670_TXDP_L_VOL_SFT			8
+#define RT5670_TXDP_R_VOL_MASK			(0x7f)
+#define RT5670_TXDP_R_VOL_SFT			0
+
+/* Digital Interface Data Control (0x2f) */
+#define RT5670_IF1_ADC2_IN_SEL			(0x1 << 15)
+#define RT5670_IF1_ADC2_IN_SFT			15
+#define RT5670_IF2_ADC_IN_MASK			(0x7 << 12)
+#define RT5670_IF2_ADC_IN_SFT			12
+#define RT5670_IF2_DAC_SEL_MASK			(0x3 << 10)
+#define RT5670_IF2_DAC_SEL_SFT			10
+#define RT5670_IF2_ADC_SEL_MASK			(0x3 << 8)
+#define RT5670_IF2_ADC_SEL_SFT			8
+
+/* Digital Interface Data Control (0x30) */
+#define RT5670_IF4_ADC_IN_MASK			(0x3 << 4)
+#define RT5670_IF4_ADC_IN_SFT			4
+
+/* PDM Output Control (0x31) */
+#define RT5670_PDM1_L_MASK			(0x1 << 15)
+#define RT5670_PDM1_L_SFT			15
+#define RT5670_M_PDM1_L				(0x1 << 14)
+#define RT5670_M_PDM1_L_SFT			14
+#define RT5670_PDM1_R_MASK			(0x1 << 13)
+#define RT5670_PDM1_R_SFT			13
+#define RT5670_M_PDM1_R				(0x1 << 12)
+#define RT5670_M_PDM1_R_SFT			12
+#define RT5670_PDM2_L_MASK			(0x1 << 11)
+#define RT5670_PDM2_L_SFT			11
+#define RT5670_M_PDM2_L				(0x1 << 10)
+#define RT5670_M_PDM2_L_SFT			10
+#define RT5670_PDM2_R_MASK			(0x1 << 9)
+#define RT5670_PDM2_R_SFT			9
+#define RT5670_M_PDM2_R				(0x1 << 8)
+#define RT5670_M_PDM2_R_SFT			8
+#define RT5670_PDM2_BUSY			(0x1 << 7)
+#define RT5670_PDM1_BUSY			(0x1 << 6)
+#define RT5670_PDM_PATTERN			(0x1 << 5)
+#define RT5670_PDM_GAIN				(0x1 << 4)
+#define RT5670_PDM_DIV_MASK			(0x3)
+
+/* REC Left Mixer Control 1 (0x3b) */
+#define RT5670_G_HP_L_RM_L_MASK			(0x7 << 13)
+#define RT5670_G_HP_L_RM_L_SFT			13
+#define RT5670_G_IN_L_RM_L_MASK			(0x7 << 10)
+#define RT5670_G_IN_L_RM_L_SFT			10
+#define RT5670_G_BST4_RM_L_MASK			(0x7 << 7)
+#define RT5670_G_BST4_RM_L_SFT			7
+#define RT5670_G_BST3_RM_L_MASK			(0x7 << 4)
+#define RT5670_G_BST3_RM_L_SFT			4
+#define RT5670_G_BST2_RM_L_MASK			(0x7 << 1)
+#define RT5670_G_BST2_RM_L_SFT			1
+
+/* REC Left Mixer Control 2 (0x3c) */
+#define RT5670_G_BST1_RM_L_MASK			(0x7 << 13)
+#define RT5670_G_BST1_RM_L_SFT			13
+#define RT5670_M_IN_L_RM_L			(0x1 << 5)
+#define RT5670_M_IN_L_RM_L_SFT			5
+#define RT5670_M_BST2_RM_L			(0x1 << 3)
+#define RT5670_M_BST2_RM_L_SFT			3
+#define RT5670_M_BST1_RM_L			(0x1 << 1)
+#define RT5670_M_BST1_RM_L_SFT			1
+
+/* REC Right Mixer Control 1 (0x3d) */
+#define RT5670_G_HP_R_RM_R_MASK			(0x7 << 13)
+#define RT5670_G_HP_R_RM_R_SFT			13
+#define RT5670_G_IN_R_RM_R_MASK			(0x7 << 10)
+#define RT5670_G_IN_R_RM_R_SFT			10
+#define RT5670_G_BST4_RM_R_MASK			(0x7 << 7)
+#define RT5670_G_BST4_RM_R_SFT			7
+#define RT5670_G_BST3_RM_R_MASK			(0x7 << 4)
+#define RT5670_G_BST3_RM_R_SFT			4
+#define RT5670_G_BST2_RM_R_MASK			(0x7 << 1)
+#define RT5670_G_BST2_RM_R_SFT			1
+
+/* REC Right Mixer Control 2 (0x3e) */
+#define RT5670_G_BST1_RM_R_MASK			(0x7 << 13)
+#define RT5670_G_BST1_RM_R_SFT			13
+#define RT5670_M_IN_R_RM_R			(0x1 << 5)
+#define RT5670_M_IN_R_RM_R_SFT			5
+#define RT5670_M_BST2_RM_R			(0x1 << 3)
+#define RT5670_M_BST2_RM_R_SFT			3
+#define RT5670_M_BST1_RM_R			(0x1 << 1)
+#define RT5670_M_BST1_RM_R_SFT			1
+
+/* HPMIX Control (0x45) */
+#define RT5670_M_DAC2_HM			(0x1 << 15)
+#define RT5670_M_DAC2_HM_SFT			15
+#define RT5670_M_HPVOL_HM			(0x1 << 14)
+#define RT5670_M_HPVOL_HM_SFT			14
+#define RT5670_M_DAC1_HM			(0x1 << 13)
+#define RT5670_M_DAC1_HM_SFT			13
+#define RT5670_G_HPOMIX_MASK			(0x1 << 12)
+#define RT5670_G_HPOMIX_SFT			12
+#define RT5670_M_INR1_HMR			(0x1 << 3)
+#define RT5670_M_INR1_HMR_SFT			3
+#define RT5670_M_DACR1_HMR			(0x1 << 2)
+#define RT5670_M_DACR1_HMR_SFT			2
+#define RT5670_M_INL1_HML			(0x1 << 1)
+#define RT5670_M_INL1_HML_SFT			1
+#define RT5670_M_DACL1_HML			(0x1)
+#define RT5670_M_DACL1_HML_SFT			0
+
+/* Mono Output Mixer Control (0x4c) */
+#define RT5670_M_DAC_R2_MA			(0x1 << 15)
+#define RT5670_M_DAC_R2_MA_SFT			15
+#define RT5670_M_DAC_L2_MA			(0x1 << 14)
+#define RT5670_M_DAC_L2_MA_SFT			14
+#define RT5670_M_OV_R_MM			(0x1 << 13)
+#define RT5670_M_OV_R_MM_SFT			13
+#define RT5670_M_OV_L_MM			(0x1 << 12)
+#define RT5670_M_OV_L_MM_SFT			12
+#define RT5670_G_MONOMIX_MASK			(0x1 << 10)
+#define RT5670_G_MONOMIX_SFT			10
+#define RT5670_M_DAC_R2_MM			(0x1 << 9)
+#define RT5670_M_DAC_R2_MM_SFT			9
+#define RT5670_M_DAC_L2_MM			(0x1 << 8)
+#define RT5670_M_DAC_L2_MM_SFT			8
+#define RT5670_M_BST4_MM			(0x1 << 7)
+#define RT5670_M_BST4_MM_SFT			7
+
+/* Output Left Mixer Control 1 (0x4d) */
+#define RT5670_G_BST3_OM_L_MASK			(0x7 << 13)
+#define RT5670_G_BST3_OM_L_SFT			13
+#define RT5670_G_BST2_OM_L_MASK			(0x7 << 10)
+#define RT5670_G_BST2_OM_L_SFT			10
+#define RT5670_G_BST1_OM_L_MASK			(0x7 << 7)
+#define RT5670_G_BST1_OM_L_SFT			7
+#define RT5670_G_IN_L_OM_L_MASK			(0x7 << 4)
+#define RT5670_G_IN_L_OM_L_SFT			4
+#define RT5670_G_RM_L_OM_L_MASK			(0x7 << 1)
+#define RT5670_G_RM_L_OM_L_SFT			1
+
+/* Output Left Mixer Control 2 (0x4e) */
+#define RT5670_G_DAC_R2_OM_L_MASK		(0x7 << 13)
+#define RT5670_G_DAC_R2_OM_L_SFT		13
+#define RT5670_G_DAC_L2_OM_L_MASK		(0x7 << 10)
+#define RT5670_G_DAC_L2_OM_L_SFT		10
+#define RT5670_G_DAC_L1_OM_L_MASK		(0x7 << 7)
+#define RT5670_G_DAC_L1_OM_L_SFT		7
+
+/* Output Left Mixer Control 3 (0x4f) */
+#define RT5670_M_BST1_OM_L			(0x1 << 5)
+#define RT5670_M_BST1_OM_L_SFT			5
+#define RT5670_M_IN_L_OM_L			(0x1 << 4)
+#define RT5670_M_IN_L_OM_L_SFT			4
+#define RT5670_M_DAC_L2_OM_L			(0x1 << 1)
+#define RT5670_M_DAC_L2_OM_L_SFT		1
+#define RT5670_M_DAC_L1_OM_L			(0x1)
+#define RT5670_M_DAC_L1_OM_L_SFT		0
+
+/* Output Right Mixer Control 1 (0x50) */
+#define RT5670_G_BST4_OM_R_MASK			(0x7 << 13)
+#define RT5670_G_BST4_OM_R_SFT			13
+#define RT5670_G_BST2_OM_R_MASK			(0x7 << 10)
+#define RT5670_G_BST2_OM_R_SFT			10
+#define RT5670_G_BST1_OM_R_MASK			(0x7 << 7)
+#define RT5670_G_BST1_OM_R_SFT			7
+#define RT5670_G_IN_R_OM_R_MASK			(0x7 << 4)
+#define RT5670_G_IN_R_OM_R_SFT			4
+#define RT5670_G_RM_R_OM_R_MASK			(0x7 << 1)
+#define RT5670_G_RM_R_OM_R_SFT			1
+
+/* Output Right Mixer Control 2 (0x51) */
+#define RT5670_G_DAC_L2_OM_R_MASK		(0x7 << 13)
+#define RT5670_G_DAC_L2_OM_R_SFT		13
+#define RT5670_G_DAC_R2_OM_R_MASK		(0x7 << 10)
+#define RT5670_G_DAC_R2_OM_R_SFT		10
+#define RT5670_G_DAC_R1_OM_R_MASK		(0x7 << 7)
+#define RT5670_G_DAC_R1_OM_R_SFT		7
+
+/* Output Right Mixer Control 3 (0x52) */
+#define RT5670_M_BST2_OM_R			(0x1 << 6)
+#define RT5670_M_BST2_OM_R_SFT			6
+#define RT5670_M_IN_R_OM_R			(0x1 << 4)
+#define RT5670_M_IN_R_OM_R_SFT			4
+#define RT5670_M_DAC_R2_OM_R			(0x1 << 1)
+#define RT5670_M_DAC_R2_OM_R_SFT		1
+#define RT5670_M_DAC_R1_OM_R			(0x1)
+#define RT5670_M_DAC_R1_OM_R_SFT		0
+
+/* LOUT Mixer Control (0x53) */
+#define RT5670_M_DAC_L1_LM			(0x1 << 15)
+#define RT5670_M_DAC_L1_LM_SFT			15
+#define RT5670_M_DAC_R1_LM			(0x1 << 14)
+#define RT5670_M_DAC_R1_LM_SFT			14
+#define RT5670_M_OV_L_LM			(0x1 << 13)
+#define RT5670_M_OV_L_LM_SFT			13
+#define RT5670_M_OV_R_LM			(0x1 << 12)
+#define RT5670_M_OV_R_LM_SFT			12
+#define RT5670_G_LOUTMIX_MASK			(0x1 << 11)
+#define RT5670_G_LOUTMIX_SFT			11
+
+/* Power Management for Digital 1 (0x61) */
+#define RT5670_PWR_I2S1				(0x1 << 15)
+#define RT5670_PWR_I2S1_BIT			15
+#define RT5670_PWR_I2S2				(0x1 << 14)
+#define RT5670_PWR_I2S2_BIT			14
+#define RT5670_PWR_DAC_L1			(0x1 << 12)
+#define RT5670_PWR_DAC_L1_BIT			12
+#define RT5670_PWR_DAC_R1			(0x1 << 11)
+#define RT5670_PWR_DAC_R1_BIT			11
+#define RT5670_PWR_DAC_L2			(0x1 << 7)
+#define RT5670_PWR_DAC_L2_BIT			7
+#define RT5670_PWR_DAC_R2			(0x1 << 6)
+#define RT5670_PWR_DAC_R2_BIT			6
+#define RT5670_PWR_ADC_L			(0x1 << 2)
+#define RT5670_PWR_ADC_L_BIT			2
+#define RT5670_PWR_ADC_R			(0x1 << 1)
+#define RT5670_PWR_ADC_R_BIT			1
+#define RT5670_PWR_CLS_D			(0x1)
+#define RT5670_PWR_CLS_D_BIT			0
+
+/* Power Management for Digital 2 (0x62) */
+#define RT5670_PWR_ADC_S1F			(0x1 << 15)
+#define RT5670_PWR_ADC_S1F_BIT			15
+#define RT5670_PWR_ADC_MF_L			(0x1 << 14)
+#define RT5670_PWR_ADC_MF_L_BIT			14
+#define RT5670_PWR_ADC_MF_R			(0x1 << 13)
+#define RT5670_PWR_ADC_MF_R_BIT			13
+#define RT5670_PWR_I2S_DSP			(0x1 << 12)
+#define RT5670_PWR_I2S_DSP_BIT			12
+#define RT5670_PWR_DAC_S1F			(0x1 << 11)
+#define RT5670_PWR_DAC_S1F_BIT			11
+#define RT5670_PWR_DAC_MF_L			(0x1 << 10)
+#define RT5670_PWR_DAC_MF_L_BIT			10
+#define RT5670_PWR_DAC_MF_R			(0x1 << 9)
+#define RT5670_PWR_DAC_MF_R_BIT			9
+#define RT5670_PWR_ADC_S2F			(0x1 << 8)
+#define RT5670_PWR_ADC_S2F_BIT			8
+#define RT5670_PWR_PDM1				(0x1 << 7)
+#define RT5670_PWR_PDM1_BIT			7
+#define RT5670_PWR_PDM2				(0x1 << 6)
+#define RT5670_PWR_PDM2_BIT			6
+
+/* Power Management for Analog 1 (0x63) */
+#define RT5670_PWR_VREF1			(0x1 << 15)
+#define RT5670_PWR_VREF1_BIT			15
+#define RT5670_PWR_FV1				(0x1 << 14)
+#define RT5670_PWR_FV1_BIT			14
+#define RT5670_PWR_MB				(0x1 << 13)
+#define RT5670_PWR_MB_BIT			13
+#define RT5670_PWR_LM				(0x1 << 12)
+#define RT5670_PWR_LM_BIT			12
+#define RT5670_PWR_BG				(0x1 << 11)
+#define RT5670_PWR_BG_BIT			11
+#define RT5670_PWR_HP_L				(0x1 << 7)
+#define RT5670_PWR_HP_L_BIT			7
+#define RT5670_PWR_HP_R				(0x1 << 6)
+#define RT5670_PWR_HP_R_BIT			6
+#define RT5670_PWR_HA				(0x1 << 5)
+#define RT5670_PWR_HA_BIT			5
+#define RT5670_PWR_VREF2			(0x1 << 4)
+#define RT5670_PWR_VREF2_BIT			4
+#define RT5670_PWR_FV2				(0x1 << 3)
+#define RT5670_PWR_FV2_BIT			3
+#define RT5670_LDO_SEL_MASK			(0x3)
+#define RT5670_LDO_SEL_SFT			0
+
+/* Power Management for Analog 2 (0x64) */
+#define RT5670_PWR_BST1				(0x1 << 15)
+#define RT5670_PWR_BST1_BIT			15
+#define RT5670_PWR_BST2				(0x1 << 13)
+#define RT5670_PWR_BST2_BIT			13
+#define RT5670_PWR_MB1				(0x1 << 11)
+#define RT5670_PWR_MB1_BIT			11
+#define RT5670_PWR_MB2				(0x1 << 10)
+#define RT5670_PWR_MB2_BIT			10
+#define RT5670_PWR_PLL				(0x1 << 9)
+#define RT5670_PWR_PLL_BIT			9
+#define RT5670_PWR_BST1_P			(0x1 << 6)
+#define RT5670_PWR_BST1_P_BIT			6
+#define RT5670_PWR_BST2_P			(0x1 << 4)
+#define RT5670_PWR_BST2_P_BIT			4
+#define RT5670_PWR_JD1				(0x1 << 2)
+#define RT5670_PWR_JD1_BIT			2
+#define RT5670_PWR_JD				(0x1 << 1)
+#define RT5670_PWR_JD_BIT			1
+
+/* Power Management for Mixer (0x65) */
+#define RT5670_PWR_OM_L				(0x1 << 15)
+#define RT5670_PWR_OM_L_BIT			15
+#define RT5670_PWR_OM_R				(0x1 << 14)
+#define RT5670_PWR_OM_R_BIT			14
+#define RT5670_PWR_RM_L				(0x1 << 11)
+#define RT5670_PWR_RM_L_BIT			11
+#define RT5670_PWR_RM_R				(0x1 << 10)
+#define RT5670_PWR_RM_R_BIT			10
+
+/* Power Management for Volume (0x66) */
+#define RT5670_PWR_HV_L				(0x1 << 11)
+#define RT5670_PWR_HV_L_BIT			11
+#define RT5670_PWR_HV_R				(0x1 << 10)
+#define RT5670_PWR_HV_R_BIT			10
+#define RT5670_PWR_IN_L				(0x1 << 9)
+#define RT5670_PWR_IN_L_BIT			9
+#define RT5670_PWR_IN_R				(0x1 << 8)
+#define RT5670_PWR_IN_R_BIT			8
+#define RT5670_PWR_MIC_DET			(0x1 << 5)
+#define RT5670_PWR_MIC_DET_BIT			5
+
+/* I2S1/2/3 Audio Serial Data Port Control (0x70 0x71 0x72) */
+#define RT5670_I2S_MS_MASK			(0x1 << 15)
+#define RT5670_I2S_MS_SFT			15
+#define RT5670_I2S_MS_M				(0x0 << 15)
+#define RT5670_I2S_MS_S				(0x1 << 15)
+#define RT5670_I2S_IF_MASK			(0x7 << 12)
+#define RT5670_I2S_IF_SFT			12
+#define RT5670_I2S_O_CP_MASK			(0x3 << 10)
+#define RT5670_I2S_O_CP_SFT			10
+#define RT5670_I2S_O_CP_OFF			(0x0 << 10)
+#define RT5670_I2S_O_CP_U_LAW			(0x1 << 10)
+#define RT5670_I2S_O_CP_A_LAW			(0x2 << 10)
+#define RT5670_I2S_I_CP_MASK			(0x3 << 8)
+#define RT5670_I2S_I_CP_SFT			8
+#define RT5670_I2S_I_CP_OFF			(0x0 << 8)
+#define RT5670_I2S_I_CP_U_LAW			(0x1 << 8)
+#define RT5670_I2S_I_CP_A_LAW			(0x2 << 8)
+#define RT5670_I2S_BP_MASK			(0x1 << 7)
+#define RT5670_I2S_BP_SFT			7
+#define RT5670_I2S_BP_NOR			(0x0 << 7)
+#define RT5670_I2S_BP_INV			(0x1 << 7)
+#define RT5670_I2S_DL_MASK			(0x3 << 2)
+#define RT5670_I2S_DL_SFT			2
+#define RT5670_I2S_DL_16			(0x0 << 2)
+#define RT5670_I2S_DL_20			(0x1 << 2)
+#define RT5670_I2S_DL_24			(0x2 << 2)
+#define RT5670_I2S_DL_8				(0x3 << 2)
+#define RT5670_I2S_DF_MASK			(0x3)
+#define RT5670_I2S_DF_SFT			0
+#define RT5670_I2S_DF_I2S			(0x0)
+#define RT5670_I2S_DF_LEFT			(0x1)
+#define RT5670_I2S_DF_PCM_A			(0x2)
+#define RT5670_I2S_DF_PCM_B			(0x3)
+
+/* I2S2 Audio Serial Data Port Control (0x71) */
+#define RT5670_I2S2_SDI_MASK			(0x1 << 6)
+#define RT5670_I2S2_SDI_SFT			6
+#define RT5670_I2S2_SDI_I2S1			(0x0 << 6)
+#define RT5670_I2S2_SDI_I2S2			(0x1 << 6)
+
+/* ADC/DAC Clock Control 1 (0x73) */
+#define RT5670_I2S_BCLK_MS1_MASK		(0x1 << 15)
+#define RT5670_I2S_BCLK_MS1_SFT			15
+#define RT5670_I2S_BCLK_MS1_32			(0x0 << 15)
+#define RT5670_I2S_BCLK_MS1_64			(0x1 << 15)
+#define RT5670_I2S_PD1_MASK			(0x7 << 12)
+#define RT5670_I2S_PD1_SFT			12
+#define RT5670_I2S_PD1_1			(0x0 << 12)
+#define RT5670_I2S_PD1_2			(0x1 << 12)
+#define RT5670_I2S_PD1_3			(0x2 << 12)
+#define RT5670_I2S_PD1_4			(0x3 << 12)
+#define RT5670_I2S_PD1_6			(0x4 << 12)
+#define RT5670_I2S_PD1_8			(0x5 << 12)
+#define RT5670_I2S_PD1_12			(0x6 << 12)
+#define RT5670_I2S_PD1_16			(0x7 << 12)
+#define RT5670_I2S_BCLK_MS2_MASK		(0x1 << 11)
+#define RT5670_I2S_BCLK_MS2_SFT			11
+#define RT5670_I2S_BCLK_MS2_32			(0x0 << 11)
+#define RT5670_I2S_BCLK_MS2_64			(0x1 << 11)
+#define RT5670_I2S_PD2_MASK			(0x7 << 8)
+#define RT5670_I2S_PD2_SFT			8
+#define RT5670_I2S_PD2_1			(0x0 << 8)
+#define RT5670_I2S_PD2_2			(0x1 << 8)
+#define RT5670_I2S_PD2_3			(0x2 << 8)
+#define RT5670_I2S_PD2_4			(0x3 << 8)
+#define RT5670_I2S_PD2_6			(0x4 << 8)
+#define RT5670_I2S_PD2_8			(0x5 << 8)
+#define RT5670_I2S_PD2_12			(0x6 << 8)
+#define RT5670_I2S_PD2_16			(0x7 << 8)
+#define RT5670_I2S_BCLK_MS3_MASK		(0x1 << 7)
+#define RT5670_I2S_BCLK_MS3_SFT			7
+#define RT5670_I2S_BCLK_MS3_32			(0x0 << 7)
+#define RT5670_I2S_BCLK_MS3_64			(0x1 << 7)
+#define RT5670_I2S_PD3_MASK			(0x7 << 4)
+#define RT5670_I2S_PD3_SFT			4
+#define RT5670_I2S_PD3_1			(0x0 << 4)
+#define RT5670_I2S_PD3_2			(0x1 << 4)
+#define RT5670_I2S_PD3_3			(0x2 << 4)
+#define RT5670_I2S_PD3_4			(0x3 << 4)
+#define RT5670_I2S_PD3_6			(0x4 << 4)
+#define RT5670_I2S_PD3_8			(0x5 << 4)
+#define RT5670_I2S_PD3_12			(0x6 << 4)
+#define RT5670_I2S_PD3_16			(0x7 << 4)
+#define RT5670_DAC_OSR_MASK			(0x3 << 2)
+#define RT5670_DAC_OSR_SFT			2
+#define RT5670_DAC_OSR_128			(0x0 << 2)
+#define RT5670_DAC_OSR_64			(0x1 << 2)
+#define RT5670_DAC_OSR_32			(0x2 << 2)
+#define RT5670_DAC_OSR_16			(0x3 << 2)
+#define RT5670_ADC_OSR_MASK			(0x3)
+#define RT5670_ADC_OSR_SFT			0
+#define RT5670_ADC_OSR_128			(0x0)
+#define RT5670_ADC_OSR_64			(0x1)
+#define RT5670_ADC_OSR_32			(0x2)
+#define RT5670_ADC_OSR_16			(0x3)
+
+/* ADC/DAC Clock Control 2 (0x74) */
+#define RT5670_DAC_L_OSR_MASK			(0x3 << 14)
+#define RT5670_DAC_L_OSR_SFT			14
+#define RT5670_DAC_L_OSR_128			(0x0 << 14)
+#define RT5670_DAC_L_OSR_64			(0x1 << 14)
+#define RT5670_DAC_L_OSR_32			(0x2 << 14)
+#define RT5670_DAC_L_OSR_16			(0x3 << 14)
+#define RT5670_ADC_R_OSR_MASK			(0x3 << 12)
+#define RT5670_ADC_R_OSR_SFT			12
+#define RT5670_ADC_R_OSR_128			(0x0 << 12)
+#define RT5670_ADC_R_OSR_64			(0x1 << 12)
+#define RT5670_ADC_R_OSR_32			(0x2 << 12)
+#define RT5670_ADC_R_OSR_16			(0x3 << 12)
+#define RT5670_DAHPF_EN				(0x1 << 11)
+#define RT5670_DAHPF_EN_SFT			11
+#define RT5670_ADHPF_EN				(0x1 << 10)
+#define RT5670_ADHPF_EN_SFT			10
+
+/* Digital Microphone Control (0x75) */
+#define RT5670_DMIC_1_EN_MASK			(0x1 << 15)
+#define RT5670_DMIC_1_EN_SFT			15
+#define RT5670_DMIC_1_DIS			(0x0 << 15)
+#define RT5670_DMIC_1_EN			(0x1 << 15)
+#define RT5670_DMIC_2_EN_MASK			(0x1 << 14)
+#define RT5670_DMIC_2_EN_SFT			14
+#define RT5670_DMIC_2_DIS			(0x0 << 14)
+#define RT5670_DMIC_2_EN			(0x1 << 14)
+#define RT5670_DMIC_1L_LH_MASK			(0x1 << 13)
+#define RT5670_DMIC_1L_LH_SFT			13
+#define RT5670_DMIC_1L_LH_FALLING		(0x0 << 13)
+#define RT5670_DMIC_1L_LH_RISING		(0x1 << 13)
+#define RT5670_DMIC_1R_LH_MASK			(0x1 << 12)
+#define RT5670_DMIC_1R_LH_SFT			12
+#define RT5670_DMIC_1R_LH_FALLING		(0x0 << 12)
+#define RT5670_DMIC_1R_LH_RISING		(0x1 << 12)
+#define RT5670_DMIC_2_DP_MASK			(0x1 << 10)
+#define RT5670_DMIC_2_DP_SFT			10
+#define RT5670_DMIC_2_DP_GPIO8			(0x0 << 10)
+#define RT5670_DMIC_2_DP_IN3N			(0x1 << 10)
+#define RT5670_DMIC_2L_LH_MASK			(0x1 << 9)
+#define RT5670_DMIC_2L_LH_SFT			9
+#define RT5670_DMIC_2L_LH_FALLING		(0x0 << 9)
+#define RT5670_DMIC_2L_LH_RISING		(0x1 << 9)
+#define RT5670_DMIC_2R_LH_MASK			(0x1 << 8)
+#define RT5670_DMIC_2R_LH_SFT			8
+#define RT5670_DMIC_2R_LH_FALLING		(0x0 << 8)
+#define RT5670_DMIC_2R_LH_RISING		(0x1 << 8)
+#define RT5670_DMIC_CLK_MASK			(0x7 << 5)
+#define RT5670_DMIC_CLK_SFT			5
+#define RT5670_DMIC_3_EN_MASK			(0x1 << 4)
+#define RT5670_DMIC_3_EN_SFT			4
+#define RT5670_DMIC_3_DIS			(0x0 << 4)
+#define RT5670_DMIC_3_EN			(0x1 << 4)
+#define RT5670_DMIC_1_DP_MASK			(0x3 << 0)
+#define RT5670_DMIC_1_DP_SFT			0
+#define RT5670_DMIC_1_DP_GPIO6			(0x0 << 0)
+#define RT5670_DMIC_1_DP_IN2P			(0x1 << 0)
+#define RT5670_DMIC_1_DP_GPIO7			(0x2 << 0)
+
+/* Digital Microphone Control2 (0x76) */
+#define RT5670_DMIC_3_DP_MASK			(0x3 << 6)
+#define RT5670_DMIC_3_DP_SFT			6
+#define RT5670_DMIC_3_DP_GPIO9			(0x0 << 6)
+#define RT5670_DMIC_3_DP_GPIO10			(0x1 << 6)
+#define RT5670_DMIC_3_DP_GPIO5			(0x2 << 6)
+
+/* Global Clock Control (0x80) */
+#define RT5670_SCLK_SRC_MASK			(0x3 << 14)
+#define RT5670_SCLK_SRC_SFT			14
+#define RT5670_SCLK_SRC_MCLK			(0x0 << 14)
+#define RT5670_SCLK_SRC_PLL1			(0x1 << 14)
+#define RT5670_SCLK_SRC_RCCLK			(0x2 << 14) /* 15MHz */
+#define RT5670_PLL1_SRC_MASK			(0x3 << 12)
+#define RT5670_PLL1_SRC_SFT			12
+#define RT5670_PLL1_SRC_MCLK			(0x0 << 12)
+#define RT5670_PLL1_SRC_BCLK1			(0x1 << 12)
+#define RT5670_PLL1_SRC_BCLK2			(0x2 << 12)
+#define RT5670_PLL1_SRC_BCLK3			(0x3 << 12)
+#define RT5670_PLL1_PD_MASK			(0x1 << 3)
+#define RT5670_PLL1_PD_SFT			3
+#define RT5670_PLL1_PD_1			(0x0 << 3)
+#define RT5670_PLL1_PD_2			(0x1 << 3)
+
+#define RT5670_PLL_INP_MAX			40000000
+#define RT5670_PLL_INP_MIN			256000
+/* PLL M/N/K Code Control 1 (0x81) */
+#define RT5670_PLL_N_MAX			0x1ff
+#define RT5670_PLL_N_MASK			(RT5670_PLL_N_MAX << 7)
+#define RT5670_PLL_N_SFT			7
+#define RT5670_PLL_K_MAX			0x1f
+#define RT5670_PLL_K_MASK			(RT5670_PLL_K_MAX)
+#define RT5670_PLL_K_SFT			0
+
+/* PLL M/N/K Code Control 2 (0x82) */
+#define RT5670_PLL_M_MAX			0xf
+#define RT5670_PLL_M_MASK			(RT5670_PLL_M_MAX << 12)
+#define RT5670_PLL_M_SFT			12
+#define RT5670_PLL_M_BP				(0x1 << 11)
+#define RT5670_PLL_M_BP_SFT			11
+
+/* ASRC Control 1 (0x83) */
+#define RT5670_STO_T_MASK			(0x1 << 15)
+#define RT5670_STO_T_SFT			15
+#define RT5670_STO_T_SCLK			(0x0 << 15)
+#define RT5670_STO_T_LRCK1			(0x1 << 15)
+#define RT5670_M1_T_MASK			(0x1 << 14)
+#define RT5670_M1_T_SFT				14
+#define RT5670_M1_T_I2S2			(0x0 << 14)
+#define RT5670_M1_T_I2S2_D3			(0x1 << 14)
+#define RT5670_I2S2_F_MASK			(0x1 << 12)
+#define RT5670_I2S2_F_SFT			12
+#define RT5670_I2S2_F_I2S2_D2			(0x0 << 12)
+#define RT5670_I2S2_F_I2S1_TCLK			(0x1 << 12)
+#define RT5670_DMIC_1_M_MASK			(0x1 << 9)
+#define RT5670_DMIC_1_M_SFT			9
+#define RT5670_DMIC_1_M_NOR			(0x0 << 9)
+#define RT5670_DMIC_1_M_ASYN			(0x1 << 9)
+#define RT5670_DMIC_2_M_MASK			(0x1 << 8)
+#define RT5670_DMIC_2_M_SFT			8
+#define RT5670_DMIC_2_M_NOR			(0x0 << 8)
+#define RT5670_DMIC_2_M_ASYN			(0x1 << 8)
+
+/* ASRC Control 2 (0x84) */
+#define RT5670_MDA_L_M_MASK			(0x1 << 15)
+#define RT5670_MDA_L_M_SFT			15
+#define RT5670_MDA_L_M_NOR			(0x0 << 15)
+#define RT5670_MDA_L_M_ASYN			(0x1 << 15)
+#define RT5670_MDA_R_M_MASK			(0x1 << 14)
+#define RT5670_MDA_R_M_SFT			14
+#define RT5670_MDA_R_M_NOR			(0x0 << 14)
+#define RT5670_MDA_R_M_ASYN			(0x1 << 14)
+#define RT5670_MAD_L_M_MASK			(0x1 << 13)
+#define RT5670_MAD_L_M_SFT			13
+#define RT5670_MAD_L_M_NOR			(0x0 << 13)
+#define RT5670_MAD_L_M_ASYN			(0x1 << 13)
+#define RT5670_MAD_R_M_MASK			(0x1 << 12)
+#define RT5670_MAD_R_M_SFT			12
+#define RT5670_MAD_R_M_NOR			(0x0 << 12)
+#define RT5670_MAD_R_M_ASYN			(0x1 << 12)
+#define RT5670_ADC_M_MASK			(0x1 << 11)
+#define RT5670_ADC_M_SFT			11
+#define RT5670_ADC_M_NOR			(0x0 << 11)
+#define RT5670_ADC_M_ASYN			(0x1 << 11)
+#define RT5670_STO_DAC_M_MASK			(0x1 << 5)
+#define RT5670_STO_DAC_M_SFT			5
+#define RT5670_STO_DAC_M_NOR			(0x0 << 5)
+#define RT5670_STO_DAC_M_ASYN			(0x1 << 5)
+#define RT5670_I2S1_R_D_MASK			(0x1 << 4)
+#define RT5670_I2S1_R_D_SFT			4
+#define RT5670_I2S1_R_D_DIS			(0x0 << 4)
+#define RT5670_I2S1_R_D_EN			(0x1 << 4)
+#define RT5670_I2S2_R_D_MASK			(0x1 << 3)
+#define RT5670_I2S2_R_D_SFT			3
+#define RT5670_I2S2_R_D_DIS			(0x0 << 3)
+#define RT5670_I2S2_R_D_EN			(0x1 << 3)
+#define RT5670_PRE_SCLK_MASK			(0x3)
+#define RT5670_PRE_SCLK_SFT			0
+#define RT5670_PRE_SCLK_512			(0x0)
+#define RT5670_PRE_SCLK_1024			(0x1)
+#define RT5670_PRE_SCLK_2048			(0x2)
+
+/* ASRC Control 3 (0x85) */
+#define RT5670_I2S1_RATE_MASK			(0xf << 12)
+#define RT5670_I2S1_RATE_SFT			12
+#define RT5670_I2S2_RATE_MASK			(0xf << 8)
+#define RT5670_I2S2_RATE_SFT			8
+
+/* ASRC Control 4 (0x89) */
+#define RT5670_I2S1_PD_MASK			(0x7 << 12)
+#define RT5670_I2S1_PD_SFT			12
+#define RT5670_I2S2_PD_MASK			(0x7 << 8)
+#define RT5670_I2S2_PD_SFT			8
+
+/* HPOUT Over Current Detection (0x8b) */
+#define RT5670_HP_OVCD_MASK			(0x1 << 10)
+#define RT5670_HP_OVCD_SFT			10
+#define RT5670_HP_OVCD_DIS			(0x0 << 10)
+#define RT5670_HP_OVCD_EN			(0x1 << 10)
+#define RT5670_HP_OC_TH_MASK			(0x3 << 8)
+#define RT5670_HP_OC_TH_SFT			8
+#define RT5670_HP_OC_TH_90			(0x0 << 8)
+#define RT5670_HP_OC_TH_105			(0x1 << 8)
+#define RT5670_HP_OC_TH_120			(0x2 << 8)
+#define RT5670_HP_OC_TH_135			(0x3 << 8)
+
+/* Class D Over Current Control (0x8c) */
+#define RT5670_CLSD_OC_MASK			(0x1 << 9)
+#define RT5670_CLSD_OC_SFT			9
+#define RT5670_CLSD_OC_PU			(0x0 << 9)
+#define RT5670_CLSD_OC_PD			(0x1 << 9)
+#define RT5670_AUTO_PD_MASK			(0x1 << 8)
+#define RT5670_AUTO_PD_SFT			8
+#define RT5670_AUTO_PD_DIS			(0x0 << 8)
+#define RT5670_AUTO_PD_EN			(0x1 << 8)
+#define RT5670_CLSD_OC_TH_MASK			(0x3f)
+#define RT5670_CLSD_OC_TH_SFT			0
+
+/* Class D Output Control (0x8d) */
+#define RT5670_CLSD_RATIO_MASK			(0xf << 12)
+#define RT5670_CLSD_RATIO_SFT			12
+#define RT5670_CLSD_OM_MASK			(0x1 << 11)
+#define RT5670_CLSD_OM_SFT			11
+#define RT5670_CLSD_OM_MONO			(0x0 << 11)
+#define RT5670_CLSD_OM_STO			(0x1 << 11)
+#define RT5670_CLSD_SCH_MASK			(0x1 << 10)
+#define RT5670_CLSD_SCH_SFT			10
+#define RT5670_CLSD_SCH_L			(0x0 << 10)
+#define RT5670_CLSD_SCH_S			(0x1 << 10)
+
+/* Depop Mode Control 1 (0x8e) */
+#define RT5670_SMT_TRIG_MASK			(0x1 << 15)
+#define RT5670_SMT_TRIG_SFT			15
+#define RT5670_SMT_TRIG_DIS			(0x0 << 15)
+#define RT5670_SMT_TRIG_EN			(0x1 << 15)
+#define RT5670_HP_L_SMT_MASK			(0x1 << 9)
+#define RT5670_HP_L_SMT_SFT			9
+#define RT5670_HP_L_SMT_DIS			(0x0 << 9)
+#define RT5670_HP_L_SMT_EN			(0x1 << 9)
+#define RT5670_HP_R_SMT_MASK			(0x1 << 8)
+#define RT5670_HP_R_SMT_SFT			8
+#define RT5670_HP_R_SMT_DIS			(0x0 << 8)
+#define RT5670_HP_R_SMT_EN			(0x1 << 8)
+#define RT5670_HP_CD_PD_MASK			(0x1 << 7)
+#define RT5670_HP_CD_PD_SFT			7
+#define RT5670_HP_CD_PD_DIS			(0x0 << 7)
+#define RT5670_HP_CD_PD_EN			(0x1 << 7)
+#define RT5670_RSTN_MASK			(0x1 << 6)
+#define RT5670_RSTN_SFT				6
+#define RT5670_RSTN_DIS				(0x0 << 6)
+#define RT5670_RSTN_EN				(0x1 << 6)
+#define RT5670_RSTP_MASK			(0x1 << 5)
+#define RT5670_RSTP_SFT				5
+#define RT5670_RSTP_DIS				(0x0 << 5)
+#define RT5670_RSTP_EN				(0x1 << 5)
+#define RT5670_HP_CO_MASK			(0x1 << 4)
+#define RT5670_HP_CO_SFT			4
+#define RT5670_HP_CO_DIS			(0x0 << 4)
+#define RT5670_HP_CO_EN				(0x1 << 4)
+#define RT5670_HP_CP_MASK			(0x1 << 3)
+#define RT5670_HP_CP_SFT			3
+#define RT5670_HP_CP_PD				(0x0 << 3)
+#define RT5670_HP_CP_PU				(0x1 << 3)
+#define RT5670_HP_SG_MASK			(0x1 << 2)
+#define RT5670_HP_SG_SFT			2
+#define RT5670_HP_SG_DIS			(0x0 << 2)
+#define RT5670_HP_SG_EN				(0x1 << 2)
+#define RT5670_HP_DP_MASK			(0x1 << 1)
+#define RT5670_HP_DP_SFT			1
+#define RT5670_HP_DP_PD				(0x0 << 1)
+#define RT5670_HP_DP_PU				(0x1 << 1)
+#define RT5670_HP_CB_MASK			(0x1)
+#define RT5670_HP_CB_SFT			0
+#define RT5670_HP_CB_PD				(0x0)
+#define RT5670_HP_CB_PU				(0x1)
+
+/* Depop Mode Control 2 (0x8f) */
+#define RT5670_DEPOP_MASK			(0x1 << 13)
+#define RT5670_DEPOP_SFT			13
+#define RT5670_DEPOP_AUTO			(0x0 << 13)
+#define RT5670_DEPOP_MAN			(0x1 << 13)
+#define RT5670_RAMP_MASK			(0x1 << 12)
+#define RT5670_RAMP_SFT				12
+#define RT5670_RAMP_DIS				(0x0 << 12)
+#define RT5670_RAMP_EN				(0x1 << 12)
+#define RT5670_BPS_MASK				(0x1 << 11)
+#define RT5670_BPS_SFT				11
+#define RT5670_BPS_DIS				(0x0 << 11)
+#define RT5670_BPS_EN				(0x1 << 11)
+#define RT5670_FAST_UPDN_MASK			(0x1 << 10)
+#define RT5670_FAST_UPDN_SFT			10
+#define RT5670_FAST_UPDN_DIS			(0x0 << 10)
+#define RT5670_FAST_UPDN_EN			(0x1 << 10)
+#define RT5670_MRES_MASK			(0x3 << 8)
+#define RT5670_MRES_SFT				8
+#define RT5670_MRES_15MO			(0x0 << 8)
+#define RT5670_MRES_25MO			(0x1 << 8)
+#define RT5670_MRES_35MO			(0x2 << 8)
+#define RT5670_MRES_45MO			(0x3 << 8)
+#define RT5670_VLO_MASK				(0x1 << 7)
+#define RT5670_VLO_SFT				7
+#define RT5670_VLO_3V				(0x0 << 7)
+#define RT5670_VLO_32V				(0x1 << 7)
+#define RT5670_DIG_DP_MASK			(0x1 << 6)
+#define RT5670_DIG_DP_SFT			6
+#define RT5670_DIG_DP_DIS			(0x0 << 6)
+#define RT5670_DIG_DP_EN			(0x1 << 6)
+#define RT5670_DP_TH_MASK			(0x3 << 4)
+#define RT5670_DP_TH_SFT			4
+
+/* Depop Mode Control 3 (0x90) */
+#define RT5670_CP_SYS_MASK			(0x7 << 12)
+#define RT5670_CP_SYS_SFT			12
+#define RT5670_CP_FQ1_MASK			(0x7 << 8)
+#define RT5670_CP_FQ1_SFT			8
+#define RT5670_CP_FQ2_MASK			(0x7 << 4)
+#define RT5670_CP_FQ2_SFT			4
+#define RT5670_CP_FQ3_MASK			(0x7)
+#define RT5670_CP_FQ3_SFT			0
+#define RT5670_CP_FQ_1_5_KHZ			0
+#define RT5670_CP_FQ_3_KHZ			1
+#define RT5670_CP_FQ_6_KHZ			2
+#define RT5670_CP_FQ_12_KHZ			3
+#define RT5670_CP_FQ_24_KHZ			4
+#define RT5670_CP_FQ_48_KHZ			5
+#define RT5670_CP_FQ_96_KHZ			6
+#define RT5670_CP_FQ_192_KHZ			7
+
+/* HPOUT charge pump (0x91) */
+#define RT5670_OSW_L_MASK			(0x1 << 11)
+#define RT5670_OSW_L_SFT			11
+#define RT5670_OSW_L_DIS			(0x0 << 11)
+#define RT5670_OSW_L_EN				(0x1 << 11)
+#define RT5670_OSW_R_MASK			(0x1 << 10)
+#define RT5670_OSW_R_SFT			10
+#define RT5670_OSW_R_DIS			(0x0 << 10)
+#define RT5670_OSW_R_EN				(0x1 << 10)
+#define RT5670_PM_HP_MASK			(0x3 << 8)
+#define RT5670_PM_HP_SFT			8
+#define RT5670_PM_HP_LV				(0x0 << 8)
+#define RT5670_PM_HP_MV				(0x1 << 8)
+#define RT5670_PM_HP_HV				(0x2 << 8)
+#define RT5670_IB_HP_MASK			(0x3 << 6)
+#define RT5670_IB_HP_SFT			6
+#define RT5670_IB_HP_125IL			(0x0 << 6)
+#define RT5670_IB_HP_25IL			(0x1 << 6)
+#define RT5670_IB_HP_5IL			(0x2 << 6)
+#define RT5670_IB_HP_1IL			(0x3 << 6)
+
+/* PV detection and SPK gain control (0x92) */
+#define RT5670_PVDD_DET_MASK			(0x1 << 15)
+#define RT5670_PVDD_DET_SFT			15
+#define RT5670_PVDD_DET_DIS			(0x0 << 15)
+#define RT5670_PVDD_DET_EN			(0x1 << 15)
+#define RT5670_SPK_AG_MASK			(0x1 << 14)
+#define RT5670_SPK_AG_SFT			14
+#define RT5670_SPK_AG_DIS			(0x0 << 14)
+#define RT5670_SPK_AG_EN			(0x1 << 14)
+
+/* Micbias Control (0x93) */
+#define RT5670_MIC1_BS_MASK			(0x1 << 15)
+#define RT5670_MIC1_BS_SFT			15
+#define RT5670_MIC1_BS_9AV			(0x0 << 15)
+#define RT5670_MIC1_BS_75AV			(0x1 << 15)
+#define RT5670_MIC2_BS_MASK			(0x1 << 14)
+#define RT5670_MIC2_BS_SFT			14
+#define RT5670_MIC2_BS_9AV			(0x0 << 14)
+#define RT5670_MIC2_BS_75AV			(0x1 << 14)
+#define RT5670_MIC1_CLK_MASK			(0x1 << 13)
+#define RT5670_MIC1_CLK_SFT			13
+#define RT5670_MIC1_CLK_DIS			(0x0 << 13)
+#define RT5670_MIC1_CLK_EN			(0x1 << 13)
+#define RT5670_MIC2_CLK_MASK			(0x1 << 12)
+#define RT5670_MIC2_CLK_SFT			12
+#define RT5670_MIC2_CLK_DIS			(0x0 << 12)
+#define RT5670_MIC2_CLK_EN			(0x1 << 12)
+#define RT5670_MIC1_OVCD_MASK			(0x1 << 11)
+#define RT5670_MIC1_OVCD_SFT			11
+#define RT5670_MIC1_OVCD_DIS			(0x0 << 11)
+#define RT5670_MIC1_OVCD_EN			(0x1 << 11)
+#define RT5670_MIC1_OVTH_MASK			(0x3 << 9)
+#define RT5670_MIC1_OVTH_SFT			9
+#define RT5670_MIC1_OVTH_600UA			(0x0 << 9)
+#define RT5670_MIC1_OVTH_1500UA			(0x1 << 9)
+#define RT5670_MIC1_OVTH_2000UA			(0x2 << 9)
+#define RT5670_MIC2_OVCD_MASK			(0x1 << 8)
+#define RT5670_MIC2_OVCD_SFT			8
+#define RT5670_MIC2_OVCD_DIS			(0x0 << 8)
+#define RT5670_MIC2_OVCD_EN			(0x1 << 8)
+#define RT5670_MIC2_OVTH_MASK			(0x3 << 6)
+#define RT5670_MIC2_OVTH_SFT			6
+#define RT5670_MIC2_OVTH_600UA			(0x0 << 6)
+#define RT5670_MIC2_OVTH_1500UA			(0x1 << 6)
+#define RT5670_MIC2_OVTH_2000UA			(0x2 << 6)
+#define RT5670_PWR_MB_MASK			(0x1 << 5)
+#define RT5670_PWR_MB_SFT			5
+#define RT5670_PWR_MB_PD			(0x0 << 5)
+#define RT5670_PWR_MB_PU			(0x1 << 5)
+#define RT5670_PWR_CLK25M_MASK			(0x1 << 4)
+#define RT5670_PWR_CLK25M_SFT			4
+#define RT5670_PWR_CLK25M_PD			(0x0 << 4)
+#define RT5670_PWR_CLK25M_PU			(0x1 << 4)
+
+/* Analog JD Control 1 (0x94) */
+#define RT5670_JD1_MODE_MASK			(0x3 << 0)
+#define RT5670_JD1_MODE_0			(0x0 << 0)
+#define RT5670_JD1_MODE_1			(0x1 << 0)
+#define RT5670_JD1_MODE_2			(0x2 << 0)
+
+/* VAD Control 4 (0x9d) */
+#define RT5670_VAD_SEL_MASK			(0x3 << 8)
+#define RT5670_VAD_SEL_SFT			8
+
+/* EQ Control 1 (0xb0) */
+#define RT5670_EQ_SRC_MASK			(0x1 << 15)
+#define RT5670_EQ_SRC_SFT			15
+#define RT5670_EQ_SRC_DAC			(0x0 << 15)
+#define RT5670_EQ_SRC_ADC			(0x1 << 15)
+#define RT5670_EQ_UPD				(0x1 << 14)
+#define RT5670_EQ_UPD_BIT			14
+#define RT5670_EQ_CD_MASK			(0x1 << 13)
+#define RT5670_EQ_CD_SFT			13
+#define RT5670_EQ_CD_DIS			(0x0 << 13)
+#define RT5670_EQ_CD_EN				(0x1 << 13)
+#define RT5670_EQ_DITH_MASK			(0x3 << 8)
+#define RT5670_EQ_DITH_SFT			8
+#define RT5670_EQ_DITH_NOR			(0x0 << 8)
+#define RT5670_EQ_DITH_LSB			(0x1 << 8)
+#define RT5670_EQ_DITH_LSB_1			(0x2 << 8)
+#define RT5670_EQ_DITH_LSB_2			(0x3 << 8)
+
+/* EQ Control 2 (0xb1) */
+#define RT5670_EQ_HPF1_M_MASK			(0x1 << 8)
+#define RT5670_EQ_HPF1_M_SFT			8
+#define RT5670_EQ_HPF1_M_HI			(0x0 << 8)
+#define RT5670_EQ_HPF1_M_1ST			(0x1 << 8)
+#define RT5670_EQ_LPF1_M_MASK			(0x1 << 7)
+#define RT5670_EQ_LPF1_M_SFT			7
+#define RT5670_EQ_LPF1_M_LO			(0x0 << 7)
+#define RT5670_EQ_LPF1_M_1ST			(0x1 << 7)
+#define RT5670_EQ_HPF2_MASK			(0x1 << 6)
+#define RT5670_EQ_HPF2_SFT			6
+#define RT5670_EQ_HPF2_DIS			(0x0 << 6)
+#define RT5670_EQ_HPF2_EN			(0x1 << 6)
+#define RT5670_EQ_HPF1_MASK			(0x1 << 5)
+#define RT5670_EQ_HPF1_SFT			5
+#define RT5670_EQ_HPF1_DIS			(0x0 << 5)
+#define RT5670_EQ_HPF1_EN			(0x1 << 5)
+#define RT5670_EQ_BPF4_MASK			(0x1 << 4)
+#define RT5670_EQ_BPF4_SFT			4
+#define RT5670_EQ_BPF4_DIS			(0x0 << 4)
+#define RT5670_EQ_BPF4_EN			(0x1 << 4)
+#define RT5670_EQ_BPF3_MASK			(0x1 << 3)
+#define RT5670_EQ_BPF3_SFT			3
+#define RT5670_EQ_BPF3_DIS			(0x0 << 3)
+#define RT5670_EQ_BPF3_EN			(0x1 << 3)
+#define RT5670_EQ_BPF2_MASK			(0x1 << 2)
+#define RT5670_EQ_BPF2_SFT			2
+#define RT5670_EQ_BPF2_DIS			(0x0 << 2)
+#define RT5670_EQ_BPF2_EN			(0x1 << 2)
+#define RT5670_EQ_BPF1_MASK			(0x1 << 1)
+#define RT5670_EQ_BPF1_SFT			1
+#define RT5670_EQ_BPF1_DIS			(0x0 << 1)
+#define RT5670_EQ_BPF1_EN			(0x1 << 1)
+#define RT5670_EQ_LPF_MASK			(0x1)
+#define RT5670_EQ_LPF_SFT			0
+#define RT5670_EQ_LPF_DIS			(0x0)
+#define RT5670_EQ_LPF_EN			(0x1)
+#define RT5670_EQ_CTRL_MASK			(0x7f)
+
+/* Memory Test (0xb2) */
+#define RT5670_MT_MASK				(0x1 << 15)
+#define RT5670_MT_SFT				15
+#define RT5670_MT_DIS				(0x0 << 15)
+#define RT5670_MT_EN				(0x1 << 15)
+
+/* DRC/AGC Control 1 (0xb4) */
+#define RT5670_DRC_AGC_P_MASK			(0x1 << 15)
+#define RT5670_DRC_AGC_P_SFT			15
+#define RT5670_DRC_AGC_P_DAC			(0x0 << 15)
+#define RT5670_DRC_AGC_P_ADC			(0x1 << 15)
+#define RT5670_DRC_AGC_MASK			(0x1 << 14)
+#define RT5670_DRC_AGC_SFT			14
+#define RT5670_DRC_AGC_DIS			(0x0 << 14)
+#define RT5670_DRC_AGC_EN			(0x1 << 14)
+#define RT5670_DRC_AGC_UPD			(0x1 << 13)
+#define RT5670_DRC_AGC_UPD_BIT			13
+#define RT5670_DRC_AGC_AR_MASK			(0x1f << 8)
+#define RT5670_DRC_AGC_AR_SFT			8
+#define RT5670_DRC_AGC_R_MASK			(0x7 << 5)
+#define RT5670_DRC_AGC_R_SFT			5
+#define RT5670_DRC_AGC_R_48K			(0x1 << 5)
+#define RT5670_DRC_AGC_R_96K			(0x2 << 5)
+#define RT5670_DRC_AGC_R_192K			(0x3 << 5)
+#define RT5670_DRC_AGC_R_441K			(0x5 << 5)
+#define RT5670_DRC_AGC_R_882K			(0x6 << 5)
+#define RT5670_DRC_AGC_R_1764K			(0x7 << 5)
+#define RT5670_DRC_AGC_RC_MASK			(0x1f)
+#define RT5670_DRC_AGC_RC_SFT			0
+
+/* DRC/AGC Control 2 (0xb5) */
+#define RT5670_DRC_AGC_POB_MASK			(0x3f << 8)
+#define RT5670_DRC_AGC_POB_SFT			8
+#define RT5670_DRC_AGC_CP_MASK			(0x1 << 7)
+#define RT5670_DRC_AGC_CP_SFT			7
+#define RT5670_DRC_AGC_CP_DIS			(0x0 << 7)
+#define RT5670_DRC_AGC_CP_EN			(0x1 << 7)
+#define RT5670_DRC_AGC_CPR_MASK			(0x3 << 5)
+#define RT5670_DRC_AGC_CPR_SFT			5
+#define RT5670_DRC_AGC_CPR_1_1			(0x0 << 5)
+#define RT5670_DRC_AGC_CPR_1_2			(0x1 << 5)
+#define RT5670_DRC_AGC_CPR_1_3			(0x2 << 5)
+#define RT5670_DRC_AGC_CPR_1_4			(0x3 << 5)
+#define RT5670_DRC_AGC_PRB_MASK			(0x1f)
+#define RT5670_DRC_AGC_PRB_SFT			0
+
+/* DRC/AGC Control 3 (0xb6) */
+#define RT5670_DRC_AGC_NGB_MASK			(0xf << 12)
+#define RT5670_DRC_AGC_NGB_SFT			12
+#define RT5670_DRC_AGC_TAR_MASK			(0x1f << 7)
+#define RT5670_DRC_AGC_TAR_SFT			7
+#define RT5670_DRC_AGC_NG_MASK			(0x1 << 6)
+#define RT5670_DRC_AGC_NG_SFT			6
+#define RT5670_DRC_AGC_NG_DIS			(0x0 << 6)
+#define RT5670_DRC_AGC_NG_EN			(0x1 << 6)
+#define RT5670_DRC_AGC_NGH_MASK			(0x1 << 5)
+#define RT5670_DRC_AGC_NGH_SFT			5
+#define RT5670_DRC_AGC_NGH_DIS			(0x0 << 5)
+#define RT5670_DRC_AGC_NGH_EN			(0x1 << 5)
+#define RT5670_DRC_AGC_NGT_MASK			(0x1f)
+#define RT5670_DRC_AGC_NGT_SFT			0
+
+/* Jack Detect Control (0xbb) */
+#define RT5670_JD_MASK				(0x7 << 13)
+#define RT5670_JD_SFT				13
+#define RT5670_JD_DIS				(0x0 << 13)
+#define RT5670_JD_GPIO1				(0x1 << 13)
+#define RT5670_JD_JD1_IN4P			(0x2 << 13)
+#define RT5670_JD_JD2_IN4N			(0x3 << 13)
+#define RT5670_JD_GPIO2				(0x4 << 13)
+#define RT5670_JD_GPIO3				(0x5 << 13)
+#define RT5670_JD_GPIO4				(0x6 << 13)
+#define RT5670_JD_HP_MASK			(0x1 << 11)
+#define RT5670_JD_HP_SFT			11
+#define RT5670_JD_HP_DIS			(0x0 << 11)
+#define RT5670_JD_HP_EN				(0x1 << 11)
+#define RT5670_JD_HP_TRG_MASK			(0x1 << 10)
+#define RT5670_JD_HP_TRG_SFT			10
+#define RT5670_JD_HP_TRG_LO			(0x0 << 10)
+#define RT5670_JD_HP_TRG_HI			(0x1 << 10)
+#define RT5670_JD_SPL_MASK			(0x1 << 9)
+#define RT5670_JD_SPL_SFT			9
+#define RT5670_JD_SPL_DIS			(0x0 << 9)
+#define RT5670_JD_SPL_EN			(0x1 << 9)
+#define RT5670_JD_SPL_TRG_MASK			(0x1 << 8)
+#define RT5670_JD_SPL_TRG_SFT			8
+#define RT5670_JD_SPL_TRG_LO			(0x0 << 8)
+#define RT5670_JD_SPL_TRG_HI			(0x1 << 8)
+#define RT5670_JD_SPR_MASK			(0x1 << 7)
+#define RT5670_JD_SPR_SFT			7
+#define RT5670_JD_SPR_DIS			(0x0 << 7)
+#define RT5670_JD_SPR_EN			(0x1 << 7)
+#define RT5670_JD_SPR_TRG_MASK			(0x1 << 6)
+#define RT5670_JD_SPR_TRG_SFT			6
+#define RT5670_JD_SPR_TRG_LO			(0x0 << 6)
+#define RT5670_JD_SPR_TRG_HI			(0x1 << 6)
+#define RT5670_JD_MO_MASK			(0x1 << 5)
+#define RT5670_JD_MO_SFT			5
+#define RT5670_JD_MO_DIS			(0x0 << 5)
+#define RT5670_JD_MO_EN				(0x1 << 5)
+#define RT5670_JD_MO_TRG_MASK			(0x1 << 4)
+#define RT5670_JD_MO_TRG_SFT			4
+#define RT5670_JD_MO_TRG_LO			(0x0 << 4)
+#define RT5670_JD_MO_TRG_HI			(0x1 << 4)
+#define RT5670_JD_LO_MASK			(0x1 << 3)
+#define RT5670_JD_LO_SFT			3
+#define RT5670_JD_LO_DIS			(0x0 << 3)
+#define RT5670_JD_LO_EN				(0x1 << 3)
+#define RT5670_JD_LO_TRG_MASK			(0x1 << 2)
+#define RT5670_JD_LO_TRG_SFT			2
+#define RT5670_JD_LO_TRG_LO			(0x0 << 2)
+#define RT5670_JD_LO_TRG_HI			(0x1 << 2)
+#define RT5670_JD1_IN4P_MASK			(0x1 << 1)
+#define RT5670_JD1_IN4P_SFT			1
+#define RT5670_JD1_IN4P_DIS			(0x0 << 1)
+#define RT5670_JD1_IN4P_EN			(0x1 << 1)
+#define RT5670_JD2_IN4N_MASK			(0x1)
+#define RT5670_JD2_IN4N_SFT			0
+#define RT5670_JD2_IN4N_DIS			(0x0)
+#define RT5670_JD2_IN4N_EN			(0x1)
+
+/* IRQ Control 1 (0xbd) */
+#define RT5670_IRQ_JD_MASK			(0x1 << 15)
+#define RT5670_IRQ_JD_SFT			15
+#define RT5670_IRQ_JD_BP			(0x0 << 15)
+#define RT5670_IRQ_JD_NOR			(0x1 << 15)
+#define RT5670_IRQ_OT_MASK			(0x1 << 14)
+#define RT5670_IRQ_OT_SFT			14
+#define RT5670_IRQ_OT_BP			(0x0 << 14)
+#define RT5670_IRQ_OT_NOR			(0x1 << 14)
+#define RT5670_JD_STKY_MASK			(0x1 << 13)
+#define RT5670_JD_STKY_SFT			13
+#define RT5670_JD_STKY_DIS			(0x0 << 13)
+#define RT5670_JD_STKY_EN			(0x1 << 13)
+#define RT5670_OT_STKY_MASK			(0x1 << 12)
+#define RT5670_OT_STKY_SFT			12
+#define RT5670_OT_STKY_DIS			(0x0 << 12)
+#define RT5670_OT_STKY_EN			(0x1 << 12)
+#define RT5670_JD_P_MASK			(0x1 << 11)
+#define RT5670_JD_P_SFT				11
+#define RT5670_JD_P_NOR				(0x0 << 11)
+#define RT5670_JD_P_INV				(0x1 << 11)
+#define RT5670_OT_P_MASK			(0x1 << 10)
+#define RT5670_OT_P_SFT				10
+#define RT5670_OT_P_NOR				(0x0 << 10)
+#define RT5670_OT_P_INV				(0x1 << 10)
+#define RT5670_JD1_1_EN_MASK			(0x1 << 9)
+#define RT5670_JD1_1_EN_SFT			9
+#define RT5670_JD1_1_DIS			(0x0 << 9)
+#define RT5670_JD1_1_EN				(0x1 << 9)
+
+/* IRQ Control 2 (0xbe) */
+#define RT5670_IRQ_MB1_OC_MASK			(0x1 << 15)
+#define RT5670_IRQ_MB1_OC_SFT			15
+#define RT5670_IRQ_MB1_OC_BP			(0x0 << 15)
+#define RT5670_IRQ_MB1_OC_NOR			(0x1 << 15)
+#define RT5670_IRQ_MB2_OC_MASK			(0x1 << 14)
+#define RT5670_IRQ_MB2_OC_SFT			14
+#define RT5670_IRQ_MB2_OC_BP			(0x0 << 14)
+#define RT5670_IRQ_MB2_OC_NOR			(0x1 << 14)
+#define RT5670_MB1_OC_STKY_MASK			(0x1 << 11)
+#define RT5670_MB1_OC_STKY_SFT			11
+#define RT5670_MB1_OC_STKY_DIS			(0x0 << 11)
+#define RT5670_MB1_OC_STKY_EN			(0x1 << 11)
+#define RT5670_MB2_OC_STKY_MASK			(0x1 << 10)
+#define RT5670_MB2_OC_STKY_SFT			10
+#define RT5670_MB2_OC_STKY_DIS			(0x0 << 10)
+#define RT5670_MB2_OC_STKY_EN			(0x1 << 10)
+#define RT5670_MB1_OC_P_MASK			(0x1 << 7)
+#define RT5670_MB1_OC_P_SFT			7
+#define RT5670_MB1_OC_P_NOR			(0x0 << 7)
+#define RT5670_MB1_OC_P_INV			(0x1 << 7)
+#define RT5670_MB2_OC_P_MASK			(0x1 << 6)
+#define RT5670_MB2_OC_P_SFT			6
+#define RT5670_MB2_OC_P_NOR			(0x0 << 6)
+#define RT5670_MB2_OC_P_INV			(0x1 << 6)
+#define RT5670_MB1_OC_CLR			(0x1 << 3)
+#define RT5670_MB1_OC_CLR_SFT			3
+#define RT5670_MB2_OC_CLR			(0x1 << 2)
+#define RT5670_MB2_OC_CLR_SFT			2
+
+/* GPIO Control 1 (0xc0) */
+#define RT5670_GP1_PIN_MASK			(0x1 << 15)
+#define RT5670_GP1_PIN_SFT			15
+#define RT5670_GP1_PIN_GPIO1			(0x0 << 15)
+#define RT5670_GP1_PIN_IRQ			(0x1 << 15)
+#define RT5670_GP2_PIN_MASK			(0x1 << 14)
+#define RT5670_GP2_PIN_SFT			14
+#define RT5670_GP2_PIN_GPIO2			(0x0 << 14)
+#define RT5670_GP2_PIN_DMIC1_SCL		(0x1 << 14)
+#define RT5670_GP3_PIN_MASK			(0x3 << 12)
+#define RT5670_GP3_PIN_SFT			12
+#define RT5670_GP3_PIN_GPIO3			(0x0 << 12)
+#define RT5670_GP3_PIN_DMIC1_SDA		(0x1 << 12)
+#define RT5670_GP3_PIN_IRQ			(0x2 << 12)
+#define RT5670_GP4_PIN_MASK			(0x1 << 11)
+#define RT5670_GP4_PIN_SFT			11
+#define RT5670_GP4_PIN_GPIO4			(0x0 << 11)
+#define RT5670_GP4_PIN_DMIC2_SDA		(0x1 << 11)
+#define RT5670_DP_SIG_MASK			(0x1 << 10)
+#define RT5670_DP_SIG_SFT			10
+#define RT5670_DP_SIG_TEST			(0x0 << 10)
+#define RT5670_DP_SIG_AP			(0x1 << 10)
+#define RT5670_GPIO_M_MASK			(0x1 << 9)
+#define RT5670_GPIO_M_SFT			9
+#define RT5670_GPIO_M_FLT			(0x0 << 9)
+#define RT5670_GPIO_M_PH			(0x1 << 9)
+#define RT5670_I2S2_PIN_MASK			(0x1 << 8)
+#define RT5670_I2S2_PIN_SFT			8
+#define RT5670_I2S2_PIN_I2S			(0x0 << 8)
+#define RT5670_I2S2_PIN_GPIO			(0x1 << 8)
+#define RT5670_GP5_PIN_MASK			(0x1 << 7)
+#define RT5670_GP5_PIN_SFT			7
+#define RT5670_GP5_PIN_GPIO5			(0x0 << 7)
+#define RT5670_GP5_PIN_DMIC3_SDA		(0x1 << 7)
+#define RT5670_GP6_PIN_MASK			(0x1 << 6)
+#define RT5670_GP6_PIN_SFT			6
+#define RT5670_GP6_PIN_GPIO6			(0x0 << 6)
+#define RT5670_GP6_PIN_DMIC1_SDA		(0x1 << 6)
+#define RT5670_GP7_PIN_MASK			(0x3 << 4)
+#define RT5670_GP7_PIN_SFT			4
+#define RT5670_GP7_PIN_GPIO7			(0x0 << 4)
+#define RT5670_GP7_PIN_DMIC1_SDA		(0x1 << 4)
+#define RT5670_GP7_PIN_PDM_SCL2			(0x2 << 4)
+#define RT5670_GP8_PIN_MASK			(0x1 << 3)
+#define RT5670_GP8_PIN_SFT			3
+#define RT5670_GP8_PIN_GPIO8			(0x0 << 3)
+#define RT5670_GP8_PIN_DMIC2_SDA		(0x1 << 3)
+#define RT5670_GP9_PIN_MASK			(0x1 << 2)
+#define RT5670_GP9_PIN_SFT			2
+#define RT5670_GP9_PIN_GPIO9			(0x0 << 2)
+#define RT5670_GP9_PIN_DMIC3_SDA		(0x1 << 2)
+#define RT5670_GP10_PIN_MASK			(0x3)
+#define RT5670_GP10_PIN_SFT			0
+#define RT5670_GP10_PIN_GPIO9			(0x0)
+#define RT5670_GP10_PIN_DMIC3_SDA		(0x1)
+#define RT5670_GP10_PIN_PDM_ADT2		(0x2)
+
+/* GPIO Control 2 (0xc1) */
+#define RT5670_GP4_PF_MASK			(0x1 << 11)
+#define RT5670_GP4_PF_SFT			11
+#define RT5670_GP4_PF_IN			(0x0 << 11)
+#define RT5670_GP4_PF_OUT			(0x1 << 11)
+#define RT5670_GP4_OUT_MASK			(0x1 << 10)
+#define RT5670_GP4_OUT_SFT			10
+#define RT5670_GP4_OUT_LO			(0x0 << 10)
+#define RT5670_GP4_OUT_HI			(0x1 << 10)
+#define RT5670_GP4_P_MASK			(0x1 << 9)
+#define RT5670_GP4_P_SFT			9
+#define RT5670_GP4_P_NOR			(0x0 << 9)
+#define RT5670_GP4_P_INV			(0x1 << 9)
+#define RT5670_GP3_PF_MASK			(0x1 << 8)
+#define RT5670_GP3_PF_SFT			8
+#define RT5670_GP3_PF_IN			(0x0 << 8)
+#define RT5670_GP3_PF_OUT			(0x1 << 8)
+#define RT5670_GP3_OUT_MASK			(0x1 << 7)
+#define RT5670_GP3_OUT_SFT			7
+#define RT5670_GP3_OUT_LO			(0x0 << 7)
+#define RT5670_GP3_OUT_HI			(0x1 << 7)
+#define RT5670_GP3_P_MASK			(0x1 << 6)
+#define RT5670_GP3_P_SFT			6
+#define RT5670_GP3_P_NOR			(0x0 << 6)
+#define RT5670_GP3_P_INV			(0x1 << 6)
+#define RT5670_GP2_PF_MASK			(0x1 << 5)
+#define RT5670_GP2_PF_SFT			5
+#define RT5670_GP2_PF_IN			(0x0 << 5)
+#define RT5670_GP2_PF_OUT			(0x1 << 5)
+#define RT5670_GP2_OUT_MASK			(0x1 << 4)
+#define RT5670_GP2_OUT_SFT			4
+#define RT5670_GP2_OUT_LO			(0x0 << 4)
+#define RT5670_GP2_OUT_HI			(0x1 << 4)
+#define RT5670_GP2_P_MASK			(0x1 << 3)
+#define RT5670_GP2_P_SFT			3
+#define RT5670_GP2_P_NOR			(0x0 << 3)
+#define RT5670_GP2_P_INV			(0x1 << 3)
+#define RT5670_GP1_PF_MASK			(0x1 << 2)
+#define RT5670_GP1_PF_SFT			2
+#define RT5670_GP1_PF_IN			(0x0 << 2)
+#define RT5670_GP1_PF_OUT			(0x1 << 2)
+#define RT5670_GP1_OUT_MASK			(0x1 << 1)
+#define RT5670_GP1_OUT_SFT			1
+#define RT5670_GP1_OUT_LO			(0x0 << 1)
+#define RT5670_GP1_OUT_HI			(0x1 << 1)
+#define RT5670_GP1_P_MASK			(0x1)
+#define RT5670_GP1_P_SFT			0
+#define RT5670_GP1_P_NOR			(0x0)
+#define RT5670_GP1_P_INV			(0x1)
+
+/* Scramble Function (0xcd) */
+#define RT5670_SCB_KEY_MASK			(0xff)
+#define RT5670_SCB_KEY_SFT			0
+
+/* Scramble Control (0xce) */
+#define RT5670_SCB_SWAP_MASK			(0x1 << 15)
+#define RT5670_SCB_SWAP_SFT			15
+#define RT5670_SCB_SWAP_DIS			(0x0 << 15)
+#define RT5670_SCB_SWAP_EN			(0x1 << 15)
+#define RT5670_SCB_MASK				(0x1 << 14)
+#define RT5670_SCB_SFT				14
+#define RT5670_SCB_DIS				(0x0 << 14)
+#define RT5670_SCB_EN				(0x1 << 14)
+
+/* Baseback Control (0xcf) */
+#define RT5670_BB_MASK				(0x1 << 15)
+#define RT5670_BB_SFT				15
+#define RT5670_BB_DIS				(0x0 << 15)
+#define RT5670_BB_EN				(0x1 << 15)
+#define RT5670_BB_CT_MASK			(0x7 << 12)
+#define RT5670_BB_CT_SFT			12
+#define RT5670_BB_CT_A				(0x0 << 12)
+#define RT5670_BB_CT_B				(0x1 << 12)
+#define RT5670_BB_CT_C				(0x2 << 12)
+#define RT5670_BB_CT_D				(0x3 << 12)
+#define RT5670_M_BB_L_MASK			(0x1 << 9)
+#define RT5670_M_BB_L_SFT			9
+#define RT5670_M_BB_R_MASK			(0x1 << 8)
+#define RT5670_M_BB_R_SFT			8
+#define RT5670_M_BB_HPF_L_MASK			(0x1 << 7)
+#define RT5670_M_BB_HPF_L_SFT			7
+#define RT5670_M_BB_HPF_R_MASK			(0x1 << 6)
+#define RT5670_M_BB_HPF_R_SFT			6
+#define RT5670_G_BB_BST_MASK			(0x3f)
+#define RT5670_G_BB_BST_SFT			0
+
+/* MP3 Plus Control 1 (0xd0) */
+#define RT5670_M_MP3_L_MASK			(0x1 << 15)
+#define RT5670_M_MP3_L_SFT			15
+#define RT5670_M_MP3_R_MASK			(0x1 << 14)
+#define RT5670_M_MP3_R_SFT			14
+#define RT5670_M_MP3_MASK			(0x1 << 13)
+#define RT5670_M_MP3_SFT			13
+#define RT5670_M_MP3_DIS			(0x0 << 13)
+#define RT5670_M_MP3_EN				(0x1 << 13)
+#define RT5670_EG_MP3_MASK			(0x1f << 8)
+#define RT5670_EG_MP3_SFT			8
+#define RT5670_MP3_HLP_MASK			(0x1 << 7)
+#define RT5670_MP3_HLP_SFT			7
+#define RT5670_MP3_HLP_DIS			(0x0 << 7)
+#define RT5670_MP3_HLP_EN			(0x1 << 7)
+#define RT5670_M_MP3_ORG_L_MASK			(0x1 << 6)
+#define RT5670_M_MP3_ORG_L_SFT			6
+#define RT5670_M_MP3_ORG_R_MASK			(0x1 << 5)
+#define RT5670_M_MP3_ORG_R_SFT			5
+
+/* MP3 Plus Control 2 (0xd1) */
+#define RT5670_MP3_WT_MASK			(0x1 << 13)
+#define RT5670_MP3_WT_SFT			13
+#define RT5670_MP3_WT_1_4			(0x0 << 13)
+#define RT5670_MP3_WT_1_2			(0x1 << 13)
+#define RT5670_OG_MP3_MASK			(0x1f << 8)
+#define RT5670_OG_MP3_SFT			8
+#define RT5670_HG_MP3_MASK			(0x3f)
+#define RT5670_HG_MP3_SFT			0
+
+/* 3D HP Control 1 (0xd2) */
+#define RT5670_3D_CF_MASK			(0x1 << 15)
+#define RT5670_3D_CF_SFT			15
+#define RT5670_3D_CF_DIS			(0x0 << 15)
+#define RT5670_3D_CF_EN				(0x1 << 15)
+#define RT5670_3D_HP_MASK			(0x1 << 14)
+#define RT5670_3D_HP_SFT			14
+#define RT5670_3D_HP_DIS			(0x0 << 14)
+#define RT5670_3D_HP_EN				(0x1 << 14)
+#define RT5670_3D_BT_MASK			(0x1 << 13)
+#define RT5670_3D_BT_SFT			13
+#define RT5670_3D_BT_DIS			(0x0 << 13)
+#define RT5670_3D_BT_EN				(0x1 << 13)
+#define RT5670_3D_1F_MIX_MASK			(0x3 << 11)
+#define RT5670_3D_1F_MIX_SFT			11
+#define RT5670_3D_HP_M_MASK			(0x1 << 10)
+#define RT5670_3D_HP_M_SFT			10
+#define RT5670_3D_HP_M_SUR			(0x0 << 10)
+#define RT5670_3D_HP_M_FRO			(0x1 << 10)
+#define RT5670_M_3D_HRTF_MASK			(0x1 << 9)
+#define RT5670_M_3D_HRTF_SFT			9
+#define RT5670_M_3D_D2H_MASK			(0x1 << 8)
+#define RT5670_M_3D_D2H_SFT			8
+#define RT5670_M_3D_D2R_MASK			(0x1 << 7)
+#define RT5670_M_3D_D2R_SFT			7
+#define RT5670_M_3D_REVB_MASK			(0x1 << 6)
+#define RT5670_M_3D_REVB_SFT			6
+
+/* Adjustable high pass filter control 1 (0xd3) */
+#define RT5670_2ND_HPF_MASK			(0x1 << 15)
+#define RT5670_2ND_HPF_SFT			15
+#define RT5670_2ND_HPF_DIS			(0x0 << 15)
+#define RT5670_2ND_HPF_EN			(0x1 << 15)
+#define RT5670_HPF_CF_L_MASK			(0x7 << 12)
+#define RT5670_HPF_CF_L_SFT			12
+#define RT5670_1ST_HPF_MASK			(0x1 << 11)
+#define RT5670_1ST_HPF_SFT			11
+#define RT5670_1ST_HPF_DIS			(0x0 << 11)
+#define RT5670_1ST_HPF_EN			(0x1 << 11)
+#define RT5670_HPF_CF_R_MASK			(0x7 << 8)
+#define RT5670_HPF_CF_R_SFT			8
+#define RT5670_ZD_T_MASK			(0x3 << 6)
+#define RT5670_ZD_T_SFT				6
+#define RT5670_ZD_F_MASK			(0x3 << 4)
+#define RT5670_ZD_F_SFT				4
+#define RT5670_ZD_F_IM				(0x0 << 4)
+#define RT5670_ZD_F_ZC_IM			(0x1 << 4)
+#define RT5670_ZD_F_ZC_IOD			(0x2 << 4)
+#define RT5670_ZD_F_UN				(0x3 << 4)
+
+/* HP calibration control and Amp detection (0xd6) */
+#define RT5670_SI_DAC_MASK			(0x1 << 11)
+#define RT5670_SI_DAC_SFT			11
+#define RT5670_SI_DAC_AUTO			(0x0 << 11)
+#define RT5670_SI_DAC_TEST			(0x1 << 11)
+#define RT5670_DC_CAL_M_MASK			(0x1 << 10)
+#define RT5670_DC_CAL_M_SFT			10
+#define RT5670_DC_CAL_M_CAL			(0x0 << 10)
+#define RT5670_DC_CAL_M_NOR			(0x1 << 10)
+#define RT5670_DC_CAL_MASK			(0x1 << 9)
+#define RT5670_DC_CAL_SFT			9
+#define RT5670_DC_CAL_DIS			(0x0 << 9)
+#define RT5670_DC_CAL_EN			(0x1 << 9)
+#define RT5670_HPD_RCV_MASK			(0x7 << 6)
+#define RT5670_HPD_RCV_SFT			6
+#define RT5670_HPD_PS_MASK			(0x1 << 5)
+#define RT5670_HPD_PS_SFT			5
+#define RT5670_HPD_PS_DIS			(0x0 << 5)
+#define RT5670_HPD_PS_EN			(0x1 << 5)
+#define RT5670_CAL_M_MASK			(0x1 << 4)
+#define RT5670_CAL_M_SFT			4
+#define RT5670_CAL_M_DEP			(0x0 << 4)
+#define RT5670_CAL_M_CAL			(0x1 << 4)
+#define RT5670_CAL_MASK				(0x1 << 3)
+#define RT5670_CAL_SFT				3
+#define RT5670_CAL_DIS				(0x0 << 3)
+#define RT5670_CAL_EN				(0x1 << 3)
+#define RT5670_CAL_TEST_MASK			(0x1 << 2)
+#define RT5670_CAL_TEST_SFT			2
+#define RT5670_CAL_TEST_DIS			(0x0 << 2)
+#define RT5670_CAL_TEST_EN			(0x1 << 2)
+#define RT5670_CAL_P_MASK			(0x3)
+#define RT5670_CAL_P_SFT			0
+#define RT5670_CAL_P_NONE			(0x0)
+#define RT5670_CAL_P_CAL			(0x1)
+#define RT5670_CAL_P_DAC_CAL			(0x2)
+
+/* Soft volume and zero cross control 1 (0xd9) */
+#define RT5670_SV_MASK				(0x1 << 15)
+#define RT5670_SV_SFT				15
+#define RT5670_SV_DIS				(0x0 << 15)
+#define RT5670_SV_EN				(0x1 << 15)
+#define RT5670_SPO_SV_MASK			(0x1 << 14)
+#define RT5670_SPO_SV_SFT			14
+#define RT5670_SPO_SV_DIS			(0x0 << 14)
+#define RT5670_SPO_SV_EN			(0x1 << 14)
+#define RT5670_OUT_SV_MASK			(0x1 << 13)
+#define RT5670_OUT_SV_SFT			13
+#define RT5670_OUT_SV_DIS			(0x0 << 13)
+#define RT5670_OUT_SV_EN			(0x1 << 13)
+#define RT5670_HP_SV_MASK			(0x1 << 12)
+#define RT5670_HP_SV_SFT			12
+#define RT5670_HP_SV_DIS			(0x0 << 12)
+#define RT5670_HP_SV_EN				(0x1 << 12)
+#define RT5670_ZCD_DIG_MASK			(0x1 << 11)
+#define RT5670_ZCD_DIG_SFT			11
+#define RT5670_ZCD_DIG_DIS			(0x0 << 11)
+#define RT5670_ZCD_DIG_EN			(0x1 << 11)
+#define RT5670_ZCD_MASK				(0x1 << 10)
+#define RT5670_ZCD_SFT				10
+#define RT5670_ZCD_PD				(0x0 << 10)
+#define RT5670_ZCD_PU				(0x1 << 10)
+#define RT5670_M_ZCD_MASK			(0x3f << 4)
+#define RT5670_M_ZCD_SFT			4
+#define RT5670_M_ZCD_RM_L			(0x1 << 9)
+#define RT5670_M_ZCD_RM_R			(0x1 << 8)
+#define RT5670_M_ZCD_SM_L			(0x1 << 7)
+#define RT5670_M_ZCD_SM_R			(0x1 << 6)
+#define RT5670_M_ZCD_OM_L			(0x1 << 5)
+#define RT5670_M_ZCD_OM_R			(0x1 << 4)
+#define RT5670_SV_DLY_MASK			(0xf)
+#define RT5670_SV_DLY_SFT			0
+
+/* Soft volume and zero cross control 2 (0xda) */
+#define RT5670_ZCD_HP_MASK			(0x1 << 15)
+#define RT5670_ZCD_HP_SFT			15
+#define RT5670_ZCD_HP_DIS			(0x0 << 15)
+#define RT5670_ZCD_HP_EN			(0x1 << 15)
+
+
+/* Codec Private Register definition */
+/* 3D Speaker Control (0x63) */
+#define RT5670_3D_SPK_MASK			(0x1 << 15)
+#define RT5670_3D_SPK_SFT			15
+#define RT5670_3D_SPK_DIS			(0x0 << 15)
+#define RT5670_3D_SPK_EN			(0x1 << 15)
+#define RT5670_3D_SPK_M_MASK			(0x3 << 13)
+#define RT5670_3D_SPK_M_SFT			13
+#define RT5670_3D_SPK_CG_MASK			(0x1f << 8)
+#define RT5670_3D_SPK_CG_SFT			8
+#define RT5670_3D_SPK_SG_MASK			(0x1f)
+#define RT5670_3D_SPK_SG_SFT			0
+
+/* Wind Noise Detection Control 1 (0x6c) */
+#define RT5670_WND_MASK				(0x1 << 15)
+#define RT5670_WND_SFT				15
+#define RT5670_WND_DIS				(0x0 << 15)
+#define RT5670_WND_EN				(0x1 << 15)
+
+/* Wind Noise Detection Control 2 (0x6d) */
+#define RT5670_WND_FC_NW_MASK			(0x3f << 10)
+#define RT5670_WND_FC_NW_SFT			10
+#define RT5670_WND_FC_WK_MASK			(0x3f << 4)
+#define RT5670_WND_FC_WK_SFT			4
+
+/* Wind Noise Detection Control 3 (0x6e) */
+#define RT5670_HPF_FC_MASK			(0x3f << 6)
+#define RT5670_HPF_FC_SFT			6
+#define RT5670_WND_FC_ST_MASK			(0x3f)
+#define RT5670_WND_FC_ST_SFT			0
+
+/* Wind Noise Detection Control 4 (0x6f) */
+#define RT5670_WND_TH_LO_MASK			(0x3ff)
+#define RT5670_WND_TH_LO_SFT			0
+
+/* Wind Noise Detection Control 5 (0x70) */
+#define RT5670_WND_TH_HI_MASK			(0x3ff)
+#define RT5670_WND_TH_HI_SFT			0
+
+/* Wind Noise Detection Control 8 (0x73) */
+#define RT5670_WND_WIND_MASK			(0x1 << 13) /* Read-Only */
+#define RT5670_WND_WIND_SFT			13
+#define RT5670_WND_STRONG_MASK			(0x1 << 12) /* Read-Only */
+#define RT5670_WND_STRONG_SFT			12
+enum {
+	RT5670_NO_WIND,
+	RT5670_BREEZE,
+	RT5670_STORM,
+};
+
+/* Dipole Speaker Interface (0x75) */
+#define RT5670_DP_ATT_MASK			(0x3 << 14)
+#define RT5670_DP_ATT_SFT			14
+#define RT5670_DP_SPK_MASK			(0x1 << 10)
+#define RT5670_DP_SPK_SFT			10
+#define RT5670_DP_SPK_DIS			(0x0 << 10)
+#define RT5670_DP_SPK_EN			(0x1 << 10)
+
+/* EQ Pre Volume Control (0xb3) */
+#define RT5670_EQ_PRE_VOL_MASK			(0xffff)
+#define RT5670_EQ_PRE_VOL_SFT			0
+
+/* EQ Post Volume Control (0xb4) */
+#define RT5670_EQ_PST_VOL_MASK			(0xffff)
+#define RT5670_EQ_PST_VOL_SFT			0
+
+/* Jack Detect Control 3 (0xf8) */
+#define RT5670_CMP_MIC_IN_DET_MASK		(0x7 << 12)
+#define RT5670_JD_CBJ_EN			(0x1 << 7)
+#define RT5670_JD_CBJ_POL			(0x1 << 6)
+#define RT5670_JD_TRI_CBJ_SEL_MASK		(0x7 << 3)
+#define RT5670_JD_TRI_CBJ_SEL_SFT		(3)
+#define RT5670_JD_CBJ_GPIO_JD1			(0x0 << 3)
+#define RT5670_JD_CBJ_JD1_1			(0x1 << 3)
+#define RT5670_JD_CBJ_JD1_2			(0x2 << 3)
+#define RT5670_JD_CBJ_JD2			(0x3 << 3)
+#define RT5670_JD_CBJ_JD3			(0x4 << 3)
+#define RT5670_JD_CBJ_GPIO_JD2			(0x5 << 3)
+#define RT5670_JD_CBJ_MX0B_12			(0x6 << 3)
+#define RT5670_JD_TRI_HPO_SEL_MASK		(0x7 << 3)
+#define RT5670_JD_TRI_HPO_SEL_SFT		(0)
+#define RT5670_JD_HPO_GPIO_JD1			(0x0)
+#define RT5670_JD_HPO_JD1_1			(0x1)
+#define RT5670_JD_HPO_JD1_2			(0x2)
+#define RT5670_JD_HPO_JD2			(0x3)
+#define RT5670_JD_HPO_JD3			(0x4)
+#define RT5670_JD_HPO_GPIO_JD2			(0x5)
+#define RT5670_JD_HPO_MX0B_12			(0x6)
+
+/* Digital Misc Control (0xfa) */
+#define RT5670_RST_DSP				(0x1 << 13)
+#define RT5670_IF1_ADC1_IN1_SEL			(0x1 << 12)
+#define RT5670_IF1_ADC1_IN1_SFT			12
+#define RT5670_IF1_ADC1_IN2_SEL			(0x1 << 11)
+#define RT5670_IF1_ADC1_IN2_SFT			11
+#define RT5670_IF1_ADC2_IN1_SEL			(0x1 << 10)
+#define RT5670_IF1_ADC2_IN1_SFT			10
+
+/* General Control2 (0xfb) */
+#define RT5670_RXDC_SRC_MASK			(0x1 << 7)
+#define RT5670_RXDC_SRC_STO			(0x0 << 7)
+#define RT5670_RXDC_SRC_MONO			(0x1 << 7)
+#define RT5670_RXDC_SRC_SFT			(7)
+#define RT5670_RXDP2_SEL_MASK			(0x1 << 3)
+#define RT5670_RXDP2_SEL_IF2			(0x0 << 3)
+#define RT5670_RXDP2_SEL_ADC			(0x1 << 3)
+#define RT5670_RXDP2_SEL_SFT			(3)
+
+/* System Clock Source */
+enum {
+	RT5670_SCLK_S_MCLK,
+	RT5670_SCLK_S_PLL1,
+	RT5670_SCLK_S_RCCLK,
+};
+
+/* PLL1 Source */
+enum {
+	RT5670_PLL1_S_MCLK,
+	RT5670_PLL1_S_BCLK1,
+	RT5670_PLL1_S_BCLK2,
+	RT5670_PLL1_S_BCLK3,
+	RT5670_PLL1_S_BCLK4,
+};
+
+enum {
+	RT5670_AIF1,
+	RT5670_AIF2,
+	RT5670_AIF3,
+	RT5670_AIF4,
+	RT5670_AIFS,
+};
+
+enum {
+	RT5670_DMIC_DATA_GPIO6,
+	RT5670_DMIC_DATA_IN2P,
+	RT5670_DMIC_DATA_GPIO7,
+};
+
+enum {
+	RT5670_DMIC_DATA_GPIO8,
+	RT5670_DMIC_DATA_IN3N,
+};
+
+enum {
+	RT5670_DMIC_DATA_GPIO9,
+	RT5670_DMIC_DATA_GPIO10,
+	RT5670_DMIC_DATA_GPIO5,
+};
+
+struct rt5670_priv {
+	struct snd_soc_codec *codec;
+	struct rt5670_platform_data pdata;
+	struct regmap *regmap;
+
+	int sysclk;
+	int sysclk_src;
+	int lrck[RT5670_AIFS];
+	int bclk[RT5670_AIFS];
+	int master[RT5670_AIFS];
+
+	int pll_src;
+	int pll_in;
+	int pll_out;
+
+	int dsp_sw; /* expected parameter setting */
+	int dsp_rate;
+	int jack_type;
+};
+
+#endif /* __RT5670_H__ */
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c
index 833231e27340..67f14556462f 100644
--- a/sound/soc/codecs/rt5677.c
+++ b/sound/soc/codecs/rt5677.c
@@ -27,6 +27,7 @@
 #include <sound/initval.h>
 #include <sound/tlv.h>
 
+#include "rl6231.h"
 #include "rt5677.h"
 
 #define RT5677_DEVICE_ID 0x6327
@@ -604,19 +605,19 @@ static const struct snd_kcontrol_new rt5677_snd_controls[] = {
 		adc_vol_tlv),
 
 	/* ADC Boost Volume Control */
-	SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5677_STO1_2_ADC_BST,
+	SOC_DOUBLE_TLV("STO1 ADC Boost Volume", RT5677_STO1_2_ADC_BST,
 		RT5677_STO1_ADC_L_BST_SFT, RT5677_STO1_ADC_R_BST_SFT, 3, 0,
 		adc_bst_tlv),
-	SOC_DOUBLE_TLV("STO2 ADC Boost Gain", RT5677_STO1_2_ADC_BST,
+	SOC_DOUBLE_TLV("STO2 ADC Boost Volume", RT5677_STO1_2_ADC_BST,
 		RT5677_STO2_ADC_L_BST_SFT, RT5677_STO2_ADC_R_BST_SFT, 3, 0,
 		adc_bst_tlv),
-	SOC_DOUBLE_TLV("STO3 ADC Boost Gain", RT5677_STO3_4_ADC_BST,
+	SOC_DOUBLE_TLV("STO3 ADC Boost Volume", RT5677_STO3_4_ADC_BST,
 		RT5677_STO3_ADC_L_BST_SFT, RT5677_STO3_ADC_R_BST_SFT, 3, 0,
 		adc_bst_tlv),
-	SOC_DOUBLE_TLV("STO4 ADC Boost Gain", RT5677_STO3_4_ADC_BST,
+	SOC_DOUBLE_TLV("STO4 ADC Boost Volume", RT5677_STO3_4_ADC_BST,
 		RT5677_STO4_ADC_L_BST_SFT, RT5677_STO4_ADC_R_BST_SFT, 3, 0,
 		adc_bst_tlv),
-	SOC_DOUBLE_TLV("Mono ADC Boost Gain", RT5677_ADC_BST_CTRL2,
+	SOC_DOUBLE_TLV("Mono ADC Boost Volume", RT5677_ADC_BST_CTRL2,
 		RT5677_MONO_ADC_L_BST_SFT, RT5677_MONO_ADC_R_BST_SFT, 3, 0,
 		adc_bst_tlv),
 };
@@ -636,21 +637,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
 {
 	struct snd_soc_codec *codec = w->codec;
 	struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
-	int div[] = {2, 3, 4, 6, 8, 12}, idx = -EINVAL, i;
-	int rate, red, bound, temp;
-
-	rate = rt5677->sysclk;
-	red = 3000000 * 12;
-	for (i = 0; i < ARRAY_SIZE(div); i++) {
-		bound = div[i] * 3000000;
-		if (rate > bound)
-			continue;
-		temp = bound - rate;
-		if (temp < red) {
-			red = temp;
-			idx = i;
-		}
-	}
+	int idx = rl6231_calc_dmic_clk(rt5677->sysclk);
 
 	if (idx < 0)
 		dev_err(codec->dev, "Failed to set DMIC clock\n");
@@ -951,7 +938,7 @@ static const struct snd_kcontrol_new rt5677_ob_7_mix[] = {
 
 
 /* Mux */
-/* DAC1 L/R source */ /* MX-29 [10:8] */
+/* DAC1 L/R Source */ /* MX-29 [10:8] */
 static const char * const rt5677_dac1_src[] = {
 	"IF1 DAC 01", "IF2 DAC 01", "IF3 DAC LR", "IF4 DAC LR", "SLB DAC 01",
 	"OB 01"
@@ -962,9 +949,9 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_DAC1_L_SEL_SFT, rt5677_dac1_src);
 
 static const struct snd_kcontrol_new rt5677_dac1_mux =
-	SOC_DAPM_ENUM("DAC1 source", rt5677_dac1_enum);
+	SOC_DAPM_ENUM("DAC1 Source", rt5677_dac1_enum);
 
-/* ADDA1 L/R source */ /* MX-29 [1:0] */
+/* ADDA1 L/R Source */ /* MX-29 [1:0] */
 static const char * const rt5677_adda1_src[] = {
 	"STO1 ADC MIX", "STO2 ADC MIX", "OB 67",
 };
@@ -974,10 +961,10 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_ADDA1_SEL_SFT, rt5677_adda1_src);
 
 static const struct snd_kcontrol_new rt5677_adda1_mux =
-	SOC_DAPM_ENUM("ADDA1 source", rt5677_adda1_enum);
+	SOC_DAPM_ENUM("ADDA1 Source", rt5677_adda1_enum);
 
 
-/*DAC2 L/R source*/ /* MX-1B [6:4] [2:0] */
+/*DAC2 L/R Source*/ /* MX-1B [6:4] [2:0] */
 static const char * const rt5677_dac2l_src[] = {
 	"IF1 DAC 2", "IF2 DAC 2", "IF3 DAC L", "IF4 DAC L", "SLB DAC 2",
 	"OB 2",
@@ -988,7 +975,7 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_DAC2_L_SRC_SFT, rt5677_dac2l_src);
 
 static const struct snd_kcontrol_new rt5677_dac2_l_mux =
-	SOC_DAPM_ENUM("DAC2 L source", rt5677_dac2l_enum);
+	SOC_DAPM_ENUM("DAC2 L Source", rt5677_dac2l_enum);
 
 static const char * const rt5677_dac2r_src[] = {
 	"IF1 DAC 3", "IF2 DAC 3", "IF3 DAC R", "IF4 DAC R", "SLB DAC 3",
@@ -1000,9 +987,9 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_DAC2_R_SRC_SFT, rt5677_dac2r_src);
 
 static const struct snd_kcontrol_new rt5677_dac2_r_mux =
-	SOC_DAPM_ENUM("DAC2 R source", rt5677_dac2r_enum);
+	SOC_DAPM_ENUM("DAC2 R Source", rt5677_dac2r_enum);
 
-/*DAC3 L/R source*/ /* MX-16 [6:4] [2:0] */
+/*DAC3 L/R Source*/ /* MX-16 [6:4] [2:0] */
 static const char * const rt5677_dac3l_src[] = {
 	"IF1 DAC 4", "IF2 DAC 4", "IF3 DAC L", "IF4 DAC L",
 	"SLB DAC 4", "OB 4"
@@ -1013,7 +1000,7 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_DAC3_L_SRC_SFT, rt5677_dac3l_src);
 
 static const struct snd_kcontrol_new rt5677_dac3_l_mux =
-	SOC_DAPM_ENUM("DAC3 L source", rt5677_dac3l_enum);
+	SOC_DAPM_ENUM("DAC3 L Source", rt5677_dac3l_enum);
 
 static const char * const rt5677_dac3r_src[] = {
 	"IF1 DAC 5", "IF2 DAC 5", "IF3 DAC R", "IF4 DAC R",
@@ -1025,9 +1012,9 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_DAC3_R_SRC_SFT, rt5677_dac3r_src);
 
 static const struct snd_kcontrol_new rt5677_dac3_r_mux =
-	SOC_DAPM_ENUM("DAC3 R source", rt5677_dac3r_enum);
+	SOC_DAPM_ENUM("DAC3 R Source", rt5677_dac3r_enum);
 
-/*DAC4 L/R source*/ /* MX-16 [14:12] [10:8] */
+/*DAC4 L/R Source*/ /* MX-16 [14:12] [10:8] */
 static const char * const rt5677_dac4l_src[] = {
 	"IF1 DAC 6", "IF2 DAC 6", "IF3 DAC L", "IF4 DAC L",
 	"SLB DAC 6", "OB 6"
@@ -1038,7 +1025,7 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_DAC4_L_SRC_SFT, rt5677_dac4l_src);
 
 static const struct snd_kcontrol_new rt5677_dac4_l_mux =
-	SOC_DAPM_ENUM("DAC4 L source", rt5677_dac4l_enum);
+	SOC_DAPM_ENUM("DAC4 L Source", rt5677_dac4l_enum);
 
 static const char * const rt5677_dac4r_src[] = {
 	"IF1 DAC 7", "IF2 DAC 7", "IF3 DAC R", "IF4 DAC R",
@@ -1050,7 +1037,7 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_DAC4_R_SRC_SFT, rt5677_dac4r_src);
 
 static const struct snd_kcontrol_new rt5677_dac4_r_mux =
-	SOC_DAPM_ENUM("DAC4 R source", rt5677_dac4r_enum);
+	SOC_DAPM_ENUM("DAC4 R Source", rt5677_dac4r_enum);
 
 /* In/OutBound Source Pass SRC */ /* MX-A5 [3] [4] [0] [1] [2] */
 static const char * const rt5677_iob_bypass_src[] = {
@@ -1062,35 +1049,35 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_SRC_OB01_SFT, rt5677_iob_bypass_src);
 
 static const struct snd_kcontrol_new rt5677_ob01_bypass_src_mux =
-	SOC_DAPM_ENUM("OB01 Bypass source", rt5677_ob01_bypass_src_enum);
+	SOC_DAPM_ENUM("OB01 Bypass Source", rt5677_ob01_bypass_src_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_ob23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL,
 	RT5677_SEL_SRC_OB23_SFT, rt5677_iob_bypass_src);
 
 static const struct snd_kcontrol_new rt5677_ob23_bypass_src_mux =
-	SOC_DAPM_ENUM("OB23 Bypass source", rt5677_ob23_bypass_src_enum);
+	SOC_DAPM_ENUM("OB23 Bypass Source", rt5677_ob23_bypass_src_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_ib01_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL,
 	RT5677_SEL_SRC_IB01_SFT, rt5677_iob_bypass_src);
 
 static const struct snd_kcontrol_new rt5677_ib01_bypass_src_mux =
-	SOC_DAPM_ENUM("IB01 Bypass source", rt5677_ib01_bypass_src_enum);
+	SOC_DAPM_ENUM("IB01 Bypass Source", rt5677_ib01_bypass_src_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_ib23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL,
 	RT5677_SEL_SRC_IB23_SFT, rt5677_iob_bypass_src);
 
 static const struct snd_kcontrol_new rt5677_ib23_bypass_src_mux =
-	SOC_DAPM_ENUM("IB23 Bypass source", rt5677_ib23_bypass_src_enum);
+	SOC_DAPM_ENUM("IB23 Bypass Source", rt5677_ib23_bypass_src_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_ib45_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL,
 	RT5677_SEL_SRC_IB45_SFT, rt5677_iob_bypass_src);
 
 static const struct snd_kcontrol_new rt5677_ib45_bypass_src_mux =
-	SOC_DAPM_ENUM("IB45 Bypass source", rt5677_ib45_bypass_src_enum);
+	SOC_DAPM_ENUM("IB45 Bypass Source", rt5677_ib45_bypass_src_enum);
 
 /* Stereo ADC Source 2 */ /* MX-27 MX26  MX25 [11:10] */
 static const char * const rt5677_stereo_adc2_src[] = {
@@ -1102,21 +1089,21 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_STO1_ADC2_SFT, rt5677_stereo_adc2_src);
 
 static const struct snd_kcontrol_new rt5677_sto1_adc2_mux =
-	SOC_DAPM_ENUM("Stereo1 ADC2 source", rt5677_stereo1_adc2_enum);
+	SOC_DAPM_ENUM("Stereo1 ADC2 Source", rt5677_stereo1_adc2_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_stereo2_adc2_enum, RT5677_STO2_ADC_MIXER,
 	RT5677_SEL_STO2_ADC2_SFT, rt5677_stereo_adc2_src);
 
 static const struct snd_kcontrol_new rt5677_sto2_adc2_mux =
-	SOC_DAPM_ENUM("Stereo2 ADC2 source", rt5677_stereo2_adc2_enum);
+	SOC_DAPM_ENUM("Stereo2 ADC2 Source", rt5677_stereo2_adc2_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_stereo3_adc2_enum, RT5677_STO3_ADC_MIXER,
 	RT5677_SEL_STO3_ADC2_SFT, rt5677_stereo_adc2_src);
 
 static const struct snd_kcontrol_new rt5677_sto3_adc2_mux =
-	SOC_DAPM_ENUM("Stereo3 ADC2 source", rt5677_stereo3_adc2_enum);
+	SOC_DAPM_ENUM("Stereo3 ADC2 Source", rt5677_stereo3_adc2_enum);
 
 /* DMIC Source */ /* MX-28 [9:8][1:0] MX-27 MX-26 MX-25 MX-24 [9:8] */
 static const char * const rt5677_dmic_src[] = {
@@ -1128,44 +1115,44 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_MONO_DMIC_L_SFT, rt5677_dmic_src);
 
 static const struct snd_kcontrol_new rt5677_mono_dmic_l_mux =
-	SOC_DAPM_ENUM("Mono DMIC L source", rt5677_mono_dmic_l_enum);
+	SOC_DAPM_ENUM("Mono DMIC L Source", rt5677_mono_dmic_l_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_mono_dmic_r_enum, RT5677_MONO_ADC_MIXER,
 	RT5677_SEL_MONO_DMIC_R_SFT, rt5677_dmic_src);
 
 static const struct snd_kcontrol_new rt5677_mono_dmic_r_mux =
-	SOC_DAPM_ENUM("Mono DMIC R source", rt5677_mono_dmic_r_enum);
+	SOC_DAPM_ENUM("Mono DMIC R Source", rt5677_mono_dmic_r_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_stereo1_dmic_enum, RT5677_STO1_ADC_MIXER,
 	RT5677_SEL_STO1_DMIC_SFT, rt5677_dmic_src);
 
 static const struct snd_kcontrol_new rt5677_sto1_dmic_mux =
-	SOC_DAPM_ENUM("Stereo1 DMIC source", rt5677_stereo1_dmic_enum);
+	SOC_DAPM_ENUM("Stereo1 DMIC Source", rt5677_stereo1_dmic_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_stereo2_dmic_enum, RT5677_STO2_ADC_MIXER,
 	RT5677_SEL_STO2_DMIC_SFT, rt5677_dmic_src);
 
 static const struct snd_kcontrol_new rt5677_sto2_dmic_mux =
-	SOC_DAPM_ENUM("Stereo2 DMIC source", rt5677_stereo2_dmic_enum);
+	SOC_DAPM_ENUM("Stereo2 DMIC Source", rt5677_stereo2_dmic_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_stereo3_dmic_enum, RT5677_STO3_ADC_MIXER,
 	RT5677_SEL_STO3_DMIC_SFT, rt5677_dmic_src);
 
 static const struct snd_kcontrol_new rt5677_sto3_dmic_mux =
-	SOC_DAPM_ENUM("Stereo3 DMIC source", rt5677_stereo3_dmic_enum);
+	SOC_DAPM_ENUM("Stereo3 DMIC Source", rt5677_stereo3_dmic_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_stereo4_dmic_enum, RT5677_STO4_ADC_MIXER,
 	RT5677_SEL_STO4_DMIC_SFT, rt5677_dmic_src);
 
 static const struct snd_kcontrol_new rt5677_sto4_dmic_mux =
-	SOC_DAPM_ENUM("Stereo4 DMIC source", rt5677_stereo4_dmic_enum);
+	SOC_DAPM_ENUM("Stereo4 DMIC Source", rt5677_stereo4_dmic_enum);
 
-/* Stereo2 ADC source */ /* MX-26 [0] */
+/* Stereo2 ADC Source */ /* MX-26 [0] */
 static const char * const rt5677_stereo2_adc_lr_src[] = {
 	"L", "LR"
 };
@@ -1175,7 +1162,7 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_STO2_LR_MIX_SFT, rt5677_stereo2_adc_lr_src);
 
 static const struct snd_kcontrol_new rt5677_sto2_adc_lr_mux =
-	SOC_DAPM_ENUM("Stereo2 ADC LR source", rt5677_stereo2_adc_lr_enum);
+	SOC_DAPM_ENUM("Stereo2 ADC LR Source", rt5677_stereo2_adc_lr_enum);
 
 /* Stereo1 ADC Source 1 */ /* MX-27 MX26  MX25 [13:12] */
 static const char * const rt5677_stereo_adc1_src[] = {
@@ -1187,23 +1174,23 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_STO1_ADC1_SFT, rt5677_stereo_adc1_src);
 
 static const struct snd_kcontrol_new rt5677_sto1_adc1_mux =
-	SOC_DAPM_ENUM("Stereo1 ADC1 source", rt5677_stereo1_adc1_enum);
+	SOC_DAPM_ENUM("Stereo1 ADC1 Source", rt5677_stereo1_adc1_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_stereo2_adc1_enum, RT5677_STO2_ADC_MIXER,
 	RT5677_SEL_STO2_ADC1_SFT, rt5677_stereo_adc1_src);
 
 static const struct snd_kcontrol_new rt5677_sto2_adc1_mux =
-	SOC_DAPM_ENUM("Stereo2 ADC1 source", rt5677_stereo2_adc1_enum);
+	SOC_DAPM_ENUM("Stereo2 ADC1 Source", rt5677_stereo2_adc1_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_stereo3_adc1_enum, RT5677_STO3_ADC_MIXER,
 	RT5677_SEL_STO3_ADC1_SFT, rt5677_stereo_adc1_src);
 
 static const struct snd_kcontrol_new rt5677_sto3_adc1_mux =
-	SOC_DAPM_ENUM("Stereo3 ADC1 source", rt5677_stereo3_adc1_enum);
+	SOC_DAPM_ENUM("Stereo3 ADC1 Source", rt5677_stereo3_adc1_enum);
 
-/* Mono ADC Left source 2 */ /* MX-28 [11:10] */
+/* Mono ADC Left Source 2 */ /* MX-28 [11:10] */
 static const char * const rt5677_mono_adc2_l_src[] = {
 	"DD MIX1L", "DMIC", "MONO DAC MIXL"
 };
@@ -1213,9 +1200,9 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_MONO_ADC_L2_SFT, rt5677_mono_adc2_l_src);
 
 static const struct snd_kcontrol_new rt5677_mono_adc2_l_mux =
-	SOC_DAPM_ENUM("Mono ADC2 L source", rt5677_mono_adc2_l_enum);
+	SOC_DAPM_ENUM("Mono ADC2 L Source", rt5677_mono_adc2_l_enum);
 
-/* Mono ADC Left source 1 */ /* MX-28 [13:12] */
+/* Mono ADC Left Source 1 */ /* MX-28 [13:12] */
 static const char * const rt5677_mono_adc1_l_src[] = {
 	"DD MIX1L", "ADC1", "MONO DAC MIXL"
 };
@@ -1225,9 +1212,9 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_MONO_ADC_L1_SFT, rt5677_mono_adc1_l_src);
 
 static const struct snd_kcontrol_new rt5677_mono_adc1_l_mux =
-	SOC_DAPM_ENUM("Mono ADC1 L source", rt5677_mono_adc1_l_enum);
+	SOC_DAPM_ENUM("Mono ADC1 L Source", rt5677_mono_adc1_l_enum);
 
-/* Mono ADC Right source 2 */ /* MX-28 [3:2] */
+/* Mono ADC Right Source 2 */ /* MX-28 [3:2] */
 static const char * const rt5677_mono_adc2_r_src[] = {
 	"DD MIX1R", "DMIC", "MONO DAC MIXR"
 };
@@ -1237,9 +1224,9 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_MONO_ADC_R2_SFT, rt5677_mono_adc2_r_src);
 
 static const struct snd_kcontrol_new rt5677_mono_adc2_r_mux =
-	SOC_DAPM_ENUM("Mono ADC2 R source", rt5677_mono_adc2_r_enum);
+	SOC_DAPM_ENUM("Mono ADC2 R Source", rt5677_mono_adc2_r_enum);
 
-/* Mono ADC Right source 1 */ /* MX-28 [5:4] */
+/* Mono ADC Right Source 1 */ /* MX-28 [5:4] */
 static const char * const rt5677_mono_adc1_r_src[] = {
 	"DD MIX1R", "ADC2", "MONO DAC MIXR"
 };
@@ -1249,7 +1236,7 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_MONO_ADC_R1_SFT, rt5677_mono_adc1_r_src);
 
 static const struct snd_kcontrol_new rt5677_mono_adc1_r_mux =
-	SOC_DAPM_ENUM("Mono ADC1 R source", rt5677_mono_adc1_r_enum);
+	SOC_DAPM_ENUM("Mono ADC1 R Source", rt5677_mono_adc1_r_enum);
 
 /* Stereo4 ADC Source 2 */ /* MX-24 [11:10] */
 static const char * const rt5677_stereo4_adc2_src[] = {
@@ -1261,7 +1248,7 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_STO4_ADC2_SFT, rt5677_stereo4_adc2_src);
 
 static const struct snd_kcontrol_new rt5677_sto4_adc2_mux =
-	SOC_DAPM_ENUM("Stereo4 ADC2 source", rt5677_stereo4_adc2_enum);
+	SOC_DAPM_ENUM("Stereo4 ADC2 Source", rt5677_stereo4_adc2_enum);
 
 
 /* Stereo4 ADC Source 1 */ /* MX-24 [13:12] */
@@ -1274,7 +1261,7 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_STO4_ADC1_SFT, rt5677_stereo4_adc1_src);
 
 static const struct snd_kcontrol_new rt5677_sto4_adc1_mux =
-	SOC_DAPM_ENUM("Stereo4 ADC1 source", rt5677_stereo4_adc1_enum);
+	SOC_DAPM_ENUM("Stereo4 ADC1 Source", rt5677_stereo4_adc1_enum);
 
 /* InBound0/1 Source */ /* MX-A3 [14:12] */
 static const char * const rt5677_inbound01_src[] = {
@@ -1416,7 +1403,7 @@ static SOC_ENUM_SINGLE_DECL(
 static const struct snd_kcontrol_new rt5677_dac3_mux =
 	SOC_DAPM_ENUM("Analog DAC3 Source", rt5677_dac3_enum);
 
-/* PDM channel source */ /* MX-31 [13:12][9:8][5:4][1:0] */
+/* PDM channel Source */ /* MX-31 [13:12][9:8][5:4][1:0] */
 static const char * const rt5677_pdm_src[] = {
 	"STO1 DAC MIX", "MONO DAC MIX", "DD MIX1", "DD MIX2"
 };
@@ -1426,28 +1413,28 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_SEL_PDM1_L_SFT, rt5677_pdm_src);
 
 static const struct snd_kcontrol_new rt5677_pdm1_l_mux =
-	SOC_DAPM_ENUM("PDM1 source", rt5677_pdm1_l_enum);
+	SOC_DAPM_ENUM("PDM1 Source", rt5677_pdm1_l_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_pdm2_l_enum, RT5677_PDM_OUT_CTRL,
 	RT5677_SEL_PDM2_L_SFT, rt5677_pdm_src);
 
 static const struct snd_kcontrol_new rt5677_pdm2_l_mux =
-	SOC_DAPM_ENUM("PDM2 source", rt5677_pdm2_l_enum);
+	SOC_DAPM_ENUM("PDM2 Source", rt5677_pdm2_l_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_pdm1_r_enum, RT5677_PDM_OUT_CTRL,
 	RT5677_SEL_PDM1_R_SFT, rt5677_pdm_src);
 
 static const struct snd_kcontrol_new rt5677_pdm1_r_mux =
-	SOC_DAPM_ENUM("PDM1 source", rt5677_pdm1_r_enum);
+	SOC_DAPM_ENUM("PDM1 Source", rt5677_pdm1_r_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_pdm2_r_enum, RT5677_PDM_OUT_CTRL,
 	RT5677_SEL_PDM2_R_SFT, rt5677_pdm_src);
 
 static const struct snd_kcontrol_new rt5677_pdm2_r_mux =
-	SOC_DAPM_ENUM("PDM2 source", rt5677_pdm2_r_enum);
+	SOC_DAPM_ENUM("PDM2 Source", rt5677_pdm2_r_enum);
 
 /* TDM IF1/2 SLB ADC1 Data Selection */ /* MX-3C MX-41 [5:4] MX-08 [1:0]*/
 static const char * const rt5677_if12_adc1_src[] = {
@@ -1459,21 +1446,21 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_IF1_ADC1_SFT, rt5677_if12_adc1_src);
 
 static const struct snd_kcontrol_new rt5677_if1_adc1_mux =
-	SOC_DAPM_ENUM("IF1 ADC1 source", rt5677_if1_adc1_enum);
+	SOC_DAPM_ENUM("IF1 ADC1 Source", rt5677_if1_adc1_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_if2_adc1_enum, RT5677_TDM2_CTRL2,
 	RT5677_IF2_ADC1_SFT, rt5677_if12_adc1_src);
 
 static const struct snd_kcontrol_new rt5677_if2_adc1_mux =
-	SOC_DAPM_ENUM("IF2 ADC1 source", rt5677_if2_adc1_enum);
+	SOC_DAPM_ENUM("IF2 ADC1 Source", rt5677_if2_adc1_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_slb_adc1_enum, RT5677_SLIMBUS_RX,
 	RT5677_SLB_ADC1_SFT, rt5677_if12_adc1_src);
 
 static const struct snd_kcontrol_new rt5677_slb_adc1_mux =
-	SOC_DAPM_ENUM("SLB ADC1 source", rt5677_slb_adc1_enum);
+	SOC_DAPM_ENUM("SLB ADC1 Source", rt5677_slb_adc1_enum);
 
 /* TDM IF1/2 SLB ADC2 Data Selection */ /* MX-3C MX-41 [7:6] MX-08 [3:2] */
 static const char * const rt5677_if12_adc2_src[] = {
@@ -1485,21 +1472,21 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_IF1_ADC2_SFT, rt5677_if12_adc2_src);
 
 static const struct snd_kcontrol_new rt5677_if1_adc2_mux =
-	SOC_DAPM_ENUM("IF1 ADC2 source", rt5677_if1_adc2_enum);
+	SOC_DAPM_ENUM("IF1 ADC2 Source", rt5677_if1_adc2_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_if2_adc2_enum, RT5677_TDM2_CTRL2,
 	RT5677_IF2_ADC2_SFT, rt5677_if12_adc2_src);
 
 static const struct snd_kcontrol_new rt5677_if2_adc2_mux =
-	SOC_DAPM_ENUM("IF2 ADC2 source", rt5677_if2_adc2_enum);
+	SOC_DAPM_ENUM("IF2 ADC2 Source", rt5677_if2_adc2_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_slb_adc2_enum, RT5677_SLIMBUS_RX,
 	RT5677_SLB_ADC2_SFT, rt5677_if12_adc2_src);
 
 static const struct snd_kcontrol_new rt5677_slb_adc2_mux =
-	SOC_DAPM_ENUM("SLB ADC2 source", rt5677_slb_adc2_enum);
+	SOC_DAPM_ENUM("SLB ADC2 Source", rt5677_slb_adc2_enum);
 
 /* TDM IF1/2 SLB ADC3 Data Selection */ /* MX-3C MX-41 [9:8] MX-08 [5:4] */
 static const char * const rt5677_if12_adc3_src[] = {
@@ -1511,21 +1498,21 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_IF1_ADC3_SFT, rt5677_if12_adc3_src);
 
 static const struct snd_kcontrol_new rt5677_if1_adc3_mux =
-	SOC_DAPM_ENUM("IF1 ADC3 source", rt5677_if1_adc3_enum);
+	SOC_DAPM_ENUM("IF1 ADC3 Source", rt5677_if1_adc3_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_if2_adc3_enum, RT5677_TDM2_CTRL2,
 	RT5677_IF2_ADC3_SFT, rt5677_if12_adc3_src);
 
 static const struct snd_kcontrol_new rt5677_if2_adc3_mux =
-	SOC_DAPM_ENUM("IF2 ADC3 source", rt5677_if2_adc3_enum);
+	SOC_DAPM_ENUM("IF2 ADC3 Source", rt5677_if2_adc3_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_slb_adc3_enum, RT5677_SLIMBUS_RX,
 	RT5677_SLB_ADC3_SFT, rt5677_if12_adc3_src);
 
 static const struct snd_kcontrol_new rt5677_slb_adc3_mux =
-	SOC_DAPM_ENUM("SLB ADC3 source", rt5677_slb_adc3_enum);
+	SOC_DAPM_ENUM("SLB ADC3 Source", rt5677_slb_adc3_enum);
 
 /* TDM IF1/2 SLB ADC4 Data Selection */ /* MX-3C MX-41 [11:10]  MX-08 [7:6] */
 static const char * const rt5677_if12_adc4_src[] = {
@@ -1537,21 +1524,21 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_IF1_ADC4_SFT, rt5677_if12_adc4_src);
 
 static const struct snd_kcontrol_new rt5677_if1_adc4_mux =
-	SOC_DAPM_ENUM("IF1 ADC4 source", rt5677_if1_adc4_enum);
+	SOC_DAPM_ENUM("IF1 ADC4 Source", rt5677_if1_adc4_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_if2_adc4_enum, RT5677_TDM2_CTRL2,
 	RT5677_IF2_ADC4_SFT, rt5677_if12_adc4_src);
 
 static const struct snd_kcontrol_new rt5677_if2_adc4_mux =
-	SOC_DAPM_ENUM("IF2 ADC4 source", rt5677_if2_adc4_enum);
+	SOC_DAPM_ENUM("IF2 ADC4 Source", rt5677_if2_adc4_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_slb_adc4_enum, RT5677_SLIMBUS_RX,
 	RT5677_SLB_ADC4_SFT, rt5677_if12_adc4_src);
 
 static const struct snd_kcontrol_new rt5677_slb_adc4_mux =
-	SOC_DAPM_ENUM("SLB ADC4 source", rt5677_slb_adc4_enum);
+	SOC_DAPM_ENUM("SLB ADC4 Source", rt5677_slb_adc4_enum);
 
 /* Interface3/4 ADC Data Input */ /* MX-2F [3:0] MX-30 [7:4]*/
 static const char * const rt5677_if34_adc_src[] = {
@@ -1564,14 +1551,14 @@ static SOC_ENUM_SINGLE_DECL(
 	RT5677_IF3_ADC_IN_SFT, rt5677_if34_adc_src);
 
 static const struct snd_kcontrol_new rt5677_if3_adc_mux =
-	SOC_DAPM_ENUM("IF3 ADC source", rt5677_if3_adc_enum);
+	SOC_DAPM_ENUM("IF3 ADC Source", rt5677_if3_adc_enum);
 
 static SOC_ENUM_SINGLE_DECL(
 	rt5677_if4_adc_enum, RT5677_IF4_DATA,
 	RT5677_IF4_ADC_IN_SFT, rt5677_if34_adc_src);
 
 static const struct snd_kcontrol_new rt5677_if4_adc_mux =
-	SOC_DAPM_ENUM("IF4 ADC source", rt5677_if4_adc_enum);
+	SOC_DAPM_ENUM("IF4 ADC Source", rt5677_if4_adc_enum);
 
 static int rt5677_bst1_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
@@ -1670,6 +1657,13 @@ static int rt5677_set_micbias1_event(struct snd_soc_dapm_widget *w,
 			RT5677_PWR_CLK_MB, RT5677_PWR_CLK_MB1 |
 			RT5677_PWR_PP_MB1 | RT5677_PWR_CLK_MB);
 		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
+			RT5677_PWR_CLK_MB1 | RT5677_PWR_PP_MB1 |
+			RT5677_PWR_CLK_MB, 0);
+		break;
+
 	default:
 		return 0;
 	}
@@ -1685,8 +1679,9 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = {
 
 	/* Input Side */
 	/* micbias */
-	SND_SOC_DAPM_SUPPLY("micbias1", RT5677_PWR_ANLG2, RT5677_PWR_MB1_BIT,
-		0, rt5677_set_micbias1_event, SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5677_PWR_ANLG2, RT5677_PWR_MB1_BIT,
+		0, rt5677_set_micbias1_event, SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_POST_PMU),
 
 	/* Input Lines */
 	SND_SOC_DAPM_INPUT("DMIC L1"),
@@ -2798,21 +2793,6 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = {
 	{ "PDM2R", NULL, "PDM2 R Mux" },
 };
 
-static int get_clk_info(int sclk, int rate)
-{
-	int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
-
-	if (sclk <= 0 || rate <= 0)
-		return -EINVAL;
-
-	rate = rate << 8;
-	for (i = 0; i < ARRAY_SIZE(pd); i++)
-		if (sclk == rate * pd[i])
-			return i;
-
-	return -EINVAL;
-}
-
 static int rt5677_hw_params(struct snd_pcm_substream *substream,
 	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
@@ -2822,7 +2802,7 @@ static int rt5677_hw_params(struct snd_pcm_substream *substream,
 	int pre_div, bclk_ms, frame_size;
 
 	rt5677->lrck[dai->id] = params_rate(params);
-	pre_div = get_clk_info(rt5677->sysclk, rt5677->lrck[dai->id]);
+	pre_div = rl6231_get_clk_info(rt5677->sysclk, rt5677->lrck[dai->id]);
 	if (pre_div < 0) {
 		dev_err(codec->dev, "Unsupported clock setting\n");
 		return -EINVAL;
@@ -3016,62 +2996,12 @@ static int rt5677_set_dai_sysclk(struct snd_soc_dai *dai,
  * Returns 0 for success or negative error code.
  */
 static int rt5677_pll_calc(const unsigned int freq_in,
-	const unsigned int freq_out, struct rt5677_pll_code *pll_code)
+	const unsigned int freq_out, struct rl6231_pll_code *pll_code)
 {
-	int max_n = RT5677_PLL_N_MAX, max_m = RT5677_PLL_M_MAX;
-	int k, red, n_t, pll_out, in_t;
-	int n = 0, m = 0, m_t = 0;
-	int out_t, red_t = abs(freq_out - freq_in);
-	bool m_bp = false, k_bp = false;
-
-	if (RT5677_PLL_INP_MAX < freq_in || RT5677_PLL_INP_MIN > freq_in)
+	if (RT5677_PLL_INP_MIN > freq_in)
 		return -EINVAL;
 
-	k = 100000000 / freq_out - 2;
-	if (k > RT5677_PLL_K_MAX)
-		k = RT5677_PLL_K_MAX;
-	for (n_t = 0; n_t <= max_n; n_t++) {
-		in_t = freq_in / (k + 2);
-		pll_out = freq_out / (n_t + 2);
-		if (in_t < 0)
-			continue;
-		if (in_t == pll_out) {
-			m_bp = true;
-			n = n_t;
-			goto code_find;
-		}
-		red = abs(in_t - pll_out);
-		if (red < red_t) {
-			m_bp = true;
-			n = n_t;
-			m = m_t;
-			if (red == 0)
-				goto code_find;
-			red_t = red;
-		}
-		for (m_t = 0; m_t <= max_m; m_t++) {
-			out_t = in_t / (m_t + 2);
-			red = abs(out_t - pll_out);
-			if (red < red_t) {
-				m_bp = false;
-				n = n_t;
-				m = m_t;
-				if (red == 0)
-					goto code_find;
-				red_t = red;
-			}
-		}
-	}
-	pr_debug("Only get approximation about PLL\n");
-
-code_find:
-
-	pll_code->m_bp = m_bp;
-	pll_code->k_bp = k_bp;
-	pll_code->m_code = m;
-	pll_code->n_code = n;
-	pll_code->k_code = k;
-	return 0;
+	return rl6231_pll_calc(freq_in, freq_out, pll_code);
 }
 
 static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
@@ -3079,7 +3009,7 @@ static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
 {
 	struct snd_soc_codec *codec = dai->codec;
 	struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
-	struct rt5677_pll_code pll_code;
+	struct rl6231_pll_code pll_code;
 	int ret;
 
 	if (source == rt5677->pll_src && freq_in == rt5677->pll_in &&
@@ -3137,15 +3067,12 @@ static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
 		return ret;
 	}
 
-	dev_dbg(codec->dev, "m_bypass=%d k_bypass=%d m=%d n=%d k=%d\n",
-		pll_code.m_bp, pll_code.k_bp,
-		(pll_code.m_bp ? 0 : pll_code.m_code), pll_code.n_code,
-		(pll_code.k_bp ? 0 : pll_code.k_code));
+	dev_dbg(codec->dev, "m_bypass=%d m=%d n=%d k=%d\n",
+		pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
+		pll_code.n_code, pll_code.k_code);
 
 	regmap_write(rt5677->regmap, RT5677_PLL1_CTRL1,
-		pll_code.n_code << RT5677_PLL_N_SFT |
-		pll_code.k_bp << RT5677_PLL_K_BP_SFT |
-		(pll_code.k_bp ? 0 : pll_code.k_code));
+		pll_code.n_code << RT5677_PLL_N_SFT | pll_code.k_code);
 	regmap_write(rt5677->regmap, RT5677_PLL1_CTRL2,
 		(pll_code.m_bp ? 0 : pll_code.m_code) << RT5677_PLL_M_SFT |
 		pll_code.m_bp << RT5677_PLL_M_BP_SFT);
@@ -3197,7 +3124,7 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec,
 		regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x1, 0x0);
 		regmap_write(rt5677->regmap, RT5677_PWR_DIG1, 0x0000);
 		regmap_write(rt5677->regmap, RT5677_PWR_DIG2, 0x0000);
-		regmap_write(rt5677->regmap, RT5677_PWR_ANLG1, 0x0000);
+		regmap_write(rt5677->regmap, RT5677_PWR_ANLG1, 0x0022);
 		regmap_write(rt5677->regmap, RT5677_PWR_ANLG2, 0x0000);
 		regmap_update_bits(rt5677->regmap,
 			RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000);
@@ -3454,14 +3381,8 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
 		regmap_update_bits(rt5677->regmap, RT5677_IN1,
 					RT5677_IN_DF2, RT5677_IN_DF2);
 
-	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677,
-			rt5677_dai, ARRAY_SIZE(rt5677_dai));
-	if (ret < 0)
-		goto err;
-
-	return 0;
-err:
-	return ret;
+	return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677,
+				      rt5677_dai, ARRAY_SIZE(rt5677_dai));
 }
 
 static int rt5677_i2c_remove(struct i2c_client *i2c)
@@ -3480,18 +3401,7 @@ static struct i2c_driver rt5677_i2c_driver = {
 	.remove   = rt5677_i2c_remove,
 	.id_table = rt5677_i2c_id,
 };
-
-static int __init rt5677_modinit(void)
-{
-	return i2c_add_driver(&rt5677_i2c_driver);
-}
-module_init(rt5677_modinit);
-
-static void __exit rt5677_modexit(void)
-{
-	i2c_del_driver(&rt5677_i2c_driver);
-}
-module_exit(rt5677_modexit);
+module_i2c_driver(rt5677_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC RT5677 driver");
 MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h
index af4e9c797408..863393e62096 100644
--- a/sound/soc/codecs/rt5677.h
+++ b/sound/soc/codecs/rt5677.h
@@ -1393,13 +1393,6 @@
 #define RT5677_DSP_IB_9_L			(0x1 << 1)
 #define RT5677_DSP_IB_9_L_SFT			1
 
-/* Debug String Length */
-#define RT5677_REG_DISP_LEN 23
-
-#define RT5677_NO_JACK		BIT(0)
-#define RT5677_HEADSET_DET	BIT(1)
-#define RT5677_HEADPHO_DET	BIT(2)
-
 /* System Clock Source */
 enum {
 	RT5677_SCLK_S_MCLK,
@@ -1425,14 +1418,6 @@ enum {
 	RT5677_AIFS,
 };
 
-struct rt5677_pll_code {
-	bool m_bp; /* Indicates bypass m code or not. */
-	bool k_bp; /* Indicates bypass k code or not. */
-	int m_code;
-	int n_code;
-	int k_code;
-};
-
 struct rt5677_priv {
 	struct snd_soc_codec *codec;
 	struct rt5677_platform_data pdata;
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 3d39f0b5b4a8..e997d271728d 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -724,25 +724,25 @@ static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream,
 		return ret;
 
 	/* set i2s data format */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J)
 			return -EINVAL;
 		i2s_ctl |= SGTL5000_I2S_DLEN_16 << SGTL5000_I2S_DLEN_SHIFT;
 		i2s_ctl |= SGTL5000_I2S_SCLKFREQ_32FS <<
 		    SGTL5000_I2S_SCLKFREQ_SHIFT;
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		i2s_ctl |= SGTL5000_I2S_DLEN_20 << SGTL5000_I2S_DLEN_SHIFT;
 		i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS <<
 		    SGTL5000_I2S_SCLKFREQ_SHIFT;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		i2s_ctl |= SGTL5000_I2S_DLEN_24 << SGTL5000_I2S_DLEN_SHIFT;
 		i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS <<
 		    SGTL5000_I2S_SCLKFREQ_SHIFT;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J)
 			return -EINVAL;
 		i2s_ctl |= SGTL5000_I2S_DLEN_32 << SGTL5000_I2S_DLEN_SHIFT;
@@ -843,10 +843,8 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
 
 	ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL);
 
-	if (!ldo) {
-		dev_err(codec->dev, "failed to allocate ldo_regulator\n");
+	if (!ldo)
 		return -ENOMEM;
-	}
 
 	ldo->desc.name = kstrdup(dev_name(codec->dev), GFP_KERNEL);
 	if (!ldo->desc.name) {
@@ -1277,7 +1275,7 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
 			return ret;
 	}
 
-	ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
+	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
 				 sgtl5000->supplies);
 	if (ret)
 		goto err_ldo_remove;
@@ -1285,13 +1283,16 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
 	ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
 					sgtl5000->supplies);
 	if (ret)
-		goto err_ldo_remove;
+		goto err_regulator_free;
 
 	/* wait for all power rails bring up */
 	udelay(10);
 
 	return 0;
 
+err_regulator_free:
+	regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
+				sgtl5000->supplies);
 err_ldo_remove:
 	if (!external_vddd)
 		ldo_regulator_remove(codec);
@@ -1361,6 +1362,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
 err:
 	regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
 						sgtl5000->supplies);
+	regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
+				sgtl5000->supplies);
 	ldo_regulator_remove(codec);
 
 	return ret;
@@ -1374,6 +1377,8 @@ static int sgtl5000_remove(struct snd_soc_codec *codec)
 
 	regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
 						sgtl5000->supplies);
+	regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
+				sgtl5000->supplies);
 	ldo_regulator_remove(codec);
 
 	return 0;
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
index f26befb0c297..cdf882fa7716 100644
--- a/sound/soc/codecs/si476x.c
+++ b/sound/soc/codecs/si476x.c
@@ -167,17 +167,17 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S8:
+	switch (params_width(params)) {
+	case 8:
 		width = SI476X_PCM_FORMAT_S8;
 		break;
-	case SNDRV_PCM_FORMAT_S16_LE:
+	case 16:
 		width = SI476X_PCM_FORMAT_S16_LE;
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		width = SI476X_PCM_FORMAT_S20_3LE;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		width = SI476X_PCM_FORMAT_S24_LE;
 		break;
 	default:
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c
index d90cb0fafcb2..06ba4923fd5a 100644
--- a/sound/soc/codecs/sirf-audio-codec.c
+++ b/sound/soc/codecs/sirf-audio-codec.c
@@ -471,8 +471,8 @@ static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
 
 	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	base = devm_ioremap_resource(&pdev->dev, mem_res);
-	if (base == NULL)
-		return -ENOMEM;
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 	sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
 					    &sirf_audio_codec_regmap_config);
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index 42dff26b3a2a..cf8fa40662f0 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -661,12 +661,12 @@ static int sn95031_pcm_hw_params(struct snd_pcm_substream *substream,
 {
 	unsigned int format, rate;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		format = BIT(4)|BIT(5);
 		break;
 
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		format = 0;
 		break;
 	default:
diff --git a/sound/soc/codecs/spdif_transmitter.c b/sound/soc/codecs/spdif_transmitter.c
index a078aa31052a..e0df537dd4b7 100644
--- a/sound/soc/codecs/spdif_transmitter.c
+++ b/sound/soc/codecs/spdif_transmitter.c
@@ -24,7 +24,7 @@
 
 #define DRV_NAME "spdif-dit"
 
-#define STUB_RATES	SNDRV_PCM_RATE_8000_96000
+#define STUB_RATES	SNDRV_PCM_RATE_8000_192000
 #define STUB_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \
 			SNDRV_PCM_FMTBIT_S20_3LE | \
 			SNDRV_PCM_FMTBIT_S24_LE)
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c
index 56adb3e2def9..e8680bea5f86 100644
--- a/sound/soc/codecs/ssm2518.c
+++ b/sound/soc/codecs/ssm2518.c
@@ -361,11 +361,11 @@ static int ssm2518_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 
 	if (ssm2518->right_j) {
-		switch (params_format(params)) {
-		case SNDRV_PCM_FORMAT_S16_LE:
+		switch (params_width(params)) {
+		case 16:
 			ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_16BIT;
 			break;
-		case SNDRV_PCM_FORMAT_S24_LE:
+		case 24:
 			ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT;
 			break;
 		default:
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 97b0454eb346..484b3bbe8624 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -275,17 +275,17 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
 	regmap_write(ssm2602->regmap, SSM2602_SRATE, srate);
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		iface = 0x0;
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface = 0x4;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface = 0x8;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		iface = 0xc;
 		break;
 	default:
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index 0579d187135b..48740855566d 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -678,15 +678,11 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
 
 	confb = snd_soc_read(codec, STA32X_CONFB);
 	confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB);
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
+	switch (params_width(params)) {
+	case 24:
 		pr_debug("24bit\n");
 		/* fall through */
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
+	case 32:
 		pr_debug("24bit or 32bit\n");
 		switch (sta32x->format) {
 		case SND_SOC_DAIFMT_I2S:
@@ -701,8 +697,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
 		}
 
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
+	case 20:
 		pr_debug("20bit\n");
 		switch (sta32x->format) {
 		case SND_SOC_DAIFMT_I2S:
@@ -717,8 +712,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
 		}
 
 		break;
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
+	case 18:
 		pr_debug("18bit\n");
 		switch (sta32x->format) {
 		case SND_SOC_DAIFMT_I2S:
@@ -733,8 +727,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
 		}
 
 		break;
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
+	case 16:
 		pr_debug("16bit\n");
 		switch (sta32x->format) {
 		case SND_SOC_DAIFMT_I2S:
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c
index a40c4b0196a3..9aa1323fb2ab 100644
--- a/sound/soc/codecs/sta529.c
+++ b/sound/soc/codecs/sta529.c
@@ -197,16 +197,16 @@ static int sta529_hw_params(struct snd_pcm_substream *substream,
 	int pdata, play_freq_val, record_freq_val;
 	int bclk_to_fs_ratio;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		pdata = 1;
 		bclk_to_fs_ratio = 0;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		pdata = 2;
 		bclk_to_fs_ratio = 1;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		pdata = 3;
 		bclk_to_fs_ratio = 2;
 		break;
@@ -380,10 +380,8 @@ static int sta529_i2c_probe(struct i2c_client *i2c,
 		return -EINVAL;
 
 	sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL);
-	if (sta529 == NULL) {
-		dev_err(&i2c->dev, "Can not allocate memory\n");
+	if (!sta529)
 		return -ENOMEM;
-	}
 
 	sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap);
 	if (IS_ERR(sta529->regmap)) {
diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c
new file mode 100644
index 000000000000..23b32960ff1d
--- /dev/null
+++ b/sound/soc/codecs/tas2552.c
@@ -0,0 +1,544 @@
+/*
+ * tas2552.c - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated -  http://www.ti.com
+ *
+ * Author: Dan Murphy <dmurphy@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
+
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/tas2552-plat.h>
+
+#include "tas2552.h"
+
+static struct reg_default tas2552_reg_defs[] = {
+	{TAS2552_CFG_1, 0x22},
+	{TAS2552_CFG_3, 0x80},
+	{TAS2552_DOUT, 0x00},
+	{TAS2552_OUTPUT_DATA, 0xc0},
+	{TAS2552_PDM_CFG, 0x01},
+	{TAS2552_PGA_GAIN, 0x00},
+	{TAS2552_BOOST_PT_CTRL, 0x0f},
+	{TAS2552_RESERVED_0D, 0x00},
+	{TAS2552_LIMIT_RATE_HYS, 0x08},
+	{TAS2552_CFG_2, 0xef},
+	{TAS2552_SER_CTRL_1, 0x00},
+	{TAS2552_SER_CTRL_2, 0x00},
+	{TAS2552_PLL_CTRL_1, 0x10},
+	{TAS2552_PLL_CTRL_2, 0x00},
+	{TAS2552_PLL_CTRL_3, 0x00},
+	{TAS2552_BTIP, 0x8f},
+	{TAS2552_BTS_CTRL, 0x80},
+	{TAS2552_LIMIT_RELEASE, 0x04},
+	{TAS2552_LIMIT_INT_COUNT, 0x00},
+	{TAS2552_EDGE_RATE_CTRL, 0x40},
+	{TAS2552_VBAT_DATA, 0x00},
+};
+
+#define TAS2552_NUM_SUPPLIES	3
+static const char *tas2552_supply_names[TAS2552_NUM_SUPPLIES] = {
+	"vbat",		/* vbat voltage */
+	"iovdd",	/* I/O Voltage */
+	"avdd",		/* Analog DAC Voltage */
+};
+
+struct tas2552_data {
+	struct snd_soc_codec *codec;
+	struct regmap *regmap;
+	struct i2c_client *tas2552_client;
+	struct regulator_bulk_data supplies[TAS2552_NUM_SUPPLIES];
+	struct gpio_desc *enable_gpio;
+	unsigned char regs[TAS2552_VBAT_DATA];
+	unsigned int mclk;
+};
+
+static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown)
+{
+	u8 cfg1_reg;
+
+	if (sw_shutdown)
+		cfg1_reg = 0;
+	else
+		cfg1_reg = TAS2552_SWS_MASK;
+
+	snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1,
+						 TAS2552_SWS_MASK, cfg1_reg);
+}
+
+static int tas2552_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params,
+			     struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
+	int sample_rate, pll_clk;
+	int d;
+	u8 p, j;
+
+	/* Turn on Class D amplifier */
+	snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_CLASSD_EN_MASK,
+						TAS2552_CLASSD_EN);
+
+	if (!tas2552->mclk)
+		return -EINVAL;
+
+	snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0);
+
+	if (tas2552->mclk == TAS2552_245MHZ_CLK ||
+		tas2552->mclk == TAS2552_225MHZ_CLK) {
+		/* By pass the PLL configuration */
+		snd_soc_update_bits(codec, TAS2552_PLL_CTRL_2,
+				    TAS2552_PLL_BYPASS_MASK,
+				    TAS2552_PLL_BYPASS);
+	} else {
+		/* Fill in the PLL control registers for J & D
+		 * PLL_CLK = (.5 * freq * J.D) / 2^p
+		 * Need to fill in J and D here based on incoming freq
+		 */
+		p = snd_soc_read(codec, TAS2552_PLL_CTRL_1);
+		p = (p >> 7);
+		sample_rate = params_rate(params);
+
+		if (sample_rate == 48000)
+			pll_clk = TAS2552_245MHZ_CLK;
+		else if (sample_rate == 44100)
+			pll_clk = TAS2552_225MHZ_CLK;
+		else {
+			dev_vdbg(codec->dev, "Substream sample rate is not found %i\n",
+					params_rate(params));
+			return -EINVAL;
+		}
+
+		j = (pll_clk * 2 * (1 << p)) / tas2552->mclk;
+		d = (pll_clk * 2 * (1 << p)) % tas2552->mclk;
+
+		snd_soc_update_bits(codec, TAS2552_PLL_CTRL_1,
+				TAS2552_PLL_J_MASK, j);
+		snd_soc_write(codec, TAS2552_PLL_CTRL_2,
+					(d >> 7) & TAS2552_PLL_D_UPPER_MASK);
+		snd_soc_write(codec, TAS2552_PLL_CTRL_3,
+				d & TAS2552_PLL_D_LOWER_MASK);
+
+	}
+
+	snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE,
+						TAS2552_PLL_ENABLE);
+
+	return 0;
+}
+
+static int tas2552_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u8 serial_format;
+	u8 serial_control_mask;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		serial_format = 0x00;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFM:
+		serial_format = TAS2552_WORD_CLK_MASK;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFS:
+		serial_format = TAS2552_BIT_CLK_MASK;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		serial_format = (TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK);
+		break;
+	default:
+		dev_vdbg(codec->dev, "DAI Format master is not found\n");
+		return -EINVAL;
+	}
+
+	serial_control_mask = TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		serial_format &= TAS2552_DAIFMT_I2S_MASK;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		serial_format |= TAS2552_DAIFMT_DSP;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		serial_format |= TAS2552_DAIFMT_RIGHT_J;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		serial_format |= TAS2552_DAIFMT_LEFT_J;
+		break;
+	default:
+		dev_vdbg(codec->dev, "DAI Format is not found\n");
+		return -EINVAL;
+	}
+
+	if (fmt & SND_SOC_DAIFMT_FORMAT_MASK)
+		serial_control_mask |= TAS2552_DATA_FORMAT_MASK;
+
+	snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, serial_control_mask,
+						serial_format);
+
+	return 0;
+}
+
+static int tas2552_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
+				  unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
+
+	tas2552->mclk = freq;
+
+	return 0;
+}
+
+static int tas2552_mute(struct snd_soc_dai *dai, int mute)
+{
+	u8 cfg1_reg;
+	struct snd_soc_codec *codec = dai->codec;
+
+	if (mute)
+		cfg1_reg = TAS2552_MUTE_MASK;
+	else
+		cfg1_reg = ~TAS2552_MUTE_MASK;
+
+	snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK, cfg1_reg);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int tas2552_runtime_suspend(struct device *dev)
+{
+	struct tas2552_data *tas2552 = dev_get_drvdata(dev);
+
+	tas2552_sw_shutdown(tas2552, 0);
+
+	regcache_cache_only(tas2552->regmap, true);
+	regcache_mark_dirty(tas2552->regmap);
+
+	if (tas2552->enable_gpio)
+		gpiod_set_value(tas2552->enable_gpio, 0);
+
+	return 0;
+}
+
+static int tas2552_runtime_resume(struct device *dev)
+{
+	struct tas2552_data *tas2552 = dev_get_drvdata(dev);
+
+	if (tas2552->enable_gpio)
+		gpiod_set_value(tas2552->enable_gpio, 1);
+
+	tas2552_sw_shutdown(tas2552, 1);
+
+	regcache_cache_only(tas2552->regmap, false);
+	regcache_sync(tas2552->regmap);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops tas2552_pm = {
+	SET_RUNTIME_PM_OPS(tas2552_runtime_suspend, tas2552_runtime_resume,
+			   NULL)
+};
+
+static void tas2552_shutdown(struct snd_pcm_substream *substream,
+			   struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+
+	snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0);
+}
+
+static struct snd_soc_dai_ops tas2552_speaker_dai_ops = {
+	.hw_params	= tas2552_hw_params,
+	.set_sysclk	= tas2552_set_dai_sysclk,
+	.set_fmt	= tas2552_set_dai_fmt,
+	.shutdown	= tas2552_shutdown,
+	.digital_mute = tas2552_mute,
+};
+
+/* Formats supported by TAS2552 driver. */
+#define TAS2552_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+			 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+/* TAS2552 dai structure. */
+static struct snd_soc_dai_driver tas2552_dai[] = {
+	{
+		.name = "tas2552-amplifier",
+		.playback = {
+			.stream_name = "Speaker",
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = TAS2552_FORMATS,
+		},
+		.ops = &tas2552_speaker_dai_ops,
+	},
+};
+
+/*
+ * DAC digital volumes. From -7 to 24 dB in 1 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 24);
+
+static const struct snd_kcontrol_new tas2552_snd_controls[] = {
+	SOC_SINGLE_TLV("Speaker Driver Playback Volume",
+			 TAS2552_PGA_GAIN, 0, 0x1f, 1, dac_tlv),
+};
+
+static const struct reg_default tas2552_init_regs[] = {
+	{ TAS2552_RESERVED_0D, 0xc0 },
+};
+
+static int tas2552_codec_probe(struct snd_soc_codec *codec)
+{
+	struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	tas2552->codec = codec;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies),
+				    tas2552->supplies);
+
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to enable supplies: %d\n",
+			ret);
+		return ret;
+	}
+
+	if (tas2552->enable_gpio)
+		gpiod_set_value(tas2552->enable_gpio, 1);
+
+	ret = pm_runtime_get_sync(codec->dev);
+	if (ret < 0) {
+		dev_err(codec->dev, "Enabling device failed: %d\n",
+			ret);
+		goto probe_fail;
+	}
+
+	snd_soc_write(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK |
+				TAS2552_PLL_SRC_BCLK);
+	snd_soc_write(codec, TAS2552_CFG_3, TAS2552_I2S_OUT_SEL |
+				TAS2552_DIN_SRC_SEL_AVG_L_R | TAS2552_88_96KHZ);
+	snd_soc_write(codec, TAS2552_DOUT, TAS2552_PDM_DATA_I);
+	snd_soc_write(codec, TAS2552_OUTPUT_DATA, TAS2552_PDM_DATA_V_I | 0x8);
+	snd_soc_write(codec, TAS2552_PDM_CFG, TAS2552_PDM_BCLK_SEL);
+	snd_soc_write(codec, TAS2552_BOOST_PT_CTRL, TAS2552_APT_DELAY_200 |
+				TAS2552_APT_THRESH_2_1_7);
+
+	ret = regmap_register_patch(tas2552->regmap, tas2552_init_regs,
+					    ARRAY_SIZE(tas2552_init_regs));
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to write init registers: %d\n",
+			ret);
+		goto patch_fail;
+	}
+
+	snd_soc_write(codec, TAS2552_CFG_2, TAS2552_CLASSD_EN |
+				  TAS2552_BOOST_EN | TAS2552_APT_EN |
+				  TAS2552_LIM_EN);
+	return 0;
+
+patch_fail:
+	pm_runtime_put(codec->dev);
+probe_fail:
+	if (tas2552->enable_gpio)
+		gpiod_set_value(tas2552->enable_gpio, 0);
+
+	regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies),
+					tas2552->supplies);
+	return -EIO;
+}
+
+static int tas2552_codec_remove(struct snd_soc_codec *codec)
+{
+	struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
+
+	pm_runtime_put(codec->dev);
+
+	if (tas2552->enable_gpio)
+		gpiod_set_value(tas2552->enable_gpio, 0);
+
+	return 0;
+};
+
+#ifdef CONFIG_PM
+static int tas2552_suspend(struct snd_soc_codec *codec)
+{
+	struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	ret = regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies),
+					tas2552->supplies);
+
+	if (ret != 0)
+		dev_err(codec->dev, "Failed to disable supplies: %d\n",
+			ret);
+	return 0;
+}
+
+static int tas2552_resume(struct snd_soc_codec *codec)
+{
+	struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies),
+				    tas2552->supplies);
+
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to enable supplies: %d\n",
+			ret);
+	}
+
+	return 0;
+}
+#else
+#define tas2552_suspend NULL
+#define tas2552_resume NULL
+#endif
+
+static struct snd_soc_codec_driver soc_codec_dev_tas2552 = {
+	.probe = tas2552_codec_probe,
+	.remove = tas2552_codec_remove,
+	.suspend =	tas2552_suspend,
+	.resume = tas2552_resume,
+	.controls = tas2552_snd_controls,
+	.num_controls = ARRAY_SIZE(tas2552_snd_controls),
+};
+
+static const struct regmap_config tas2552_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = TAS2552_MAX_REG,
+	.reg_defaults = tas2552_reg_defs,
+	.num_reg_defaults = ARRAY_SIZE(tas2552_reg_defs),
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static int tas2552_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct device *dev;
+	struct tas2552_data *data;
+	int ret;
+	int i;
+
+	dev = &client->dev;
+	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+
+	data->enable_gpio = devm_gpiod_get(dev, "enable");
+	if (IS_ERR(data->enable_gpio)) {
+		ret = PTR_ERR(data->enable_gpio);
+		if (ret != -ENOENT && ret != -ENOSYS)
+			return ret;
+
+		data->enable_gpio = NULL;
+	} else {
+		gpiod_direction_output(data->enable_gpio, 0);
+	}
+
+	data->tas2552_client = client;
+	data->regmap = devm_regmap_init_i2c(client, &tas2552_regmap_config);
+	if (IS_ERR(data->regmap)) {
+		ret = PTR_ERR(data->regmap);
+		dev_err(&client->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
+		data->supplies[i].supply = tas2552_supply_names[i];
+
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies),
+				      data->supplies);
+	if (ret != 0) {
+		dev_err(dev, "Failed to request supplies: %d\n", ret);
+		return ret;
+	}
+
+	pm_runtime_set_active(&client->dev);
+	pm_runtime_set_autosuspend_delay(&client->dev, 1000);
+	pm_runtime_use_autosuspend(&client->dev);
+	pm_runtime_enable(&client->dev);
+	pm_runtime_mark_last_busy(&client->dev);
+	pm_runtime_put_sync_autosuspend(&client->dev);
+
+	dev_set_drvdata(&client->dev, data);
+
+	ret = snd_soc_register_codec(&client->dev,
+				      &soc_codec_dev_tas2552,
+				      tas2552_dai, ARRAY_SIZE(tas2552_dai));
+	if (ret < 0)
+		dev_err(&client->dev, "Failed to register codec: %d\n", ret);
+
+	return ret;
+}
+
+static int tas2552_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	return 0;
+}
+
+static const struct i2c_device_id tas2552_id[] = {
+	{ "tas2552", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tas2552_id);
+
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id tas2552_of_match[] = {
+	{ .compatible = "ti,tas2552", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tas2552_of_match);
+#endif
+
+static struct i2c_driver tas2552_i2c_driver = {
+	.driver = {
+		.name = "tas2552",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(tas2552_of_match),
+		.pm = &tas2552_pm,
+	},
+	.probe = tas2552_probe,
+	.remove = tas2552_i2c_remove,
+	.id_table = tas2552_id,
+};
+
+module_i2c_driver(tas2552_i2c_driver);
+
+MODULE_AUTHOR("Dan Muprhy <dmurphy@ti.com>");
+MODULE_DESCRIPTION("TAS2552 Audio amplifier driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tas2552.h b/sound/soc/codecs/tas2552.h
new file mode 100644
index 000000000000..6cea8f31bf88
--- /dev/null
+++ b/sound/soc/codecs/tas2552.h
@@ -0,0 +1,129 @@
+/*
+ * tas2552.h - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated -  http://www.ti.com
+ *
+ * Author: Dan Murphy <dmurphy@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __TAS2552_H__
+#define __TAS2552_H__
+
+/* Register Address Map */
+#define TAS2552_DEVICE_STATUS	0x00
+#define TAS2552_CFG_1			0x01
+#define TAS2552_CFG_2			0x02
+#define TAS2552_CFG_3			0x03
+#define TAS2552_DOUT			0x04
+#define TAS2552_SER_CTRL_1		0x05
+#define TAS2552_SER_CTRL_2		0x06
+#define TAS2552_OUTPUT_DATA		0x07
+#define TAS2552_PLL_CTRL_1		0x08
+#define TAS2552_PLL_CTRL_2		0x09
+#define TAS2552_PLL_CTRL_3		0x0a
+#define TAS2552_BTIP			0x0b
+#define TAS2552_BTS_CTRL		0x0c
+#define TAS2552_RESERVED_0D		0x0d
+#define TAS2552_LIMIT_RATE_HYS	0x0e
+#define TAS2552_LIMIT_RELEASE	0x0f
+#define TAS2552_LIMIT_INT_COUNT	0x10
+#define TAS2552_PDM_CFG			0x11
+#define TAS2552_PGA_GAIN		0x12
+#define TAS2552_EDGE_RATE_CTRL	0x13
+#define TAS2552_BOOST_PT_CTRL	0x14
+#define TAS2552_VER_NUM			0x16
+#define TAS2552_VBAT_DATA		0x19
+#define TAS2552_MAX_REG			0x20
+
+/* CFG1 Register Masks */
+#define TAS2552_MUTE_MASK		(1 << 2)
+#define TAS2552_SWS_MASK		(1 << 1)
+#define TAS2552_WCLK_MASK		0x07
+#define TAS2552_CLASSD_EN_MASK	(1 << 7)
+
+/* CFG2 Register Masks */
+#define TAS2552_CLASSD_EN		(1 << 7)
+#define TAS2552_BOOST_EN		(1 << 6)
+#define TAS2552_APT_EN			(1 << 5)
+#define TAS2552_PLL_ENABLE		(1 << 3)
+#define TAS2552_LIM_EN			(1 << 2)
+#define TAS2552_IVSENSE_EN		(1 << 1)
+
+/* CFG3 Register Masks */
+#define TAS2552_WORD_CLK_MASK		(1 << 7)
+#define TAS2552_BIT_CLK_MASK		(1 << 6)
+#define TAS2552_DATA_FORMAT_MASK	(0x11 << 2)
+
+#define TAS2552_DAIFMT_I2S_MASK		0xf3
+#define TAS2552_DAIFMT_DSP			(1 << 3)
+#define TAS2552_DAIFMT_RIGHT_J		(1 << 4)
+#define TAS2552_DAIFMT_LEFT_J		(0x11 << 3)
+
+#define TAS2552_PLL_SRC_MCLK	0x00
+#define TAS2552_PLL_SRC_BCLK	(1 << 3)
+#define TAS2552_PLL_SRC_IVCLKIN	(1 << 4)
+#define TAS2552_PLL_SRC_1_8_FIXED (0x11 << 3)
+
+#define TAS2552_DIN_SRC_SEL_MUTED	0x00
+#define TAS2552_DIN_SRC_SEL_LEFT	(1 << 4)
+#define TAS2552_DIN_SRC_SEL_RIGHT	(1 << 5)
+#define TAS2552_DIN_SRC_SEL_AVG_L_R	(0x11 << 4)
+
+#define TAS2552_PDM_IN_SEL		(1 << 5)
+#define TAS2552_I2S_OUT_SEL		(1 << 6)
+#define TAS2552_ANALOG_IN_SEL	(1 << 7)
+
+/* CFG3 WCLK Dividers */
+#define TAS2552_8KHZ		0x00
+#define TAS2552_11_12KHZ	(1 << 1)
+#define TAS2552_16KHZ		(1 << 2)
+#define TAS2552_22_24KHZ	(1 << 3)
+#define TAS2552_32KHZ		(1 << 4)
+#define TAS2552_44_48KHZ	(1 << 5)
+#define TAS2552_88_96KHZ	(1 << 6)
+#define TAS2552_176_192KHZ	(1 << 7)
+
+/* OUTPUT_DATA register */
+#define TAS2552_PDM_DATA_I		0x00
+#define TAS2552_PDM_DATA_V		(1 << 6)
+#define TAS2552_PDM_DATA_I_V	(1 << 7)
+#define TAS2552_PDM_DATA_V_I	(0x11 << 6)
+
+/* PDM CFG Register */
+#define TAS2552_PDM_DATA_ES_RISE 0x4
+
+#define TAS2552_PDM_PLL_CLK_SEL 0x00
+#define TAS2552_PDM_IV_CLK_SEL	(1 << 1)
+#define TAS2552_PDM_BCLK_SEL	(1 << 2)
+#define TAS2552_PDM_MCLK_SEL	(1 << 3)
+
+/* Boost pass-through register */
+#define TAS2552_APT_DELAY_50	0x00
+#define TAS2552_APT_DELAY_75	(1 << 1)
+#define TAS2552_APT_DELAY_125	(1 << 2)
+#define TAS2552_APT_DELAY_200	(1 << 3)
+
+#define TAS2552_APT_THRESH_2_5		0x00
+#define TAS2552_APT_THRESH_1_7		(1 << 3)
+#define TAS2552_APT_THRESH_1_4_1_1	(1 << 4)
+#define TAS2552_APT_THRESH_2_1_7	(0x11 << 2)
+
+/* PLL Control Register */
+#define TAS2552_245MHZ_CLK			24576000
+#define TAS2552_225MHZ_CLK			22579200
+#define TAS2552_PLL_J_MASK			0x7f
+#define TAS2552_PLL_D_UPPER_MASK	0x3f
+#define TAS2552_PLL_D_LOWER_MASK	0xff
+#define TAS2552_PLL_BYPASS_MASK		0x80
+#define TAS2552_PLL_BYPASS			0x80
+
+#endif
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c
index d48491a4a19d..249ef5c4c762 100644
--- a/sound/soc/codecs/tas5086.c
+++ b/sound/soc/codecs/tas5086.c
@@ -36,6 +36,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -240,6 +241,10 @@ static int tas5086_reg_read(void *context, unsigned int reg,
 	return 0;
 }
 
+static const char * const supply_names[] = {
+	"dvdd", "avdd"
+};
+
 struct tas5086_private {
 	struct regmap	*regmap;
 	unsigned int	mclk, sclk;
@@ -251,6 +256,7 @@ struct tas5086_private {
 	int		rate;
 	/* GPIO driving Reset pin, if any */
 	int		gpio_nreset;
+	struct		regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
 };
 
 static int tas5086_deemph[] = { 0, 32000, 44100, 48000 };
@@ -419,14 +425,14 @@ static int tas5086_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	/* ... then add the offset for the sample bit depth. */
-	switch (params_format(params)) {
-        case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+        case 16:
 		val += 0;
                 break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		val += 1;
 		break;
-	case SNDRV_PCM_FORMAT_S24_3LE:
+	case 24:
 		val += 2;
 		break;
 	default:
@@ -773,6 +779,8 @@ static int tas5086_soc_suspend(struct snd_soc_codec *codec)
 	if (ret < 0)
 		return ret;
 
+	regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
+
 	return 0;
 }
 
@@ -781,6 +789,10 @@ static int tas5086_soc_resume(struct snd_soc_codec *codec)
 	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
+	ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
+	if (ret < 0)
+		return ret;
+
 	tas5086_reset(priv);
 	regcache_mark_dirty(priv->regmap);
 
@@ -812,6 +824,12 @@ static int tas5086_probe(struct snd_soc_codec *codec)
 	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
 	int i, ret;
 
+	ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
 	priv->pwm_start_mid_z = 0;
 	priv->charge_period = 1300000; /* hardware default is 1300 ms */
 
@@ -832,16 +850,22 @@ static int tas5086_probe(struct snd_soc_codec *codec)
 		}
 	}
 
+	tas5086_reset(priv);
 	ret = tas5086_init(codec->dev, priv);
 	if (ret < 0)
-		return ret;
+		goto exit_disable_regulators;
 
 	/* set master volume to 0 dB */
 	ret = regmap_write(priv->regmap, TAS5086_MASTER_VOL, 0x30);
 	if (ret < 0)
-		return ret;
+		goto exit_disable_regulators;
 
 	return 0;
+
+exit_disable_regulators:
+	regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
+
+	return ret;
 }
 
 static int tas5086_remove(struct snd_soc_codec *codec)
@@ -852,6 +876,8 @@ static int tas5086_remove(struct snd_soc_codec *codec)
 		/* Set codec to the reset state */
 		gpio_set_value(priv->gpio_nreset, 0);
 
+	regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
+
 	return 0;
 };
 
@@ -900,6 +926,16 @@ static int tas5086_i2c_probe(struct i2c_client *i2c,
 	if (!priv)
 		return -ENOMEM;
 
+	for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+		priv->supplies[i].supply = supply_names[i];
+
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
+				      priv->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to get regulators: %d\n", ret);
+		return ret;
+	}
+
 	priv->regmap = devm_regmap_init(dev, NULL, i2c, &tas5086_regmap);
 	if (IS_ERR(priv->regmap)) {
 		ret = PTR_ERR(priv->regmap);
@@ -919,21 +955,34 @@ static int tas5086_i2c_probe(struct i2c_client *i2c,
 			gpio_nreset = -EINVAL;
 
 	priv->gpio_nreset = gpio_nreset;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
 	tas5086_reset(priv);
 
 	/* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */
 	ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i);
-	if (ret < 0)
-		return ret;
-
-	if (i != 0x3) {
+	if (ret == 0 && i != 0x3) {
 		dev_err(dev,
 			"Failed to identify TAS5086 codec (got %02x)\n", i);
-		return -ENODEV;
+		ret = -ENODEV;
 	}
 
-	return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086,
-		&tas5086_dai, 1);
+	/*
+	 * The chip has been identified, so we can turn off the power
+	 * again until the dai link is set up.
+	 */
+	regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
+
+	if (ret == 0)
+		ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086,
+					     &tas5086_dai, 1);
+
+	return ret;
 }
 
 static int tas5086_i2c_remove(struct i2c_client *i2c)
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 686b8b85b956..d67167920c2f 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -364,16 +364,16 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
 
 	iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface_reg |= (0x01 << 2);
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface_reg |= (0x02 << 2);
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		iface_reg |= (0x03 << 2);
 		break;
 	}
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 43069de3d56a..620ab9ea1ef0 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -71,8 +71,8 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
 
 	dev_dbg(&aic26->spi->dev, "aic26_hw_params(substream=%p, params=%p)\n",
 		substream, params);
-	dev_dbg(&aic26->spi->dev, "rate=%i format=%i\n", params_rate(params),
-		params_format(params));
+	dev_dbg(&aic26->spi->dev, "rate=%i width=%d\n", params_rate(params),
+		params_width(params));
 
 	switch (params_rate(params)) {
 	case 8000:  fsref = 48000; divisor = AIC26_DIV_6; break;
@@ -89,11 +89,11 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	/* select data word length */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S8:     wlen = AIC26_WLEN_16; break;
-	case SNDRV_PCM_FORMAT_S16_BE: wlen = AIC26_WLEN_16; break;
-	case SNDRV_PCM_FORMAT_S24_BE: wlen = AIC26_WLEN_24; break;
-	case SNDRV_PCM_FORMAT_S32_BE: wlen = AIC26_WLEN_32; break;
+	switch (params_width(params)) {
+	case 8:  wlen = AIC26_WLEN_16; break;
+	case 16: wlen = AIC26_WLEN_16; break;
+	case 24: wlen = AIC26_WLEN_24; break;
+	case 32: wlen = AIC26_WLEN_32; break;
 	default:
 		dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL;
 	}
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 23419109ecac..0f64c7890eed 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -249,17 +249,16 @@ static const char * const mic_select_text[] = {
 	"Off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm"
 };
 
-static const
-SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, mic_select_text);
-static const
-SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, mic_select_text);
-static const
-SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, mic_select_text);
-
-static const
-SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text);
-static const
-SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, mic_select_text);
+static SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6,
+	mic_select_text);
+static SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4,
+	mic_select_text);
+static SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2,
+	mic_select_text);
+
+static SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text);
+static SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4,
+	mic_select_text);
 
 static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0);
 static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0);
@@ -329,6 +328,7 @@ static int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg,
 	unsigned int bits;
 	int counter = count;
 	int ret = regmap_read(aic31xx->regmap, reg, &bits);
+
 	while ((bits & mask) != wbits && counter && !ret) {
 		usleep_range(sleep, sleep * 2);
 		ret = regmap_read(aic31xx->regmap, reg, &bits);
@@ -435,6 +435,7 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w,
 {
 	struct snd_soc_codec *codec = w->codec;
 	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
 		/* change mic bias voltage to user defined */
@@ -759,8 +760,8 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_codec *codec = dai->codec;
 	u8 data = 0;
 
-	dev_dbg(codec->dev, "## %s: format %d width %d rate %d\n",
-		__func__, params_format(params), params_width(params),
+	dev_dbg(codec->dev, "## %s: width %d rate %d\n",
+		__func__, params_width(params),
 		params_rate(params));
 
 	switch (params_width(params)) {
@@ -779,8 +780,8 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream,
 			AIC31XX_IFACE1_DATALEN_SHIFT);
 		break;
 	default:
-		dev_err(codec->dev, "%s: Unsupported format %d\n",
-			__func__, params_format(params));
+		dev_err(codec->dev, "%s: Unsupported width %d\n",
+			__func__, params_width(params));
 		return -EINVAL;
 	}
 
@@ -1178,7 +1179,7 @@ static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx)
 }
 #endif /* CONFIG_OF */
 
-static void aic31xx_device_init(struct aic31xx_priv *aic31xx)
+static int aic31xx_device_init(struct aic31xx_priv *aic31xx)
 {
 	int ret, i;
 
@@ -1197,7 +1198,7 @@ static void aic31xx_device_init(struct aic31xx_priv *aic31xx)
 					    "aic31xx-reset-pin");
 		if (ret < 0) {
 			dev_err(aic31xx->dev, "not able to acquire gpio\n");
-			return;
+			return ret;
 		}
 	}
 
@@ -1210,6 +1211,7 @@ static void aic31xx_device_init(struct aic31xx_priv *aic31xx)
 	if (ret != 0)
 		dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret);
 
+	return ret;
 }
 
 static int aic31xx_i2c_probe(struct i2c_client *i2c,
@@ -1239,7 +1241,9 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
 
 	aic31xx->pdata.codec_type = id->driver_data;
 
-	aic31xx_device_init(aic31xx);
+	ret = aic31xx_device_init(aic31xx);
+	if (ret)
+		return ret;
 
 	return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx,
 				     aic31xx_dai_driver,
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 1d9b117345a3..6ea662db2410 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -450,16 +450,16 @@ static int aic32x4_hw_params(struct snd_pcm_substream *substream,
 
 	data = snd_soc_read(codec, AIC32X4_IFACE1);
 	data = data & ~(3 << 4);
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		data |= (AIC32X4_WORD_LEN_20BITS << AIC32X4_DOSRMSB_SHIFT);
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		data |= (AIC32X4_WORD_LEN_24BITS << AIC32X4_DOSRMSB_SHIFT);
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		data |= (AIC32X4_WORD_LEN_32BITS << AIC32X4_DOSRMSB_SHIFT);
 		break;
 	}
@@ -626,32 +626,33 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
 		snd_soc_write(codec, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN |
 						      AIC32X4_MICBIAS_2075V);
 	}
-	if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) {
+	if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE)
 		snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
-	}
 
 	tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ?
 			AIC32X4_LDOCTLEN : 0;
 	snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg);
 
 	tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE);
-	if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) {
+	if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36)
 		tmp_reg |= AIC32X4_LDOIN_18_36;
-	}
-	if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) {
+	if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED)
 		tmp_reg |= AIC32X4_LDOIN2HP;
-	}
 	snd_soc_write(codec, AIC32X4_CMMODE, tmp_reg);
 
 	/* Mic PGA routing */
 	if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K)
-		snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_IN2R_10K);
+		snd_soc_write(codec, AIC32X4_LMICPGANIN,
+				AIC32X4_LMICPGANIN_IN2R_10K);
 	else
-		snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_CM1L_10K);
+		snd_soc_write(codec, AIC32X4_LMICPGANIN,
+				AIC32X4_LMICPGANIN_CM1L_10K);
 	if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K)
-		snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_IN1L_10K);
+		snd_soc_write(codec, AIC32X4_RMICPGANIN,
+				AIC32X4_RMICPGANIN_IN1L_10K);
 	else
-		snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_CM1R_10K);
+		snd_soc_write(codec, AIC32X4_RMICPGANIN,
+				AIC32X4_RMICPGANIN_CM1R_10K);
 
 	aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index e12fafbb1e09..64f179ee9834 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -873,16 +873,16 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
 
 	/* select data word length */
 	data = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4));
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		data |= (0x01 << 4);
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		data |= (0x02 << 4);
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		data |= (0x03 << 4);
 		break;
 	}
@@ -1194,7 +1194,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
 
 #define AIC3X_RATES	SNDRV_PCM_RATE_8000_96000
 #define AIC3X_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
-			 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+			 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE | \
+			 SNDRV_PCM_FMTBIT_S32_LE)
 
 static const struct snd_soc_dai_ops aic3x_dai_ops = {
 	.hw_params	= aic3x_hw_params,
@@ -1477,10 +1478,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
 	u32 value;
 
 	aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL);
-	if (aic3x == NULL) {
-		dev_err(&i2c->dev, "failed to create private data\n");
+	if (!aic3x)
 		return -ENOMEM;
-	}
 
 	aic3x->regmap = devm_regmap_init_i2c(i2c, &aic3x_regmap);
 	if (IS_ERR(aic3x->regmap)) {
@@ -1498,10 +1497,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
 	} else if (np) {
 		ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup),
 								GFP_KERNEL);
-		if (ai3x_setup == NULL) {
-			dev_err(&i2c->dev, "failed to create private data\n");
+		if (!ai3x_setup)
 			return -ENOMEM;
-		}
 
 		ret = of_get_named_gpio(np, "gpio-reset", 0);
 		if (ret >= 0)
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index df3a7506c023..e21ed934bdbf 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -832,18 +832,18 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		dac33->fifo_size = DAC33_FIFO_SIZE_16BIT;
 		dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 32);
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		dac33->fifo_size = DAC33_FIFO_SIZE_24BIT;
 		dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 64);
 		break;
 	default:
-		dev_err(codec->dev, "unsupported format %d\n",
-			params_format(params));
+		dev_err(codec->dev, "unsupported width %d\n",
+			params_width(params));
 		return -EINVAL;
 	}
 
@@ -1404,7 +1404,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
 	if (dac33->irq >= 0) {
 		ret = request_irq(dac33->irq, dac33_interrupt_handler,
 				  IRQF_TRIGGER_RISING,
-				  codec->name, codec);
+				  codec->component.name, codec);
 		if (ret < 0) {
 			dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
 						dac33->irq, ret);
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 8fc5a647453b..6fac9e034c48 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -381,10 +381,8 @@ static int tpa6130a2_probe(struct i2c_client *client,
 	dev = &client->dev;
 
 	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(dev, "Can not allocate memory\n");
+	if (!data)
 		return -ENOMEM;
-	}
 
 	if (pdata) {
 		data->power_gpio = pdata->power_gpio;
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 69e12a311ba2..b6b0cb399599 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -344,17 +344,16 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
 static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable)
 {
 	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
-	int status = -1;
 
 	if (enable) {
 		twl4030->apll_enabled++;
 		if (twl4030->apll_enabled == 1)
-			status = twl4030_audio_enable_resource(
+			twl4030_audio_enable_resource(
 							TWL4030_AUDIO_RES_APLL);
 	} else {
 		twl4030->apll_enabled--;
 		if (!twl4030->apll_enabled)
-			status = twl4030_audio_disable_resource(
+			twl4030_audio_disable_resource(
 							TWL4030_AUDIO_RES_APLL);
 	}
 }
@@ -1764,16 +1763,16 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
 	old_format = twl4030_read(codec, TWL4030_REG_AUDIO_IF);
 	format = old_format;
 	format &= ~TWL4030_DATA_WIDTH;
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		format |= TWL4030_DATA_WIDTH_16S_16W;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		format |= TWL4030_DATA_WIDTH_32S_24W;
 		break;
 	default:
-		dev_err(codec->dev, "%s: unknown format %d\n", __func__,
-			params_format(params));
+		dev_err(codec->dev, "%s: unsupported bits/sample %d\n",
+			__func__, params_width(params));
 		return -EINVAL;
 	}
 
@@ -2162,10 +2161,8 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
 
 	twl4030 = devm_kzalloc(codec->dev, sizeof(struct twl4030_priv),
 			       GFP_KERNEL);
-	if (twl4030 == NULL) {
-		dev_err(codec->dev, "Can not allocate memory\n");
+	if (!twl4030)
 		return -ENOMEM;
-	}
 	snd_soc_codec_set_drvdata(codec, twl4030);
 	/* Set the defaults, and power up the codec */
 	twl4030->sysclk = twl4030_audio_get_mclk() / 1000;
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index edf27acc1d77..32b2f78aa62c 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -243,14 +243,14 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream,
 	case SND_SOC_DAIFMT_I2S:
 		break;
 	case SND_SOC_DAIFMT_RIGHT_J:
-		switch (params_format(params)) {
-		case SNDRV_PCM_FORMAT_S16_LE:
+		switch (params_width(params)) {
+		case 16:
 			hw_params |= (1<<1);
 			break;
-		case SNDRV_PCM_FORMAT_S18_3LE:
+		case 18:
 			hw_params |= (1<<2);
 			break;
-		case SNDRV_PCM_FORMAT_S20_3LE:
+		case 20:
 			hw_params |= ((1<<2) | (1<<1));
 			break;
 		default:
@@ -479,7 +479,7 @@ static struct snd_soc_dai_driver uda134x_dai = {
 static int uda134x_soc_probe(struct snd_soc_codec *codec)
 {
 	struct uda134x_priv *uda134x;
-	struct uda134x_platform_data *pd = codec->card->dev->platform_data;
+	struct uda134x_platform_data *pd = codec->component.card->dev->platform_data;
 	const struct snd_soc_dapm_widget *widgets;
 	unsigned num_widgets;
 
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index 4ead0dc02b87..f3d4e88d0b7b 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -341,8 +341,9 @@ static int wl1273_hw_params(struct snd_pcm_substream *substream,
 	struct wl1273_core *core = wl1273->core;
 	unsigned int rate, width, r;
 
-	if (params_format(params) != SNDRV_PCM_FORMAT_S16_LE) {
-		pr_err("Only SNDRV_PCM_FORMAT_S16_LE supported.\n");
+	if (params_width(params) != 16) {
+		dev_err(dai->dev, "%d bits/sample not supported\n",
+			params_width(params));
 		return -EINVAL;
 	}
 
@@ -461,10 +462,8 @@ static int wl1273_probe(struct snd_soc_codec *codec)
 	}
 
 	wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL);
-	if (wl1273 == NULL) {
-		dev_err(codec->dev, "Cannot allocate memory.\n");
+	if (!wl1273)
 		return -ENOMEM;
-	}
 
 	wl1273->mode = WL1273_MODE_BT;
 	wl1273->core = *core;
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c
index 71ce3159a62e..f37989ec7cba 100644
--- a/sound/soc/codecs/wm0010.c
+++ b/sound/soc/codecs/wm0010.c
@@ -144,7 +144,7 @@ static const struct snd_soc_dapm_route wm0010_dapm_routes[] = {
 
 static const char *wm0010_state_to_str(enum wm0010_state state)
 {
-	const char *state_to_str[] = {
+	static const char * const state_to_str[] = {
 		"Power off",
 		"Out of reset",
 		"Boot ROM",
@@ -413,7 +413,6 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec)
 
 		xfer = kzalloc(sizeof(*xfer), GFP_KERNEL);
 		if (!xfer) {
-			dev_err(codec->dev, "Failed to allocate xfer\n");
 			ret = -ENOMEM;
 			goto abort;
 		}
@@ -423,8 +422,6 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec)
 
 		out = kzalloc(len, GFP_KERNEL | GFP_DMA);
 		if (!out) {
-			dev_err(codec->dev,
-				"Failed to allocate RX buffer\n");
 			ret = -ENOMEM;
 			goto abort1;
 		}
@@ -432,8 +429,6 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec)
 
 		img = kzalloc(len, GFP_KERNEL | GFP_DMA);
 		if (!img) {
-			dev_err(codec->dev,
-				"Failed to allocate image buffer\n");
 			ret = -ENOMEM;
 			goto abort1;
 		}
@@ -526,14 +521,12 @@ static int wm0010_stage2_load(struct snd_soc_codec *codec)
 	/* Copy to local buffer first as vmalloc causes problems for dma */
 	img = kzalloc(fw->size, GFP_KERNEL | GFP_DMA);
 	if (!img) {
-		dev_err(codec->dev, "Failed to allocate image buffer\n");
 		ret = -ENOMEM;
 		goto abort2;
 	}
 
 	out = kzalloc(fw->size, GFP_KERNEL | GFP_DMA);
 	if (!out) {
-		dev_err(codec->dev, "Failed to allocate output buffer\n");
 		ret = -ENOMEM;
 		goto abort1;
 	}
@@ -679,11 +672,8 @@ static int wm0010_boot(struct snd_soc_codec *codec)
 		}
 
 		img_swap = kzalloc(len, GFP_KERNEL | GFP_DMA);
-		if (!img_swap) {
-			dev_err(codec->dev,
-				"Failed to allocate image buffer\n");
+		if (!img_swap)
 			goto abort;
-		}
 
 		/* We need to re-order for 0010 */
 		byte_swap_64((u64 *)&pll_rec, img_swap, len);
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c
index 6e6b93d4696e..8011f75fb6cb 100644
--- a/sound/soc/codecs/wm1250-ev1.c
+++ b/sound/soc/codecs/wm1250-ev1.c
@@ -164,7 +164,6 @@ static int wm1250_ev1_pdata(struct i2c_client *i2c)
 
 	wm1250 = devm_kzalloc(&i2c->dev, sizeof(*wm1250), GFP_KERNEL);
 	if (!wm1250) {
-		dev_err(&i2c->dev, "Unable to allocate private data\n");
 		ret = -ENOMEM;
 		goto err;
 	}
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index a4c352cc3464..34ef65c52a7d 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -826,10 +826,8 @@ static int wm2000_i2c_probe(struct i2c_client *i2c,
 
 	wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv),
 			      GFP_KERNEL);
-	if (wm2000 == NULL) {
-		dev_err(&i2c->dev, "Unable to allocate private data\n");
+	if (!wm2000)
 		return -ENOMEM;
-	}
 
 	mutex_init(&wm2000->lock);
 
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index 91a9ea2a2056..7bb0d36d4c54 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -735,8 +735,7 @@ WM5100_MIXER_CONTROLS("LHPF4", WM5100_HPLP4MIX_INPUT_1_SOURCE),
 static void wm5100_seq_notifier(struct snd_soc_dapm_context *dapm,
 				enum snd_soc_dapm_type event, int subseq)
 {
-	struct snd_soc_codec *codec = container_of(dapm,
-						   struct snd_soc_codec, dapm);
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
 	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
 	u16 val, expect, i;
 
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 289b64d89abd..f60234962527 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -612,6 +612,62 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+	uint16_t data;
+
+	mutex_lock(&codec->mutex);
+	data = cpu_to_be16(arizona->dac_comp_coeff);
+	memcpy(ucontrol->value.bytes.data, &data, sizeof(data));
+	mutex_unlock(&codec->mutex);
+
+	return 0;
+}
+
+static int wm5102_out_comp_coeff_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+
+	mutex_lock(&codec->mutex);
+	memcpy(&arizona->dac_comp_coeff, ucontrol->value.bytes.data,
+	       sizeof(arizona->dac_comp_coeff));
+	arizona->dac_comp_coeff = be16_to_cpu(arizona->dac_comp_coeff);
+	mutex_unlock(&codec->mutex);
+
+	return 0;
+}
+
+static int wm5102_out_comp_switch_get(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+
+	mutex_lock(&codec->mutex);
+	ucontrol->value.integer.value[0] = arizona->dac_comp_enabled;
+	mutex_unlock(&codec->mutex);
+
+	return 0;
+}
+
+static int wm5102_out_comp_switch_put(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+
+	mutex_lock(&codec->mutex);
+	arizona->dac_comp_enabled = ucontrol->value.integer.value[0];
+	mutex_unlock(&codec->mutex);
+
+	return 0;
+}
+
 static const char *wm5102_osr_text[] = {
 	"Low power", "Normal", "High performance",
 };
@@ -843,6 +899,12 @@ SOC_SINGLE_TLV("Noise Gate Threshold Volume", ARIZONA_NOISE_GATE_CONTROL,
 	       ARIZONA_NGATE_THR_SHIFT, 7, 1, ng_tlv),
 SOC_ENUM("Noise Gate Hold", arizona_ng_hold),
 
+SND_SOC_BYTES_EXT("Output Compensation Coefficient", 2,
+		  wm5102_out_comp_coeff_get, wm5102_out_comp_coeff_put),
+
+SOC_SINGLE_EXT("Output Compensation Switch", 0, 0, 1, 0,
+	       wm5102_out_comp_switch_get, wm5102_out_comp_switch_put),
+
 WM5102_NG_SRC("HPOUT1L", ARIZONA_NOISE_GATE_SELECT_1L),
 WM5102_NG_SRC("HPOUT1R", ARIZONA_NOISE_GATE_SELECT_1R),
 WM5102_NG_SRC("HPOUT2L", ARIZONA_NOISE_GATE_SELECT_2L),
@@ -1653,6 +1715,7 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
 		 },
 		.ops = &arizona_dai_ops,
 		.symmetric_rates = 1,
+		.symmetric_samplebits = 1,
 	},
 	{
 		.name = "wm5102-aif2",
@@ -1674,6 +1737,7 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
 		 },
 		.ops = &arizona_dai_ops,
 		.symmetric_rates = 1,
+		.symmetric_samplebits = 1,
 	},
 	{
 		.name = "wm5102-aif3",
@@ -1695,6 +1759,7 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
 		 },
 		.ops = &arizona_dai_ops,
 		.symmetric_rates = 1,
+		.symmetric_samplebits = 1,
 	},
 	{
 		.name = "wm5102-slim1",
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 2e5fcb559e90..2f2ec26d831c 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -1485,6 +1485,7 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
 		 },
 		.ops = &arizona_dai_ops,
 		.symmetric_rates = 1,
+		.symmetric_samplebits = 1,
 	},
 	{
 		.name = "wm5110-aif2",
@@ -1506,6 +1507,7 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
 		 },
 		.ops = &arizona_dai_ops,
 		.symmetric_rates = 1,
+		.symmetric_samplebits = 1,
 	},
 	{
 		.name = "wm5110-aif3",
@@ -1527,6 +1529,7 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
 		 },
 		.ops = &arizona_dai_ops,
 		.symmetric_rates = 1,
+		.symmetric_samplebits = 1,
 	},
 	{
 		.name = "wm5110-slim1",
@@ -1596,6 +1599,7 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
 
 	arizona_init_spk(codec);
 	arizona_init_gpio(codec);
+	arizona_init_mono(codec);
 
 	ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8);
 	if (ret != 0)
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 392285edb595..3dfdcc4197fa 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -918,16 +918,16 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
 	    ~WM8350_AIF_WL_MASK;
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface |= 0x1 << 10;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface |= 0x2 << 10;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		iface |= 0x3 << 10;
 		break;
 	}
@@ -1341,21 +1341,18 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
 {
 	struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec);
 	struct wm8350 *wm8350 = priv->wm8350;
-	int irq;
 	int ena;
 
 	switch (which) {
 	case WM8350_JDL:
 		priv->hpl.jack = jack;
 		priv->hpl.report = report;
-		irq = WM8350_IRQ_CODEC_JCK_DET_L;
 		ena = WM8350_JDL_ENA;
 		break;
 
 	case WM8350_JDR:
 		priv->hpr.jack = jack;
 		priv->hpr.report = report;
-		irq = WM8350_IRQ_CODEC_JCK_DET_R;
 		ena = WM8350_JDR_ENA;
 		break;
 
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 06e913d3fea1..72471bef2e9a 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -1095,16 +1095,16 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream,
 
 	audio1 &= ~WM8400_AIF_WL_MASK;
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		audio1 |= WM8400_AIF_WL_20BITS;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		audio1 |= WM8400_AIF_WL_24BITS;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		audio1 |= WM8400_AIF_WL_32BITS;
 		break;
 	}
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 1c1e328feeb8..e11127f9069e 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -449,16 +449,16 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
 	u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1;
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface |= 0x0020;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface |= 0x0040;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		iface |= 0x0060;
 		break;
 	}
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 601ee8178af1..ec1f5740dbd0 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -163,16 +163,16 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream,
 	aifctrl2 |= lrclk_ratios[i].value;
 
 	aifctrl1 &= ~WM8523_WL_MASK;
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		aifctrl1 |= 0x8;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		aifctrl1 |= 0x10;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		aifctrl1 |= 0x18;
 		break;
 	}
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 7665ff6aea6d..911605ee25b0 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -511,19 +511,19 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
 	int i, ratio, osr;
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		paifa |= 0x8;
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		paifa |= 0x0;
 		paifb |= WM8580_AIF_LENGTH_20;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		paifa |= 0x0;
 		paifb |= WM8580_AIF_LENGTH_24;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		paifa |= 0x0;
 		paifb |= WM8580_AIF_LENGTH_32;
 		break;
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index b0fbcb377baf..32187e739b4f 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -169,13 +169,13 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream,
 	snd_soc_write(codec, WM8711_SRATE, srate);
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface |= 0x0004;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface |= 0x0008;
 		break;
 	}
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index bac7fc28fe71..38ff826f589a 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -94,13 +94,13 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
 
 	dac &= ~0x18;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		dac |= 0x10;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		dac |= 0x08;
 		break;
 	default:
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 5ada61611324..eebb3280bfad 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -348,13 +348,13 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
 	snd_soc_write(codec, WM8731_SRATE, srate);
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface |= 0x0004;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface |= 0x0008;
 		break;
 	}
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
index b27f26cdc049..744a422ecb05 100644
--- a/sound/soc/codecs/wm8737.c
+++ b/sound/soc/codecs/wm8737.c
@@ -367,16 +367,16 @@ static int wm8737_hw_params(struct snd_pcm_substream *substream,
 
 	clocking |= coeff_div[i].usb | (coeff_div[i].sr << WM8737_SR_SHIFT);
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		af |= 0x8;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		af |= 0x10;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		af |= 0x18;
 		break;
 	default:
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index b33542a04607..a237f1627f61 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -241,26 +241,26 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface |= 0x0001;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface |= 0x0002;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		iface |= 0x0003;
 		break;
 	default:
 		dev_dbg(codec->dev, "wm8741_hw_params:    Unsupported bit size param = %d",
-			params_format(params));
+			params_width(params));
 		return -EINVAL;
 	}
 
 	dev_dbg(codec->dev, "wm8741_hw_params:    bit size param = %d",
-		params_format(params));
+		params_width(params));
 
 	snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface);
 	return 0;
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 33990b63d214..67653a2db223 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -586,16 +586,16 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
 	int coeff = get_coeff(wm8750->sysclk, params_rate(params));
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface |= 0x0004;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface |= 0x0008;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		iface |= 0x000c;
 		break;
 	}
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 53e57b4049a8..e54e097f4fcb 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -937,16 +937,16 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
 	u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f;
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		voice |= 0x0004;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		voice |= 0x0008;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		voice |= 0x000c;
 		break;
 	}
@@ -1176,16 +1176,16 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
 		coeff_div[coeff].usb);
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		hifi |= 0x0004;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		hifi |= 0x0008;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		hifi |= 0x000c;
 		break;
 	}
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index c61aeb38efb8..180e7a098726 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -426,16 +426,16 @@ static int wm8770_hw_params(struct snd_pcm_substream *substream,
 	wm8770 = snd_soc_codec_get_drvdata(codec);
 
 	iface = 0;
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface |= 0x10;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface |= 0x20;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		iface |= 0x30;
 		break;
 	}
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index d96e5963ee35..0ea01dfcb6e1 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -270,19 +270,19 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream,
 
 	codec = dai->codec;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		blen = 0x0;
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		blen = 0x1;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		blen = 0x2;
 		break;
 	default:
 		dev_err(dai->dev, "Unsupported word length: %u\n",
-			params_format(params));
+			params_width(params));
 		return -EINVAL;
 	}
 
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index d09fdce57f5a..44a5f1511f0f 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -640,16 +640,16 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
 
 	reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		reg |= 0x20;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		reg |= 0x40;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		reg |= 0x60;
 		break;
 	default:
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index b84940c359a1..aa0984864e76 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -281,8 +281,7 @@ static int wm8903_dcs_event(struct snd_soc_dapm_widget *w,
 static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm,
 				enum snd_soc_dapm_type event, int subseq)
 {
-	struct snd_soc_codec *codec = container_of(dapm,
-						   struct snd_soc_codec, dapm);
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
 	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
 	int dcs_mode = WM8903_DCS_MODE_WRITE_STOP;
 	int i, val;
@@ -1477,19 +1476,19 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
 
 	aif1 &= ~WM8903_AIF_WL_MASK;
 	bclk = 2 * fs;
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		bclk *= 16;
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		bclk *= 20;
 		aif1 |= 0x4;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		bclk *= 24;
 		aif1 |= 0x8;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		bclk *= 32;
 		aif1 |= 0xc;
 		break;
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index f7c549949c54..4d2d2b1380d5 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -49,6 +50,7 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
 /* codec private data */
 struct wm8904_priv {
 	struct regmap *regmap;
+	struct clk *mclk;
 
 	enum wm8904_type devtype;
 
@@ -1290,16 +1292,16 @@ static int wm8904_hw_params(struct snd_pcm_substream *substream,
 		wm8904->bclk = snd_soc_params_to_bclk(params);
 	}
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		aif1 |= 0x40;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		aif1 |= 0x80;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		aif1 |= 0xc0;
 		break;
 	default:
@@ -1828,6 +1830,7 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec,
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
+		clk_prepare_enable(wm8904->mclk);
 		break;
 
 	case SND_SOC_BIAS_PREPARE:
@@ -1894,6 +1897,7 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec,
 
 		regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies),
 				       wm8904->supplies);
+		clk_disable_unprepare(wm8904->mclk);
 		break;
 	}
 	codec->dapm.bias_level = level;
@@ -2013,12 +2017,8 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
 		/* We need an array of texts for the enum API */
 		wm8904->drc_texts = kmalloc(sizeof(char *)
 					    * pdata->num_drc_cfgs, GFP_KERNEL);
-		if (!wm8904->drc_texts) {
-			dev_err(codec->dev,
-				"Failed to allocate %d DRC config texts\n",
-				pdata->num_drc_cfgs);
+		if (!wm8904->drc_texts)
 			return;
-		}
 
 		for (i = 0; i < pdata->num_drc_cfgs; i++)
 			wm8904->drc_texts[i] = pdata->drc_cfgs[i].name;
@@ -2110,6 +2110,13 @@ static int wm8904_i2c_probe(struct i2c_client *i2c,
 	if (wm8904 == NULL)
 		return -ENOMEM;
 
+	wm8904->mclk = devm_clk_get(&i2c->dev, "mclk");
+	if (IS_ERR(wm8904->mclk)) {
+		ret = PTR_ERR(wm8904->mclk);
+		dev_err(&i2c->dev, "Failed to get MCLK\n");
+		return ret;
+	}
+
 	wm8904->regmap = devm_regmap_init_i2c(i2c, &wm8904_regmap);
 	if (IS_ERR(wm8904->regmap)) {
 		ret = PTR_ERR(wm8904->regmap);
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index fc6eec9ad66b..52011043e54c 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -430,19 +430,19 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
 	if (ret)
 		goto error_ret;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S8:
+	switch (params_width(params)) {
+	case 8:
 		companding = companding | (1 << 5);
 		break;
-	case SNDRV_PCM_FORMAT_S16_LE:
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface |= (1 << 5);
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface |= (2 << 5);
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		iface |= (3 << 5);
 		break;
 	}
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 2a35108f233d..09d91d9dc4ee 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -597,17 +597,17 @@ static int wm8955_hw_params(struct snd_pcm_substream *substream,
 	int ret;
 	int wl;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		wl = 0;
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		wl = 0x4;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		wl = 0x8;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		wl = 0xc;
 		break;
 	default:
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index b2ebb104d879..0dada7f0105e 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -934,12 +934,8 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
 		/* We need an array of texts for the enum API */
 		wm8994->mbc_texts = kmalloc(sizeof(char *)
 					    * pdata->num_mbc_cfgs, GFP_KERNEL);
-		if (!wm8994->mbc_texts) {
-			dev_err(wm8994->hubs.codec->dev,
-				"Failed to allocate %d MBC config texts\n",
-				pdata->num_mbc_cfgs);
+		if (!wm8994->mbc_texts)
 			return;
-		}
 
 		for (i = 0; i < pdata->num_mbc_cfgs; i++)
 			wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name;
@@ -963,12 +959,8 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
 		/* We need an array of texts for the enum API */
 		wm8994->vss_texts = kmalloc(sizeof(char *)
 					    * pdata->num_vss_cfgs, GFP_KERNEL);
-		if (!wm8994->vss_texts) {
-			dev_err(wm8994->hubs.codec->dev,
-				"Failed to allocate %d VSS config texts\n",
-				pdata->num_vss_cfgs);
+		if (!wm8994->vss_texts)
 			return;
-		}
 
 		for (i = 0; i < pdata->num_vss_cfgs; i++)
 			wm8994->vss_texts[i] = pdata->vss_cfgs[i].name;
@@ -993,12 +985,8 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
 		/* We need an array of texts for the enum API */
 		wm8994->vss_hpf_texts = kmalloc(sizeof(char *)
 						* pdata->num_vss_hpf_cfgs, GFP_KERNEL);
-		if (!wm8994->vss_hpf_texts) {
-			dev_err(wm8994->hubs.codec->dev,
-				"Failed to allocate %d VSS HPF config texts\n",
-				pdata->num_vss_hpf_cfgs);
+		if (!wm8994->vss_hpf_texts)
 			return;
-		}
 
 		for (i = 0; i < pdata->num_vss_hpf_cfgs; i++)
 			wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name;
@@ -1024,12 +1012,8 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
 		/* We need an array of texts for the enum API */
 		wm8994->enh_eq_texts = kmalloc(sizeof(char *)
 						* pdata->num_enh_eq_cfgs, GFP_KERNEL);
-		if (!wm8994->enh_eq_texts) {
-			dev_err(wm8994->hubs.codec->dev,
-				"Failed to allocate %d enhanced EQ config texts\n",
-				pdata->num_enh_eq_cfgs);
+		if (!wm8994->enh_eq_texts)
 			return;
-		}
 
 		for (i = 0; i < pdata->num_enh_eq_cfgs; i++)
 			wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name;
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index a145d0431b63..4dc4e85116cd 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -472,7 +472,7 @@ static int wm8960_add_widgets(struct snd_soc_codec *codec)
 	 * list each time to find the desired power state do so now
 	 * and save the result.
 	 */
-	list_for_each_entry(w, &codec->card->widgets, list) {
+	list_for_each_entry(w, &codec->component.card->widgets, list) {
 		if (w->dapm != &codec->dapm)
 			continue;
 		if (strcmp(w->name, "LOUT1 PGA") == 0)
@@ -567,24 +567,21 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_codec *codec = dai->codec;
 	struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
 	u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3;
-	snd_pcm_format_t format = params_format(params);
 	int i;
 
 	/* bit size */
-	switch (format) {
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
+	case 20:
 		iface |= 0x0004;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
+	case 24:
 		iface |= 0x0008;
 		break;
 	default:
-		dev_err(codec->dev, "unsupported format %i\n", format);
+		dev_err(codec->dev, "unsupported width %d\n",
+			params_width(params));
 		return -EINVAL;
 	}
 
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 9c88f04442b3..41d23e920ad5 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -565,16 +565,16 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream,
 
 	reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0);
 	reg &= ~WM8961_WL_MASK;
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		reg |= 1 << WM8961_WL_SHIFT;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		reg |= 2 << WM8961_WL_SHIFT;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		reg |= 3 << WM8961_WL_SHIFT;
 		break;
 	default:
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index ca2fda9d72be..1098ae32f1f9 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/gcd.h>
@@ -2586,16 +2587,16 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
 	if (wm8962->lrclk % 8000 == 0)
 		adctl3 |= WM8962_SAMPLE_RATE_INT_MODE;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		aif0 |= 0x4;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		aif0 |= 0x8;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		aif0 |= 0xc;
 		break;
 	default:
@@ -3541,6 +3542,8 @@ static int wm8962_set_pdata_from_of(struct i2c_client *i2c,
 				pdata->gpio_init[i] = 0x0;
 		}
 
+	pdata->mclk = devm_clk_get(&i2c->dev, NULL);
+
 	return 0;
 }
 
@@ -3572,6 +3575,14 @@ static int wm8962_i2c_probe(struct i2c_client *i2c,
 			return ret;
 	}
 
+	/* Mark the mclk pointer to NULL if no mclk assigned */
+	if (IS_ERR(wm8962->pdata.mclk)) {
+		/* But do not ignore the request for probe defer */
+		if (PTR_ERR(wm8962->pdata.mclk) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		wm8962->pdata.mclk = NULL;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
 		wm8962->supplies[i].supply = wm8962_supply_names[i];
 
@@ -3780,6 +3791,12 @@ static int wm8962_runtime_resume(struct device *dev)
 	struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
 	int ret;
 
+	ret = clk_prepare_enable(wm8962->pdata.mclk);
+	if (ret) {
+		dev_err(dev, "Failed to enable MCLK: %d\n", ret);
+		return ret;
+	}
+
 	ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
 				    wm8962->supplies);
 	if (ret != 0) {
@@ -3839,6 +3856,8 @@ static int wm8962_runtime_suspend(struct device *dev)
 	regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
 			       wm8962->supplies);
 
+	clk_disable_unprepare(wm8962->pdata.mclk);
+
 	return 0;
 }
 #endif
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 09b7b4200221..0499cd4cfb71 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -517,16 +517,16 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
 	int coeff = get_coeff(wm8971->sysclk, params_rate(params));
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface |= 0x0004;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface |= 0x0008;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		iface |= 0x000c;
 		break;
 	}
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 0627c56fa44e..682e9eda1019 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -445,16 +445,16 @@ static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream,
 	u16 adn = snd_soc_read(codec, WM8974_ADD) & 0x1f1;
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface |= 0x0020;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface |= 0x0040;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		iface |= 0x0060;
 		break;
 	}
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 28ef46c91f62..ee2ba574952b 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -736,16 +736,16 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface_ctl |= 0x20;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface_ctl |= 0x40;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		iface_ctl |= 0x60;
 		break;
 	}
@@ -817,8 +817,8 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream,
 			wm8978->sysclk == WM8978_MCLK ?
 			", consider using PLL" : "");
 
-	dev_dbg(codec->dev, "%s: fmt %d, rate %u, MCLK divisor #%d\n", __func__,
-		params_format(params), params_rate(params), best);
+	dev_dbg(codec->dev, "%s: width %d, rate %u, MCLK divisor #%d\n", __func__,
+		params_width(params), params_rate(params), best);
 
 	/* MCLK divisor mask = 0xe0 */
 	snd_soc_update_bits(codec, WM8978_CLOCKING, 0xe0, best << 5);
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index 19d5baa38f5c..ac5defda8824 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -719,22 +719,22 @@ static int wm8983_hw_params(struct snd_pcm_substream *substream,
 
 	wm8983->bclk = ret;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		blen = 0x0;
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		blen = 0x1;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		blen = 0x2;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		blen = 0x3;
 		break;
 	default:
 		dev_err(dai->dev, "Unsupported word length %u\n",
-			params_format(params));
+			params_width(params));
 		return -EINVAL;
 	}
 
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index 0f5780c09f3a..ee380190399f 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -698,22 +698,22 @@ static int wm8985_hw_params(struct snd_pcm_substream *substream,
 	if ((int)wm8985->bclk < 0)
 		return wm8985->bclk;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		blen = 0x0;
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		blen = 0x1;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		blen = 0x2;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		blen = 0x3;
 		break;
 	default:
 		dev_err(dai->dev, "Unsupported word length %u\n",
-			params_format(params));
+			params_width(params));
 		return -EINVAL;
 	}
 
@@ -980,9 +980,6 @@ static int wm8985_resume(struct snd_soc_codec *codec)
 
 static int wm8985_remove(struct snd_soc_codec *codec)
 {
-	struct wm8985_priv *wm8985;
-
-	wm8985 = snd_soc_codec_get_drvdata(codec);
 	wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
 }
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index d3fea46d58e8..a5130d965146 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -687,16 +687,16 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		iface |= 0x0004;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		iface |= 0x0008;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		iface |= 0x000c;
 		break;
 	}
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index b5c1f0f07058..03e43e3f395e 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -1073,16 +1073,16 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
 
 	audio1 &= ~WM8990_AIF_WL_MASK;
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		audio1 |= WM8990_AIF_WL_20BITS;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		audio1 |= WM8990_AIF_WL_24BITS;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		audio1 |= WM8990_AIF_WL_32BITS;
 		break;
 	}
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index b8fd284fc0c0..d0be89731cdb 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -1081,16 +1081,16 @@ static int wm8991_hw_params(struct snd_pcm_substream *substream,
 
 	audio1 &= ~WM8991_AIF_WL_MASK;
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		audio1 |= WM8991_AIF_WL_20BITS;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		audio1 |= WM8991_AIF_WL_24BITS;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		audio1 |= WM8991_AIF_WL_32BITS;
 		break;
 	}
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index f825dc04ebe1..93b14eda355a 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -1214,19 +1214,19 @@ static int wm8993_hw_params(struct snd_pcm_substream *substream,
 			wm8993->tdm_slots, wm8993->tdm_width);
 		wm8993->bclk *= wm8993->tdm_width * wm8993->tdm_slots;
 	} else {
-		switch (params_format(params)) {
-		case SNDRV_PCM_FORMAT_S16_LE:
+		switch (params_width(params)) {
+		case 16:
 			wm8993->bclk *= 16;
 			break;
-		case SNDRV_PCM_FORMAT_S20_3LE:
+		case 20:
 			wm8993->bclk *= 20;
 			aif1 |= 0x8;
 			break;
-		case SNDRV_PCM_FORMAT_S24_LE:
+		case 24:
 			wm8993->bclk *= 24;
 			aif1 |= 0x10;
 			break;
-		case SNDRV_PCM_FORMAT_S32_LE:
+		case 32:
 			wm8993->bclk *= 32;
 			aif1 |= 0x18;
 			break;
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 247b39013fba..6cc0566dc29a 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -2815,19 +2815,19 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	bclk_rate = params_rate(params);
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		bclk_rate *= 16;
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		bclk_rate *= 20;
 		aif1 |= 0x20;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		bclk_rate *= 24;
 		aif1 |= 0x40;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		bclk_rate *= 32;
 		aif1 |= 0x60;
 		break;
@@ -2966,16 +2966,16 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream,
 		return 0;
 	}
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		aif1 |= 0x20;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		aif1 |= 0x40;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		aif1 |= 0x60;
 		break;
 	default:
@@ -3296,12 +3296,8 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
 		/* We need an array of texts for the enum API */
 		wm8994->drc_texts = devm_kzalloc(wm8994->hubs.codec->dev,
 			    sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL);
-		if (!wm8994->drc_texts) {
-			dev_err(wm8994->hubs.codec->dev,
-				"Failed to allocate %d DRC config texts\n",
-				pdata->num_drc_cfgs);
+		if (!wm8994->drc_texts)
 			return;
-		}
 
 		for (i = 0; i < pdata->num_drc_cfgs; i++)
 			wm8994->drc_texts[i] = pdata->drc_cfgs[i].name;
@@ -3505,6 +3501,7 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+/* Should be called with accdet_lock held */
 static void wm1811_micd_stop(struct snd_soc_codec *codec)
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
@@ -3512,14 +3509,10 @@ static void wm1811_micd_stop(struct snd_soc_codec *codec)
 	if (!wm8994->jackdet)
 		return;
 
-	mutex_lock(&wm8994->accdet_lock);
-
 	snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0);
 
 	wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK);
 
-	mutex_unlock(&wm8994->accdet_lock);
-
 	if (wm8994->wm8994->pdata.jd_ext_cap)
 		snd_soc_dapm_disable_pin(&codec->dapm,
 					 "MICBIAS2");
@@ -3560,10 +3553,10 @@ static void wm8958_open_circuit_work(struct work_struct *work)
 						  open_circuit_work.work);
 	struct device *dev = wm8994->wm8994->dev;
 
-	wm1811_micd_stop(wm8994->hubs.codec);
-
 	mutex_lock(&wm8994->accdet_lock);
 
+	wm1811_micd_stop(wm8994->hubs.codec);
+
 	dev_dbg(dev, "Reporting open circuit\n");
 
 	wm8994->jack_mic = false;
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 863a2c38bcb5..cae4ac5a5730 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -1597,21 +1597,21 @@ static int wm8995_hw_params(struct snd_pcm_substream *substream,
 		return bclk_rate;
 
 	aif1 = 0;
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		aif1 |= (0x1 << WM8995_AIF1_WL_SHIFT);
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		aif1 |= (0x2 << WM8995_AIF1_WL_SHIFT);
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		aif1 |= (0x3 << WM8995_AIF1_WL_SHIFT);
 		break;
 	default:
 		dev_err(dai->dev, "Unsupported word length %u\n",
-			params_format(params));
+			params_width(params));
 		return -EINVAL;
 	}
 
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 69266332760e..f16ff4f56923 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -620,15 +620,12 @@ static int bg_event(struct snd_soc_dapm_widget *w,
 static int cp_event(struct snd_soc_dapm_widget *w,
 		    struct snd_kcontrol *kcontrol, int event)
 {
-	int ret = 0;
-
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
 		msleep(5);
 		break;
 	default:
 		WARN(1, "Invalid event %d\n", event);
-		ret = -EINVAL;
 	}
 
 	return 0;
@@ -690,8 +687,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask)
 static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
 				enum snd_soc_dapm_type event, int subseq)
 {
-	struct snd_soc_codec *codec = container_of(dapm,
-						   struct snd_soc_codec, dapm);
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
 	struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
 	u16 val, mask;
 
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c
index bb9b47b956aa..ab33fe596519 100644
--- a/sound/soc/codecs/wm8997.c
+++ b/sound/soc/codecs/wm8997.c
@@ -967,6 +967,7 @@ static struct snd_soc_dai_driver wm8997_dai[] = {
 		 },
 		.ops = &arizona_dai_ops,
 		.symmetric_rates = 1,
+		.symmetric_samplebits = 1,
 	},
 	{
 		.name = "wm8997-aif2",
@@ -988,6 +989,7 @@ static struct snd_soc_dai_driver wm8997_dai[] = {
 		 },
 		.ops = &arizona_dai_ops,
 		.symmetric_rates = 1,
+		.symmetric_samplebits = 1,
 	},
 	{
 		.name = "wm8997-slim1",
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 185eb97769e7..0cdc9e2184ab 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -1029,19 +1029,19 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream,
 		/* Otherwise work out a BCLK from the sample size */
 		wm9081->bclk = 2 * wm9081->fs;
 
-		switch (params_format(params)) {
-		case SNDRV_PCM_FORMAT_S16_LE:
+		switch (params_width(params)) {
+		case 16:
 			wm9081->bclk *= 16;
 			break;
-		case SNDRV_PCM_FORMAT_S20_3LE:
+		case 20:
 			wm9081->bclk *= 20;
 			aif2 |= 0x4;
 			break;
-		case SNDRV_PCM_FORMAT_S24_LE:
+		case 24:
 			wm9081->bclk *= 24;
 			aif2 |= 0x8;
 			break;
-		case SNDRV_PCM_FORMAT_S32_LE:
+		case 32:
 			wm9081->bclk *= 32;
 			aif2 |= 0xc;
 			break;
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 87934171f063..a13f0725611a 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -613,10 +613,8 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
 	int ret;
 
 	wm9090 = devm_kzalloc(&i2c->dev, sizeof(*wm9090), GFP_KERNEL);
-	if (wm9090 == NULL) {
-		dev_err(&i2c->dev, "Can not allocate memory\n");
+	if (!wm9090)
 		return -ENOMEM;
-	}
 
 	wm9090->regmap = devm_regmap_init_i2c(i2c, &wm9090_regmap);
 	if (IS_ERR(wm9090->regmap)) {
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 2a9c6d11330c..bddee30a4bc7 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -953,16 +953,16 @@ static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_codec *codec = dai->codec;
 	u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		reg |= 0x0004;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		reg |= 0x0008;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		reg |= 0x000c;
 		break;
 	}
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 060027182dcb..f412a9911a75 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -1382,7 +1382,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
 	int ret;
 	int val;
 
-	dsp->card = codec->card;
+	dsp->card = codec->component.card;
 
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
@@ -1617,7 +1617,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
 	struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
 	struct wm_adsp *dsp = &dsps[w->shift];
 
-	dsp->card = codec->card;
+	dsp->card = codec->component.card;
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
@@ -1758,3 +1758,5 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(wm_adsp2_init);
+
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 916817fe6632..374537d5e179 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -183,10 +183,8 @@ static void wm_hubs_dcs_cache_set(struct snd_soc_codec *codec, u16 dcs_cfg)
 		return;
 
 	cache = devm_kzalloc(codec->dev, sizeof(*cache), GFP_KERNEL);
-	if (!cache) {
-		dev_err(codec->dev, "Failed to allocate DCS cache entry\n");
+	if (!cache)
 		return;
-	}
 
 	cache->left = snd_soc_read(codec, WM8993_LEFT_OUTPUT_VOLUME);
 	cache->left &= WM8993_HPOUT1L_VOL_MASK;
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 50a098749b9e..d69510c53239 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -1,12 +1,29 @@
 config SND_DAVINCI_SOC
-	tristate "SoC Audio for TI DAVINCI or AM33XX/AM43XX chips"
-	depends on ARCH_DAVINCI || SOC_AM33XX || SOC_AM43XX
+	tristate "SoC Audio for TI DAVINCI"
+	depends on ARCH_DAVINCI
+
+config SND_EDMA_SOC
+	tristate "SoC Audio for Texas Instruments chips using eDMA (AM33XX/43XX)"
+	depends on SOC_AM33XX || SOC_AM43XX
+	select SND_SOC_GENERIC_DMAENGINE_PCM
+	help
+	  Say Y or M here if you want audio support for TI SoC which uses eDMA.
+	  The following line of SoCs are supported by this platform driver:
+	  - AM335x
+	  - AM437x/AM438x
 
 config SND_DAVINCI_SOC_I2S
 	tristate
 
 config SND_DAVINCI_SOC_MCASP
-	tristate
+	tristate "Multichannel Audio Serial Port (McASP) support"
+	depends on SND_DAVINCI_SOC || SND_OMAP_SOC || SND_EDMA_SOC
+	help
+	  Say Y or M here if you want to have support for McASP IP found in
+	  various Texas Instruments SoCs like:
+	  - daVinci devices
+	  - Sitara line of SoCs (AM335x, AM438x, etc)
+	  - DRA7x devices
 
 config SND_DAVINCI_SOC_VCIF
 	tristate
@@ -18,7 +35,7 @@ config SND_DAVINCI_SOC_GENERIC_EVM
 
 config SND_AM33XX_SOC_EVM
 	tristate "SoC Audio for the AM33XX chip based boards"
-	depends on SND_DAVINCI_SOC && SOC_AM33XX && I2C
+	depends on SND_EDMA_SOC && SOC_AM33XX && I2C
 	select SND_DAVINCI_SOC_GENERIC_EVM
 	help
 	  Say Y or M if you want to add support for SoC audio on AM33XX
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
index 744d4d9a0184..09bf2ba92d38 100644
--- a/sound/soc/davinci/Makefile
+++ b/sound/soc/davinci/Makefile
@@ -1,10 +1,12 @@
 # DAVINCI Platform Support
 snd-soc-davinci-objs := davinci-pcm.o
+snd-soc-edma-objs := edma-pcm.o
 snd-soc-davinci-i2s-objs := davinci-i2s.o
 snd-soc-davinci-mcasp-objs:= davinci-mcasp.o
 snd-soc-davinci-vcif-objs:= davinci-vcif.o
 
 obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
+obj-$(CONFIG_SND_EDMA_SOC) += snd-soc-edma.o
 obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
 obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o
 obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 9afb14629a17..c28508da34cf 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -27,6 +27,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 
+#include <sound/asoundef.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -36,6 +37,7 @@
 #include <sound/omap-pcm.h>
 
 #include "davinci-pcm.h"
+#include "edma-pcm.h"
 #include "davinci-mcasp.h"
 
 #define MCASP_MAX_AFIFO_DEPTH	64
@@ -63,6 +65,7 @@ struct davinci_mcasp {
 	u8	num_serializer;
 	u8	*serial_dir;
 	u8	version;
+	u8	bclk_div;
 	u16	bclk_lrclk_ratio;
 	int	streams;
 
@@ -417,6 +420,7 @@ static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div
 			       ACLKXDIV(div - 1), ACLKXDIV_MASK);
 		mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG,
 			       ACLKRDIV(div - 1), ACLKRDIV_MASK);
+		mcasp->bclk_div = div;
 		break;
 
 	case 2:		/* BCLK/LRCLK ratio */
@@ -637,8 +641,12 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream)
 }
 
 /* S/PDIF */
-static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp)
+static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
+			      unsigned int rate)
 {
+	u32 cs_value = 0;
+	u8 *cs_bytes = (u8*) &cs_value;
+
 	/* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
 	   and LSB first */
 	mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15));
@@ -660,6 +668,46 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp)
 	/* Enable the DIT */
 	mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN);
 
+	/* Set S/PDIF channel status bits */
+	cs_bytes[0] = IEC958_AES0_CON_NOT_COPYRIGHT;
+	cs_bytes[1] = IEC958_AES1_CON_PCM_CODER;
+
+	switch (rate) {
+	case 22050:
+		cs_bytes[3] |= IEC958_AES3_CON_FS_22050;
+		break;
+	case 24000:
+		cs_bytes[3] |= IEC958_AES3_CON_FS_24000;
+		break;
+	case 32000:
+		cs_bytes[3] |= IEC958_AES3_CON_FS_32000;
+		break;
+	case 44100:
+		cs_bytes[3] |= IEC958_AES3_CON_FS_44100;
+		break;
+	case 48000:
+		cs_bytes[3] |= IEC958_AES3_CON_FS_48000;
+		break;
+	case 88200:
+		cs_bytes[3] |= IEC958_AES3_CON_FS_88200;
+		break;
+	case 96000:
+		cs_bytes[3] |= IEC958_AES3_CON_FS_96000;
+		break;
+	case 176400:
+		cs_bytes[3] |= IEC958_AES3_CON_FS_176400;
+		break;
+	case 192000:
+		cs_bytes[3] |= IEC958_AES3_CON_FS_192000;
+		break;
+	default:
+		printk(KERN_WARNING "unsupported sampling rate: %d\n", rate);
+		return -EINVAL;
+	}
+
+	mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRA_REG, cs_value);
+	mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRB_REG, cs_value);
+
 	return 0;
 }
 
@@ -675,15 +723,22 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 	int period_size = params_period_size(params);
 	int ret;
 
-	/* If mcasp is BCLK master we need to set BCLK divider */
-	if (mcasp->bclk_master) {
+	/*
+	 * If mcasp is BCLK master, and a BCLK divider was not provided by
+	 * the machine driver, we need to calculate the ratio.
+	 */
+	if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) {
 		unsigned int bclk_freq = snd_soc_params_to_bclk(params);
+		unsigned int div = mcasp->sysclk_freq / bclk_freq;
 		if (mcasp->sysclk_freq % bclk_freq != 0) {
-			dev_err(mcasp->dev, "Can't produce required BCLK\n");
-			return -EINVAL;
+			if (((mcasp->sysclk_freq / div) - bclk_freq) >
+			    (bclk_freq - (mcasp->sysclk_freq / (div+1))))
+				div++;
+			dev_warn(mcasp->dev,
+				 "Inaccurate BCLK: %u Hz / %u != %u Hz\n",
+				 mcasp->sysclk_freq, div, bclk_freq);
 		}
-		davinci_mcasp_set_clkdiv(
-			cpu_dai, 1, mcasp->sysclk_freq / bclk_freq);
+		davinci_mcasp_set_clkdiv(cpu_dai, 1, div);
 	}
 
 	ret = mcasp_common_hw_param(mcasp, substream->stream,
@@ -692,7 +747,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 		return ret;
 
 	if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
-		ret = mcasp_dit_hw_param(mcasp);
+		ret = mcasp_dit_hw_param(mcasp, params_rate(params));
 	else
 		ret = mcasp_i2s_hw_param(mcasp, substream->stream);
 
@@ -720,6 +775,10 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 
 	case SNDRV_PCM_FORMAT_U24_LE:
 	case SNDRV_PCM_FORMAT_S24_LE:
+		dma_params->data_type = 4;
+		word_length = 24;
+		break;
+
 	case SNDRV_PCM_FORMAT_U32_LE:
 	case SNDRV_PCM_FORMAT_S32_LE:
 		dma_params->data_type = 4;
@@ -778,7 +837,7 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai)
 {
 	struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
 
-	if (mcasp->version == MCASP_VERSION_4) {
+	if (mcasp->version >= MCASP_VERSION_3) {
 		/* Using dmaengine PCM */
 		dai->playback_dma_data =
 				&mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
@@ -1223,14 +1282,28 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 		goto err;
 
 	switch (mcasp->version) {
+#if IS_BUILTIN(CONFIG_SND_DAVINCI_SOC) || \
+	(IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \
+	 IS_MODULE(CONFIG_SND_DAVINCI_SOC))
 	case MCASP_VERSION_1:
 	case MCASP_VERSION_2:
-	case MCASP_VERSION_3:
 		ret = davinci_soc_platform_register(&pdev->dev);
 		break;
+#endif
+#if IS_BUILTIN(CONFIG_SND_EDMA_SOC) || \
+	(IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \
+	 IS_MODULE(CONFIG_SND_EDMA_SOC))
+	case MCASP_VERSION_3:
+		ret = edma_pcm_platform_register(&pdev->dev);
+		break;
+#endif
+#if IS_BUILTIN(CONFIG_SND_OMAP_SOC) || \
+	(IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \
+	 IS_MODULE(CONFIG_SND_OMAP_SOC))
 	case MCASP_VERSION_4:
 		ret = omap_pcm_platform_register(&pdev->dev);
 		break;
+#endif
 	default:
 		dev_err(&pdev->dev, "Invalid McASP version: %d\n",
 			mcasp->version);
diff --git a/sound/soc/davinci/edma-pcm.c b/sound/soc/davinci/edma-pcm.c
index d38afb1c61ae..605e643133db 100644
--- a/sound/soc/davinci/edma-pcm.c
+++ b/sound/soc/davinci/edma-pcm.c
@@ -28,8 +28,8 @@
 static const struct snd_pcm_hardware edma_pcm_hardware = {
 	.info			= SNDRV_PCM_INFO_MMAP |
 				  SNDRV_PCM_INFO_MMAP_VALID |
-				  SNDRV_PCM_INFO_BATCH |
 				  SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
+				  SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
 				  SNDRV_PCM_INFO_INTERLEAVED,
 	.buffer_bytes_max	= 128 * 1024,
 	.period_bytes_min	= 32,
diff --git a/sound/soc/davinci/edma-pcm.h b/sound/soc/davinci/edma-pcm.h
index 894c378c0f74..b0957744851c 100644
--- a/sound/soc/davinci/edma-pcm.h
+++ b/sound/soc/davinci/edma-pcm.h
@@ -20,6 +20,13 @@
 #ifndef __EDMA_PCM_H__
 #define __EDMA_PCM_H__
 
+#if IS_ENABLED(CONFIG_SND_EDMA_SOC)
 int edma_pcm_platform_register(struct device *dev);
+#else
+static inline int edma_pcm_platform_register(struct device *dev)
+{
+	return 0;
+}
+#endif /* CONFIG_SND_EDMA_SOC */
 
 #endif /* __EDMA_PCM_H__ */
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 37933629cbed..f54a8fc99291 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -2,9 +2,20 @@ menu "SoC Audio for Freescale CPUs"
 
 comment "Common SoC Audio options for Freescale CPUs:"
 
+config SND_SOC_FSL_ASRC
+	tristate "Asynchronous Sample Rate Converter (ASRC) module support"
+	select REGMAP_MMIO
+	select SND_SOC_GENERIC_DMAENGINE_PCM
+	help
+	  Say Y if you want to add Asynchronous Sample Rate Converter (ASRC)
+	  support for the Freescale CPUs.
+	  This option is only useful for out-of-tree drivers since
+	  in-tree drivers select it automatically.
+
 config SND_SOC_FSL_SAI
 	tristate "Synchronous Audio Interface (SAI) module support"
 	select REGMAP_MMIO
+	select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n
 	select SND_SOC_GENERIC_DMAENGINE_PCM
 	help
 	  Say Y if you want to add Synchronous Audio Interface (SAI)
@@ -15,7 +26,7 @@ config SND_SOC_FSL_SAI
 config SND_SOC_FSL_SSI
 	tristate "Synchronous Serial Interface module support"
 	select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n
-	select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && ARCH_MXC
+	select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && (MXC_TZIC || MXC_AVIC)
 	select REGMAP_MMIO
 	help
 	  Say Y if you want to add Synchronous Serial Interface (SSI)
@@ -27,7 +38,7 @@ config SND_SOC_FSL_SPDIF
 	tristate "Sony/Philips Digital Interface module support"
 	select REGMAP_MMIO
 	select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n
-	select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && ARCH_MXC
+	select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && (MXC_TZIC || MXC_AVIC)
 	help
 	  Say Y if you want to add Sony/Philips Digital Interface (SPDIF)
 	  support for the Freescale CPUs.
@@ -37,6 +48,7 @@ config SND_SOC_FSL_SPDIF
 config SND_SOC_FSL_ESAI
 	tristate "Enhanced Serial Audio Interface (ESAI) module support"
 	select REGMAP_MMIO
+	select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n
 	select SND_SOC_FSL_UTILS
 	help
 	  Say Y if you want to add Enhanced Synchronous Audio Interface
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index db254e358c18..9ff59267eac9 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -11,6 +11,7 @@ snd-soc-p1022-rdk-objs := p1022_rdk.o
 obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
 
 # Freescale SSI/DMA/SAI/SPDIF Support
+snd-soc-fsl-asrc-objs := fsl_asrc.o fsl_asrc_dma.o
 snd-soc-fsl-sai-objs := fsl_sai.o
 snd-soc-fsl-ssi-y := fsl_ssi.o
 snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o
@@ -18,6 +19,7 @@ snd-soc-fsl-spdif-objs := fsl_spdif.o
 snd-soc-fsl-esai-objs := fsl_esai.o
 snd-soc-fsl-utils-objs := fsl_utils.o
 snd-soc-fsl-dma-objs := fsl_dma.o
+obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o
 obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o
 obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o
 obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
new file mode 100644
index 000000000000..822110420b71
--- /dev/null
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -0,0 +1,995 @@
+/*
+ * Freescale ASRC ALSA SoC Digital Audio Interface (DAI) driver
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Nicolin Chen <nicoleotsuka@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_data/dma-imx.h>
+#include <linux/pm_runtime.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm_params.h>
+
+#include "fsl_asrc.h"
+
+#define IDEAL_RATIO_DECIMAL_DEPTH 26
+
+#define pair_err(fmt, ...) \
+	dev_err(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
+
+#define pair_dbg(fmt, ...) \
+	dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
+
+/* Sample rates are aligned with that defined in pcm.h file */
+static const u8 process_option[][8][2] = {
+	/* 32kHz 44.1kHz 48kHz   64kHz   88.2kHz 96kHz   176kHz  192kHz */
+	{{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},	/* 5512Hz */
+	{{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},	/* 8kHz */
+	{{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},	/* 11025Hz */
+	{{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},	/* 16kHz */
+	{{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},	/* 22050Hz */
+	{{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},},	/* 32kHz */
+	{{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},},	/* 44.1kHz */
+	{{0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},},	/* 48kHz */
+	{{1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},},	/* 64kHz */
+	{{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},},	/* 88.2kHz */
+	{{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},},	/* 96kHz */
+	{{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},},	/* 176kHz */
+	{{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},},	/* 192kHz */
+};
+
+/* Corresponding to process_option */
+static int supported_input_rate[] = {
+	5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200,
+	96000, 176400, 192000,
+};
+
+static int supported_asrc_rate[] = {
+	32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000,
+};
+
+/**
+ * The following tables map the relationship between asrc_inclk/asrc_outclk in
+ * fsl_asrc.h and the registers of ASRCSR
+ */
+static unsigned char input_clk_map_imx35[] = {
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
+};
+
+static unsigned char output_clk_map_imx35[] = {
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
+};
+
+/* i.MX53 uses the same map for input and output */
+static unsigned char input_clk_map_imx53[] = {
+/*	0x0  0x1  0x2  0x3  0x4  0x5  0x6  0x7  0x8  0x9  0xa  0xb  0xc  0xd  0xe  0xf */
+	0x0, 0x1, 0x2, 0x7, 0x4, 0x5, 0x6, 0x3, 0x8, 0x9, 0xa, 0xb, 0xc, 0xf, 0xe, 0xd,
+};
+
+static unsigned char output_clk_map_imx53[] = {
+/*	0x0  0x1  0x2  0x3  0x4  0x5  0x6  0x7  0x8  0x9  0xa  0xb  0xc  0xd  0xe  0xf */
+	0x8, 0x9, 0xa, 0x7, 0xc, 0x5, 0x6, 0xb, 0x0, 0x1, 0x2, 0x3, 0x4, 0xf, 0xe, 0xd,
+};
+
+static unsigned char *clk_map[2];
+
+/**
+ * Request ASRC pair
+ *
+ * It assigns pair by the order of A->C->B because allocation of pair B,
+ * within range [ANCA, ANCA+ANCB-1], depends on the channels of pair A
+ * while pair A and pair C are comparatively independent.
+ */
+static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
+{
+	enum asrc_pair_index index = ASRC_INVALID_PAIR;
+	struct fsl_asrc *asrc_priv = pair->asrc_priv;
+	struct device *dev = &asrc_priv->pdev->dev;
+	unsigned long lock_flags;
+	int i, ret = 0;
+
+	spin_lock_irqsave(&asrc_priv->lock, lock_flags);
+
+	for (i = ASRC_PAIR_A; i < ASRC_PAIR_MAX_NUM; i++) {
+		if (asrc_priv->pair[i] != NULL)
+			continue;
+
+		index = i;
+
+		if (i != ASRC_PAIR_B)
+			break;
+	}
+
+	if (index == ASRC_INVALID_PAIR) {
+		dev_err(dev, "all pairs are busy now\n");
+		ret = -EBUSY;
+	} else if (asrc_priv->channel_avail < channels) {
+		dev_err(dev, "can't afford required channels: %d\n", channels);
+		ret = -EINVAL;
+	} else {
+		asrc_priv->channel_avail -= channels;
+		asrc_priv->pair[index] = pair;
+		pair->channels = channels;
+		pair->index = index;
+	}
+
+	spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
+
+	return ret;
+}
+
+/**
+ * Release ASRC pair
+ *
+ * It clears the resource from asrc_priv and releases the occupied channels.
+ */
+static void fsl_asrc_release_pair(struct fsl_asrc_pair *pair)
+{
+	struct fsl_asrc *asrc_priv = pair->asrc_priv;
+	enum asrc_pair_index index = pair->index;
+	unsigned long lock_flags;
+
+	/* Make sure the pair is disabled */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+			   ASRCTR_ASRCEi_MASK(index), 0);
+
+	spin_lock_irqsave(&asrc_priv->lock, lock_flags);
+
+	asrc_priv->channel_avail += pair->channels;
+	asrc_priv->pair[index] = NULL;
+	pair->error = 0;
+
+	spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
+}
+
+/**
+ * Configure input and output thresholds
+ */
+static void fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 out)
+{
+	struct fsl_asrc *asrc_priv = pair->asrc_priv;
+	enum asrc_pair_index index = pair->index;
+
+	regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index),
+			   ASRMCRi_EXTTHRSHi_MASK |
+			   ASRMCRi_INFIFO_THRESHOLD_MASK |
+			   ASRMCRi_OUTFIFO_THRESHOLD_MASK,
+			   ASRMCRi_EXTTHRSHi |
+			   ASRMCRi_INFIFO_THRESHOLD(in) |
+			   ASRMCRi_OUTFIFO_THRESHOLD(out));
+}
+
+/**
+ * Calculate the total divisor between asrck clock rate and sample rate
+ *
+ * It follows the formula clk_rate = samplerate * (2 ^ prescaler) * divider
+ */
+static u32 fsl_asrc_cal_asrck_divisor(struct fsl_asrc_pair *pair, u32 div)
+{
+	u32 ps;
+
+	/* Calculate the divisors: prescaler [2^0, 2^7], divder [1, 8] */
+	for (ps = 0; div > 8; ps++)
+		div >>= 1;
+
+	return ((div - 1) << ASRCDRi_AxCPi_WIDTH) | ps;
+}
+
+/**
+ * Calculate and set the ratio for Ideal Ratio mode only
+ *
+ * The ratio is a 32-bit fixed point value with 26 fractional bits.
+ */
+static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair,
+				    int inrate, int outrate)
+{
+	struct fsl_asrc *asrc_priv = pair->asrc_priv;
+	enum asrc_pair_index index = pair->index;
+	unsigned long ratio;
+	int i;
+
+	if (!outrate) {
+		pair_err("output rate should not be zero\n");
+		return -EINVAL;
+	}
+
+	/* Calculate the intergal part of the ratio */
+	ratio = (inrate / outrate) << IDEAL_RATIO_DECIMAL_DEPTH;
+
+	/* ... and then the 26 depth decimal part */
+	inrate %= outrate;
+
+	for (i = 1; i <= IDEAL_RATIO_DECIMAL_DEPTH; i++) {
+		inrate <<= 1;
+
+		if (inrate < outrate)
+			continue;
+
+		ratio |= 1 << (IDEAL_RATIO_DECIMAL_DEPTH - i);
+		inrate -= outrate;
+
+		if (!inrate)
+			break;
+	}
+
+	regmap_write(asrc_priv->regmap, REG_ASRIDRL(index), ratio);
+	regmap_write(asrc_priv->regmap, REG_ASRIDRH(index), ratio >> 24);
+
+	return 0;
+}
+
+/**
+ * Configure the assigned ASRC pair
+ *
+ * It configures those ASRC registers according to a configuration instance
+ * of struct asrc_config which includes in/output sample rate, width, channel
+ * and clock settings.
+ */
+static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
+{
+	struct asrc_config *config = pair->config;
+	struct fsl_asrc *asrc_priv = pair->asrc_priv;
+	enum asrc_pair_index index = pair->index;
+	u32 inrate, outrate, indiv, outdiv;
+	u32 clk_index[2], div[2];
+	int in, out, channels;
+	struct clk *clk;
+	bool ideal;
+
+	if (!config) {
+		pair_err("invalid pair config\n");
+		return -EINVAL;
+	}
+
+	/* Validate channels */
+	if (config->channel_num < 1 || config->channel_num > 10) {
+		pair_err("does not support %d channels\n", config->channel_num);
+		return -EINVAL;
+	}
+
+	/* Validate output width */
+	if (config->output_word_width == ASRC_WIDTH_8_BIT) {
+		pair_err("does not support 8bit width output\n");
+		return -EINVAL;
+	}
+
+	inrate = config->input_sample_rate;
+	outrate = config->output_sample_rate;
+	ideal = config->inclk == INCLK_NONE;
+
+	/* Validate input and output sample rates */
+	for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++)
+		if (inrate == supported_input_rate[in])
+			break;
+
+	if (in == ARRAY_SIZE(supported_input_rate)) {
+		pair_err("unsupported input sample rate: %dHz\n", inrate);
+		return -EINVAL;
+	}
+
+	for (out = 0; out < ARRAY_SIZE(supported_asrc_rate); out++)
+		if (outrate == supported_asrc_rate[out])
+			break;
+
+	if (out == ARRAY_SIZE(supported_asrc_rate)) {
+		pair_err("unsupported output sample rate: %dHz\n", outrate);
+		return -EINVAL;
+	}
+
+	/* Validate input and output clock sources */
+	clk_index[IN] = clk_map[IN][config->inclk];
+	clk_index[OUT] = clk_map[OUT][config->outclk];
+
+	/* We only have output clock for ideal ratio mode */
+	clk = asrc_priv->asrck_clk[clk_index[ideal ? OUT : IN]];
+
+	div[IN] = clk_get_rate(clk) / inrate;
+	if (div[IN] == 0) {
+		pair_err("failed to support input sample rate %dHz by asrck_%x\n",
+				inrate, clk_index[ideal ? OUT : IN]);
+		return -EINVAL;
+	}
+
+	clk = asrc_priv->asrck_clk[clk_index[OUT]];
+
+	/* Use fixed output rate for Ideal Ratio mode (INCLK_NONE) */
+	if (ideal)
+		div[OUT] = clk_get_rate(clk) / IDEAL_RATIO_RATE;
+	else
+		div[OUT] = clk_get_rate(clk) / outrate;
+
+	if (div[OUT] == 0) {
+		pair_err("failed to support output sample rate %dHz by asrck_%x\n",
+				outrate, clk_index[OUT]);
+		return -EINVAL;
+	}
+
+	/* Set the channel number */
+	channels = config->channel_num;
+
+	if (asrc_priv->channel_bits < 4)
+		channels /= 2;
+
+	/* Update channels for current pair */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRCNCR,
+			   ASRCNCR_ANCi_MASK(index, asrc_priv->channel_bits),
+			   ASRCNCR_ANCi(index, channels, asrc_priv->channel_bits));
+
+	/* Default setting: Automatic selection for processing mode */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+			   ASRCTR_ATSi_MASK(index), ASRCTR_ATS(index));
+	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+			   ASRCTR_USRi_MASK(index), 0);
+
+	/* Set the input and output clock sources */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRCSR,
+			   ASRCSR_AICSi_MASK(index) | ASRCSR_AOCSi_MASK(index),
+			   ASRCSR_AICS(index, clk_index[IN]) |
+			   ASRCSR_AOCS(index, clk_index[OUT]));
+
+	/* Calculate the input clock divisors */
+	indiv = fsl_asrc_cal_asrck_divisor(pair, div[IN]);
+	outdiv = fsl_asrc_cal_asrck_divisor(pair, div[OUT]);
+
+	/* Suppose indiv and outdiv includes prescaler, so add its MASK too */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRCDR(index),
+			   ASRCDRi_AOCPi_MASK(index) | ASRCDRi_AICPi_MASK(index) |
+			   ASRCDRi_AOCDi_MASK(index) | ASRCDRi_AICDi_MASK(index),
+			   ASRCDRi_AOCP(index, outdiv) | ASRCDRi_AICP(index, indiv));
+
+	/* Implement word_width configurations */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRMCR1(index),
+			   ASRMCR1i_OW16_MASK | ASRMCR1i_IWD_MASK,
+			   ASRMCR1i_OW16(config->output_word_width) |
+			   ASRMCR1i_IWD(config->input_word_width));
+
+	/* Enable BUFFER STALL */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index),
+			   ASRMCRi_BUFSTALLi_MASK, ASRMCRi_BUFSTALLi);
+
+	/* Set default thresholds for input and output FIFO */
+	fsl_asrc_set_watermarks(pair, ASRC_INPUTFIFO_THRESHOLD,
+				ASRC_INPUTFIFO_THRESHOLD);
+
+	/* Configure the followings only for Ideal Ratio mode */
+	if (!ideal)
+		return 0;
+
+	/* Clear ASTSx bit to use Ideal Ratio mode */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+			   ASRCTR_ATSi_MASK(index), 0);
+
+	/* Enable Ideal Ratio mode */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+			   ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index),
+			   ASRCTR_IDR(index) | ASRCTR_USR(index));
+
+	/* Apply configurations for pre- and post-processing */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRCFG,
+			   ASRCFG_PREMODi_MASK(index) |	ASRCFG_POSTMODi_MASK(index),
+			   ASRCFG_PREMOD(index, process_option[in][out][0]) |
+			   ASRCFG_POSTMOD(index, process_option[in][out][1]));
+
+	return fsl_asrc_set_ideal_ratio(pair, inrate, outrate);
+}
+
+/**
+ * Start the assigned ASRC pair
+ *
+ * It enables the assigned pair and makes it stopped at the stall level.
+ */
+static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair)
+{
+	struct fsl_asrc *asrc_priv = pair->asrc_priv;
+	enum asrc_pair_index index = pair->index;
+	int reg, retry = 10, i;
+
+	/* Enable the current pair */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+			   ASRCTR_ASRCEi_MASK(index), ASRCTR_ASRCE(index));
+
+	/* Wait for status of initialization */
+	do {
+		udelay(5);
+		regmap_read(asrc_priv->regmap, REG_ASRCFG, &reg);
+		reg &= ASRCFG_INIRQi_MASK(index);
+	} while (!reg && --retry);
+
+	/* Make the input fifo to ASRC STALL level */
+	regmap_read(asrc_priv->regmap, REG_ASRCNCR, &reg);
+	for (i = 0; i < pair->channels * 4; i++)
+		regmap_write(asrc_priv->regmap, REG_ASRDI(index), 0);
+
+	/* Enable overload interrupt */
+	regmap_write(asrc_priv->regmap, REG_ASRIER, ASRIER_AOLIE);
+}
+
+/**
+ * Stop the assigned ASRC pair
+ */
+static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair)
+{
+	struct fsl_asrc *asrc_priv = pair->asrc_priv;
+	enum asrc_pair_index index = pair->index;
+
+	/* Stop the current pair */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+			   ASRCTR_ASRCEi_MASK(index), 0);
+}
+
+/**
+ * Get DMA channel according to the pair and direction.
+ */
+struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir)
+{
+	struct fsl_asrc *asrc_priv = pair->asrc_priv;
+	enum asrc_pair_index index = pair->index;
+	char name[4];
+
+	sprintf(name, "%cx%c", dir == IN ? 'r' : 't', index + 'a');
+
+	return dma_request_slave_channel(&asrc_priv->pdev->dev, name);
+}
+EXPORT_SYMBOL_GPL(fsl_asrc_get_dma_channel);
+
+static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *params,
+				  struct snd_soc_dai *dai)
+{
+	struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai);
+	int width = snd_pcm_format_width(params_format(params));
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct fsl_asrc_pair *pair = runtime->private_data;
+	unsigned int channels = params_channels(params);
+	unsigned int rate = params_rate(params);
+	struct asrc_config config;
+	int word_width, ret;
+
+	ret = fsl_asrc_request_pair(channels, pair);
+	if (ret) {
+		dev_err(dai->dev, "fail to request asrc pair\n");
+		return ret;
+	}
+
+	pair->config = &config;
+
+	if (width == 16)
+		width = ASRC_WIDTH_16_BIT;
+	else
+		width = ASRC_WIDTH_24_BIT;
+
+	if (asrc_priv->asrc_width == 16)
+		word_width = ASRC_WIDTH_16_BIT;
+	else
+		word_width = ASRC_WIDTH_24_BIT;
+
+	config.pair = pair->index;
+	config.channel_num = channels;
+	config.inclk = INCLK_NONE;
+	config.outclk = OUTCLK_ASRCK1_CLK;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		config.input_word_width   = width;
+		config.output_word_width  = word_width;
+		config.input_sample_rate  = rate;
+		config.output_sample_rate = asrc_priv->asrc_rate;
+	} else {
+		config.input_word_width   = word_width;
+		config.output_word_width  = width;
+		config.input_sample_rate  = asrc_priv->asrc_rate;
+		config.output_sample_rate = rate;
+	}
+
+	ret = fsl_asrc_config_pair(pair);
+	if (ret) {
+		dev_err(dai->dev, "fail to config asrc pair\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int fsl_asrc_dai_hw_free(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct fsl_asrc_pair *pair = runtime->private_data;
+
+	if (pair)
+		fsl_asrc_release_pair(pair);
+
+	return 0;
+}
+
+static int fsl_asrc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+				struct snd_soc_dai *dai)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct fsl_asrc_pair *pair = runtime->private_data;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		fsl_asrc_start_pair(pair);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		fsl_asrc_stop_pair(pair);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops fsl_asrc_dai_ops = {
+	.hw_params    = fsl_asrc_dai_hw_params,
+	.hw_free      = fsl_asrc_dai_hw_free,
+	.trigger      = fsl_asrc_dai_trigger,
+};
+
+static int fsl_asrc_dai_probe(struct snd_soc_dai *dai)
+{
+	struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai);
+
+	snd_soc_dai_init_dma_data(dai, &asrc_priv->dma_params_tx,
+				  &asrc_priv->dma_params_rx);
+
+	return 0;
+}
+
+#define FSL_ASRC_RATES		 SNDRV_PCM_RATE_8000_192000
+#define FSL_ASRC_FORMATS	(SNDRV_PCM_FMTBIT_S24_LE | \
+				 SNDRV_PCM_FMTBIT_S16_LE | \
+				 SNDRV_PCM_FMTBIT_S20_3LE)
+
+static struct snd_soc_dai_driver fsl_asrc_dai = {
+	.probe = fsl_asrc_dai_probe,
+	.playback = {
+		.stream_name = "ASRC-Playback",
+		.channels_min = 1,
+		.channels_max = 10,
+		.rates = FSL_ASRC_RATES,
+		.formats = FSL_ASRC_FORMATS,
+	},
+	.capture = {
+		.stream_name = "ASRC-Capture",
+		.channels_min = 1,
+		.channels_max = 10,
+		.rates = FSL_ASRC_RATES,
+		.formats = FSL_ASRC_FORMATS,
+	},
+	.ops = &fsl_asrc_dai_ops,
+};
+
+static const struct snd_soc_component_driver fsl_asrc_component = {
+	.name = "fsl-asrc-dai",
+};
+
+static bool fsl_asrc_readable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case REG_ASRCTR:
+	case REG_ASRIER:
+	case REG_ASRCNCR:
+	case REG_ASRCFG:
+	case REG_ASRCSR:
+	case REG_ASRCDR1:
+	case REG_ASRCDR2:
+	case REG_ASRSTR:
+	case REG_ASRPM1:
+	case REG_ASRPM2:
+	case REG_ASRPM3:
+	case REG_ASRPM4:
+	case REG_ASRPM5:
+	case REG_ASRTFR1:
+	case REG_ASRCCR:
+	case REG_ASRDOA:
+	case REG_ASRDOB:
+	case REG_ASRDOC:
+	case REG_ASRIDRHA:
+	case REG_ASRIDRLA:
+	case REG_ASRIDRHB:
+	case REG_ASRIDRLB:
+	case REG_ASRIDRHC:
+	case REG_ASRIDRLC:
+	case REG_ASR76K:
+	case REG_ASR56K:
+	case REG_ASRMCRA:
+	case REG_ASRFSTA:
+	case REG_ASRMCRB:
+	case REG_ASRFSTB:
+	case REG_ASRMCRC:
+	case REG_ASRFSTC:
+	case REG_ASRMCR1A:
+	case REG_ASRMCR1B:
+	case REG_ASRMCR1C:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool fsl_asrc_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case REG_ASRSTR:
+	case REG_ASRDIA:
+	case REG_ASRDIB:
+	case REG_ASRDIC:
+	case REG_ASRDOA:
+	case REG_ASRDOB:
+	case REG_ASRDOC:
+	case REG_ASRFSTA:
+	case REG_ASRFSTB:
+	case REG_ASRFSTC:
+	case REG_ASRCFG:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool fsl_asrc_writeable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case REG_ASRCTR:
+	case REG_ASRIER:
+	case REG_ASRCNCR:
+	case REG_ASRCFG:
+	case REG_ASRCSR:
+	case REG_ASRCDR1:
+	case REG_ASRCDR2:
+	case REG_ASRSTR:
+	case REG_ASRPM1:
+	case REG_ASRPM2:
+	case REG_ASRPM3:
+	case REG_ASRPM4:
+	case REG_ASRPM5:
+	case REG_ASRTFR1:
+	case REG_ASRCCR:
+	case REG_ASRDIA:
+	case REG_ASRDIB:
+	case REG_ASRDIC:
+	case REG_ASRIDRHA:
+	case REG_ASRIDRLA:
+	case REG_ASRIDRHB:
+	case REG_ASRIDRLB:
+	case REG_ASRIDRHC:
+	case REG_ASRIDRLC:
+	case REG_ASR76K:
+	case REG_ASR56K:
+	case REG_ASRMCRA:
+	case REG_ASRMCRB:
+	case REG_ASRMCRC:
+	case REG_ASRMCR1A:
+	case REG_ASRMCR1B:
+	case REG_ASRMCR1C:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static struct regmap_config fsl_asrc_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+
+	.max_register = REG_ASRMCR1C,
+	.readable_reg = fsl_asrc_readable_reg,
+	.volatile_reg = fsl_asrc_volatile_reg,
+	.writeable_reg = fsl_asrc_writeable_reg,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+/**
+ * Initialize ASRC registers with a default configurations
+ */
+static int fsl_asrc_init(struct fsl_asrc *asrc_priv)
+{
+	/* Halt ASRC internal FP when input FIFO needs data for pair A, B, C */
+	regmap_write(asrc_priv->regmap, REG_ASRCTR, ASRCTR_ASRCEN);
+
+	/* Disable interrupt by default */
+	regmap_write(asrc_priv->regmap, REG_ASRIER, 0x0);
+
+	/* Apply recommended settings for parameters from Reference Manual */
+	regmap_write(asrc_priv->regmap, REG_ASRPM1, 0x7fffff);
+	regmap_write(asrc_priv->regmap, REG_ASRPM2, 0x255555);
+	regmap_write(asrc_priv->regmap, REG_ASRPM3, 0xff7280);
+	regmap_write(asrc_priv->regmap, REG_ASRPM4, 0xff7280);
+	regmap_write(asrc_priv->regmap, REG_ASRPM5, 0xff7280);
+
+	/* Base address for task queue FIFO. Set to 0x7C */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRTFR1,
+			   ASRTFR1_TF_BASE_MASK, ASRTFR1_TF_BASE(0xfc));
+
+	/* Set the processing clock for 76KHz to 133M */
+	regmap_write(asrc_priv->regmap, REG_ASR76K, 0x06D6);
+
+	/* Set the processing clock for 56KHz to 133M */
+	return regmap_write(asrc_priv->regmap, REG_ASR56K, 0x0947);
+}
+
+/**
+ * Interrupt handler for ASRC
+ */
+static irqreturn_t fsl_asrc_isr(int irq, void *dev_id)
+{
+	struct fsl_asrc *asrc_priv = (struct fsl_asrc *)dev_id;
+	struct device *dev = &asrc_priv->pdev->dev;
+	enum asrc_pair_index index;
+	u32 status;
+
+	regmap_read(asrc_priv->regmap, REG_ASRSTR, &status);
+
+	/* Clean overload error */
+	regmap_write(asrc_priv->regmap, REG_ASRSTR, ASRSTR_AOLE);
+
+	/*
+	 * We here use dev_dbg() for all exceptions because ASRC itself does
+	 * not care if FIFO overflowed or underrun while a warning in the
+	 * interrupt would result a ridged conversion.
+	 */
+	for (index = ASRC_PAIR_A; index < ASRC_PAIR_MAX_NUM; index++) {
+		if (!asrc_priv->pair[index])
+			continue;
+
+		if (status & ASRSTR_ATQOL) {
+			asrc_priv->pair[index]->error |= ASRC_TASK_Q_OVERLOAD;
+			dev_dbg(dev, "ASRC Task Queue FIFO overload\n");
+		}
+
+		if (status & ASRSTR_AOOL(index)) {
+			asrc_priv->pair[index]->error |= ASRC_OUTPUT_TASK_OVERLOAD;
+			pair_dbg("Output Task Overload\n");
+		}
+
+		if (status & ASRSTR_AIOL(index)) {
+			asrc_priv->pair[index]->error |= ASRC_INPUT_TASK_OVERLOAD;
+			pair_dbg("Input Task Overload\n");
+		}
+
+		if (status & ASRSTR_AODO(index)) {
+			asrc_priv->pair[index]->error |= ASRC_OUTPUT_BUFFER_OVERFLOW;
+			pair_dbg("Output Data Buffer has overflowed\n");
+		}
+
+		if (status & ASRSTR_AIDU(index)) {
+			asrc_priv->pair[index]->error |= ASRC_INPUT_BUFFER_UNDERRUN;
+			pair_dbg("Input Data Buffer has underflowed\n");
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int fsl_asrc_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct fsl_asrc *asrc_priv;
+	struct resource *res;
+	void __iomem *regs;
+	int irq, ret, i;
+	char tmp[16];
+
+	asrc_priv = devm_kzalloc(&pdev->dev, sizeof(*asrc_priv), GFP_KERNEL);
+	if (!asrc_priv)
+		return -ENOMEM;
+
+	asrc_priv->pdev = pdev;
+	strcpy(asrc_priv->name, np->name);
+
+	/* Get the addresses and IRQ */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	asrc_priv->paddr = res->start;
+
+	/* Register regmap and let it prepare core clock */
+	if (of_property_read_bool(np, "big-endian"))
+		fsl_asrc_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG;
+
+	asrc_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "mem", regs,
+						      &fsl_asrc_regmap_config);
+	if (IS_ERR(asrc_priv->regmap)) {
+		dev_err(&pdev->dev, "failed to init regmap\n");
+		return PTR_ERR(asrc_priv->regmap);
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
+		return irq;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, fsl_asrc_isr, 0,
+			       asrc_priv->name, asrc_priv);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to claim irq %u: %d\n", irq, ret);
+		return ret;
+	}
+
+	asrc_priv->mem_clk = devm_clk_get(&pdev->dev, "mem");
+	if (IS_ERR(asrc_priv->mem_clk)) {
+		dev_err(&pdev->dev, "failed to get mem clock\n");
+		return PTR_ERR(asrc_priv->mem_clk);
+	}
+
+	asrc_priv->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(asrc_priv->ipg_clk)) {
+		dev_err(&pdev->dev, "failed to get ipg clock\n");
+		return PTR_ERR(asrc_priv->ipg_clk);
+	}
+
+	for (i = 0; i < ASRC_CLK_MAX_NUM; i++) {
+		sprintf(tmp, "asrck_%x", i);
+		asrc_priv->asrck_clk[i] = devm_clk_get(&pdev->dev, tmp);
+		if (IS_ERR(asrc_priv->asrck_clk[i])) {
+			dev_err(&pdev->dev, "failed to get %s clock\n", tmp);
+			return PTR_ERR(asrc_priv->asrck_clk[i]);
+		}
+	}
+
+	if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx35-asrc")) {
+		asrc_priv->channel_bits = 3;
+		clk_map[IN] = input_clk_map_imx35;
+		clk_map[OUT] = output_clk_map_imx35;
+	} else {
+		asrc_priv->channel_bits = 4;
+		clk_map[IN] = input_clk_map_imx53;
+		clk_map[OUT] = output_clk_map_imx53;
+	}
+
+	ret = fsl_asrc_init(asrc_priv);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to init asrc %d\n", ret);
+		return -EINVAL;
+	}
+
+	asrc_priv->channel_avail = 10;
+
+	ret = of_property_read_u32(np, "fsl,asrc-rate",
+				   &asrc_priv->asrc_rate);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to get output rate\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(np, "fsl,asrc-width",
+				   &asrc_priv->asrc_width);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to get output width\n");
+		return -EINVAL;
+	}
+
+	if (asrc_priv->asrc_width != 16 && asrc_priv->asrc_width != 24) {
+		dev_warn(&pdev->dev, "unsupported width, switching to 24bit\n");
+		asrc_priv->asrc_width = 24;
+	}
+
+	platform_set_drvdata(pdev, asrc_priv);
+	pm_runtime_enable(&pdev->dev);
+	spin_lock_init(&asrc_priv->lock);
+
+	ret = devm_snd_soc_register_component(&pdev->dev, &fsl_asrc_component,
+					      &fsl_asrc_dai, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register ASoC DAI\n");
+		return ret;
+	}
+
+	ret = devm_snd_soc_register_platform(&pdev->dev, &fsl_asrc_platform);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register ASoC platform\n");
+		return ret;
+	}
+
+	dev_info(&pdev->dev, "driver registered\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int fsl_asrc_runtime_resume(struct device *dev)
+{
+	struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
+	int i;
+
+	clk_prepare_enable(asrc_priv->mem_clk);
+	clk_prepare_enable(asrc_priv->ipg_clk);
+	for (i = 0; i < ASRC_CLK_MAX_NUM; i++)
+		clk_prepare_enable(asrc_priv->asrck_clk[i]);
+
+	return 0;
+}
+
+static int fsl_asrc_runtime_suspend(struct device *dev)
+{
+	struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < ASRC_CLK_MAX_NUM; i++)
+		clk_disable_unprepare(asrc_priv->asrck_clk[i]);
+	clk_disable_unprepare(asrc_priv->ipg_clk);
+	clk_disable_unprepare(asrc_priv->mem_clk);
+
+	return 0;
+}
+#endif /* CONFIG_PM_RUNTIME */
+
+#ifdef CONFIG_PM_SLEEP
+static int fsl_asrc_suspend(struct device *dev)
+{
+	struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
+
+	regcache_cache_only(asrc_priv->regmap, true);
+	regcache_mark_dirty(asrc_priv->regmap);
+
+	return 0;
+}
+
+static int fsl_asrc_resume(struct device *dev)
+{
+	struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
+	u32 asrctr;
+
+	/* Stop all pairs provisionally */
+	regmap_read(asrc_priv->regmap, REG_ASRCTR, &asrctr);
+	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+			   ASRCTR_ASRCEi_ALL_MASK, 0);
+
+	/* Restore all registers */
+	regcache_cache_only(asrc_priv->regmap, false);
+	regcache_sync(asrc_priv->regmap);
+
+	/* Restart enabled pairs */
+	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+			   ASRCTR_ASRCEi_ALL_MASK, asrctr);
+
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops fsl_asrc_pm = {
+	SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(fsl_asrc_suspend, fsl_asrc_resume)
+};
+
+static const struct of_device_id fsl_asrc_ids[] = {
+	{ .compatible = "fsl,imx35-asrc", },
+	{ .compatible = "fsl,imx53-asrc", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, fsl_asrc_ids);
+
+static struct platform_driver fsl_asrc_driver = {
+	.probe = fsl_asrc_probe,
+	.driver = {
+		.name = "fsl-asrc",
+		.of_match_table = fsl_asrc_ids,
+		.pm = &fsl_asrc_pm,
+	},
+};
+module_platform_driver(fsl_asrc_driver);
+
+MODULE_DESCRIPTION("Freescale ASRC ASoC driver");
+MODULE_AUTHOR("Nicolin Chen <nicoleotsuka@gmail.com>");
+MODULE_ALIAS("platform:fsl-asrc");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h
new file mode 100644
index 000000000000..a3f211f53c23
--- /dev/null
+++ b/sound/soc/fsl/fsl_asrc.h
@@ -0,0 +1,461 @@
+/*
+ * fsl_asrc.h - Freescale ASRC ALSA SoC header file
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Nicolin Chen <nicoleotsuka@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef _FSL_ASRC_H
+#define _FSL_ASRC_H
+
+#define IN	0
+#define OUT	1
+
+#define ASRC_DMA_BUFFER_NUM		2
+#define ASRC_INPUTFIFO_THRESHOLD	32
+#define ASRC_OUTPUTFIFO_THRESHOLD	32
+#define ASRC_FIFO_THRESHOLD_MIN		0
+#define ASRC_FIFO_THRESHOLD_MAX		63
+#define ASRC_DMA_BUFFER_SIZE		(1024 * 48 * 4)
+#define ASRC_MAX_BUFFER_SIZE		(1024 * 48)
+#define ASRC_OUTPUT_LAST_SAMPLE		8
+
+#define IDEAL_RATIO_RATE		1000000
+
+#define REG_ASRCTR			0x00
+#define REG_ASRIER			0x04
+#define REG_ASRCNCR			0x0C
+#define REG_ASRCFG			0x10
+#define REG_ASRCSR			0x14
+
+#define REG_ASRCDR1			0x18
+#define REG_ASRCDR2			0x1C
+#define REG_ASRCDR(i)			((i < 2) ? REG_ASRCDR1 : REG_ASRCDR2)
+
+#define REG_ASRSTR			0x20
+#define REG_ASRRA			0x24
+#define REG_ASRRB			0x28
+#define REG_ASRRC			0x2C
+#define REG_ASRPM1			0x40
+#define REG_ASRPM2			0x44
+#define REG_ASRPM3			0x48
+#define REG_ASRPM4			0x4C
+#define REG_ASRPM5			0x50
+#define REG_ASRTFR1			0x54
+#define REG_ASRCCR			0x5C
+
+#define REG_ASRDIA			0x60
+#define REG_ASRDOA			0x64
+#define REG_ASRDIB			0x68
+#define REG_ASRDOB			0x6C
+#define REG_ASRDIC			0x70
+#define REG_ASRDOC			0x74
+#define REG_ASRDI(i)			(REG_ASRDIA + (i << 3))
+#define REG_ASRDO(i)			(REG_ASRDOA + (i << 3))
+#define REG_ASRDx(x, i)			(x == IN ? REG_ASRDI(i) : REG_ASRDO(i))
+
+#define REG_ASRIDRHA			0x80
+#define REG_ASRIDRLA			0x84
+#define REG_ASRIDRHB			0x88
+#define REG_ASRIDRLB			0x8C
+#define REG_ASRIDRHC			0x90
+#define REG_ASRIDRLC			0x94
+#define REG_ASRIDRH(i)			(REG_ASRIDRHA + (i << 3))
+#define REG_ASRIDRL(i)			(REG_ASRIDRLA + (i << 3))
+
+#define REG_ASR76K			0x98
+#define REG_ASR56K			0x9C
+
+#define REG_ASRMCRA			0xA0
+#define REG_ASRFSTA			0xA4
+#define REG_ASRMCRB			0xA8
+#define REG_ASRFSTB			0xAC
+#define REG_ASRMCRC			0xB0
+#define REG_ASRFSTC			0xB4
+#define REG_ASRMCR(i)			(REG_ASRMCRA + (i << 3))
+#define REG_ASRFST(i)			(REG_ASRFSTA + (i << 3))
+
+#define REG_ASRMCR1A			0xC0
+#define REG_ASRMCR1B			0xC4
+#define REG_ASRMCR1C			0xC8
+#define REG_ASRMCR1(i)			(REG_ASRMCR1A + (i << 2))
+
+
+/* REG0 0x00 REG_ASRCTR */
+#define ASRCTR_ATSi_SHIFT(i)		(20 + i)
+#define ASRCTR_ATSi_MASK(i)		(1 << ASRCTR_ATSi_SHIFT(i))
+#define ASRCTR_ATS(i)			(1 << ASRCTR_ATSi_SHIFT(i))
+#define ASRCTR_USRi_SHIFT(i)		(14 + (i << 1))
+#define ASRCTR_USRi_MASK(i)		(1 << ASRCTR_USRi_SHIFT(i))
+#define ASRCTR_USR(i)			(1 << ASRCTR_USRi_SHIFT(i))
+#define ASRCTR_IDRi_SHIFT(i)		(13 + (i << 1))
+#define ASRCTR_IDRi_MASK(i)		(1 << ASRCTR_IDRi_SHIFT(i))
+#define ASRCTR_IDR(i)			(1 << ASRCTR_IDRi_SHIFT(i))
+#define ASRCTR_SRST_SHIFT		4
+#define ASRCTR_SRST_MASK		(1 << ASRCTR_SRST_SHIFT)
+#define ASRCTR_SRST			(1 << ASRCTR_SRST_SHIFT)
+#define ASRCTR_ASRCEi_SHIFT(i)		(1 + i)
+#define ASRCTR_ASRCEi_MASK(i)		(1 << ASRCTR_ASRCEi_SHIFT(i))
+#define ASRCTR_ASRCE(i)			(1 << ASRCTR_ASRCEi_SHIFT(i))
+#define ASRCTR_ASRCEi_ALL_MASK		(0x7 << ASRCTR_ASRCEi_SHIFT(0))
+#define ASRCTR_ASRCEN_SHIFT		0
+#define ASRCTR_ASRCEN_MASK		(1 << ASRCTR_ASRCEN_SHIFT)
+#define ASRCTR_ASRCEN			(1 << ASRCTR_ASRCEN_SHIFT)
+
+/* REG1 0x04 REG_ASRIER */
+#define ASRIER_AFPWE_SHIFT		7
+#define ASRIER_AFPWE_MASK		(1 << ASRIER_AFPWE_SHIFT)
+#define ASRIER_AFPWE			(1 << ASRIER_AFPWE_SHIFT)
+#define ASRIER_AOLIE_SHIFT		6
+#define ASRIER_AOLIE_MASK		(1 << ASRIER_AOLIE_SHIFT)
+#define ASRIER_AOLIE			(1 << ASRIER_AOLIE_SHIFT)
+#define ASRIER_ADOEi_SHIFT(i)		(3 + i)
+#define ASRIER_ADOEi_MASK(i)		(1 << ASRIER_ADOEi_SHIFT(i))
+#define ASRIER_ADOE(i)			(1 << ASRIER_ADOEi_SHIFT(i))
+#define ASRIER_ADIEi_SHIFT(i)		(0 + i)
+#define ASRIER_ADIEi_MASK(i)		(1 << ASRIER_ADIEi_SHIFT(i))
+#define ASRIER_ADIE(i)			(1 << ASRIER_ADIEi_SHIFT(i))
+
+/* REG2 0x0C REG_ASRCNCR */
+#define ASRCNCR_ANCi_SHIFT(i, b)	(b * i)
+#define ASRCNCR_ANCi_MASK(i, b)		(((1 << b) - 1) << ASRCNCR_ANCi_SHIFT(i, b))
+#define ASRCNCR_ANCi(i, v, b)		((v << ASRCNCR_ANCi_SHIFT(i, b)) & ASRCNCR_ANCi_MASK(i, b))
+
+/* REG3 0x10 REG_ASRCFG */
+#define ASRCFG_INIRQi_SHIFT(i)		(21 + i)
+#define ASRCFG_INIRQi_MASK(i)		(1 << ASRCFG_INIRQi_SHIFT(i))
+#define ASRCFG_INIRQi			(1 << ASRCFG_INIRQi_SHIFT(i))
+#define ASRCFG_NDPRi_SHIFT(i)		(18 + i)
+#define ASRCFG_NDPRi_MASK(i)		(1 << ASRCFG_NDPRi_SHIFT(i))
+#define ASRCFG_NDPRi			(1 << ASRCFG_NDPRi_SHIFT(i))
+#define ASRCFG_POSTMODi_SHIFT(i)	(8 + (i << 2))
+#define ASRCFG_POSTMODi_WIDTH		2
+#define ASRCFG_POSTMODi_MASK(i)		(((1 << ASRCFG_POSTMODi_WIDTH) - 1) << ASRCFG_POSTMODi_SHIFT(i))
+#define ASRCFG_POSTMOD(i, v)		((v) << ASRCFG_POSTMODi_SHIFT(i))
+#define ASRCFG_POSTMODi_UP(i)		(0 << ASRCFG_POSTMODi_SHIFT(i))
+#define ASRCFG_POSTMODi_DCON(i)		(1 << ASRCFG_POSTMODi_SHIFT(i))
+#define ASRCFG_POSTMODi_DOWN(i)		(2 << ASRCFG_POSTMODi_SHIFT(i))
+#define ASRCFG_PREMODi_SHIFT(i)		(6 + (i << 2))
+#define ASRCFG_PREMODi_WIDTH		2
+#define ASRCFG_PREMODi_MASK(i)		(((1 << ASRCFG_PREMODi_WIDTH) - 1) << ASRCFG_PREMODi_SHIFT(i))
+#define ASRCFG_PREMOD(i, v)		((v) << ASRCFG_PREMODi_SHIFT(i))
+#define ASRCFG_PREMODi_UP(i)		(0 << ASRCFG_PREMODi_SHIFT(i))
+#define ASRCFG_PREMODi_DCON(i)		(1 << ASRCFG_PREMODi_SHIFT(i))
+#define ASRCFG_PREMODi_DOWN(i)		(2 << ASRCFG_PREMODi_SHIFT(i))
+#define ASRCFG_PREMODi_BYPASS(i)	(3 << ASRCFG_PREMODi_SHIFT(i))
+
+/* REG4 0x14 REG_ASRCSR */
+#define ASRCSR_AxCSi_WIDTH		4
+#define ASRCSR_AxCSi_MASK		((1 << ASRCSR_AxCSi_WIDTH) - 1)
+#define ASRCSR_AOCSi_SHIFT(i)		(12 + (i << 2))
+#define ASRCSR_AOCSi_MASK(i)		(((1 << ASRCSR_AxCSi_WIDTH) - 1) << ASRCSR_AOCSi_SHIFT(i))
+#define ASRCSR_AOCS(i, v)		((v) << ASRCSR_AOCSi_SHIFT(i))
+#define ASRCSR_AICSi_SHIFT(i)		(i << 2)
+#define ASRCSR_AICSi_MASK(i)		(((1 << ASRCSR_AxCSi_WIDTH) - 1) << ASRCSR_AICSi_SHIFT(i))
+#define ASRCSR_AICS(i, v)		((v) << ASRCSR_AICSi_SHIFT(i))
+
+/* REG5&6 0x18 & 0x1C REG_ASRCDR1 & ASRCDR2 */
+#define ASRCDRi_AxCPi_WIDTH		3
+#define ASRCDRi_AICPi_SHIFT(i)		(0 + (i % 2) * 6)
+#define ASRCDRi_AICPi_MASK(i)		(((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AICPi_SHIFT(i))
+#define ASRCDRi_AICP(i, v)		((v) << ASRCDRi_AICPi_SHIFT(i))
+#define ASRCDRi_AICDi_SHIFT(i)		(3 + (i % 2) * 6)
+#define ASRCDRi_AICDi_MASK(i)		(((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AICDi_SHIFT(i))
+#define ASRCDRi_AICD(i, v)		((v) << ASRCDRi_AICDi_SHIFT(i))
+#define ASRCDRi_AOCPi_SHIFT(i)		((i < 2) ? 12 + i * 6 : 6)
+#define ASRCDRi_AOCPi_MASK(i)		(((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AOCPi_SHIFT(i))
+#define ASRCDRi_AOCP(i, v)		((v) << ASRCDRi_AOCPi_SHIFT(i))
+#define ASRCDRi_AOCDi_SHIFT(i)		((i < 2) ? 15 + i * 6 : 9)
+#define ASRCDRi_AOCDi_MASK(i)		(((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AOCDi_SHIFT(i))
+#define ASRCDRi_AOCD(i, v)		((v) << ASRCDRi_AOCDi_SHIFT(i))
+
+/* REG7 0x20 REG_ASRSTR */
+#define ASRSTR_DSLCNT_SHIFT		21
+#define ASRSTR_DSLCNT_MASK		(1 << ASRSTR_DSLCNT_SHIFT)
+#define ASRSTR_DSLCNT			(1 << ASRSTR_DSLCNT_SHIFT)
+#define ASRSTR_ATQOL_SHIFT		20
+#define ASRSTR_ATQOL_MASK		(1 << ASRSTR_ATQOL_SHIFT)
+#define ASRSTR_ATQOL			(1 << ASRSTR_ATQOL_SHIFT)
+#define ASRSTR_AOOLi_SHIFT(i)		(17 + i)
+#define ASRSTR_AOOLi_MASK(i)		(1 << ASRSTR_AOOLi_SHIFT(i))
+#define ASRSTR_AOOL(i)			(1 << ASRSTR_AOOLi_SHIFT(i))
+#define ASRSTR_AIOLi_SHIFT(i)		(14 + i)
+#define ASRSTR_AIOLi_MASK(i)		(1 << ASRSTR_AIOLi_SHIFT(i))
+#define ASRSTR_AIOL(i)			(1 << ASRSTR_AIOLi_SHIFT(i))
+#define ASRSTR_AODOi_SHIFT(i)		(11 + i)
+#define ASRSTR_AODOi_MASK(i)		(1 << ASRSTR_AODOi_SHIFT(i))
+#define ASRSTR_AODO(i)			(1 << ASRSTR_AODOi_SHIFT(i))
+#define ASRSTR_AIDUi_SHIFT(i)		(8 + i)
+#define ASRSTR_AIDUi_MASK(i)		(1 << ASRSTR_AIDUi_SHIFT(i))
+#define ASRSTR_AIDU(i)			(1 << ASRSTR_AIDUi_SHIFT(i))
+#define ASRSTR_FPWT_SHIFT		7
+#define ASRSTR_FPWT_MASK		(1 << ASRSTR_FPWT_SHIFT)
+#define ASRSTR_FPWT			(1 << ASRSTR_FPWT_SHIFT)
+#define ASRSTR_AOLE_SHIFT		6
+#define ASRSTR_AOLE_MASK		(1 << ASRSTR_AOLE_SHIFT)
+#define ASRSTR_AOLE			(1 << ASRSTR_AOLE_SHIFT)
+#define ASRSTR_AODEi_SHIFT(i)		(3 + i)
+#define ASRSTR_AODFi_MASK(i)		(1 << ASRSTR_AODEi_SHIFT(i))
+#define ASRSTR_AODF(i)			(1 << ASRSTR_AODEi_SHIFT(i))
+#define ASRSTR_AIDEi_SHIFT(i)		(0 + i)
+#define ASRSTR_AIDEi_MASK(i)		(1 << ASRSTR_AIDEi_SHIFT(i))
+#define ASRSTR_AIDE(i)			(1 << ASRSTR_AIDEi_SHIFT(i))
+
+/* REG10 0x54 REG_ASRTFR1 */
+#define ASRTFR1_TF_BASE_WIDTH		7
+#define ASRTFR1_TF_BASE_SHIFT		6
+#define ASRTFR1_TF_BASE_MASK		(((1 << ASRTFR1_TF_BASE_WIDTH) - 1) << ASRTFR1_TF_BASE_SHIFT)
+#define ASRTFR1_TF_BASE(i)		((i) << ASRTFR1_TF_BASE_SHIFT)
+
+/*
+ * REG22 0xA0 REG_ASRMCRA
+ * REG24 0xA8 REG_ASRMCRB
+ * REG26 0xB0 REG_ASRMCRC
+ */
+#define ASRMCRi_ZEROBUFi_SHIFT		23
+#define ASRMCRi_ZEROBUFi_MASK		(1 << ASRMCRi_ZEROBUFi_SHIFT)
+#define ASRMCRi_ZEROBUFi		(1 << ASRMCRi_ZEROBUFi_SHIFT)
+#define ASRMCRi_EXTTHRSHi_SHIFT		22
+#define ASRMCRi_EXTTHRSHi_MASK		(1 << ASRMCRi_EXTTHRSHi_SHIFT)
+#define ASRMCRi_EXTTHRSHi		(1 << ASRMCRi_EXTTHRSHi_SHIFT)
+#define ASRMCRi_BUFSTALLi_SHIFT		21
+#define ASRMCRi_BUFSTALLi_MASK		(1 << ASRMCRi_BUFSTALLi_SHIFT)
+#define ASRMCRi_BUFSTALLi		(1 << ASRMCRi_BUFSTALLi_SHIFT)
+#define ASRMCRi_BYPASSPOLYi_SHIFT	20
+#define ASRMCRi_BYPASSPOLYi_MASK	(1 << ASRMCRi_BYPASSPOLYi_SHIFT)
+#define ASRMCRi_BYPASSPOLYi		(1 << ASRMCRi_BYPASSPOLYi_SHIFT)
+#define ASRMCRi_OUTFIFO_THRESHOLD_WIDTH	6
+#define ASRMCRi_OUTFIFO_THRESHOLD_SHIFT	12
+#define ASRMCRi_OUTFIFO_THRESHOLD_MASK	(((1 << ASRMCRi_OUTFIFO_THRESHOLD_WIDTH) - 1) << ASRMCRi_OUTFIFO_THRESHOLD_SHIFT)
+#define ASRMCRi_OUTFIFO_THRESHOLD(v)	(((v) << ASRMCRi_OUTFIFO_THRESHOLD_SHIFT) & ASRMCRi_OUTFIFO_THRESHOLD_MASK)
+#define ASRMCRi_RSYNIFi_SHIFT		11
+#define ASRMCRi_RSYNIFi_MASK		(1 << ASRMCRi_RSYNIFi_SHIFT)
+#define ASRMCRi_RSYNIFi			(1 << ASRMCRi_RSYNIFi_SHIFT)
+#define ASRMCRi_RSYNOFi_SHIFT		10
+#define ASRMCRi_RSYNOFi_MASK		(1 << ASRMCRi_RSYNOFi_SHIFT)
+#define ASRMCRi_RSYNOFi			(1 << ASRMCRi_RSYNOFi_SHIFT)
+#define ASRMCRi_INFIFO_THRESHOLD_WIDTH	6
+#define ASRMCRi_INFIFO_THRESHOLD_SHIFT	0
+#define ASRMCRi_INFIFO_THRESHOLD_MASK	(((1 << ASRMCRi_INFIFO_THRESHOLD_WIDTH) - 1) << ASRMCRi_INFIFO_THRESHOLD_SHIFT)
+#define ASRMCRi_INFIFO_THRESHOLD(v)	(((v) << ASRMCRi_INFIFO_THRESHOLD_SHIFT) & ASRMCRi_INFIFO_THRESHOLD_MASK)
+
+/*
+ * REG23 0xA4 REG_ASRFSTA
+ * REG25 0xAC REG_ASRFSTB
+ * REG27 0xB4 REG_ASRFSTC
+ */
+#define ASRFSTi_OAFi_SHIFT		23
+#define ASRFSTi_OAFi_MASK		(1 << ASRFSTi_OAFi_SHIFT)
+#define ASRFSTi_OAFi			(1 << ASRFSTi_OAFi_SHIFT)
+#define ASRFSTi_OUTPUT_FIFO_WIDTH	7
+#define ASRFSTi_OUTPUT_FIFO_SHIFT	12
+#define ASRFSTi_OUTPUT_FIFO_MASK	(((1 << ASRFSTi_OUTPUT_FIFO_WIDTH) - 1) << ASRFSTi_OUTPUT_FIFO_SHIFT)
+#define ASRFSTi_IAEi_SHIFT		11
+#define ASRFSTi_IAEi_MASK		(1 << ASRFSTi_OAFi_SHIFT)
+#define ASRFSTi_IAEi			(1 << ASRFSTi_OAFi_SHIFT)
+#define ASRFSTi_INPUT_FIFO_WIDTH	7
+#define ASRFSTi_INPUT_FIFO_SHIFT	0
+#define ASRFSTi_INPUT_FIFO_MASK		((1 << ASRFSTi_INPUT_FIFO_WIDTH) - 1)
+
+/* REG28 0xC0 & 0xC4 & 0xC8 REG_ASRMCR1i */
+#define ASRMCR1i_IWD_WIDTH		3
+#define ASRMCR1i_IWD_SHIFT		9
+#define ASRMCR1i_IWD_MASK		(((1 << ASRMCR1i_IWD_WIDTH) - 1) << ASRMCR1i_IWD_SHIFT)
+#define ASRMCR1i_IWD(v)			((v) << ASRMCR1i_IWD_SHIFT)
+#define ASRMCR1i_IMSB_SHIFT		8
+#define ASRMCR1i_IMSB_MASK		(1 << ASRMCR1i_IMSB_SHIFT)
+#define ASRMCR1i_IMSB_MSB		(1 << ASRMCR1i_IMSB_SHIFT)
+#define ASRMCR1i_IMSB_LSB		(0 << ASRMCR1i_IMSB_SHIFT)
+#define ASRMCR1i_OMSB_SHIFT		2
+#define ASRMCR1i_OMSB_MASK		(1 << ASRMCR1i_OMSB_SHIFT)
+#define ASRMCR1i_OMSB_MSB		(1 << ASRMCR1i_OMSB_SHIFT)
+#define ASRMCR1i_OMSB_LSB		(0 << ASRMCR1i_OMSB_SHIFT)
+#define ASRMCR1i_OSGN_SHIFT		1
+#define ASRMCR1i_OSGN_MASK		(1 << ASRMCR1i_OSGN_SHIFT)
+#define ASRMCR1i_OSGN			(1 << ASRMCR1i_OSGN_SHIFT)
+#define ASRMCR1i_OW16_SHIFT		0
+#define ASRMCR1i_OW16_MASK		(1 << ASRMCR1i_OW16_SHIFT)
+#define ASRMCR1i_OW16(v)		((v) << ASRMCR1i_OW16_SHIFT)
+
+
+enum asrc_pair_index {
+	ASRC_INVALID_PAIR = -1,
+	ASRC_PAIR_A = 0,
+	ASRC_PAIR_B = 1,
+	ASRC_PAIR_C = 2,
+};
+
+#define ASRC_PAIR_MAX_NUM	(ASRC_PAIR_C + 1)
+
+enum asrc_inclk {
+	INCLK_NONE = 0x03,
+	INCLK_ESAI_RX = 0x00,
+	INCLK_SSI1_RX = 0x01,
+	INCLK_SSI2_RX = 0x02,
+	INCLK_SSI3_RX = 0x07,
+	INCLK_SPDIF_RX = 0x04,
+	INCLK_MLB_CLK = 0x05,
+	INCLK_PAD = 0x06,
+	INCLK_ESAI_TX = 0x08,
+	INCLK_SSI1_TX = 0x09,
+	INCLK_SSI2_TX = 0x0a,
+	INCLK_SSI3_TX = 0x0b,
+	INCLK_SPDIF_TX = 0x0c,
+	INCLK_ASRCK1_CLK = 0x0f,
+};
+
+enum asrc_outclk {
+	OUTCLK_NONE = 0x03,
+	OUTCLK_ESAI_TX = 0x00,
+	OUTCLK_SSI1_TX = 0x01,
+	OUTCLK_SSI2_TX = 0x02,
+	OUTCLK_SSI3_TX = 0x07,
+	OUTCLK_SPDIF_TX = 0x04,
+	OUTCLK_MLB_CLK = 0x05,
+	OUTCLK_PAD = 0x06,
+	OUTCLK_ESAI_RX = 0x08,
+	OUTCLK_SSI1_RX = 0x09,
+	OUTCLK_SSI2_RX = 0x0a,
+	OUTCLK_SSI3_RX = 0x0b,
+	OUTCLK_SPDIF_RX = 0x0c,
+	OUTCLK_ASRCK1_CLK = 0x0f,
+};
+
+#define ASRC_CLK_MAX_NUM	16
+
+enum asrc_word_width {
+	ASRC_WIDTH_24_BIT = 0,
+	ASRC_WIDTH_16_BIT = 1,
+	ASRC_WIDTH_8_BIT = 2,
+};
+
+struct asrc_config {
+	enum asrc_pair_index pair;
+	unsigned int channel_num;
+	unsigned int buffer_num;
+	unsigned int dma_buffer_size;
+	unsigned int input_sample_rate;
+	unsigned int output_sample_rate;
+	enum asrc_word_width input_word_width;
+	enum asrc_word_width output_word_width;
+	enum asrc_inclk inclk;
+	enum asrc_outclk outclk;
+};
+
+struct asrc_req {
+	unsigned int chn_num;
+	enum asrc_pair_index index;
+};
+
+struct asrc_querybuf {
+	unsigned int buffer_index;
+	unsigned int input_length;
+	unsigned int output_length;
+	unsigned long input_offset;
+	unsigned long output_offset;
+};
+
+struct asrc_convert_buffer {
+	void *input_buffer_vaddr;
+	void *output_buffer_vaddr;
+	unsigned int input_buffer_length;
+	unsigned int output_buffer_length;
+};
+
+struct asrc_status_flags {
+	enum asrc_pair_index index;
+	unsigned int overload_error;
+};
+
+enum asrc_error_status {
+	ASRC_TASK_Q_OVERLOAD		= 0x01,
+	ASRC_OUTPUT_TASK_OVERLOAD	= 0x02,
+	ASRC_INPUT_TASK_OVERLOAD	= 0x04,
+	ASRC_OUTPUT_BUFFER_OVERFLOW	= 0x08,
+	ASRC_INPUT_BUFFER_UNDERRUN	= 0x10,
+};
+
+struct dma_block {
+	dma_addr_t dma_paddr;
+	void *dma_vaddr;
+	unsigned int length;
+};
+
+/**
+ * fsl_asrc_pair: ASRC Pair private data
+ *
+ * @asrc_priv: pointer to its parent module
+ * @config: configuration profile
+ * @error: error record
+ * @index: pair index (ASRC_PAIR_A, ASRC_PAIR_B, ASRC_PAIR_C)
+ * @channels: occupied channel number
+ * @desc: input and output dma descriptors
+ * @dma_chan: inputer and output DMA channels
+ * @dma_data: private dma data
+ * @pos: hardware pointer position
+ * @private: pair private area
+ */
+struct fsl_asrc_pair {
+	struct fsl_asrc *asrc_priv;
+	struct asrc_config *config;
+	unsigned int error;
+
+	enum asrc_pair_index index;
+	unsigned int channels;
+
+	struct dma_async_tx_descriptor *desc[2];
+	struct dma_chan *dma_chan[2];
+	struct imx_dma_data dma_data;
+	unsigned int pos;
+
+	void *private;
+};
+
+/**
+ * fsl_asrc_pair: ASRC private data
+ *
+ * @dma_params_rx: DMA parameters for receive channel
+ * @dma_params_tx: DMA parameters for transmit channel
+ * @pdev: platform device pointer
+ * @regmap: regmap handler
+ * @paddr: physical address to the base address of registers
+ * @mem_clk: clock source to access register
+ * @ipg_clk: clock source to drive peripheral
+ * @asrck_clk: clock sources to driver ASRC internal logic
+ * @lock: spin lock for resource protection
+ * @pair: pair pointers
+ * @channel_bits: width of ASRCNCR register for each pair
+ * @channel_avail: non-occupied channel numbers
+ * @asrc_rate: default sample rate for ASoC Back-Ends
+ * @asrc_width: default sample width for ASoC Back-Ends
+ * @name: driver name
+ */
+struct fsl_asrc {
+	struct snd_dmaengine_dai_dma_data dma_params_rx;
+	struct snd_dmaengine_dai_dma_data dma_params_tx;
+	struct platform_device *pdev;
+	struct regmap *regmap;
+	unsigned long paddr;
+	struct clk *mem_clk;
+	struct clk *ipg_clk;
+	struct clk *asrck_clk[ASRC_CLK_MAX_NUM];
+	spinlock_t lock;
+
+	struct fsl_asrc_pair *pair[ASRC_PAIR_MAX_NUM];
+	unsigned int channel_bits;
+	unsigned int channel_avail;
+
+	int asrc_rate;
+	int asrc_width;
+
+	char name[32];
+};
+
+extern struct snd_soc_platform_driver fsl_asrc_platform;
+struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir);
+#endif /* _FSL_ASRC_H */
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
new file mode 100644
index 000000000000..ffc000bc1f15
--- /dev/null
+++ b/sound/soc/fsl/fsl_asrc_dma.c
@@ -0,0 +1,391 @@
+/*
+ * Freescale ASRC ALSA SoC Platform (DMA) driver
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Nicolin Chen <nicoleotsuka@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/platform_data/dma-imx.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm_params.h>
+
+#include "fsl_asrc.h"
+
+#define FSL_ASRC_DMABUF_SIZE	(256 * 1024)
+
+static struct snd_pcm_hardware snd_imx_hardware = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_MMAP_VALID |
+		SNDRV_PCM_INFO_PAUSE |
+		SNDRV_PCM_INFO_RESUME,
+	.buffer_bytes_max = FSL_ASRC_DMABUF_SIZE,
+	.period_bytes_min = 128,
+	.period_bytes_max = 65535, /* Limited by SDMA engine */
+	.periods_min = 2,
+	.periods_max = 255,
+	.fifo_size = 0,
+};
+
+static bool filter(struct dma_chan *chan, void *param)
+{
+	if (!imx_dma_is_general_purpose(chan))
+		return false;
+
+	chan->private = param;
+
+	return true;
+}
+
+static void fsl_asrc_dma_complete(void *arg)
+{
+	struct snd_pcm_substream *substream = arg;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct fsl_asrc_pair *pair = runtime->private_data;
+
+	pair->pos += snd_pcm_lib_period_bytes(substream);
+	if (pair->pos >= snd_pcm_lib_buffer_bytes(substream))
+		pair->pos = 0;
+
+	snd_pcm_period_elapsed(substream);
+}
+
+static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream)
+{
+	u8 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? OUT : IN;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct fsl_asrc_pair *pair = runtime->private_data;
+	struct device *dev = rtd->platform->dev;
+	unsigned long flags = DMA_CTRL_ACK;
+
+	/* Prepare and submit Front-End DMA channel */
+	if (!substream->runtime->no_period_wakeup)
+		flags |= DMA_PREP_INTERRUPT;
+
+	pair->pos = 0;
+	pair->desc[!dir] = dmaengine_prep_dma_cyclic(
+			pair->dma_chan[!dir], runtime->dma_addr,
+			snd_pcm_lib_buffer_bytes(substream),
+			snd_pcm_lib_period_bytes(substream),
+			dir == OUT ? DMA_TO_DEVICE : DMA_FROM_DEVICE, flags);
+	if (!pair->desc[!dir]) {
+		dev_err(dev, "failed to prepare slave DMA for Front-End\n");
+		return -ENOMEM;
+	}
+
+	pair->desc[!dir]->callback = fsl_asrc_dma_complete;
+	pair->desc[!dir]->callback_param = substream;
+
+	dmaengine_submit(pair->desc[!dir]);
+
+	/* Prepare and submit Back-End DMA channel */
+	pair->desc[dir] = dmaengine_prep_dma_cyclic(
+			pair->dma_chan[dir], 0xffff, 64, 64, DMA_DEV_TO_DEV, 0);
+	if (!pair->desc[dir]) {
+		dev_err(dev, "failed to prepare slave DMA for Back-End\n");
+		return -ENOMEM;
+	}
+
+	dmaengine_submit(pair->desc[dir]);
+
+	return 0;
+}
+
+static int fsl_asrc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct fsl_asrc_pair *pair = runtime->private_data;
+	int ret;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		ret = fsl_asrc_dma_prepare_and_submit(substream);
+		if (ret)
+			return ret;
+		dma_async_issue_pending(pair->dma_chan[IN]);
+		dma_async_issue_pending(pair->dma_chan[OUT]);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		dmaengine_terminate_all(pair->dma_chan[OUT]);
+		dmaengine_terminate_all(pair->dma_chan[IN]);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *params)
+{
+	enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+	struct snd_dmaengine_dai_dma_data *dma_params_fe = NULL;
+	struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct fsl_asrc_pair *pair = runtime->private_data;
+	struct fsl_asrc *asrc_priv = pair->asrc_priv;
+	struct dma_slave_config config_fe, config_be;
+	enum asrc_pair_index index = pair->index;
+	struct device *dev = rtd->platform->dev;
+	int stream = substream->stream;
+	struct imx_dma_data *tmp_data;
+	struct snd_soc_dpcm *dpcm;
+	struct dma_chan *tmp_chan;
+	struct device *dev_be;
+	u8 dir = tx ? OUT : IN;
+	dma_cap_mask_t mask;
+	int ret;
+
+	/* Fetch the Back-End dma_data from DPCM */
+	list_for_each_entry(dpcm, &rtd->dpcm[stream].be_clients, list_be) {
+		struct snd_soc_pcm_runtime *be = dpcm->be;
+		struct snd_pcm_substream *substream_be;
+		struct snd_soc_dai *dai = be->cpu_dai;
+
+		if (dpcm->fe != rtd)
+			continue;
+
+		substream_be = snd_soc_dpcm_get_substream(be, stream);
+		dma_params_be = snd_soc_dai_get_dma_data(dai, substream_be);
+		dev_be = dai->dev;
+		break;
+	}
+
+	if (!dma_params_be) {
+		dev_err(dev, "failed to get the substream of Back-End\n");
+		return -EINVAL;
+	}
+
+	/* Override dma_data of the Front-End and config its dmaengine */
+	dma_params_fe = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+	dma_params_fe->addr = asrc_priv->paddr + REG_ASRDx(!dir, index);
+	dma_params_fe->maxburst = dma_params_be->maxburst;
+
+	pair->dma_chan[!dir] = fsl_asrc_get_dma_channel(pair, !dir);
+	if (!pair->dma_chan[!dir]) {
+		dev_err(dev, "failed to request DMA channel\n");
+		return -EINVAL;
+	}
+
+	memset(&config_fe, 0, sizeof(config_fe));
+	ret = snd_dmaengine_pcm_prepare_slave_config(substream, params, &config_fe);
+	if (ret) {
+		dev_err(dev, "failed to prepare DMA config for Front-End\n");
+		return ret;
+	}
+
+	ret = dmaengine_slave_config(pair->dma_chan[!dir], &config_fe);
+	if (ret) {
+		dev_err(dev, "failed to config DMA channel for Front-End\n");
+		return ret;
+	}
+
+	/* Request and config DMA channel for Back-End */
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	dma_cap_set(DMA_CYCLIC, mask);
+
+	/* Get DMA request of Back-End */
+	tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
+	tmp_data = tmp_chan->private;
+	pair->dma_data.dma_request = tmp_data->dma_request;
+	dma_release_channel(tmp_chan);
+
+	/* Get DMA request of Front-End */
+	tmp_chan = fsl_asrc_get_dma_channel(pair, dir);
+	tmp_data = tmp_chan->private;
+	pair->dma_data.dma_request2 = tmp_data->dma_request;
+	pair->dma_data.peripheral_type = tmp_data->peripheral_type;
+	pair->dma_data.priority = tmp_data->priority;
+	dma_release_channel(tmp_chan);
+
+	pair->dma_chan[dir] = dma_request_channel(mask, filter, &pair->dma_data);
+	if (!pair->dma_chan[dir]) {
+		dev_err(dev, "failed to request DMA channel for Back-End\n");
+		return -EINVAL;
+	}
+
+	if (asrc_priv->asrc_width == 16)
+		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	else
+		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+
+	config_be.direction = DMA_DEV_TO_DEV;
+	config_be.src_addr_width = buswidth;
+	config_be.src_maxburst = dma_params_be->maxburst;
+	config_be.dst_addr_width = buswidth;
+	config_be.dst_maxburst = dma_params_be->maxburst;
+
+	if (tx) {
+		config_be.src_addr = asrc_priv->paddr + REG_ASRDO(index);
+		config_be.dst_addr = dma_params_be->addr;
+	} else {
+		config_be.dst_addr = asrc_priv->paddr + REG_ASRDI(index);
+		config_be.src_addr = dma_params_be->addr;
+	}
+
+	ret = dmaengine_slave_config(pair->dma_chan[dir], &config_be);
+	if (ret) {
+		dev_err(dev, "failed to config DMA channel for Back-End\n");
+		return ret;
+	}
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+
+	return 0;
+}
+
+static int fsl_asrc_dma_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct fsl_asrc_pair *pair = runtime->private_data;
+
+	snd_pcm_set_runtime_buffer(substream, NULL);
+
+	if (pair->dma_chan[IN])
+		dma_release_channel(pair->dma_chan[IN]);
+
+	if (pair->dma_chan[OUT])
+		dma_release_channel(pair->dma_chan[OUT]);
+
+	pair->dma_chan[IN] = NULL;
+	pair->dma_chan[OUT] = NULL;
+
+	return 0;
+}
+
+static int fsl_asrc_dma_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct device *dev = rtd->platform->dev;
+	struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
+	struct fsl_asrc_pair *pair;
+
+	pair = kzalloc(sizeof(struct fsl_asrc_pair), GFP_KERNEL);
+	if (!pair) {
+		dev_err(dev, "failed to allocate pair\n");
+		return -ENOMEM;
+	}
+
+	pair->asrc_priv = asrc_priv;
+
+	runtime->private_data = pair;
+
+	snd_pcm_hw_constraint_integer(substream->runtime,
+				      SNDRV_PCM_HW_PARAM_PERIODS);
+	snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
+
+	return 0;
+}
+
+static int fsl_asrc_dma_shutdown(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct fsl_asrc_pair *pair = runtime->private_data;
+	struct fsl_asrc *asrc_priv;
+
+	if (!pair)
+		return 0;
+
+	asrc_priv = pair->asrc_priv;
+
+	if (asrc_priv->pair[pair->index] == pair)
+		asrc_priv->pair[pair->index] = NULL;
+
+	kfree(pair);
+
+	return 0;
+}
+
+static snd_pcm_uframes_t fsl_asrc_dma_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct fsl_asrc_pair *pair = runtime->private_data;
+
+	return bytes_to_frames(substream->runtime, pair->pos);
+}
+
+static struct snd_pcm_ops fsl_asrc_dma_pcm_ops = {
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= fsl_asrc_dma_hw_params,
+	.hw_free	= fsl_asrc_dma_hw_free,
+	.trigger	= fsl_asrc_dma_trigger,
+	.open		= fsl_asrc_dma_startup,
+	.close		= fsl_asrc_dma_shutdown,
+	.pointer	= fsl_asrc_dma_pcm_pointer,
+};
+
+static int fsl_asrc_dma_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_pcm_substream *substream;
+	struct snd_pcm *pcm = rtd->pcm;
+	int ret, i;
+
+	ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_err(card->dev, "failed to set DMA mask\n");
+		return ret;
+	}
+
+	for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) {
+		substream = pcm->streams[i].substream;
+		if (!substream)
+			continue;
+
+		ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
+				FSL_ASRC_DMABUF_SIZE, &substream->dma_buffer);
+		if (ret) {
+			dev_err(card->dev, "failed to allocate DMA buffer\n");
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	if (--i == 0 && pcm->streams[i].substream)
+		snd_dma_free_pages(&pcm->streams[i].substream->dma_buffer);
+
+	return ret;
+}
+
+static void fsl_asrc_dma_pcm_free(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream;
+	int i;
+
+	for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) {
+		substream = pcm->streams[i].substream;
+		if (!substream)
+			continue;
+
+		snd_dma_free_pages(&substream->dma_buffer);
+		substream->dma_buffer.area = NULL;
+		substream->dma_buffer.addr = 0;
+	}
+}
+
+struct snd_soc_platform_driver fsl_asrc_platform = {
+	.ops		= &fsl_asrc_dma_pcm_ops,
+	.pcm_new	= fsl_asrc_dma_pcm_new,
+	.pcm_free	= fsl_asrc_dma_pcm_free,
+};
+EXPORT_SYMBOL_GPL(fsl_asrc_platform);
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index d719caf26dc2..72d154e7dd03 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -624,12 +624,14 @@ static int fsl_esai_dai_probe(struct snd_soc_dai *dai)
 static struct snd_soc_dai_driver fsl_esai_dai = {
 	.probe = fsl_esai_dai_probe,
 	.playback = {
+		.stream_name = "CPU-Playback",
 		.channels_min = 1,
 		.channels_max = 12,
 		.rates = FSL_ESAI_RATES,
 		.formats = FSL_ESAI_FORMATS,
 	},
 	.capture = {
+		.stream_name = "CPU-Capture",
 		.channels_min = 1,
 		.channels_max = 8,
 		.rates = FSL_ESAI_RATES,
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index c5a0e8af8226..faa049797897 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -106,7 +106,7 @@ irq_rx:
 	xcsr &= ~FSL_SAI_CSR_xF_MASK;
 
 	if (flags)
-		regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr);
+		regmap_write(sai->regmap, FSL_SAI_RCSR, flags | xcsr);
 
 out:
 	if (irq_none)
@@ -327,7 +327,7 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
 	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-	u32 tcsr, rcsr;
+	u32 xcsr, count = 100;
 
 	/*
 	 * The transmitter bit clock and frame sync are to be
@@ -338,9 +338,6 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 	regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC,
 			   FSL_SAI_CR2_SYNC);
 
-	regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr);
-	regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr);
-
 	/*
 	 * It is recommended that the transmitter is the last enabled
 	 * and the first disabled.
@@ -349,17 +346,16 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (!(tcsr & FSL_SAI_CSR_FRDE || rcsr & FSL_SAI_CSR_FRDE)) {
-			regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
-					   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
-			regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
-					   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
-		}
+		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+				   FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);
+
+		regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+				   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
+		regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+				   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
 
 		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
 				   FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS);
-		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
-				   FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -370,11 +366,24 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 				   FSL_SAI_CSR_xIE_MASK, 0);
 
 		/* Check if the opposite FRDE is also disabled */
-		if (!(tx ? rcsr & FSL_SAI_CSR_FRDE : tcsr & FSL_SAI_CSR_FRDE)) {
+		regmap_read(sai->regmap, FSL_SAI_xCSR(!tx), &xcsr);
+		if (!(xcsr & FSL_SAI_CSR_FRDE)) {
+			/* Disable both directions and reset their FIFOs */
 			regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
 					   FSL_SAI_CSR_TERE, 0);
 			regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
 					   FSL_SAI_CSR_TERE, 0);
+
+			/* TERE will remain set till the end of current frame */
+			do {
+				udelay(10);
+				regmap_read(sai->regmap, FSL_SAI_xCSR(tx), &xcsr);
+			} while (--count && xcsr & FSL_SAI_CSR_TERE);
+
+			regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+					   FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
+			regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+					   FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
 		}
 		break;
 	default:
@@ -446,12 +455,14 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
 static struct snd_soc_dai_driver fsl_sai_dai = {
 	.probe = fsl_sai_dai_probe,
 	.playback = {
+		.stream_name = "CPU-Playback",
 		.channels_min = 1,
 		.channels_max = 2,
 		.rates = SNDRV_PCM_RATE_8000_96000,
 		.formats = FSL_SAI_FORMATS,
 	},
 	.capture = {
+		.stream_name = "CPU-Capture",
 		.channels_min = 1,
 		.channels_max = 2,
 		.rates = SNDRV_PCM_RATE_8000_96000,
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index d7a60614dd21..70acfe4a9bd5 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -32,10 +32,13 @@
 #define FSL_SPDIF_TXFIFO_WML	0x8
 #define FSL_SPDIF_RXFIFO_WML	0x8
 
-#define INTR_FOR_PLAYBACK (INT_TXFIFO_RESYNC)
-#define INTR_FOR_CAPTURE (INT_SYM_ERR | INT_BIT_ERR | INT_URX_FUL | INT_URX_OV|\
-		INT_QRX_FUL | INT_QRX_OV | INT_UQ_SYNC | INT_UQ_ERR |\
-		INT_RXFIFO_RESYNC | INT_LOSS_LOCK | INT_DPLL_LOCKED)
+#define INTR_FOR_PLAYBACK	(INT_TXFIFO_RESYNC)
+#define INTR_FOR_CAPTURE	(INT_SYM_ERR | INT_BIT_ERR | INT_URX_FUL |\
+				INT_URX_OV | INT_QRX_FUL | INT_QRX_OV |\
+				INT_UQ_SYNC | INT_UQ_ERR | INT_RXFIFO_RESYNC |\
+				INT_LOSS_LOCK | INT_DPLL_LOCKED)
+
+#define SIE_INTR_FOR(tx)	(tx ? INTR_FOR_PLAYBACK : INTR_FOR_CAPTURE)
 
 /* Index list for the values that has if (DPLL Locked) condition */
 static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0xa, 0xb };
@@ -96,7 +99,7 @@ struct fsl_spdif_priv {
 	struct platform_device *pdev;
 	struct regmap *regmap;
 	bool dpll_locked;
-	u16 txrate[SPDIF_TXRATE_MAX];
+	u32 txrate[SPDIF_TXRATE_MAX];
 	u8 txclk_df[SPDIF_TXRATE_MAX];
 	u8 sysclk_df[SPDIF_TXRATE_MAX];
 	u8 txclk_src[SPDIF_TXRATE_MAX];
@@ -137,10 +140,9 @@ static void spdif_irq_sym_error(struct fsl_spdif_priv *spdif_priv)
 
 	dev_dbg(&pdev->dev, "isr: receiver found illegal symbol\n");
 
-	if (!spdif_priv->dpll_locked) {
-		/* DPLL unlocked seems no audio stream */
+	/* Clear illegal symbol if DPLL unlocked since no audio stream */
+	if (!spdif_priv->dpll_locked)
 		regmap_update_bits(regmap, REG_SPDIF_SIE, INT_SYM_ERR, 0);
-	}
 }
 
 /* U/Q Channel receive register full */
@@ -335,8 +337,8 @@ static void spdif_write_channel_status(struct fsl_spdif_priv *spdif_priv)
 	u32 ch_status;
 
 	ch_status = (bitrev8(ctrl->ch_status[0]) << 16) |
-		(bitrev8(ctrl->ch_status[1]) << 8) |
-		bitrev8(ctrl->ch_status[2]);
+		    (bitrev8(ctrl->ch_status[1]) << 8) |
+		    bitrev8(ctrl->ch_status[2]);
 	regmap_write(regmap, REG_SPDIF_STCSCH, ch_status);
 
 	dev_dbg(&pdev->dev, "STCSCH: 0x%06x\n", ch_status);
@@ -390,6 +392,14 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
 		rate = SPDIF_TXRATE_48000;
 		csfs = IEC958_AES3_CON_FS_48000;
 		break;
+	case 96000:
+		rate = SPDIF_TXRATE_96000;
+		csfs = IEC958_AES3_CON_FS_96000;
+		break;
+	case 192000:
+		rate = SPDIF_TXRATE_192000;
+		csfs = IEC958_AES3_CON_FS_192000;
+		break;
 	default:
 		dev_err(&pdev->dev, "unsupported sample rate %d\n", sample_rate);
 		return -EINVAL;
@@ -433,13 +443,12 @@ clk_set_bypass:
 	spdif_set_cstatus(ctrl, IEC958_AES3_CON_FS, csfs);
 
 	/* select clock source and divisor */
-	stc = STC_TXCLK_ALL_EN | STC_TXCLK_SRC_SET(clk) | STC_TXCLK_DF(txclk_df);
-	mask = STC_TXCLK_ALL_EN_MASK | STC_TXCLK_SRC_MASK | STC_TXCLK_DF_MASK;
+	stc = STC_TXCLK_ALL_EN | STC_TXCLK_SRC_SET(clk) |
+	      STC_TXCLK_DF(txclk_df) | STC_SYSCLK_DF(sysclk_df);
+	mask = STC_TXCLK_ALL_EN_MASK | STC_TXCLK_SRC_MASK |
+	       STC_TXCLK_DF_MASK | STC_SYSCLK_DF_MASK;
 	regmap_update_bits(regmap, REG_SPDIF_STC, mask, stc);
 
-	regmap_update_bits(regmap, REG_SPDIF_STC,
-			   STC_SYSCLK_DF_MASK, STC_SYSCLK_DF(sysclk_df));
-
 	dev_dbg(&pdev->dev, "set sample rate to %dHz for %dHz playback\n",
 			spdif_priv->txrate[rate], sample_rate);
 
@@ -553,7 +562,7 @@ static int fsl_spdif_hw_params(struct snd_pcm_substream *substream,
 			return ret;
 		}
 		spdif_set_cstatus(ctrl, IEC958_AES3_CON_CLOCK,
-				IEC958_AES3_CON_CLOCK_1000PPM);
+				  IEC958_AES3_CON_CLOCK_1000PPM);
 		spdif_write_channel_status(spdif_priv);
 	} else {
 		/* Setup rx clock source */
@@ -569,9 +578,9 @@ static int fsl_spdif_trigger(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
 	struct regmap *regmap = spdif_priv->regmap;
-	int is_playack = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
-	u32 intr = is_playack ? INTR_FOR_PLAYBACK : INTR_FOR_CAPTURE;
-	u32 dmaen = is_playack ? SCR_DMA_TX_EN : SCR_DMA_RX_EN;;
+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+	u32 intr = SIE_INTR_FOR(tx);
+	u32 dmaen = SCR_DMA_xX_EN(tx);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -662,9 +671,8 @@ static int fsl_spdif_capture_get(struct snd_kcontrol *kcontrol,
 	u32 cstatus, val;
 
 	regmap_read(regmap, REG_SPDIF_SIS, &val);
-	if (!(val & INT_CNEW)) {
+	if (!(val & INT_CNEW))
 		return -EAGAIN;
-	}
 
 	regmap_read(regmap, REG_SPDIF_SRCSH, &cstatus);
 	ucontrol->value.iec958.status[0] = (cstatus >> 16) & 0xFF;
@@ -693,15 +701,14 @@ static int fsl_spdif_subcode_get(struct snd_kcontrol *kcontrol,
 	struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
 	struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
 	unsigned long flags;
-	int ret = 0;
+	int ret = -EAGAIN;
 
 	spin_lock_irqsave(&ctrl->ctl_lock, flags);
 	if (ctrl->ready_buf) {
 		int idx = (ctrl->ready_buf - 1) * SPDIF_UBITS_SIZE;
 		memcpy(&ucontrol->value.iec958.subcode[0],
 				&ctrl->subcode[idx], SPDIF_UBITS_SIZE);
-	} else {
-		ret = -EAGAIN;
+		ret = 0;
 	}
 	spin_unlock_irqrestore(&ctrl->ctl_lock, flags);
 
@@ -726,15 +733,14 @@ static int fsl_spdif_qget(struct snd_kcontrol *kcontrol,
 	struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
 	struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
 	unsigned long flags;
-	int ret = 0;
+	int ret = -EAGAIN;
 
 	spin_lock_irqsave(&ctrl->ctl_lock, flags);
 	if (ctrl->ready_buf) {
 		int idx = (ctrl->ready_buf - 1) * SPDIF_QSUB_SIZE;
 		memcpy(&ucontrol->value.bytes.data[0],
 				&ctrl->qsub[idx], SPDIF_QSUB_SIZE);
-	} else {
-		ret = -EAGAIN;
+		ret = 0;
 	}
 	spin_unlock_irqrestore(&ctrl->ctl_lock, flags);
 
@@ -799,10 +805,10 @@ static int spdif_get_rxclk_rate(struct fsl_spdif_priv *spdif_priv,
 	regmap_read(regmap, REG_SPDIF_SRPC, &phaseconf);
 
 	clksrc = (phaseconf >> SRPC_CLKSRC_SEL_OFFSET) & 0xf;
-	if (srpc_dpll_locked[clksrc] && (phaseconf & SRPC_DPLL_LOCKED)) {
-		/* Get bus clock from system */
+
+	/* Get bus clock from system */
+	if (srpc_dpll_locked[clksrc] && (phaseconf & SRPC_DPLL_LOCKED))
 		busclk_freq = clk_get_rate(spdif_priv->sysclk);
-	}
 
 	/* FreqMeas_CLK = (BUS_CLK * FreqMeas) / 2 ^ 10 / GAINSEL / 128 */
 	tmpval64 = (u64) busclk_freq * freqmeas;
@@ -826,12 +832,12 @@ static int fsl_spdif_rxrate_get(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
 	struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
-	int rate = spdif_get_rxclk_rate(spdif_priv, SPDIF_DEFAULT_GAINSEL);
+	int rate = 0;
 
 	if (spdif_priv->dpll_locked)
-		ucontrol->value.integer.value[0] = rate;
-	else
-		ucontrol->value.integer.value[0] = 0;
+		rate = spdif_get_rxclk_rate(spdif_priv, SPDIF_DEFAULT_GAINSEL);
+
+	ucontrol->value.integer.value[0] = rate;
 
 	return 0;
 }
@@ -969,12 +975,14 @@ static int fsl_spdif_dai_probe(struct snd_soc_dai *dai)
 static struct snd_soc_dai_driver fsl_spdif_dai = {
 	.probe = &fsl_spdif_dai_probe,
 	.playback = {
+		.stream_name = "CPU-Playback",
 		.channels_min = 2,
 		.channels_max = 2,
 		.rates = FSL_SPDIF_RATES_PLAYBACK,
 		.formats = FSL_SPDIF_FORMATS_PLAYBACK,
 	},
 	.capture = {
+		.stream_name = "CPU-Capture",
 		.channels_min = 2,
 		.channels_max = 2,
 		.rates = FSL_SPDIF_RATES_CAPTURE,
@@ -1046,7 +1054,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
 				struct clk *clk, u64 savesub,
 				enum spdif_txrate index, bool round)
 {
-	const u32 rate[] = { 32000, 44100, 48000 };
+	const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 };
 	bool is_sysclk = clk == spdif_priv->sysclk;
 	u64 rate_ideal, rate_actual, sub;
 	u32 sysclk_dfmin, sysclk_dfmax;
@@ -1105,7 +1113,7 @@ out:
 static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
 				enum spdif_txrate index)
 {
-	const u32 rate[] = { 32000, 44100, 48000 };
+	const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 };
 	struct platform_device *pdev = spdif_priv->pdev;
 	struct device *dev = &pdev->dev;
 	u64 savesub = 100000, ret;
@@ -1238,12 +1246,12 @@ static int fsl_spdif_probe(struct platform_device *pdev)
 	spin_lock_init(&ctrl->ctl_lock);
 
 	/* Init tx channel status default value */
-	ctrl->ch_status[0] =
-		IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_5015;
+	ctrl->ch_status[0] = IEC958_AES0_CON_NOT_COPYRIGHT |
+			     IEC958_AES0_CON_EMPHASIS_5015;
 	ctrl->ch_status[1] = IEC958_AES1_CON_DIGDIGCONV_ID;
 	ctrl->ch_status[2] = 0x00;
-	ctrl->ch_status[3] =
-		IEC958_AES3_CON_FS_44100 | IEC958_AES3_CON_CLOCK_1000PPM;
+	ctrl->ch_status[3] = IEC958_AES3_CON_FS_44100 |
+			     IEC958_AES3_CON_CLOCK_1000PPM;
 
 	spdif_priv->dpll_locked = false;
 
diff --git a/sound/soc/fsl/fsl_spdif.h b/sound/soc/fsl/fsl_spdif.h
index 16fde4b927d3..00bd3514c610 100644
--- a/sound/soc/fsl/fsl_spdif.h
+++ b/sound/soc/fsl/fsl_spdif.h
@@ -93,6 +93,8 @@
 #define SCR_USRC_SEL_RECV		(0x1 << SCR_USRC_SEL_OFFSET)
 #define SCR_USRC_SEL_CHIP		(0x3 << SCR_USRC_SEL_OFFSET)
 
+#define SCR_DMA_xX_EN(tx)		(tx ? SCR_DMA_TX_EN : SCR_DMA_RX_EN)
+
 /* SPDIF CDText control */
 #define SRCD_CD_USER_OFFSET		1
 #define SRCD_CD_USER			(1 << SRCD_CD_USER_OFFSET)
@@ -164,8 +166,10 @@ enum spdif_txrate {
 	SPDIF_TXRATE_32000 = 0,
 	SPDIF_TXRATE_44100,
 	SPDIF_TXRATE_48000,
+	SPDIF_TXRATE_96000,
+	SPDIF_TXRATE_192000,
 };
-#define SPDIF_TXRATE_MAX		(SPDIF_TXRATE_48000 + 1)
+#define SPDIF_TXRATE_MAX		(SPDIF_TXRATE_192000 + 1)
 
 
 #define SPDIF_CSTATUS_BYTE		6
@@ -175,7 +179,9 @@ enum spdif_txrate {
 
 #define FSL_SPDIF_RATES_PLAYBACK	(SNDRV_PCM_RATE_32000 |	\
 					 SNDRV_PCM_RATE_44100 |	\
-					 SNDRV_PCM_RATE_48000)
+					 SNDRV_PCM_RATE_48000 |	\
+					 SNDRV_PCM_RATE_96000 |	\
+					 SNDRV_PCM_RATE_192000)
 
 #define FSL_SPDIF_RATES_CAPTURE		(SNDRV_PCM_RATE_16000 | \
 					 SNDRV_PCM_RATE_32000 |	\
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 9bfef55d77d1..87eb5776a39b 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -590,8 +590,8 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
 		else
 			clkrate = clk_round_rate(ssi_private->baudclk, tmprate);
 
-		do_div(clkrate, factor);
-		afreq = (u32)clkrate / (i + 1);
+		clkrate /= factor;
+		afreq = clkrate / (i + 1);
 
 		if (freq == afreq)
 			sub = 0;
@@ -1032,12 +1032,14 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
 static struct snd_soc_dai_driver fsl_ssi_dai_template = {
 	.probe = fsl_ssi_dai_probe,
 	.playback = {
+		.stream_name = "CPU-Playback",
 		.channels_min = 1,
 		.channels_max = 2,
 		.rates = FSLSSI_I2S_RATES,
 		.formats = FSLSSI_I2S_FORMATS,
 	},
 	.capture = {
+		.stream_name = "CPU-Capture",
 		.channels_min = 1,
 		.channels_max = 2,
 		.rates = FSLSSI_I2S_RATES,
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index 267717aa96c1..46f9beb6b273 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -67,7 +67,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
 {
 	ssize_t ret;
 	char *buf;
-	int port = (int)file->private_data;
+	uintptr_t port = (uintptr_t)file->private_data;
 	u32 pdcr, ptcr;
 
 	if (audmux_clk) {
@@ -147,7 +147,7 @@ static const struct file_operations audmux_debugfs_fops = {
 
 static void audmux_debugfs_init(void)
 {
-	int i;
+	uintptr_t i;
 	char buf[20];
 
 	audmux_debugfs_root = debugfs_create_dir("audmux", NULL);
@@ -157,10 +157,10 @@ static void audmux_debugfs_init(void)
 	}
 
 	for (i = 0; i < MX31_AUDMUX_PORT7_SSI_PINS_7 + 1; i++) {
-		snprintf(buf, sizeof(buf), "ssi%d", i);
+		snprintf(buf, sizeof(buf), "ssi%lu", i);
 		if (!debugfs_create_file(buf, 0444, audmux_debugfs_root,
 					 (void *)i, &audmux_debugfs_fops))
-			pr_warning("Failed to create AUDMUX port %d debugfs file\n",
+			pr_warning("Failed to create AUDMUX port %lu debugfs file\n",
 				   i);
 	}
 }
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 03a7fdcdf114..159e517fa09a 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -116,6 +116,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
 {
 	struct device_node *node;
 	struct clk *clk;
+	u32 val;
 	int ret;
 
 	/*
@@ -151,10 +152,8 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
 		}
 
 		dai->sysclk = clk_get_rate(clk);
-	} else if (of_property_read_bool(np, "system-clock-frequency")) {
-		of_property_read_u32(np,
-				     "system-clock-frequency",
-				     &dai->sysclk);
+	} else if (!of_property_read_u32(np, "system-clock-frequency", &val)) {
+		dai->sysclk = val;
 	} else {
 		clk = of_clk_get(node, 0);
 		if (!IS_ERR(clk))
@@ -303,6 +302,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
 {
 	struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link;
 	struct simple_dai_props *dai_props = priv->dai_props;
+	u32 val;
 	int ret;
 
 	/* parsing the card name from DT */
@@ -325,8 +325,9 @@ static int asoc_simple_card_parse_of(struct device_node *node,
 	}
 
 	/* Factor to mclk, used in hw_params() */
-	of_property_read_u32(node, "simple-audio-card,mclk-fs",
-			     &priv->mclk_fs);
+	ret = of_property_read_u32(node, "simple-audio-card,mclk-fs", &val);
+	if (ret == 0)
+		priv->mclk_fs = val;
 
 	dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ?
 		priv->snd_card.name : "");
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index c30fedb3e149..f5b4a9c79cdf 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -58,3 +58,15 @@ config SND_SOC_INTEL_BYT_MAX98090_MACH
 	help
 	  This adds audio driver for Intel Baytrail platform based boards
 	  with the MAX98090 audio codec.
+
+config SND_SOC_INTEL_BROADWELL_MACH
+	tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint"
+	depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && DW_DMAC
+	select SND_SOC_INTEL_HASWELL
+	select SND_COMPRESS_OFFLOAD
+	select SND_SOC_RT286
+	help
+	  This adds support for the Wilcatpoint Audio DSP on Intel(R) Broadwell
+	  Ultrabook platforms.
+	  Say Y if you have such a device
+	  If unsure select "N".
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile
index 4bfca79a42ba..7acbfc43a0c6 100644
--- a/sound/soc/intel/Makefile
+++ b/sound/soc/intel/Makefile
@@ -24,7 +24,9 @@ obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += snd-soc-sst-baytrail-pcm.o
 snd-soc-sst-haswell-objs := haswell.o
 snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o
 snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o
+snd-soc-sst-broadwell-objs := broadwell.o
 
 obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
 obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
 obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
+obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o
diff --git a/sound/soc/intel/broadwell.c b/sound/soc/intel/broadwell.c
new file mode 100644
index 000000000000..0e550f14028f
--- /dev/null
+++ b/sound/soc/intel/broadwell.c
@@ -0,0 +1,251 @@
+/*
+ * Intel Broadwell Wildcatpoint SST Audio
+ *
+ * Copyright (C) 2013, Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+
+#include "sst-dsp.h"
+#include "sst-haswell-ipc.h"
+
+#include "../codecs/rt286.h"
+
+static const struct snd_soc_dapm_widget broadwell_widgets[] = {
+	SND_SOC_DAPM_HP("Headphones", NULL),
+	SND_SOC_DAPM_SPK("Speaker", NULL),
+	SND_SOC_DAPM_MIC("Mic Jack", NULL),
+	SND_SOC_DAPM_MIC("DMIC1", NULL),
+	SND_SOC_DAPM_MIC("DMIC2", NULL),
+	SND_SOC_DAPM_LINE("Line Jack", NULL),
+};
+
+static const struct snd_soc_dapm_route broadwell_rt286_map[] = {
+
+	/* speaker */
+	{"Speaker", NULL, "SPOR"},
+	{"Speaker", NULL, "SPOL"},
+
+	/* HP jack connectors - unknown if we have jack deteck */
+	{"Headphones", NULL, "HPO Pin"},
+
+	/* other jacks */
+	{"MIC1", NULL, "Mic Jack"},
+	{"LINE1", NULL, "Line Jack"},
+
+	/* digital mics */
+	{"DMIC1 Pin", NULL, "DMIC1"},
+	{"DMIC2 Pin", NULL, "DMIC2"},
+
+	/* CODEC BE connections */
+	{"SSP0 CODEC IN", NULL, "AIF1 Capture"},
+	{"AIF1 Playback", NULL, "SSP0 CODEC OUT"},
+};
+
+static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval *channels = hw_param_interval(params,
+						SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	/* The ADSP will covert the FE rate to 48k, stereo */
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = 2;
+
+	/* set SSP0 to 16 bit */
+	snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
+				    SNDRV_PCM_HW_PARAM_FIRST_MASK],
+				    SNDRV_PCM_FORMAT_S16_LE);
+	return 0;
+}
+
+static int broadwell_rt286_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000,
+		SND_SOC_CLOCK_IN);
+
+	if (ret < 0) {
+		dev_err(rtd->dev, "can't set codec sysclk configuration\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static struct snd_soc_ops broadwell_rt286_ops = {
+	.hw_params = broadwell_rt286_hw_params,
+};
+
+static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev);
+	struct sst_hsw *broadwell = pdata->dsp;
+	int ret;
+
+	/* Set ADSP SSP port settings */
+	ret = sst_hsw_device_set_config(broadwell, SST_HSW_DEVICE_SSP_0,
+		SST_HSW_DEVICE_MCLK_FREQ_24_MHZ,
+		SST_HSW_DEVICE_CLOCK_MASTER, 9);
+	if (ret < 0) {
+		dev_err(rtd->dev, "error: failed to set device config\n");
+		return ret;
+	}
+
+	/* always connected - check HP for jack detect */
+	snd_soc_dapm_enable_pin(dapm, "Headphones");
+	snd_soc_dapm_enable_pin(dapm, "Speaker");
+	snd_soc_dapm_enable_pin(dapm, "Mic Jack");
+	snd_soc_dapm_enable_pin(dapm, "Line Jack");
+	snd_soc_dapm_enable_pin(dapm, "DMIC1");
+	snd_soc_dapm_enable_pin(dapm, "DMIC2");
+
+	return 0;
+}
+
+/* broadwell digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link broadwell_rt286_dais[] = {
+	/* Front End DAI links */
+	{
+		.name = "System PCM",
+		.stream_name = "System Playback",
+		.cpu_dai_name = "System Pin",
+		.platform_name = "haswell-pcm-audio",
+		.dynamic = 1,
+		.codec_name = "snd-soc-dummy",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.init = broadwell_rtd_init,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+		.dpcm_playback = 1,
+	},
+	{
+		.name = "Offload0",
+		.stream_name = "Offload0 Playback",
+		.cpu_dai_name = "Offload0 Pin",
+		.platform_name = "haswell-pcm-audio",
+		.dynamic = 1,
+		.codec_name = "snd-soc-dummy",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+		.dpcm_playback = 1,
+	},
+	{
+		.name = "Offload1",
+		.stream_name = "Offload1 Playback",
+		.cpu_dai_name = "Offload1 Pin",
+		.platform_name = "haswell-pcm-audio",
+		.dynamic = 1,
+		.codec_name = "snd-soc-dummy",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+		.dpcm_playback = 1,
+	},
+	{
+		.name = "Loopback PCM",
+		.stream_name = "Loopback",
+		.cpu_dai_name = "Loopback Pin",
+		.platform_name = "haswell-pcm-audio",
+		.dynamic = 0,
+		.codec_name = "snd-soc-dummy",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+		.dpcm_capture = 1,
+	},
+	{
+		.name = "Capture PCM",
+		.stream_name = "Capture",
+		.cpu_dai_name = "Capture Pin",
+		.platform_name = "haswell-pcm-audio",
+		.dynamic = 1,
+		.codec_name = "snd-soc-dummy",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+		.dpcm_capture = 1,
+	},
+
+	/* Back End DAI links */
+	{
+		/* SSP0 - Codec */
+		.name = "Codec",
+		.be_id = 0,
+		.cpu_dai_name = "snd-soc-dummy-dai",
+		.platform_name = "snd-soc-dummy",
+		.no_pcm = 1,
+		.codec_name = "i2c-INT343A:00",
+		.codec_dai_name = "rt286-aif1",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.be_hw_params_fixup = broadwell_ssp0_fixup,
+		.ops = &broadwell_rt286_ops,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+	},
+};
+
+/* broadwell audio machine driver for WPT + RT286S */
+static struct snd_soc_card broadwell_rt286 = {
+	.name = "broadwell-rt286",
+	.owner = THIS_MODULE,
+	.dai_link = broadwell_rt286_dais,
+	.num_links = ARRAY_SIZE(broadwell_rt286_dais),
+	.dapm_widgets = broadwell_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(broadwell_widgets),
+	.dapm_routes = broadwell_rt286_map,
+	.num_dapm_routes = ARRAY_SIZE(broadwell_rt286_map),
+	.fully_routed = true,
+};
+
+static int broadwell_audio_probe(struct platform_device *pdev)
+{
+	broadwell_rt286.dev = &pdev->dev;
+
+	return snd_soc_register_card(&broadwell_rt286);
+}
+
+static int broadwell_audio_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_card(&broadwell_rt286);
+	return 0;
+}
+
+static struct platform_driver broadwell_audio = {
+	.probe = broadwell_audio_probe,
+	.remove = broadwell_audio_remove,
+	.driver = {
+		.name = "broadwell-audio",
+		.owner = THIS_MODULE,
+	},
+};
+
+module_platform_driver(broadwell_audio)
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood, Xingchao Wang");
+MODULE_DESCRIPTION("Intel SST Audio for WPT/Broadwell");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:broadwell-audio");
diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/byt-max98090.c
index 5fc98c64a3f4..b8b8af571ef1 100644
--- a/sound/soc/intel/byt-max98090.c
+++ b/sound/soc/intel/byt-max98090.c
@@ -39,8 +39,7 @@ static const struct snd_soc_dapm_widget byt_max98090_widgets[] = {
 
 static const struct snd_soc_dapm_route byt_max98090_audio_map[] = {
 	{"IN34", NULL, "Headset Mic"},
-	{"IN34", NULL, "MICBIAS"},
-	{"MICBIAS", NULL, "Headset Mic"},
+	{"Headset Mic", NULL, "MICBIAS"},
 	{"DMICL", NULL, "Int Mic"},
 	{"Headphone", NULL, "HPL"},
 	{"Headphone", NULL, "HPR"},
@@ -64,14 +63,6 @@ static struct snd_soc_jack_pin hs_jack_pins[] = {
 		.pin	= "Headset Mic",
 		.mask	= SND_JACK_MICROPHONE,
 	},
-	{
-		.pin	= "Ext Spk",
-		.mask	= SND_JACK_LINEOUT,
-	},
-	{
-		.pin	= "Int Mic",
-		.mask	= SND_JACK_LINEIN,
-	},
 };
 
 static struct snd_soc_jack_gpio hs_jack_gpios[] = {
@@ -84,7 +75,8 @@ static struct snd_soc_jack_gpio hs_jack_gpios[] = {
 	{
 		.name		= "mic-gpio",
 		.idx		= 1,
-		.report		= SND_JACK_MICROPHONE | SND_JACK_LINEIN,
+		.invert		= 1,
+		.report		= SND_JACK_MICROPHONE,
 		.debounce_time	= 200,
 	},
 };
@@ -108,7 +100,8 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime)
 	}
 
 	/* Enable jack detection */
-	ret = snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, jack);
+	ret = snd_soc_jack_new(codec, "Headset",
+			       SND_JACK_LINEOUT | SND_JACK_HEADSET, jack);
 	if (ret)
 		return ret;
 
@@ -117,13 +110,9 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime)
 	if (ret)
 		return ret;
 
-	ret = snd_soc_jack_add_gpiods(card->dev->parent, jack,
-				      ARRAY_SIZE(hs_jack_gpios),
-				      hs_jack_gpios);
-	if (ret)
-		return ret;
-
-	return max98090_mic_detect(codec, jack);
+	return snd_soc_jack_add_gpiods(card->dev->parent, jack,
+				       ARRAY_SIZE(hs_jack_gpios),
+				       hs_jack_gpios);
 }
 
 static struct snd_soc_dai_link byt_max98090_dais[] = {
diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/byt-rt5640.c
index 53d160d39972..234a58de3c53 100644
--- a/sound/soc/intel/byt-rt5640.c
+++ b/sound/soc/intel/byt-rt5640.c
@@ -34,6 +34,7 @@ static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
 };
 
 static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
+	{"Headset Mic", NULL, "MICBIAS1"},
 	{"IN2P", NULL, "Headset Mic"},
 	{"IN2N", NULL, "Headset Mic"},
 	{"DMIC1", NULL, "Internal Mic"},
diff --git a/sound/soc/intel/sst-atom-controls.h b/sound/soc/intel/sst-atom-controls.h
new file mode 100644
index 000000000000..14063ab8c7c5
--- /dev/null
+++ b/sound/soc/intel/sst-atom-controls.h
@@ -0,0 +1,30 @@
+/*
+ *  Copyright (C) 2013-14 Intel Corp
+ *  Author: Ramesh Babu <ramesh.babu.koul@intel.com>
+ *  	Omair M Abdullah <omair.m.abdullah@intel.com>
+ *  	Samreen Nilofer <samreen.nilofer@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#ifndef __SST_CONTROLS_V2_H__
+#define __SST_CONTROLS_V2_H__
+
+enum {
+	MERR_DPCM_AUDIO = 0,
+	MERR_DPCM_COMPR,
+};
+
+
+#endif
diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c
index d207b22ea330..67673a2c0f41 100644
--- a/sound/soc/intel/sst-baytrail-ipc.c
+++ b/sound/soc/intel/sst-baytrail-ipc.c
@@ -122,6 +122,26 @@ struct sst_byt_tstamp {
 	u32 channel_peak[8];
 } __packed;
 
+struct sst_byt_fw_version {
+	u8 build;
+	u8 minor;
+	u8 major;
+	u8 type;
+} __packed;
+
+struct sst_byt_fw_build_info {
+	u8 date[16];
+	u8 time[16];
+} __packed;
+
+struct sst_byt_fw_init {
+	struct sst_byt_fw_version fw_version;
+	struct sst_byt_fw_build_info build_info;
+	u16 result;
+	u8 module_id;
+	u8 debug_info;
+} __packed;
+
 /* driver internal IPC message structure */
 struct ipc_message {
 	struct list_head list;
@@ -868,6 +888,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
 {
 	struct sst_byt *byt;
 	struct sst_fw *byt_sst_fw;
+	struct sst_byt_fw_init init;
 	int err;
 
 	dev_dbg(dev, "initialising Byt DSP IPC\n");
@@ -929,6 +950,15 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
 		goto boot_err;
 	}
 
+	/* show firmware information */
+	sst_dsp_inbox_read(byt->dsp, &init, sizeof(init));
+	dev_info(byt->dev, "FW version: %02x.%02x.%02x.%02x\n",
+		 init.fw_version.major, init.fw_version.minor,
+		 init.fw_version.build, init.fw_version.type);
+	dev_info(byt->dev, "Build type: %x\n", init.fw_version.type);
+	dev_info(byt->dev, "Build date: %s %s\n",
+		 init.build_info.date, init.build_info.time);
+
 	pdata->dsp = byt;
 	byt->fw = byt_sst_fw;
 
diff --git a/sound/soc/intel/sst-baytrail-pcm.c b/sound/soc/intel/sst-baytrail-pcm.c
index 8eab97368ea7..599401c0c655 100644
--- a/sound/soc/intel/sst-baytrail-pcm.c
+++ b/sound/soc/intel/sst-baytrail-pcm.c
@@ -32,7 +32,7 @@ static const struct snd_pcm_hardware sst_byt_pcm_hardware = {
 				  SNDRV_PCM_INFO_PAUSE |
 				  SNDRV_PCM_INFO_RESUME,
 	.formats		= SNDRV_PCM_FMTBIT_S16_LE |
-				  SNDRV_PCM_FORMAT_S24_LE,
+				  SNDRV_PCM_FMTBIT_S24_LE,
 	.period_bytes_min	= 384,
 	.period_bytes_max	= 48000,
 	.periods_min		= 2,
diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c
index 0b715b20a2d7..cd23060a0d86 100644
--- a/sound/soc/intel/sst-dsp.c
+++ b/sound/soc/intel/sst-dsp.c
@@ -224,19 +224,23 @@ EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64);
 
 void sst_dsp_dump(struct sst_dsp *sst)
 {
-	sst->ops->dump(sst);
+	if (sst->ops->dump)
+		sst->ops->dump(sst);
 }
 EXPORT_SYMBOL_GPL(sst_dsp_dump);
 
 void sst_dsp_reset(struct sst_dsp *sst)
 {
-	sst->ops->reset(sst);
+	if (sst->ops->reset)
+		sst->ops->reset(sst);
 }
 EXPORT_SYMBOL_GPL(sst_dsp_reset);
 
 int sst_dsp_boot(struct sst_dsp *sst)
 {
-	sst->ops->boot(sst);
+	if (sst->ops->boot)
+		sst->ops->boot(sst);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(sst_dsp_boot);
diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h
index e44423be66c4..3165dfa97408 100644
--- a/sound/soc/intel/sst-dsp.h
+++ b/sound/soc/intel/sst-dsp.h
@@ -52,7 +52,11 @@
 #define SST_CLKCTL		0x78
 #define SST_CSR2		0x80
 #define SST_LTRC		0xE0
-#define SST_HDMC		0xE8
+#define SST_HMDC		0xE8
+
+#define SST_SHIM_BEGIN		SST_CSR
+#define SST_SHIM_END		SST_HDMC
+
 #define SST_DBGO		0xF0
 
 #define SST_SHIM_SIZE		0x100
@@ -73,6 +77,8 @@
 #define SST_CSR_S0IOCS		(0x1 << 21)
 #define SST_CSR_S1IOCS		(0x1 << 23)
 #define SST_CSR_LPCS		(0x1 << 31)
+#define SST_CSR_24MHZ_LPCS	(SST_CSR_SBCS0 | SST_CSR_SBCS1 | SST_CSR_LPCS)
+#define SST_CSR_24MHZ_NO_LPCS	(SST_CSR_SBCS0 | SST_CSR_SBCS1)
 #define SST_BYT_CSR_RST		(0x1 << 0)
 #define SST_BYT_CSR_VECTOR_SEL	(0x1 << 1)
 #define SST_BYT_CSR_STALL	(0x1 << 2)
@@ -92,6 +98,14 @@
 #define SST_IMRX_DONE		(0x1 << 0)
 #define SST_BYT_IMRX_REQUEST	(0x1 << 1)
 
+/* IMRD / IMD */
+#define SST_IMRD_DONE		(0x1 << 0)
+#define SST_IMRD_BUSY		(0x1 << 1)
+#define SST_IMRD_SSP0		(0x1 << 16)
+#define SST_IMRD_DMAC0		(0x1 << 21)
+#define SST_IMRD_DMAC1		(0x1 << 22)
+#define SST_IMRD_DMAC		(SST_IMRD_DMAC0 | SST_IMRD_DMAC1)
+
 /*  IPCX / IPCC */
 #define	SST_IPCX_DONE		(0x1 << 30)
 #define	SST_IPCX_BUSY		(0x1 << 31)
@@ -118,9 +132,21 @@
 /* LTRC */
 #define SST_LTRC_VAL(x)		(x << 0)
 
-/* HDMC */
-#define SST_HDMC_HDDA0(x)	(x << 0)
-#define SST_HDMC_HDDA1(x)	(x << 7)
+/* HMDC */
+#define SST_HMDC_HDDA0(x)	(x << 0)
+#define SST_HMDC_HDDA1(x)	(x << 7)
+#define SST_HMDC_HDDA_E0_CH0	1
+#define SST_HMDC_HDDA_E0_CH1	2
+#define SST_HMDC_HDDA_E0_CH2	4
+#define SST_HMDC_HDDA_E0_CH3	8
+#define SST_HMDC_HDDA_E1_CH0	SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH0)
+#define SST_HMDC_HDDA_E1_CH1	SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH1)
+#define SST_HMDC_HDDA_E1_CH2	SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH2)
+#define SST_HMDC_HDDA_E1_CH3	SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH3)
+#define SST_HMDC_HDDA_E0_ALLCH	(SST_HMDC_HDDA_E0_CH0 | SST_HMDC_HDDA_E0_CH1 | \
+				 SST_HMDC_HDDA_E0_CH2 | SST_HMDC_HDDA_E0_CH3)
+#define SST_HMDC_HDDA_E1_ALLCH	(SST_HMDC_HDDA_E1_CH0 | SST_HMDC_HDDA_E1_CH1 | \
+				 SST_HMDC_HDDA_E1_CH2 | SST_HMDC_HDDA_E1_CH3)
 
 
 /* SST Vendor Defined Registers and bits */
@@ -130,11 +156,16 @@
 #define SST_VDRTCTL3		0xaC
 
 /* VDRTCTL0 */
+#define SST_VDRTCL0_APLLSE_MASK		1
 #define SST_VDRTCL0_DSRAMPGE_SHIFT	16
 #define SST_VDRTCL0_DSRAMPGE_MASK	(0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT)
 #define SST_VDRTCL0_ISRAMPGE_SHIFT	6
 #define SST_VDRTCL0_ISRAMPGE_MASK	(0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT)
 
+/* PMCS */
+#define SST_PMCS		0x84
+#define SST_PMCS_PS_MASK	0x3
+
 struct sst_dsp;
 
 /*
diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c
index 535f517629fd..4b6c163c10ff 100644
--- a/sound/soc/intel/sst-haswell-dsp.c
+++ b/sound/soc/intel/sst-haswell-dsp.c
@@ -28,9 +28,6 @@
 #include <linux/firmware.h>
 #include <linux/pm_runtime.h>
 
-#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-
 #include "sst-dsp.h"
 #include "sst-dsp-priv.h"
 #include "sst-haswell-ipc.h"
@@ -272,9 +269,9 @@ static void hsw_boot(struct sst_dsp *sst)
 		SST_CSR2_SDFD_SSP1);
 
 	/* enable DMA engine 0,1 all channels to access host memory */
-	sst_dsp_shim_update_bits_unlocked(sst, SST_HDMC,
-		SST_HDMC_HDDA1(0xff)  | SST_HDMC_HDDA0(0xff),
-		SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff));
+	sst_dsp_shim_update_bits_unlocked(sst, SST_HMDC,
+		SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff),
+		SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff));
 
 	/* disable all clock gating */
 	writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2);
@@ -313,9 +310,7 @@ static const struct sst_adsp_memregion lp_region[] = {
 
 /* wild cat point ADSP mem regions */
 static const struct sst_adsp_memregion wpt_region[] = {
-	{0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */
-	{0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */
-	{0x80000, 0xA0000, 4, SST_MEM_DRAM}, /* D-SRAM2 - 4 * 32kB */
+	{0x00000, 0xA0000, 20, SST_MEM_DRAM}, /* D-SRAM0,D-SRAM1,D-SRAM2 - 20 * 32kB */
 	{0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */
 };
 
@@ -339,26 +334,56 @@ static int hsw_acpi_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata)
 	return 0;
 }
 
+struct sst_sram_shift {
+	u32 dev_id;	/* SST Device IDs  */
+	u32 iram_shift;
+	u32 dram_shift;
+};
+
+static const struct sst_sram_shift sram_shift[] = {
+	{SST_DEV_ID_LYNX_POINT, 6, 16}, /* lp */
+	{SST_DEV_ID_WILDCAT_POINT, 2, 12}, /* wpt */
+};
 static u32 hsw_block_get_bit(struct sst_mem_block *block)
 {
-	u32 bit = 0, shift = 0;
+	u32 bit = 0, shift = 0, index;
+	struct sst_dsp *sst = block->dsp;
 
-	switch (block->type) {
-	case SST_MEM_DRAM:
-		shift = 16;
-		break;
-	case SST_MEM_IRAM:
-		shift = 6;
-		break;
-	default:
-		return 0;
+	for (index = 0; index < ARRAY_SIZE(sram_shift); index++) {
+		if (sram_shift[index].dev_id == sst->id)
+			break;
 	}
 
+	if (index < ARRAY_SIZE(sram_shift)) {
+		switch (block->type) {
+		case SST_MEM_DRAM:
+			shift = sram_shift[index].dram_shift;
+			break;
+		case SST_MEM_IRAM:
+			shift = sram_shift[index].iram_shift;
+			break;
+		default:
+			shift = 0;
+		}
+	} else
+		shift = 0;
+
 	bit = 1 << (block->index + shift);
 
 	return bit;
 }
 
+/*dummy read a SRAM block.*/
+static void sst_mem_block_dummy_read(struct sst_mem_block *block)
+{
+	u32 size;
+	u8 tmp_buf[4];
+	struct sst_dsp *sst = block->dsp;
+
+	size = block->size > 4 ? 4 : block->size;
+	memcpy_fromio(tmp_buf, sst->addr.lpe + block->offset, size);
+}
+
 /* enable 32kB memory block - locks held by caller */
 static int hsw_block_enable(struct sst_mem_block *block)
 {
@@ -378,6 +403,8 @@ static int hsw_block_enable(struct sst_mem_block *block)
 	/* wait 18 DSP clock ticks */
 	udelay(10);
 
+	/*add a dummy read before the SRAM block is written, otherwise the writing may miss bytes sometimes.*/
+	sst_mem_block_dummy_read(block);
 	return 0;
 }
 
@@ -488,8 +515,9 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata)
 		}
 	}
 
-	/* set default power gating mask */
-	writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL0);
+	/* set default power gating control, enable power gating control for all blocks. that is,
+	can't be accessed, please enable each block before accessing. */
+	writel(0xffffffff, sst->addr.pci_cfg + SST_VDRTCTL0);
 
 	return 0;
 }
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c
index 434236343ddf..b6291516dbbf 100644
--- a/sound/soc/intel/sst-haswell-ipc.c
+++ b/sound/soc/intel/sst-haswell-ipc.c
@@ -183,7 +183,7 @@ struct sst_hsw_ipc_fw_ready {
 	u32 inbox_size;
 	u32 outbox_size;
 	u32 fw_info_size;
-	u8 fw_info[1];
+	u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)];
 } __attribute__((packed));
 
 struct ipc_message {
@@ -457,9 +457,10 @@ static void ipc_tx_msgs(struct kthread_work *work)
 		return;
 	}
 
-	/* if the DSP is busy we will TX messages after IRQ */
+	/* if the DSP is busy, we will TX messages after IRQ.
+	 * also postpone if we are in the middle of procesing completion irq*/
 	ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX);
-	if (ipcx & SST_IPCX_BUSY) {
+	if (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)) {
 		spin_unlock_irqrestore(&hsw->dsp->spinlock, flags);
 		return;
 	}
@@ -502,6 +503,7 @@ static int tx_wait_done(struct sst_hsw *hsw, struct ipc_message *msg,
 		ipc_shim_dbg(hsw, "message timeout");
 
 		trace_ipc_error("error message timeout for", msg->header);
+		list_del(&msg->list);
 		ret = -ETIMEDOUT;
 	} else {
 
@@ -569,6 +571,9 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header)
 {
 	struct sst_hsw_ipc_fw_ready fw_ready;
 	u32 offset;
+	u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)];
+	char *tmp[5], *pinfo;
+	int i = 0;
 
 	offset = (header & 0x1FFFFFFF) << 3;
 
@@ -589,6 +594,19 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header)
 		fw_ready.inbox_offset, fw_ready.inbox_size);
 	dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n",
 		fw_ready.outbox_offset, fw_ready.outbox_size);
+	if (fw_ready.fw_info_size < sizeof(fw_ready.fw_info)) {
+		fw_ready.fw_info[fw_ready.fw_info_size] = 0;
+		dev_dbg(hsw->dev, " Firmware info: %s \n", fw_ready.fw_info);
+
+		/* log the FW version info got from the mailbox here. */
+		memcpy(fw_info, fw_ready.fw_info, fw_ready.fw_info_size);
+		pinfo = &fw_info[0];
+		for (i = 0; i < sizeof(tmp) / sizeof(char *); i++)
+			tmp[i] = strsep(&pinfo, " ");
+		dev_info(hsw->dev, "FW loaded, mailbox readback FW info: type %s, - "
+			"version: %s.%s, build %s, source commit id: %s\n",
+			tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]);
+	}
 }
 
 static void hsw_notification_work(struct work_struct *work)
@@ -671,7 +689,9 @@ static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg)
 	switch (stream_msg) {
 	case IPC_STR_STAGE_MESSAGE:
 	case IPC_STR_NOTIFICATION:
+		break;
 	case IPC_STR_RESET:
+		trace_ipc_notification("stream reset", stream->reply.stream_hw_id);
 		break;
 	case IPC_STR_PAUSE:
 		stream->running = false;
@@ -762,7 +782,8 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header)
 	}
 
 	/* update any stream states */
-	hsw_stream_update(hsw, msg);
+	if (msg_get_global_type(header) == IPC_GLB_STREAM_MESSAGE)
+		hsw_stream_update(hsw, msg);
 
 	/* wake up and return the error if we have waiters on this message ? */
 	list_del(&msg->list);
@@ -1628,7 +1649,7 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw,
 	enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx)
 {
 	u32 header, state_;
-	int ret;
+	int ret, item;
 
 	header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE);
 	state_ = state;
@@ -1642,6 +1663,13 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw,
 		return ret;
 	}
 
+	for (item = 0; item < dx->entries_no; item++) {
+		dev_dbg(hsw->dev,
+			"Item[%d] offset[%x] - size[%x] - source[%x]\n",
+			item, dx->mem_info[item].offset,
+			dx->mem_info[item].size,
+			dx->mem_info[item].source);
+	}
 	dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n",
 		dx->entries_no, state);
 
@@ -1775,8 +1803,6 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
 
 	/* get the FW version */
 	sst_hsw_fw_get_version(hsw, &version);
-	dev_info(hsw->dev, "FW loaded: type %d - version: %d.%d build %d\n",
-		version.type, version.major, version.minor, version.build);
 
 	/* get the globalmixer */
 	ret = sst_hsw_mixer_get_info(hsw);
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c
index 058efb17c568..61bf6da4bb02 100644
--- a/sound/soc/intel/sst-haswell-pcm.c
+++ b/sound/soc/intel/sst-haswell-pcm.c
@@ -80,7 +80,7 @@ static const struct snd_pcm_hardware hsw_pcm_hardware = {
 				  SNDRV_PCM_INFO_PAUSE |
 				  SNDRV_PCM_INFO_RESUME |
 				  SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
-	.formats		= SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE |
+	.formats		= SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
 				  SNDRV_PCM_FMTBIT_S32_LE,
 	.period_bytes_min	= PAGE_SIZE,
 	.period_bytes_max	= (HSW_PCM_PERIODS_MAX / HSW_PCM_PERIODS_MIN) * PAGE_SIZE,
@@ -400,7 +400,15 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream,
 		sst_hsw_stream_set_valid(hsw, pcm_data->stream, 16);
 		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
-		bits = SST_HSW_DEPTH_24BIT;
+		bits = SST_HSW_DEPTH_32BIT;
+		sst_hsw_stream_set_valid(hsw, pcm_data->stream, 24);
+		break;
+	case SNDRV_PCM_FORMAT_S8:
+		bits = SST_HSW_DEPTH_8BIT;
+		sst_hsw_stream_set_valid(hsw, pcm_data->stream, 8);
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		bits = SST_HSW_DEPTH_32BIT;
 		sst_hsw_stream_set_valid(hsw, pcm_data->stream, 32);
 		break;
 	default:
@@ -685,8 +693,9 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd)
 }
 
 #define HSW_FORMATS \
-	(SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\
-	 SNDRV_PCM_FMTBIT_S32_LE)
+	(SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \
+	SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\
+	SNDRV_PCM_FMTBIT_S8)
 
 static struct snd_soc_dai_driver hsw_dais[] = {
 	{
@@ -696,7 +705,7 @@ static struct snd_soc_dai_driver hsw_dais[] = {
 			.channels_min = 2,
 			.channels_max = 2,
 			.rates = SNDRV_PCM_RATE_48000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE,
 		},
 	},
 	{
@@ -727,8 +736,8 @@ static struct snd_soc_dai_driver hsw_dais[] = {
 			.stream_name = "Loopback Capture",
 			.channels_min = 2,
 			.channels_max = 2,
-			.rates = SNDRV_PCM_RATE_8000_192000,
-			.formats = HSW_FORMATS,
+			.rates = SNDRV_PCM_RATE_48000,
+			.formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE,
 		},
 	},
 	{
@@ -737,8 +746,8 @@ static struct snd_soc_dai_driver hsw_dais[] = {
 			.stream_name = "Analog Capture",
 			.channels_min = 2,
 			.channels_max = 2,
-			.rates = SNDRV_PCM_RATE_8000_192000,
-			.formats = HSW_FORMATS,
+			.rates = SNDRV_PCM_RATE_48000,
+			.formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE,
 		},
 	},
 };
diff --git a/sound/soc/intel/sst-mfld-dsp.h b/sound/soc/intel/sst-mfld-dsp.h
index 8d482d76475a..4257263157cd 100644
--- a/sound/soc/intel/sst-mfld-dsp.h
+++ b/sound/soc/intel/sst-mfld-dsp.h
@@ -3,7 +3,7 @@
 /*
  *  sst_mfld_dsp.h - Intel SST Driver for audio engine
  *
- *  Copyright (C) 2008-12 Intel Corporation
+ *  Copyright (C) 2008-14 Intel Corporation
  *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
@@ -19,6 +19,142 @@
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
+#define SST_MAX_BIN_BYTES 1024
+
+#define MAX_DBG_RW_BYTES 80
+#define MAX_NUM_SCATTER_BUFFERS 8
+#define MAX_LOOP_BACK_DWORDS 8
+/* IPC base address and mailbox, timestamp offsets */
+#define SST_MAILBOX_SIZE 0x0400
+#define SST_MAILBOX_SEND 0x0000
+#define SST_TIME_STAMP 0x1800
+#define SST_TIME_STAMP_MRFLD 0x800
+#define SST_RESERVED_OFFSET 0x1A00
+#define SST_SCU_LPE_MAILBOX 0x1000
+#define SST_LPE_SCU_MAILBOX 0x1400
+#define SST_SCU_LPE_LOG_BUF (SST_SCU_LPE_MAILBOX+16)
+#define PROCESS_MSG 0x80
+
+/* Message ID's for IPC messages */
+/* Bits B7: SST or IA/SC ; B6-B4: Msg Category; B3-B0: Msg Type */
+
+/* I2L Firmware/Codec Download msgs */
+#define IPC_IA_PREP_LIB_DNLD 0x01
+#define IPC_IA_LIB_DNLD_CMPLT 0x02
+#define IPC_IA_GET_FW_VERSION 0x04
+#define IPC_IA_GET_FW_BUILD_INF 0x05
+#define IPC_IA_GET_FW_INFO 0x06
+#define IPC_IA_GET_FW_CTXT 0x07
+#define IPC_IA_SET_FW_CTXT 0x08
+#define IPC_IA_PREPARE_SHUTDOWN 0x31
+/* I2L Codec Config/control msgs */
+#define IPC_PREP_D3 0x10
+#define IPC_IA_SET_CODEC_PARAMS 0x10
+#define IPC_IA_GET_CODEC_PARAMS 0x11
+#define IPC_IA_SET_PPP_PARAMS 0x12
+#define IPC_IA_GET_PPP_PARAMS 0x13
+#define IPC_SST_PERIOD_ELAPSED_MRFLD 0xA
+#define IPC_IA_ALG_PARAMS 0x1A
+#define IPC_IA_TUNING_PARAMS 0x1B
+#define IPC_IA_SET_RUNTIME_PARAMS 0x1C
+#define IPC_IA_SET_PARAMS 0x1
+#define IPC_IA_GET_PARAMS 0x2
+
+#define IPC_EFFECTS_CREATE 0xE
+#define IPC_EFFECTS_DESTROY 0xF
+
+/* I2L Stream config/control msgs */
+#define IPC_IA_ALLOC_STREAM_MRFLD 0x2
+#define IPC_IA_ALLOC_STREAM 0x20 /* Allocate a stream ID */
+#define IPC_IA_FREE_STREAM_MRFLD 0x03
+#define IPC_IA_FREE_STREAM 0x21 /* Free the stream ID */
+#define IPC_IA_SET_STREAM_PARAMS 0x22
+#define IPC_IA_SET_STREAM_PARAMS_MRFLD 0x12
+#define IPC_IA_GET_STREAM_PARAMS 0x23
+#define IPC_IA_PAUSE_STREAM 0x24
+#define IPC_IA_PAUSE_STREAM_MRFLD 0x4
+#define IPC_IA_RESUME_STREAM 0x25
+#define IPC_IA_RESUME_STREAM_MRFLD 0x5
+#define IPC_IA_DROP_STREAM 0x26
+#define IPC_IA_DROP_STREAM_MRFLD 0x07
+#define IPC_IA_DRAIN_STREAM 0x27 /* Short msg with str_id */
+#define IPC_IA_DRAIN_STREAM_MRFLD 0x8
+#define IPC_IA_CONTROL_ROUTING 0x29
+#define IPC_IA_VTSV_UPDATE_MODULES 0x20
+#define IPC_IA_VTSV_DETECTED 0x21
+
+#define IPC_IA_START_STREAM_MRFLD 0X06
+#define IPC_IA_START_STREAM 0x30 /* Short msg with str_id */
+
+#define IPC_IA_SET_GAIN_MRFLD 0x21
+/* Debug msgs */
+#define IPC_IA_DBG_MEM_READ 0x40
+#define IPC_IA_DBG_MEM_WRITE 0x41
+#define IPC_IA_DBG_LOOP_BACK 0x42
+#define IPC_IA_DBG_LOG_ENABLE 0x45
+#define IPC_IA_DBG_SET_PROBE_PARAMS 0x47
+
+/* L2I Firmware/Codec Download msgs */
+#define IPC_IA_FW_INIT_CMPLT 0x81
+#define IPC_IA_FW_INIT_CMPLT_MRFLD 0x01
+#define IPC_IA_FW_ASYNC_ERR_MRFLD 0x11
+
+/* L2I Codec Config/control msgs */
+#define IPC_SST_FRAGMENT_ELPASED 0x90 /* Request IA more data */
+
+#define IPC_SST_BUF_UNDER_RUN 0x92 /* PB Under run and stopped */
+#define IPC_SST_BUF_OVER_RUN 0x93 /* CAP Under run and stopped */
+#define IPC_SST_DRAIN_END 0x94 /* PB Drain complete and stopped */
+#define IPC_SST_CHNGE_SSP_PARAMS 0x95 /* PB SSP parameters changed */
+#define IPC_SST_STREAM_PROCESS_FATAL_ERR 0x96/* error in processing a stream */
+#define IPC_SST_PERIOD_ELAPSED 0x97 /* period elapsed */
+
+#define IPC_SST_ERROR_EVENT 0x99 /* Buffer over run occurred */
+/* L2S messages */
+#define IPC_SC_DDR_LINK_UP 0xC0
+#define IPC_SC_DDR_LINK_DOWN 0xC1
+#define IPC_SC_SET_LPECLK_REQ 0xC2
+#define IPC_SC_SSP_BIT_BANG 0xC3
+
+/* L2I Error reporting msgs */
+#define IPC_IA_MEM_ALLOC_FAIL 0xE0
+#define IPC_IA_PROC_ERR 0xE1 /* error in processing a
+					stream can be used by playback and
+					capture modules */
+
+/* L2I Debug msgs */
+#define IPC_IA_PRINT_STRING 0xF0
+
+/* Buffer under-run */
+#define IPC_IA_BUF_UNDER_RUN_MRFLD 0x0B
+
+/* Mrfld specific defines:
+ * For asynchronous messages(INIT_CMPLT, PERIOD_ELAPSED, ASYNC_ERROR)
+ * received from FW, the format is:
+ *  - IPC High: pvt_id is set to zero. Always short message.
+ *  - msg_id is in lower 16-bits of IPC low payload.
+ *  - pipe_id is in higher 16-bits of IPC low payload for period_elapsed.
+ *  - error id is in higher 16-bits of IPC low payload for async errors.
+ */
+#define SST_ASYNC_DRV_ID 0
+
+/* Command Response or Acknowledge message to any IPC message will have
+ * same message ID and stream ID information which is sent.
+ * There is no specific Ack message ID. The data field is used as response
+ * meaning.
+ */
+enum ackData {
+	IPC_ACK_SUCCESS = 0,
+	IPC_ACK_FAILURE,
+};
+
+enum ipc_ia_msg_id {
+	IPC_CMD = 1,		/*!< Task Control message ID */
+	IPC_SET_PARAMS = 2,/*!< Task Set param message ID */
+	IPC_GET_PARAMS = 3,	/*!< Task Get param message ID */
+	IPC_INVALID = 0xFF,	/*!<Task Get param message ID */
+};
+
 enum sst_codec_types {
 	/*  AUDIO/MUSIC	CODEC Type Definitions */
 	SST_CODEC_TYPE_UNKNOWN = 0,
@@ -35,14 +171,157 @@ enum stream_type {
 	SST_STREAM_TYPE_MUSIC = 1,
 };
 
+enum sst_error_codes {
+	/* Error code,response to msgId: Description */
+	/* Common error codes */
+	SST_SUCCESS = 0,        /* Success */
+	SST_ERR_INVALID_STREAM_ID = 1,
+	SST_ERR_INVALID_MSG_ID = 2,
+	SST_ERR_INVALID_STREAM_OP = 3,
+	SST_ERR_INVALID_PARAMS = 4,
+	SST_ERR_INVALID_CODEC = 5,
+	SST_ERR_INVALID_MEDIA_TYPE = 6,
+	SST_ERR_STREAM_ERR = 7,
+
+	SST_ERR_STREAM_IN_USE = 15,
+};
+
+struct ipc_dsp_hdr {
+	u16 mod_index_id:8;		/*!< DSP Command ID specific to tasks */
+	u16 pipe_id:8;	/*!< instance of the module in the pipeline */
+	u16 mod_id;		/*!< Pipe_id */
+	u16 cmd_id;		/*!< Module ID = lpe_algo_types_t */
+	u16 length;		/*!< Length of the payload only */
+} __packed;
+
+union ipc_header_high {
+	struct {
+		u32  msg_id:8;	    /* Message ID - Max 256 Message Types */
+		u32  task_id:4;	    /* Task ID associated with this comand */
+		u32  drv_id:4;    /* Identifier for the driver to track*/
+		u32  rsvd1:8;	    /* Reserved */
+		u32  result:4;	    /* Reserved */
+		u32  res_rqd:1;	    /* Response rqd */
+		u32  large:1;	    /* Large Message if large = 1 */
+		u32  done:1;	    /* bit 30 - Done bit */
+		u32  busy:1;	    /* bit 31 - busy bit*/
+	} part;
+	u32 full;
+} __packed;
+/* IPC header */
+union ipc_header_mrfld {
+	struct {
+		u32 header_low_payload;
+		union ipc_header_high header_high;
+	} p;
+	u64 full;
+} __packed;
+/* CAUTION NOTE: All IPC message body must be multiple of 32 bits.*/
+
+/* IPC Header */
+union ipc_header {
+	struct {
+		u32  msg_id:8; /* Message ID - Max 256 Message Types */
+		u32  str_id:5;
+		u32  large:1;	/* Large Message if large = 1 */
+		u32  reserved:2;	/* Reserved for future use */
+		u32  data:14;	/* Ack/Info for msg, size of msg in Mailbox */
+		u32  done:1; /* bit 30 */
+		u32  busy:1; /* bit 31 */
+	} part;
+	u32 full;
+} __packed;
+
+/* Firmware build info */
+struct sst_fw_build_info {
+	unsigned char  date[16]; /* Firmware build date */
+	unsigned char  time[16]; /* Firmware build time */
+} __packed;
+
+/* Firmware Version info */
+struct snd_sst_fw_version {
+	u8 build;	/* build number*/
+	u8 minor;	/* minor number*/
+	u8 major;	/* major number*/
+	u8 type;	/* build type */
+};
+
+struct ipc_header_fw_init {
+	struct snd_sst_fw_version fw_version;/* Firmware version details */
+	struct sst_fw_build_info build_info;
+	u16 result;	/* Fw init result */
+	u8 module_id; /* Module ID in case of error */
+	u8 debug_info; /* Debug info from Module ID in case of fail */
+} __packed;
+
+struct snd_sst_tstamp {
+	u64 ring_buffer_counter;	/* PB/CP: Bytes copied from/to DDR. */
+	u64 hardware_counter;	    /* PB/CP: Bytes DMAed to/from SSP. */
+	u64 frames_decoded;
+	u64 bytes_decoded;
+	u64 bytes_copied;
+	u32 sampling_frequency;
+	u32 channel_peak[8];
+} __packed;
+
+/* Stream type params struture for Alloc stream */
+struct snd_sst_str_type {
+	u8 codec_type;		/* Codec type */
+	u8 str_type;		/* 1 = voice 2 = music */
+	u8 operation;		/* Playback or Capture */
+	u8 protected_str;	/* 0=Non DRM, 1=DRM */
+	u8 time_slots;
+	u8 reserved;		/* Reserved */
+	u16 result;		/* Result used for acknowledgment */
+} __packed;
+
+/* Library info structure */
+struct module_info {
+	u32 lib_version;
+	u32 lib_type;/*TBD- KLOCKWORK u8 lib_type;*/
+	u32 media_type;
+	u8  lib_name[12];
+	u32 lib_caps;
+	unsigned char  b_date[16]; /* Lib build date */
+	unsigned char  b_time[16]; /* Lib build time */
+} __packed;
+
+/* Library slot info */
+struct lib_slot_info {
+	u8  slot_num; /* 1 or 2 */
+	u8  reserved1;
+	u16 reserved2;
+	u32 iram_size; /* slot size in IRAM */
+	u32 dram_size; /* slot size in DRAM */
+	u32 iram_offset; /* starting offset of slot in IRAM */
+	u32 dram_offset; /* starting offset of slot in DRAM */
+} __packed;
+
+struct snd_ppp_mixer_params {
+	__u32			type; /*Type of the parameter */
+	__u32			size;
+	__u32			input_stream_bitmap; /*Input stream Bit Map*/
+} __packed;
+
+struct snd_sst_lib_download {
+	struct module_info lib_info; /* library info type, capabilities etc */
+	struct lib_slot_info slot_info; /* slot info to be downloaded */
+	u32 mod_entry_pt;
+};
+
+struct snd_sst_lib_download_info {
+	struct snd_sst_lib_download dload_lib;
+	u16 result;	/* Result used for acknowledgment */
+	u8 pvt_id; /* Private ID */
+	u8 reserved;  /* for alignment */
+};
 struct snd_pcm_params {
 	u8 num_chan;	/* 1=Mono, 2=Stereo */
 	u8 pcm_wd_sz;	/* 16/24 - bit*/
-	u32 reserved;	/* Bitrate in bits per second */
-	u32 sfreq;	/* Sampling rate in Hz */
-	u8 use_offload_path;
+	u8 use_offload_path;	/* 0-PCM using period elpased & ALSA interfaces
+				   1-PCM stream via compressed interface  */
 	u8 reserved2;
-	u16 reserved3;
+	u32 sfreq;    /* Sampling rate in Hz */
 	u8 channel_map[8];
 } __packed;
 
@@ -76,6 +355,7 @@ struct snd_aac_params {
 struct snd_wma_params {
 	u8  num_chan;	/* 1=Mono, 2=Stereo */
 	u8  pcm_wd_sz;	/* 16/24 - bit*/
+	u16 reserved1;
 	u32 brate;	/* Use the hard coded value. */
 	u32 sfreq;	/* Sampling freq eg. 8000, 441000, 48000 */
 	u32 channel_mask;  /* Channel Mask */
@@ -101,26 +381,153 @@ struct sst_address_info {
 };
 
 struct snd_sst_alloc_params_ext {
-	struct sst_address_info  ring_buf_info[8];
-	u8 sg_count;
-	u8 reserved;
-	u16 reserved2;
-	u32 frag_size;	/*Number of samples after which period elapsed
+	__u16 sg_count;
+	__u16 reserved;
+	__u32 frag_size;	/*Number of samples after which period elapsed
 				  message is sent valid only if path  = 0*/
-} __packed;
+	struct sst_address_info  ring_buf_info[8];
+};
 
 struct snd_sst_stream_params {
 	union snd_sst_codec_params uc;
 } __packed;
 
 struct snd_sst_params {
+	u32 result;
 	u32 stream_id;
 	u8 codec;
 	u8 ops;
 	u8 stream_type;
 	u8 device_type;
+	u8 task;
 	struct snd_sst_stream_params sparams;
 	struct snd_sst_alloc_params_ext aparams;
 };
 
+struct snd_sst_alloc_mrfld {
+	u16 codec_type;
+	u8 operation;
+	u8 sg_count;
+	struct sst_address_info ring_buf_info[8];
+	u32 frag_size;
+	u32 ts;
+	struct snd_sst_stream_params codec_params;
+} __packed;
+
+/* Alloc stream params structure */
+struct snd_sst_alloc_params {
+	struct snd_sst_str_type str_type;
+	struct snd_sst_stream_params stream_params;
+	struct snd_sst_alloc_params_ext alloc_params;
+} __packed;
+
+/* Alloc stream response message */
+struct snd_sst_alloc_response {
+	struct snd_sst_str_type str_type; /* Stream type for allocation */
+	struct snd_sst_lib_download lib_dnld; /* Valid only for codec dnld */
+};
+
+/* Drop response */
+struct snd_sst_drop_response {
+	u32 result;
+	u32 bytes;
+};
+
+struct snd_sst_async_msg {
+	u32 msg_id; /* Async msg id */
+	u32 payload[0];
+};
+
+struct snd_sst_async_err_msg {
+	u32 fw_resp; /* Firmware Result */
+	u32 lib_resp; /*Library result */
+} __packed;
+
+struct snd_sst_vol {
+	u32	stream_id;
+	s32	volume;
+	u32	ramp_duration;
+	u32	ramp_type;		/* Ramp type, default=0 */
+};
+
+/* Gain library parameters for mrfld
+ * based on DSP command spec v0.82
+ */
+struct snd_sst_gain_v2 {
+	u16 gain_cell_num;  /* num of gain cells to modify*/
+	u8 cell_nbr_idx; /* instance index*/
+	u8 cell_path_idx; /* pipe-id */
+	u16 module_id; /*module id */
+	u16 left_cell_gain; /* left gain value in dB*/
+	u16 right_cell_gain; /* right gain value in dB*/
+	u16 gain_time_const; /* gain time constant*/
+} __packed;
+
+struct snd_sst_mute {
+	u32	stream_id;
+	u32	mute;
+};
+
+struct snd_sst_runtime_params {
+	u8 type;
+	u8 str_id;
+	u8 size;
+	u8 rsvd;
+	void *addr;
+} __packed;
+
+enum stream_param_type {
+	SST_SET_TIME_SLOT = 0,
+	SST_SET_CHANNEL_INFO = 1,
+	OTHERS = 2, /*reserved for future params*/
+};
+
+/* CSV Voice call routing structure */
+struct snd_sst_control_routing {
+	u8 control; /* 0=start, 1=Stop */
+	u8 reserved[3];	/* Reserved- for 32 bit alignment */
+};
+
+struct ipc_post {
+	struct list_head node;
+	union ipc_header header; /* driver specific */
+	bool is_large;
+	bool is_process_reply;
+	union ipc_header_mrfld mrfld_header;
+	char *mailbox_data;
+};
+
+struct snd_sst_ctxt_params {
+	u32 address; /* Physical Address in DDR where the context is stored */
+	u32 size; /* size of the context */
+};
+
+struct snd_sst_lpe_log_params {
+	u8 dbg_type;
+	u8 module_id;
+	u8 log_level;
+	u8 reserved;
+} __packed;
+
+enum snd_sst_bytes_type {
+	SND_SST_BYTES_SET = 0x1,
+	SND_SST_BYTES_GET = 0x2,
+};
+
+struct snd_sst_bytes_v2 {
+	u8 type;
+	u8 ipc_msg;
+	u8 block;
+	u8 task_id;
+	u8 pipe_id;
+	u8 rsvd;
+	u16 len;
+	char bytes[0];
+};
+
+#define MAX_VTSV_FILES 2
+struct snd_sst_vtsv_info {
+	struct sst_address_info vfiles[MAX_VTSV_FILES];
+} __packed;
+
 #endif /* __SST_MFLD_DSP_H__ */
diff --git a/sound/soc/intel/sst-mfld-platform-compress.c b/sound/soc/intel/sst-mfld-platform-compress.c
index 02abd19fce1d..29c059ca19e8 100644
--- a/sound/soc/intel/sst-mfld-platform-compress.c
+++ b/sound/soc/intel/sst-mfld-platform-compress.c
@@ -100,14 +100,19 @@ static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
 	int retval;
 	struct snd_sst_params str_params;
 	struct sst_compress_cb cb;
+	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+	struct snd_soc_platform *platform = rtd->platform;
+	struct sst_data *ctx = snd_soc_platform_get_drvdata(platform);
 
 	stream = cstream->runtime->private_data;
 	/* construct fw structure for this*/
 	memset(&str_params, 0, sizeof(str_params));
 
-	str_params.ops = STREAM_OPS_PLAYBACK;
-	str_params.stream_type = SST_STREAM_TYPE_MUSIC;
-	str_params.device_type = SND_SST_DEVICE_COMPRESS;
+	/* fill the device type and stream id to pass to SST driver */
+	retval = sst_fill_stream_params(cstream, ctx, &str_params, true);
+	pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval);
+	if (retval < 0)
+		return retval;
 
 	switch (params->codec.id) {
 	case SND_AUDIOCODEC_MP3: {
diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c
index 7c790f51d259..706212a6a68c 100644
--- a/sound/soc/intel/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/sst-mfld-platform-pcm.c
@@ -1,7 +1,7 @@
 /*
  *  sst_mfld_platform.c - Intel MID Platform driver
  *
- *  Copyright (C) 2010-2013 Intel Corp
+ *  Copyright (C) 2010-2014 Intel Corp
  *  Author: Vinod Koul <vinod.koul@intel.com>
  *  Author: Harsha Priya <priya.harsha@intel.com>
  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -27,7 +27,9 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/compress_driver.h>
+#include <asm/platform_sst_audio.h>
 #include "sst-mfld-platform.h"
+#include "sst-atom-controls.h"
 
 struct sst_device *sst;
 static DEFINE_MUTEX(sst_lock);
@@ -92,6 +94,13 @@ static struct snd_pcm_hardware sst_platform_pcm_hw = {
 	.fifo_size = SST_FIFO_SIZE,
 };
 
+static struct sst_dev_stream_map dpcm_strm_map[] = {
+	{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* Reserved, not in use */
+	{MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0},
+	{MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0},
+	{MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0},
+};
+
 /* MFLD - MSIC */
 static struct snd_soc_dai_driver sst_platform_dai[] = {
 {
@@ -143,58 +152,142 @@ static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
 	return state;
 }
 
+static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
+				struct snd_sst_alloc_params_ext *alloc_param)
+{
+	unsigned int channels;
+	snd_pcm_uframes_t period_size;
+	ssize_t periodbytes;
+	ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
+	u32 buffer_addr = virt_to_phys(substream->dma_buffer.area);
+
+	channels = substream->runtime->channels;
+	period_size = substream->runtime->period_size;
+	periodbytes = samples_to_bytes(substream->runtime, period_size);
+	alloc_param->ring_buf_info[0].addr = buffer_addr;
+	alloc_param->ring_buf_info[0].size = buffer_bytes;
+	alloc_param->sg_count = 1;
+	alloc_param->reserved = 0;
+	alloc_param->frag_size = periodbytes * channels;
+
+}
 static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
-				struct sst_pcm_params *param)
+				struct snd_sst_stream_params *param)
 {
+	param->uc.pcm_params.num_chan = (u8) substream->runtime->channels;
+	param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
+	param->uc.pcm_params.sfreq = substream->runtime->rate;
+
+	/* PCM stream via ALSA interface */
+	param->uc.pcm_params.use_offload_path = 0;
+	param->uc.pcm_params.reserved2 = 0;
+	memset(param->uc.pcm_params.channel_map, 0, sizeof(u8));
 
-	param->num_chan = (u8) substream->runtime->channels;
-	param->pcm_wd_sz = substream->runtime->sample_bits;
-	param->reserved = 0;
-	param->sfreq = substream->runtime->rate;
-	param->ring_buffer_size = snd_pcm_lib_buffer_bytes(substream);
-	param->period_count = substream->runtime->period_size;
-	param->ring_buffer_addr = virt_to_phys(substream->dma_buffer.area);
-	pr_debug("period_cnt = %d\n", param->period_count);
-	pr_debug("sfreq= %d, wd_sz = %d\n", param->sfreq, param->pcm_wd_sz);
 }
 
-static int sst_platform_alloc_stream(struct snd_pcm_substream *substream)
+static int sst_get_stream_mapping(int dev, int sdev, int dir,
+	struct sst_dev_stream_map *map, int size)
+{
+	int i;
+
+	if (map == NULL)
+		return -EINVAL;
+
+
+	/* index 0 is not used in stream map */
+	for (i = 1; i < size; i++) {
+		if ((map[i].dev_num == dev) && (map[i].direction == dir))
+			return i;
+	}
+	return 0;
+}
+
+int sst_fill_stream_params(void *substream,
+	const struct sst_data *ctx, struct snd_sst_params *str_params, bool is_compress)
+{
+	int map_size;
+	int index;
+	struct sst_dev_stream_map *map;
+	struct snd_pcm_substream *pstream = NULL;
+	struct snd_compr_stream *cstream = NULL;
+
+	map = ctx->pdata->pdev_strm_map;
+	map_size = ctx->pdata->strm_map_size;
+
+	if (is_compress == true)
+		cstream = (struct snd_compr_stream *)substream;
+	else
+		pstream = (struct snd_pcm_substream *)substream;
+
+	str_params->stream_type = SST_STREAM_TYPE_MUSIC;
+
+	/* For pcm streams */
+	if (pstream) {
+		index = sst_get_stream_mapping(pstream->pcm->device,
+					  pstream->number, pstream->stream,
+					  map, map_size);
+		if (index <= 0)
+			return -EINVAL;
+
+		str_params->stream_id = index;
+		str_params->device_type = map[index].device_id;
+		str_params->task = map[index].task_id;
+
+		str_params->ops = (u8)pstream->stream;
+	}
+
+	if (cstream) {
+		index = sst_get_stream_mapping(cstream->device->device,
+					       0, cstream->direction,
+					       map, map_size);
+		if (index <= 0)
+			return -EINVAL;
+		str_params->stream_id = index;
+		str_params->device_type = map[index].device_id;
+		str_params->task = map[index].task_id;
+
+		str_params->ops = (u8)cstream->direction;
+	}
+	return 0;
+}
+
+static int sst_platform_alloc_stream(struct snd_pcm_substream *substream,
+		struct snd_soc_platform *platform)
 {
 	struct sst_runtime_stream *stream =
 			substream->runtime->private_data;
-	struct sst_pcm_params param = {0};
-	struct sst_stream_params str_params = {0};
-	int ret_val;
+	struct snd_sst_stream_params param = {{{0,},},};
+	struct snd_sst_params str_params = {0};
+	struct snd_sst_alloc_params_ext alloc_params = {0};
+	int ret_val = 0;
+	struct sst_data *ctx = snd_soc_platform_get_drvdata(platform);
 
 	/* set codec params and inform SST driver the same */
 	sst_fill_pcm_params(substream, &param);
+	sst_fill_alloc_params(substream, &alloc_params);
 	substream->runtime->dma_area = substream->dma_buffer.area;
 	str_params.sparams = param;
-	str_params.codec =  param.codec;
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		str_params.ops = STREAM_OPS_PLAYBACK;
-		str_params.device_type = substream->pcm->device + 1;
-		pr_debug("Playbck stream,Device %d\n",
-					substream->pcm->device);
-	} else {
-		str_params.ops = STREAM_OPS_CAPTURE;
-		str_params.device_type = SND_SST_DEVICE_CAPTURE;
-		pr_debug("Capture stream,Device %d\n",
-					substream->pcm->device);
-	}
-	ret_val = stream->ops->open(&str_params);
-	pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val);
+	str_params.aparams = alloc_params;
+	str_params.codec = SST_CODEC_TYPE_PCM;
+
+	/* fill the device type and stream id to pass to SST driver */
+	ret_val = sst_fill_stream_params(substream, ctx, &str_params, false);
 	if (ret_val < 0)
 		return ret_val;
 
-	stream->stream_info.str_id = ret_val;
-	pr_debug("str id :  %d\n", stream->stream_info.str_id);
+	stream->stream_info.str_id = str_params.stream_id;
+
+	ret_val = stream->ops->open(&str_params);
+	if (ret_val <= 0)
+		return ret_val;
+
+
 	return ret_val;
 }
 
-static void sst_period_elapsed(void *mad_substream)
+static void sst_period_elapsed(void *arg)
 {
-	struct snd_pcm_substream *substream = mad_substream;
+	struct snd_pcm_substream *substream = arg;
 	struct sst_runtime_stream *stream;
 	int status;
 
@@ -218,7 +311,7 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream)
 	pr_debug("setting buffer ptr param\n");
 	sst_set_stream_status(stream, SST_PLATFORM_INIT);
 	stream->stream_info.period_elapsed = sst_period_elapsed;
-	stream->stream_info.mad_substream = substream;
+	stream->stream_info.arg = substream;
 	stream->stream_info.buffer_ptr = 0;
 	stream->stream_info.sfreq = substream->runtime->rate;
 	ret_val = stream->ops->device_control(
@@ -230,19 +323,12 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream)
 }
 /* end -- helper functions */
 
-static int sst_platform_open(struct snd_pcm_substream *substream)
+static int sst_media_open(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
 {
+	int ret_val = 0;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct sst_runtime_stream *stream;
-	int ret_val;
-
-	pr_debug("sst_platform_open called\n");
-
-	snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw);
-	ret_val = snd_pcm_hw_constraint_integer(runtime,
-						SNDRV_PCM_HW_PARAM_PERIODS);
-	if (ret_val < 0)
-		return ret_val;
 
 	stream = kzalloc(sizeof(*stream), GFP_KERNEL);
 	if (!stream)
@@ -251,50 +337,69 @@ static int sst_platform_open(struct snd_pcm_substream *substream)
 
 	/* get the sst ops */
 	mutex_lock(&sst_lock);
-	if (!sst) {
+	if (!sst ||
+	    !try_module_get(sst->dev->driver->owner)) {
 		pr_err("no device available to run\n");
-		mutex_unlock(&sst_lock);
-		kfree(stream);
-		return -ENODEV;
-	}
-	if (!try_module_get(sst->dev->driver->owner)) {
-		mutex_unlock(&sst_lock);
-		kfree(stream);
-		return -ENODEV;
+		ret_val = -ENODEV;
+		goto out_ops;
 	}
 	stream->ops = sst->ops;
 	mutex_unlock(&sst_lock);
 
 	stream->stream_info.str_id = 0;
-	sst_set_stream_status(stream, SST_PLATFORM_INIT);
-	stream->stream_info.mad_substream = substream;
+
+	stream->stream_info.arg = substream;
 	/* allocate memory for SST API set */
 	runtime->private_data = stream;
 
-	return 0;
+	/* Make sure, that the period size is always even */
+	snd_pcm_hw_constraint_step(substream->runtime, 0,
+			   SNDRV_PCM_HW_PARAM_PERIODS, 2);
+
+	return snd_pcm_hw_constraint_integer(runtime,
+			 SNDRV_PCM_HW_PARAM_PERIODS);
+out_ops:
+	kfree(stream);
+	mutex_unlock(&sst_lock);
+	return ret_val;
 }
 
-static int sst_platform_close(struct snd_pcm_substream *substream)
+static void sst_media_close(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
 {
 	struct sst_runtime_stream *stream;
 	int ret_val = 0, str_id;
 
-	pr_debug("sst_platform_close called\n");
 	stream = substream->runtime->private_data;
 	str_id = stream->stream_info.str_id;
 	if (str_id)
 		ret_val = stream->ops->close(str_id);
 	module_put(sst->dev->driver->owner);
 	kfree(stream);
-	return ret_val;
 }
 
-static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
+static inline unsigned int get_current_pipe_id(struct snd_soc_platform *platform,
+					       struct snd_pcm_substream *substream)
+{
+	struct sst_data *sst = snd_soc_platform_get_drvdata(platform);
+	struct sst_dev_stream_map *map = sst->pdata->pdev_strm_map;
+	struct sst_runtime_stream *stream =
+			substream->runtime->private_data;
+	u32 str_id = stream->stream_info.str_id;
+	unsigned int pipe_id;
+	pipe_id = map[str_id].device_id;
+
+	pr_debug("%s: got pipe_id = %#x for str_id = %d\n",
+		 __func__, pipe_id, str_id);
+	return pipe_id;
+}
+
+static int sst_media_prepare(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
 {
 	struct sst_runtime_stream *stream;
 	int ret_val = 0, str_id;
 
-	pr_debug("sst_platform_pcm_prepare called\n");
 	stream = substream->runtime->private_data;
 	str_id = stream->stream_info.str_id;
 	if (stream->stream_info.str_id) {
@@ -303,8 +408,8 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
 		return ret_val;
 	}
 
-	ret_val = sst_platform_alloc_stream(substream);
-	if (ret_val < 0)
+	ret_val = sst_platform_alloc_stream(substream, dai->platform);
+	if (ret_val <= 0)
 		return ret_val;
 	snprintf(substream->pcm->id, sizeof(substream->pcm->id),
 			"%d", stream->stream_info.str_id);
@@ -316,6 +421,41 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
 	return ret_val;
 }
 
+static int sst_media_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *dai)
+{
+	snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+	memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
+	return 0;
+}
+
+static int sst_media_hw_free(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static struct snd_soc_dai_ops sst_media_dai_ops = {
+	.startup = sst_media_open,
+	.shutdown = sst_media_close,
+	.prepare = sst_media_prepare,
+	.hw_params = sst_media_hw_params,
+	.hw_free = sst_media_hw_free,
+};
+
+static int sst_platform_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime;
+
+	if (substream->pcm->internal)
+		return 0;
+
+	runtime = substream->runtime;
+	runtime->hw = sst_platform_pcm_hw;
+	return 0;
+}
+
 static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
 					int cmd)
 {
@@ -331,7 +471,7 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
 		pr_debug("sst: Trigger Start\n");
 		str_cmd = SST_SND_START;
 		status = SST_PLATFORM_RUNNING;
-		stream->stream_info.mad_substream = substream;
+		stream->stream_info.arg = substream;
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 		pr_debug("sst: in stop\n");
@@ -377,32 +517,15 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer
 		pr_err("sst: error code = %d\n", ret_val);
 		return ret_val;
 	}
-	return stream->stream_info.buffer_ptr;
-}
-
-static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream,
-		struct snd_pcm_hw_params *params)
-{
-	snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
-	memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
-
-	return 0;
-}
-
-static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-	return snd_pcm_lib_free_pages(substream);
+	substream->runtime->delay = str_info->pcm_delay;
+	return str_info->buffer_ptr;
 }
 
 static struct snd_pcm_ops sst_platform_ops = {
 	.open = sst_platform_open,
-	.close = sst_platform_close,
 	.ioctl = snd_pcm_lib_ioctl,
-	.prepare = sst_platform_pcm_prepare,
 	.trigger = sst_platform_pcm_trigger,
 	.pointer = sst_platform_pcm_pointer,
-	.hw_params = sst_platform_pcm_hw_params,
-	.hw_free = sst_platform_pcm_hw_free,
 };
 
 static void sst_pcm_free(struct snd_pcm *pcm)
@@ -413,15 +536,15 @@ static void sst_pcm_free(struct snd_pcm *pcm)
 
 static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_soc_dai *dai = rtd->cpu_dai;
 	struct snd_pcm *pcm = rtd->pcm;
 	int retval = 0;
 
-	pr_debug("sst_pcm_new called\n");
-	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream ||
-			pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+	if (dai->driver->playback.channels_min ||
+			dai->driver->capture.channels_min) {
 		retval =  snd_pcm_lib_preallocate_pages_for_all(pcm,
 			SNDRV_DMA_TYPE_CONTINUOUS,
-			snd_dma_continuous_data(GFP_KERNEL),
+			snd_dma_continuous_data(GFP_DMA),
 			SST_MIN_BUFFER, SST_MAX_BUFFER);
 		if (retval) {
 			pr_err("dma buffer allocationf fail\n");
@@ -445,10 +568,28 @@ static const struct snd_soc_component_driver sst_component = {
 
 static int sst_platform_probe(struct platform_device *pdev)
 {
+	struct sst_data *drv;
 	int ret;
+	struct sst_platform_data *pdata;
+
+	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+	if (drv == NULL) {
+		pr_err("kzalloc failed\n");
+		return -ENOMEM;
+	}
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (pdata == NULL) {
+		pr_err("kzalloc failed for pdata\n");
+		return -ENOMEM;
+	}
+
+	pdata->pdev_strm_map = dpcm_strm_map;
+	pdata->strm_map_size = ARRAY_SIZE(dpcm_strm_map);
+	drv->pdata = pdata;
+	mutex_init(&drv->lock);
+	dev_set_drvdata(&pdev->dev, drv);
 
-	pr_debug("sst_platform_probe called\n");
-	sst = NULL;
 	ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
 	if (ret) {
 		pr_err("registering soc platform failed\n");
diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h
index 6c5e7dc49e3c..6c6a42c08e24 100644
--- a/sound/soc/intel/sst-mfld-platform.h
+++ b/sound/soc/intel/sst-mfld-platform.h
@@ -39,9 +39,10 @@ extern struct sst_device *sst;
 
 struct pcm_stream_info {
 	int str_id;
-	void *mad_substream;
-	void (*period_elapsed) (void *mad_substream);
+	void *arg;
+	void (*period_elapsed) (void *arg);
 	unsigned long long buffer_ptr;
+	unsigned long long pcm_delay;
 	int sfreq;
 };
 
@@ -62,7 +63,9 @@ enum sst_controls {
 	SST_SND_BUFFER_POINTER =	0x05,
 	SST_SND_STREAM_INIT =		0x06,
 	SST_SND_START	 =		0x07,
-	SST_MAX_CONTROLS =		0x07,
+	SST_SET_BYTE_STREAM =           0x100A,
+	SST_GET_BYTE_STREAM =           0x100B,
+	SST_MAX_CONTROLS = SST_GET_BYTE_STREAM,
 };
 
 enum sst_stream_ops {
@@ -124,8 +127,9 @@ struct compress_sst_ops {
 };
 
 struct sst_ops {
-	int (*open) (struct sst_stream_params *str_param);
+	int (*open) (struct snd_sst_params *str_param);
 	int (*device_control) (int cmd, void *arg);
+	int (*set_generic_params)(enum sst_controls cmd, void *arg);
 	int (*close) (unsigned int str_id);
 };
 
@@ -143,10 +147,27 @@ struct sst_device {
 	char *name;
 	struct device *dev;
 	struct sst_ops *ops;
+	struct platform_device *pdev;
 	struct compress_sst_ops *compr_ops;
 };
 
+struct sst_data;
 void sst_set_stream_status(struct sst_runtime_stream *stream, int state);
+int sst_fill_stream_params(void *substream, const struct sst_data *ctx,
+			   struct snd_sst_params *str_params, bool is_compress);
+
+struct sst_algo_int_control_v2 {
+	struct soc_mixer_control mc;
+	u16 module_id; /* module identifieer */
+	u16 pipe_id; /* location info: pipe_id + instance_id */
+	u16 instance_id;
+	unsigned int value; /* Value received is stored here */
+};
+struct sst_data {
+	struct platform_device *pdev;
+	struct sst_platform_data *pdata;
+	struct mutex lock;
+};
 int sst_register_dsp(struct sst_device *sst);
 int sst_unregister_dsp(struct sst_device *sst);
 #endif
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig
index 06f4e8aa93ae..132bb83f8e99 100644
--- a/sound/soc/kirkwood/Kconfig
+++ b/sound/soc/kirkwood/Kconfig
@@ -1,6 +1,6 @@
 config SND_KIRKWOOD_SOC
 	tristate "SoC Audio for the Marvell Kirkwood and Dove chips"
-	depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU || MACH_KIRKWOOD || COMPILE_TEST
+	depends on ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST
 	help
 	  Say Y or M if you want to add support for codecs attached to
 	  the Kirkwood I2S interface. You will also need to select the
@@ -15,20 +15,3 @@ config SND_KIRKWOOD_SOC_ARMADA370_DB
 	  Say Y if you want to add support for SoC audio on
 	  the Armada 370 Development Board.
 
-config SND_KIRKWOOD_SOC_OPENRD
-	tristate "SoC Audio support for Kirkwood Openrd Client"
-	depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE || COMPILE_TEST)
-	depends on I2C
-	select SND_SOC_CS42L51
-	help
-	  Say Y if you want to add support for SoC audio on
-	  Openrd Client.
-
-config SND_KIRKWOOD_SOC_T5325
-	tristate "SoC Audio support for HP t5325"
-	depends on SND_KIRKWOOD_SOC && (MACH_T5325 || COMPILE_TEST) && I2C
-	select SND_SOC_ALC5623
-	help
-	  Say Y if you want to add support for SoC audio on
-	  the HP t5325 thin client.
-
diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile
index 7c1d8fe09e6b..c36b03d8006c 100644
--- a/sound/soc/kirkwood/Makefile
+++ b/sound/soc/kirkwood/Makefile
@@ -2,10 +2,6 @@ snd-soc-kirkwood-objs := kirkwood-dma.o kirkwood-i2s.o
 
 obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o
 
-snd-soc-openrd-objs := kirkwood-openrd.o
-snd-soc-t5325-objs := kirkwood-t5325.o
 snd-soc-armada-370-db-objs := armada-370-db.o
 
 obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o
-obj-$(CONFIG_SND_KIRKWOOD_SOC_OPENRD) += snd-soc-openrd.o
-obj-$(CONFIG_SND_KIRKWOOD_SOC_T5325) += snd-soc-t5325.o
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index aac22fccdcdc..4cf2245950d7 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -28,11 +28,12 @@ static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs)
 }
 
 static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
-	.info = (SNDRV_PCM_INFO_INTERLEAVED |
-		 SNDRV_PCM_INFO_MMAP |
-		 SNDRV_PCM_INFO_MMAP_VALID |
-		 SNDRV_PCM_INFO_BLOCK_TRANSFER |
-		 SNDRV_PCM_INFO_PAUSE),
+	.info = SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_MMAP_VALID |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_PAUSE |
+		SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
 	.buffer_bytes_max	= KIRKWOOD_SND_MAX_BUFFER_BYTES,
 	.period_bytes_min	= KIRKWOOD_SND_MIN_PERIOD_BYTES,
 	.period_bytes_max	= KIRKWOOD_SND_MAX_PERIOD_BYTES,
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index 9f842222e798..0704cd6d2314 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -212,7 +212,8 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
 				    KIRKWOOD_PLAYCTL_SIZE_MASK);
 		priv->ctl_play |= ctl_play;
 	} else {
-		priv->ctl_rec &= ~KIRKWOOD_RECCTL_SIZE_MASK;
+		priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK |
+				   KIRKWOOD_RECCTL_SIZE_MASK);
 		priv->ctl_rec |= ctl_rec;
 	}
 
@@ -221,14 +222,24 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
 	return 0;
 }
 
+static unsigned kirkwood_i2s_play_mute(unsigned ctl)
+{
+	if (!(ctl & KIRKWOOD_PLAYCTL_I2S_EN))
+		ctl |= KIRKWOOD_PLAYCTL_I2S_MUTE;
+	if (!(ctl & KIRKWOOD_PLAYCTL_SPDIF_EN))
+		ctl |= KIRKWOOD_PLAYCTL_SPDIF_MUTE;
+	return ctl;
+}
+
 static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
 				int cmd, struct snd_soc_dai *dai)
 {
+	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
 	uint32_t ctl, value;
 
 	ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
-	if (ctl & KIRKWOOD_PLAYCTL_PAUSE) {
+	if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) {
 		unsigned timeout = 5000;
 		/*
 		 * The Armada510 spec says that if we enter pause mode, the
@@ -256,14 +267,16 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
 			ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN;	/* i2s */
 		else
 			ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN;	/* spdif */
-
+		ctl = kirkwood_i2s_play_mute(ctl);
 		value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
 		writel(value, priv->io + KIRKWOOD_PLAYCTL);
 
 		/* enable interrupts */
-		value = readl(priv->io + KIRKWOOD_INT_MASK);
-		value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
-		writel(value, priv->io + KIRKWOOD_INT_MASK);
+		if (!runtime->no_period_wakeup) {
+			value = readl(priv->io + KIRKWOOD_INT_MASK);
+			value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
+			writel(value, priv->io + KIRKWOOD_INT_MASK);
+		}
 
 		/* enable playback */
 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
@@ -295,6 +308,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
 				KIRKWOOD_PLAYCTL_SPDIF_MUTE);
+		ctl = kirkwood_i2s_play_mute(ctl);
 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 		break;
 
@@ -322,8 +336,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
 		else
 			ctl &= ~KIRKWOOD_RECCTL_I2S_EN;		/* spdif */
 
-		value = ctl & ~(KIRKWOOD_RECCTL_I2S_EN |
-				KIRKWOOD_RECCTL_SPDIF_EN);
+		value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK;
 		writel(value, priv->io + KIRKWOOD_RECCTL);
 
 		/* enable interrupts */
@@ -347,7 +360,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
 
 		/* disable all records */
 		value = readl(priv->io + KIRKWOOD_RECCTL);
-		value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN);
+		value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
 		writel(value, priv->io + KIRKWOOD_RECCTL);
 		break;
 
@@ -411,7 +424,7 @@ static int kirkwood_i2s_init(struct kirkwood_dma_data *priv)
 	writel(value, priv->io + KIRKWOOD_PLAYCTL);
 
 	value = readl(priv->io + KIRKWOOD_RECCTL);
-	value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN);
+	value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
 	writel(value, priv->io + KIRKWOOD_RECCTL);
 
 	return 0;
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
deleted file mode 100644
index 65f2a5b9ec3b..000000000000
--- a/sound/soc/kirkwood/kirkwood-openrd.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * kirkwood-openrd.c
- *
- * (c) 2010 Arnaud Patard <apatard@mandriva.com>
- * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <sound/soc.h>
-#include <linux/platform_data/asoc-kirkwood.h>
-#include "../codecs/cs42l51.h"
-
-static int openrd_client_hw_params(struct snd_pcm_substream *substream,
-		struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	unsigned int freq;
-
-	switch (params_rate(params)) {
-	default:
-	case 44100:
-		freq = 11289600;
-		break;
-	case 48000:
-		freq = 12288000;
-		break;
-	case 96000:
-		freq = 24576000;
-		break;
-	}
-
-	return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN);
-
-}
-
-static struct snd_soc_ops openrd_client_ops = {
-	.hw_params = openrd_client_hw_params,
-};
-
-
-static struct snd_soc_dai_link openrd_client_dai[] = {
-{
-	.name = "CS42L51",
-	.stream_name = "CS42L51 HiFi",
-	.cpu_dai_name = "i2s",
-	.platform_name = "mvebu-audio",
-	.codec_dai_name = "cs42l51-hifi",
-	.codec_name = "cs42l51-codec.0-004a",
-	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
-	.ops = &openrd_client_ops,
-},
-};
-
-
-static struct snd_soc_card openrd_client = {
-	.name = "OpenRD Client",
-	.owner = THIS_MODULE,
-	.dai_link = openrd_client_dai,
-	.num_links = ARRAY_SIZE(openrd_client_dai),
-};
-
-static int openrd_probe(struct platform_device *pdev)
-{
-	struct snd_soc_card *card = &openrd_client;
-	int ret;
-
-	card->dev = &pdev->dev;
-
-	ret = snd_soc_register_card(card);
-	if (ret)
-		dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
-			ret);
-	return ret;
-}
-
-static int openrd_remove(struct platform_device *pdev)
-{
-	struct snd_soc_card *card = platform_get_drvdata(pdev);
-
-	snd_soc_unregister_card(card);
-	return 0;
-}
-
-static struct platform_driver openrd_driver = {
-	.driver		= {
-		.name	= "openrd-client-audio",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= openrd_probe,
-	.remove		= openrd_remove,
-};
-
-module_platform_driver(openrd_driver);
-
-/* Module information */
-MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
-MODULE_DESCRIPTION("ALSA SoC OpenRD Client");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:openrd-client-audio");
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c
deleted file mode 100644
index 844b8415a011..000000000000
--- a/sound/soc/kirkwood/kirkwood-t5325.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * kirkwood-t5325.c
- *
- * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <sound/soc.h>
-#include <linux/platform_data/asoc-kirkwood.h>
-#include "../codecs/alc5623.h"
-
-static int t5325_hw_params(struct snd_pcm_substream *substream,
-		struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	unsigned int freq;
-
-	freq = params_rate(params) * 256;
-
-	return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN);
-
-}
-
-static struct snd_soc_ops t5325_ops = {
-	.hw_params = t5325_hw_params,
-};
-
-static const struct snd_soc_dapm_widget t5325_dapm_widgets[] = {
-	SND_SOC_DAPM_HP("Headphone Jack", NULL),
-	SND_SOC_DAPM_SPK("Speaker", NULL),
-	SND_SOC_DAPM_MIC("Mic Jack", NULL),
-};
-
-static const struct snd_soc_dapm_route t5325_route[] = {
-	{ "Headphone Jack",	NULL,	"HPL" },
-	{ "Headphone Jack",	NULL,	"HPR" },
-
-	{"Speaker",		NULL,	"SPKOUT"},
-	{"Speaker",		NULL,	"SPKOUTN"},
-
-	{ "MIC1",		NULL,	"Mic Jack" },
-	{ "MIC2",		NULL,	"Mic Jack" },
-};
-
-static struct snd_soc_dai_link t5325_dai[] = {
-{
-	.name = "ALC5621",
-	.stream_name = "ALC5621 HiFi",
-	.cpu_dai_name = "i2s",
-	.platform_name = "mvebu-audio",
-	.codec_dai_name = "alc5621-hifi",
-	.codec_name = "alc562x-codec.0-001a",
-	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
-	.ops = &t5325_ops,
-},
-};
-
-static struct snd_soc_card t5325 = {
-	.name = "t5325",
-	.owner = THIS_MODULE,
-	.dai_link = t5325_dai,
-	.num_links = ARRAY_SIZE(t5325_dai),
-
-	.dapm_widgets = t5325_dapm_widgets,
-	.num_dapm_widgets = ARRAY_SIZE(t5325_dapm_widgets),
-	.dapm_routes = t5325_route,
-	.num_dapm_routes = ARRAY_SIZE(t5325_route),
-};
-
-static int t5325_probe(struct platform_device *pdev)
-{
-	struct snd_soc_card *card = &t5325;
-	int ret;
-
-	card->dev = &pdev->dev;
-
-	ret = snd_soc_register_card(card);
-	if (ret)
-		dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
-			ret);
-	return ret;
-}
-
-static int t5325_remove(struct platform_device *pdev)
-{
-	struct snd_soc_card *card = platform_get_drvdata(pdev);
-
-	snd_soc_unregister_card(card);
-	return 0;
-}
-
-static struct platform_driver t5325_driver = {
-	.driver		= {
-		.name	= "t5325-audio",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= t5325_probe,
-	.remove		= t5325_remove,
-};
-
-module_platform_driver(t5325_driver);
-
-MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
-MODULE_DESCRIPTION("ALSA SoC t5325 audio client");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:t5325-audio");
diff --git a/sound/soc/kirkwood/kirkwood.h b/sound/soc/kirkwood/kirkwood.h
index bf23afbba1d7..90e32a781424 100644
--- a/sound/soc/kirkwood/kirkwood.h
+++ b/sound/soc/kirkwood/kirkwood.h
@@ -38,6 +38,9 @@
 #define KIRKWOOD_RECCTL_SIZE_24		(1<<0)
 #define KIRKWOOD_RECCTL_SIZE_32		(0<<0)
 
+#define KIRKWOOD_RECCTL_ENABLE_MASK		(KIRKWOOD_RECCTL_SPDIF_EN | \
+						 KIRKWOOD_RECCTL_I2S_EN)
+
 #define KIRKWOOD_REC_BUF_ADDR			0x1004
 #define KIRKWOOD_REC_BUF_SIZE			0x1008
 #define KIRKWOOD_REC_BYTE_COUNT			0x100C
@@ -121,9 +124,9 @@
 
 /* Theses values come from the marvell alsa driver */
 /* need to find where they come from               */
-#define KIRKWOOD_SND_MIN_PERIODS		8
+#define KIRKWOOD_SND_MIN_PERIODS		2
 #define KIRKWOOD_SND_MAX_PERIODS		16
-#define KIRKWOOD_SND_MIN_PERIOD_BYTES		0x800
+#define KIRKWOOD_SND_MIN_PERIOD_BYTES		256
 #define KIRKWOOD_SND_MAX_PERIOD_BYTES		0x8000
 #define KIRKWOOD_SND_MAX_BUFFER_BYTES		(KIRKWOOD_SND_MAX_PERIOD_BYTES \
 						 * KIRKWOOD_SND_MAX_PERIODS)
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 0cc41f94de4e..8c9cc64a9dfb 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -301,7 +301,7 @@ static int cx81801_open(struct tty_struct *tty)
 static void cx81801_close(struct tty_struct *tty)
 {
 	struct snd_soc_codec *codec = tty->disc_data;
-	struct snd_soc_dapm_context *dapm = &codec->card->dapm;
+	struct snd_soc_dapm_context *dapm = &codec->component.card->dapm;
 
 	del_timer_sync(&cx81801_timer);
 
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
index 6925d7141215..0f34e28a3d55 100644
--- a/sound/soc/omap/omap-dmic.c
+++ b/sound/soc/omap/omap-dmic.c
@@ -466,7 +466,7 @@ static int asoc_dmic_probe(struct platform_device *pdev)
 
 	mutex_init(&dmic->mutex);
 
-	dmic->fclk = clk_get(dmic->dev, "fck");
+	dmic->fclk = devm_clk_get(dmic->dev, "fck");
 	if (IS_ERR(dmic->fclk)) {
 		dev_err(dmic->dev, "cant get fck\n");
 		return -ENODEV;
@@ -475,8 +475,7 @@ static int asoc_dmic_probe(struct platform_device *pdev)
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
 	if (!res) {
 		dev_err(dmic->dev, "invalid dma memory resource\n");
-		ret = -ENODEV;
-		goto err_put_clk;
+		return -ENODEV;
 	}
 	dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG;
 
@@ -484,34 +483,19 @@ static int asoc_dmic_probe(struct platform_device *pdev)
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
 	dmic->io_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dmic->io_base)) {
-		ret = PTR_ERR(dmic->io_base);
-		goto err_put_clk;
-	}
+	if (IS_ERR(dmic->io_base))
+		return PTR_ERR(dmic->io_base);
 
 
-	ret = snd_soc_register_component(&pdev->dev, &omap_dmic_component,
-					 &omap_dmic_dai, 1);
+	ret = devm_snd_soc_register_component(&pdev->dev,
+					      &omap_dmic_component,
+					      &omap_dmic_dai, 1);
 	if (ret)
-		goto err_put_clk;
+		return ret;
 
 	ret = omap_pcm_platform_register(&pdev->dev);
 	if (ret)
-		goto err_put_clk;
-
-	return 0;
-
-err_put_clk:
-	clk_put(dmic->fclk);
-	return ret;
-}
-
-static int asoc_dmic_remove(struct platform_device *pdev)
-{
-	struct omap_dmic *dmic = platform_get_drvdata(pdev);
-
-	snd_soc_unregister_component(&pdev->dev);
-	clk_put(dmic->fclk);
+		return ret;
 
 	return 0;
 }
@@ -529,7 +513,6 @@ static struct platform_driver asoc_dmic_driver = {
 		.of_match_table = omap_dmic_of_match,
 	},
 	.probe = asoc_dmic_probe,
-	.remove = asoc_dmic_remove,
 };
 
 module_platform_driver(asoc_dmic_driver);
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index efe2cd699b77..bd3ef2a88be0 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -805,8 +805,9 @@ static int asoc_mcbsp_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	ret = snd_soc_register_component(&pdev->dev, &omap_mcbsp_component,
-					 &omap_mcbsp_dai, 1);
+	ret = devm_snd_soc_register_component(&pdev->dev,
+					      &omap_mcbsp_component,
+					      &omap_mcbsp_dai, 1);
 	if (ret)
 		return ret;
 
@@ -817,8 +818,6 @@ static int asoc_mcbsp_remove(struct platform_device *pdev)
 {
 	struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
 
-	snd_soc_unregister_component(&pdev->dev);
-
 	if (mcbsp->pdata->ops && mcbsp->pdata->ops->free)
 		mcbsp->pdata->ops->free(mcbsp->id);
 
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 8d809f8509c8..f4b05bc23e4b 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -31,6 +31,7 @@
 #include <sound/pcm_params.h>
 #include <sound/dmaengine_pcm.h>
 #include <sound/soc.h>
+#include <sound/omap-pcm.h>
 
 #ifdef CONFIG_ARCH_OMAP1
 #define pcm_omap1510()	cpu_is_omap1510()
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 199a8b377553..0109f6c2334e 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -723,7 +723,8 @@ static int pxa_ssp_probe(struct snd_soc_dai *dai)
 		ssp_handle = of_parse_phandle(dev->of_node, "port", 0);
 		if (!ssp_handle) {
 			dev_err(dev, "unable to get 'port' phandle\n");
-			return -ENODEV;
+			ret = -ENODEV;
+			goto err_priv;
 		}
 
 		priv->ssp = pxa_ssp_request_of(ssp_handle, "SoC audio");
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
new file mode 100644
index 000000000000..c196a466eef6
--- /dev/null
+++ b/sound/soc/rockchip/Kconfig
@@ -0,0 +1,12 @@
+config SND_SOC_ROCKCHIP
+	tristate "ASoC support for Rockchip"
+	depends on COMPILE_TEST || ARCH_ROCKCHIP
+	select SND_SOC_GENERIC_DMAENGINE_PCM
+	select SND_ROCKCHIP_I2S
+	help
+	  Say Y or M if you want to add support for codecs attached to
+	  the Rockchip SoCs' Audio interfaces. You will also need to
+	  select the audio interfaces to support below.
+
+config SND_ROCKCHIP_I2S
+	tristate
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
new file mode 100644
index 000000000000..1006418e1394
--- /dev/null
+++ b/sound/soc/rockchip/Makefile
@@ -0,0 +1,4 @@
+# ROCKCHIP Platform Support
+snd-soc-i2s-objs := rockchip_i2s.o
+
+obj-$(CONFIG_SND_ROCKCHIP_I2S) += snd-soc-i2s.o
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
new file mode 100644
index 000000000000..8d8e4b59049f
--- /dev/null
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -0,0 +1,529 @@
+/* sound/soc/rockchip/rockchip_i2s.c
+ *
+ * ALSA SoC Audio Layer - Rockchip I2S Controller driver
+ *
+ * Copyright (c) 2014 Rockchip Electronics Co. Ltd.
+ * Author: Jianqun <jay.xu@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/of_gpio.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include <sound/dmaengine_pcm.h>
+
+#include "rockchip_i2s.h"
+
+#define DRV_NAME "rockchip-i2s"
+
+struct rk_i2s_dev {
+	struct device *dev;
+
+	struct clk *hclk;
+	struct clk *mclk;
+
+	struct snd_dmaengine_dai_dma_data capture_dma_data;
+	struct snd_dmaengine_dai_dma_data playback_dma_data;
+
+	struct regmap *regmap;
+
+/*
+ * Used to indicate the tx/rx status.
+ * I2S controller hopes to start the tx and rx together,
+ * also to stop them when they are both try to stop.
+*/
+	bool tx_start;
+	bool rx_start;
+};
+
+static int i2s_runtime_suspend(struct device *dev)
+{
+	struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(i2s->mclk);
+
+	return 0;
+}
+
+static int i2s_runtime_resume(struct device *dev)
+{
+	struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_prepare_enable(i2s->mclk);
+	if (ret) {
+		dev_err(i2s->dev, "clock enable failed %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)
+{
+	return snd_soc_dai_get_drvdata(dai);
+}
+
+static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
+{
+	unsigned int val = 0;
+	int retry = 10;
+
+	if (on) {
+		regmap_update_bits(i2s->regmap, I2S_DMACR,
+				   I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
+
+		regmap_update_bits(i2s->regmap, I2S_XFER,
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START,
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START);
+
+		i2s->tx_start = true;
+	} else {
+		i2s->tx_start = false;
+
+		regmap_update_bits(i2s->regmap, I2S_DMACR,
+				   I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
+
+		if (!i2s->rx_start) {
+			regmap_update_bits(i2s->regmap, I2S_XFER,
+					   I2S_XFER_TXS_START |
+					   I2S_XFER_RXS_START,
+					   I2S_XFER_TXS_STOP |
+					   I2S_XFER_RXS_STOP);
+
+			regmap_update_bits(i2s->regmap, I2S_CLR,
+					   I2S_CLR_TXC | I2S_CLR_RXC,
+					   I2S_CLR_TXC | I2S_CLR_RXC);
+
+			regmap_read(i2s->regmap, I2S_CLR, &val);
+
+			/* Should wait for clear operation to finish */
+			while (val) {
+				regmap_read(i2s->regmap, I2S_CLR, &val);
+				retry--;
+				if (!retry)
+					dev_warn(i2s->dev, "fail to clear\n");
+			}
+		}
+	}
+}
+
+static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
+{
+	unsigned int val = 0;
+	int retry = 10;
+
+	if (on) {
+		regmap_update_bits(i2s->regmap, I2S_DMACR,
+				   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
+
+		regmap_update_bits(i2s->regmap, I2S_XFER,
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START,
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START);
+
+		i2s->rx_start = true;
+	} else {
+		i2s->rx_start = false;
+
+		regmap_update_bits(i2s->regmap, I2S_DMACR,
+				   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
+
+		if (!i2s->tx_start) {
+			regmap_update_bits(i2s->regmap, I2S_XFER,
+					   I2S_XFER_TXS_START |
+					   I2S_XFER_RXS_START,
+					   I2S_XFER_TXS_STOP |
+					   I2S_XFER_RXS_STOP);
+
+			regmap_update_bits(i2s->regmap, I2S_CLR,
+					   I2S_CLR_TXC | I2S_CLR_RXC,
+					   I2S_CLR_TXC | I2S_CLR_RXC);
+
+			regmap_read(i2s->regmap, I2S_CLR, &val);
+
+			/* Should wait for clear operation to finish */
+			while (val) {
+				regmap_read(i2s->regmap, I2S_CLR, &val);
+				retry--;
+				if (!retry)
+					dev_warn(i2s->dev, "fail to clear\n");
+			}
+		}
+	}
+}
+
+static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
+				unsigned int fmt)
+{
+	struct rk_i2s_dev *i2s = to_info(cpu_dai);
+	unsigned int mask = 0, val = 0;
+
+	mask = I2S_CKR_MSS_SLAVE;
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		val = I2S_CKR_MSS_SLAVE;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		val = I2S_CKR_MSS_MASTER;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
+
+	mask = I2S_TXCR_IBM_MASK;
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_RIGHT_J:
+		val = I2S_TXCR_IBM_RSJM;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		val = I2S_TXCR_IBM_LSJM;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		val = I2S_TXCR_IBM_NORMAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val);
+
+	mask = I2S_RXCR_IBM_MASK;
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_RIGHT_J:
+		val = I2S_RXCR_IBM_RSJM;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		val = I2S_RXCR_IBM_LSJM;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		val = I2S_RXCR_IBM_NORMAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val);
+
+	return 0;
+}
+
+static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *params,
+				  struct snd_soc_dai *dai)
+{
+	struct rk_i2s_dev *i2s = to_info(dai);
+	unsigned int val = 0;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+		val |= I2S_TXCR_VDW(8);
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		val |= I2S_TXCR_VDW(16);
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		val |= I2S_TXCR_VDW(20);
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		val |= I2S_TXCR_VDW(24);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(i2s->regmap, I2S_TXCR, I2S_TXCR_VDW_MASK, val);
+	regmap_update_bits(i2s->regmap, I2S_RXCR, I2S_RXCR_VDW_MASK, val);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		dai->playback_dma_data = &i2s->playback_dma_data;
+		regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
+				   I2S_DMACR_TDL(1) | I2S_DMACR_TDE_ENABLE);
+	} else {
+		dai->capture_dma_data = &i2s->capture_dma_data;
+		regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
+				   I2S_DMACR_RDL(1) | I2S_DMACR_RDE_ENABLE);
+	}
+
+	return 0;
+}
+
+static int rockchip_i2s_trigger(struct snd_pcm_substream *substream,
+				int cmd, struct snd_soc_dai *dai)
+{
+	struct rk_i2s_dev *i2s = to_info(dai);
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+			rockchip_snd_rxctrl(i2s, 1);
+		else
+			rockchip_snd_txctrl(i2s, 1);
+		break;
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+			rockchip_snd_rxctrl(i2s, 0);
+		else
+			rockchip_snd_txctrl(i2s, 0);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
+				   unsigned int freq, int dir)
+{
+	struct rk_i2s_dev *i2s = to_info(cpu_dai);
+	int ret;
+
+	ret = clk_set_rate(i2s->mclk, freq);
+	if (ret)
+		dev_err(i2s->dev, "Fail to set mclk %d\n", ret);
+
+	return ret;
+}
+
+static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
+	.hw_params = rockchip_i2s_hw_params,
+	.set_sysclk = rockchip_i2s_set_sysclk,
+	.set_fmt = rockchip_i2s_set_fmt,
+	.trigger = rockchip_i2s_trigger,
+};
+
+static struct snd_soc_dai_driver rockchip_i2s_dai = {
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 8,
+		.rates = SNDRV_PCM_RATE_8000_192000,
+		.formats = (SNDRV_PCM_FMTBIT_S8 |
+			    SNDRV_PCM_FMTBIT_S16_LE |
+			    SNDRV_PCM_FMTBIT_S20_3LE |
+			    SNDRV_PCM_FMTBIT_S24_LE),
+	},
+	.capture = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_192000,
+		.formats = (SNDRV_PCM_FMTBIT_S8 |
+			    SNDRV_PCM_FMTBIT_S16_LE |
+			    SNDRV_PCM_FMTBIT_S20_3LE |
+			    SNDRV_PCM_FMTBIT_S24_LE),
+	},
+	.ops = &rockchip_i2s_dai_ops,
+};
+
+static const struct snd_soc_component_driver rockchip_i2s_component = {
+	.name = DRV_NAME,
+};
+
+static bool rockchip_i2s_wr_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case I2S_TXCR:
+	case I2S_RXCR:
+	case I2S_CKR:
+	case I2S_DMACR:
+	case I2S_INTCR:
+	case I2S_XFER:
+	case I2S_CLR:
+	case I2S_TXDR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case I2S_TXCR:
+	case I2S_RXCR:
+	case I2S_CKR:
+	case I2S_DMACR:
+	case I2S_INTCR:
+	case I2S_XFER:
+	case I2S_CLR:
+	case I2S_RXDR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case I2S_FIFOLR:
+	case I2S_INTSR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case I2S_FIFOLR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config rockchip_i2s_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = I2S_RXDR,
+	.writeable_reg = rockchip_i2s_wr_reg,
+	.readable_reg = rockchip_i2s_rd_reg,
+	.volatile_reg = rockchip_i2s_volatile_reg,
+	.precious_reg = rockchip_i2s_precious_reg,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static int rockchip_i2s_probe(struct platform_device *pdev)
+{
+	struct rk_i2s_dev *i2s;
+	struct resource *res;
+	void __iomem *regs;
+	int ret;
+
+	i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
+	if (!i2s) {
+		dev_err(&pdev->dev, "Can't allocate rk_i2s_dev\n");
+		return -ENOMEM;
+	}
+
+	/* try to prepare related clocks */
+	i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk");
+	if (IS_ERR(i2s->hclk)) {
+		dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n");
+		return PTR_ERR(i2s->hclk);
+	}
+
+	i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk");
+	if (IS_ERR(i2s->mclk)) {
+		dev_err(&pdev->dev, "Can't retrieve i2s master clock\n");
+		return PTR_ERR(i2s->mclk);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
+					    &rockchip_i2s_regmap_config);
+	if (IS_ERR(i2s->regmap)) {
+		dev_err(&pdev->dev,
+			"Failed to initialise managed register map\n");
+		return PTR_ERR(i2s->regmap);
+	}
+
+	i2s->playback_dma_data.addr = res->start + I2S_TXDR;
+	i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	i2s->playback_dma_data.maxburst = 16;
+
+	i2s->capture_dma_data.addr = res->start + I2S_RXDR;
+	i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	i2s->capture_dma_data.maxburst = 16;
+
+	i2s->dev = &pdev->dev;
+	dev_set_drvdata(&pdev->dev, i2s);
+
+	pm_runtime_enable(&pdev->dev);
+	if (!pm_runtime_enabled(&pdev->dev)) {
+		ret = i2s_runtime_resume(&pdev->dev);
+		if (ret)
+			goto err_pm_disable;
+	}
+
+	ret = devm_snd_soc_register_component(&pdev->dev,
+					      &rockchip_i2s_component,
+					      &rockchip_i2s_dai, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "Could not register DAI\n");
+		goto err_suspend;
+	}
+
+	ret = snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+	if (ret) {
+		dev_err(&pdev->dev, "Could not register PCM\n");
+		goto err_pcm_register;
+	}
+
+	return 0;
+
+err_pcm_register:
+	snd_dmaengine_pcm_unregister(&pdev->dev);
+err_suspend:
+	if (!pm_runtime_status_suspended(&pdev->dev))
+		i2s_runtime_suspend(&pdev->dev);
+err_pm_disable:
+	pm_runtime_disable(&pdev->dev);
+
+	return ret;
+}
+
+static int rockchip_i2s_remove(struct platform_device *pdev)
+{
+	struct rk_i2s_dev *i2s = dev_get_drvdata(&pdev->dev);
+
+	pm_runtime_disable(&pdev->dev);
+	if (!pm_runtime_status_suspended(&pdev->dev))
+		i2s_runtime_suspend(&pdev->dev);
+
+	clk_disable_unprepare(i2s->mclk);
+	clk_disable_unprepare(i2s->hclk);
+	snd_dmaengine_pcm_unregister(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id rockchip_i2s_match[] = {
+	{ .compatible = "rockchip,rk3066-i2s", },
+	{},
+};
+
+static const struct dev_pm_ops rockchip_i2s_pm_ops = {
+	SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume,
+			   NULL)
+};
+
+static struct platform_driver rockchip_i2s_driver = {
+	.probe = rockchip_i2s_probe,
+	.remove = rockchip_i2s_remove,
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(rockchip_i2s_match),
+		.pm = &rockchip_i2s_pm_ops,
+	},
+};
+module_platform_driver(rockchip_i2s_driver);
+
+MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface");
+MODULE_AUTHOR("jianqun <jay.xu@rock-chips.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, rockchip_i2s_match);
diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h
new file mode 100644
index 000000000000..89a5d8bc6ee7
--- /dev/null
+++ b/sound/soc/rockchip/rockchip_i2s.h
@@ -0,0 +1,223 @@
+/*
+ * sound/soc/rockchip/rockchip_i2s.h
+ *
+ * ALSA SoC Audio Layer - Rockchip I2S Controller driver
+ *
+ * Copyright (c) 2014 Rockchip Electronics Co. Ltd.
+ * Author: Jianqun xu <jay.xu@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ROCKCHIP_IIS_H
+#define _ROCKCHIP_IIS_H
+
+/*
+ * TXCR
+ * transmit operation control register
+*/
+#define I2S_TXCR_RCNT_SHIFT	17
+#define I2S_TXCR_RCNT_MASK	(0x3f << I2S_TXCR_RCNT_SHIFT)
+#define I2S_TXCR_CSR_SHIFT	15
+#define I2S_TXCR_CSR(x)		(x << I2S_TXCR_CSR_SHIFT)
+#define I2S_TXCR_CSR_MASK	(3 << I2S_TXCR_CSR_SHIFT)
+#define I2S_TXCR_HWT		BIT(14)
+#define I2S_TXCR_SJM_SHIFT	12
+#define I2S_TXCR_SJM_R		(0 << I2S_TXCR_SJM_SHIFT)
+#define I2S_TXCR_SJM_L		(1 << I2S_TXCR_SJM_SHIFT)
+#define I2S_TXCR_FBM_SHIFT	11
+#define I2S_TXCR_FBM_MSB	(0 << I2S_TXCR_FBM_SHIFT)
+#define I2S_TXCR_FBM_LSB	(1 << I2S_TXCR_FBM_SHIFT)
+#define I2S_TXCR_IBM_SHIFT	9
+#define I2S_TXCR_IBM_NORMAL	(0 << I2S_TXCR_IBM_SHIFT)
+#define I2S_TXCR_IBM_LSJM	(1 << I2S_TXCR_IBM_SHIFT)
+#define I2S_TXCR_IBM_RSJM	(2 << I2S_TXCR_IBM_SHIFT)
+#define I2S_TXCR_IBM_MASK	(3 << I2S_TXCR_IBM_SHIFT)
+#define I2S_TXCR_PBM_SHIFT	7
+#define I2S_TXCR_PBM_MODE(x)	(x << I2S_TXCR_PBM_SHIFT)
+#define I2S_TXCR_PBM_MASK	(3 << I2S_TXCR_PBM_SHIFT)
+#define I2S_TXCR_TFS_SHIFT	5
+#define I2S_TXCR_TFS_I2S	(0 << I2S_TXCR_TFS_SHIFT)
+#define I2S_TXCR_TFS_PCM	(1 << I2S_TXCR_TFS_SHIFT)
+#define I2S_TXCR_VDW_SHIFT	0
+#define I2S_TXCR_VDW(x)		((x - 1) << I2S_TXCR_VDW_SHIFT)
+#define I2S_TXCR_VDW_MASK	(0x1f << I2S_TXCR_VDW_SHIFT)
+
+/*
+ * RXCR
+ * receive operation control register
+*/
+#define I2S_RXCR_HWT		BIT(14)
+#define I2S_RXCR_SJM_SHIFT	12
+#define I2S_RXCR_SJM_R		(0 << I2S_RXCR_SJM_SHIFT)
+#define I2S_RXCR_SJM_L		(1 << I2S_RXCR_SJM_SHIFT)
+#define I2S_RXCR_FBM_SHIFT	11
+#define I2S_RXCR_FBM_MSB	(0 << I2S_RXCR_FBM_SHIFT)
+#define I2S_RXCR_FBM_LSB	(1 << I2S_RXCR_FBM_SHIFT)
+#define I2S_RXCR_IBM_SHIFT	9
+#define I2S_RXCR_IBM_NORMAL	(0 << I2S_RXCR_IBM_SHIFT)
+#define I2S_RXCR_IBM_LSJM	(1 << I2S_RXCR_IBM_SHIFT)
+#define I2S_RXCR_IBM_RSJM	(2 << I2S_RXCR_IBM_SHIFT)
+#define I2S_RXCR_IBM_MASK	(3 << I2S_RXCR_IBM_SHIFT)
+#define I2S_RXCR_PBM_SHIFT	7
+#define I2S_RXCR_PBM_MODE(x)	(x << I2S_RXCR_PBM_SHIFT)
+#define I2S_RXCR_PBM_MASK	(3 << I2S_RXCR_PBM_SHIFT)
+#define I2S_RXCR_TFS_SHIFT	5
+#define I2S_RXCR_TFS_I2S	(0 << I2S_RXCR_TFS_SHIFT)
+#define I2S_RXCR_TFS_PCM	(1 << I2S_RXCR_TFS_SHIFT)
+#define I2S_RXCR_VDW_SHIFT	0
+#define I2S_RXCR_VDW(x)		((x - 1) << I2S_RXCR_VDW_SHIFT)
+#define I2S_RXCR_VDW_MASK	(0x1f << I2S_RXCR_VDW_SHIFT)
+
+/*
+ * CKR
+ * clock generation register
+*/
+#define I2S_CKR_MSS_SHIFT	27
+#define I2S_CKR_MSS_MASTER	(0 << I2S_CKR_MSS_SHIFT)
+#define I2S_CKR_MSS_SLAVE	(1 << I2S_CKR_MSS_SHIFT)
+#define I2S_CKR_MSS_MASK	(1 << I2S_CKR_MSS_SHIFT)
+#define I2S_CKR_CKP_SHIFT	26
+#define I2S_CKR_CKP_NEG		(0 << I2S_CKR_CKP_SHIFT)
+#define I2S_CKR_CKP_POS		(1 << I2S_CKR_CKP_SHIFT)
+#define I2S_CKR_RLP_SHIFT	25
+#define I2S_CKR_RLP_NORMAL	(0 << I2S_CKR_RLP_SHIFT)
+#define I2S_CKR_RLP_OPPSITE	(1 << I2S_CKR_RLP_SHIFT)
+#define I2S_CKR_TLP_SHIFT	24
+#define I2S_CKR_TLP_NORMAL	(0 << I2S_CKR_TLP_SHIFT)
+#define I2S_CKR_TLP_OPPSITE	(1 << I2S_CKR_TLP_SHIFT)
+#define I2S_CKR_MDIV_SHIFT	16
+#define I2S_CKR_MDIV(x)		((x - 1) << I2S_CKR_MDIV_SHIFT)
+#define I2S_CKR_MDIV_MASK	(0xff << I2S_CKR_MDIV_SHIFT)
+#define I2S_CKR_RSD_SHIFT	8
+#define I2S_CKR_RSD(x)		((x - 1) << I2S_CKR_RSD_SHIFT)
+#define I2S_CKR_RSD_MASK	(0xff << I2S_CKR_RSD_SHIFT)
+#define I2S_CKR_TSD_SHIFT	0
+#define I2S_CKR_TSD(x)		((x - 1) << I2S_CKR_TSD_SHIFT)
+#define I2S_CKR_TSD_MASK	(0xff << I2S_CKR_TSD_SHIFT)
+
+/*
+ * FIFOLR
+ * FIFO level register
+*/
+#define I2S_FIFOLR_RFL_SHIFT	24
+#define I2S_FIFOLR_RFL_MASK	(0x3f << I2S_FIFOLR_RFL_SHIFT)
+#define I2S_FIFOLR_TFL3_SHIFT	18
+#define I2S_FIFOLR_TFL3_MASK	(0x3f << I2S_FIFOLR_TFL3_SHIFT)
+#define I2S_FIFOLR_TFL2_SHIFT	12
+#define I2S_FIFOLR_TFL2_MASK	(0x3f << I2S_FIFOLR_TFL2_SHIFT)
+#define I2S_FIFOLR_TFL1_SHIFT	6
+#define I2S_FIFOLR_TFL1_MASK	(0x3f << I2S_FIFOLR_TFL1_SHIFT)
+#define I2S_FIFOLR_TFL0_SHIFT	0
+#define I2S_FIFOLR_TFL0_MASK	(0x3f << I2S_FIFOLR_TFL0_SHIFT)
+
+/*
+ * DMACR
+ * DMA control register
+*/
+#define I2S_DMACR_RDE_SHIFT	24
+#define I2S_DMACR_RDE_DISABLE	(0 << I2S_DMACR_RDE_SHIFT)
+#define I2S_DMACR_RDE_ENABLE	(1 << I2S_DMACR_RDE_SHIFT)
+#define I2S_DMACR_RDL_SHIFT	16
+#define I2S_DMACR_RDL(x)	((x - 1) << I2S_DMACR_RDL_SHIFT)
+#define I2S_DMACR_RDL_MASK	(0x1f << I2S_DMACR_RDL_SHIFT)
+#define I2S_DMACR_TDE_SHIFT	8
+#define I2S_DMACR_TDE_DISABLE	(0 << I2S_DMACR_TDE_SHIFT)
+#define I2S_DMACR_TDE_ENABLE	(1 << I2S_DMACR_TDE_SHIFT)
+#define I2S_DMACR_TDL_SHIFT	0
+#define I2S_DMACR_TDL(x)	((x - 1) << I2S_DMACR_TDL_SHIFT)
+#define I2S_DMACR_TDL_MASK	(0x1f << I2S_DMACR_TDL_SHIFT)
+
+/*
+ * INTCR
+ * interrupt control register
+*/
+#define I2S_INTCR_RFT_SHIFT	20
+#define I2S_INTCR_RFT(x)	((x - 1) << I2S_INTCR_RFT_SHIFT)
+#define I2S_INTCR_RXOIC		BIT(18)
+#define I2S_INTCR_RXOIE_SHIFT	17
+#define I2S_INTCR_RXOIE_DISABLE	(0 << I2S_INTCR_RXOIE_SHIFT)
+#define I2S_INTCR_RXOIE_ENABLE	(1 << I2S_INTCR_RXOIE_SHIFT)
+#define I2S_INTCR_RXFIE_SHIFT	16
+#define I2S_INTCR_RXFIE_DISABLE	(0 << I2S_INTCR_RXFIE_SHIFT)
+#define I2S_INTCR_RXFIE_ENABLE	(1 << I2S_INTCR_RXFIE_SHIFT)
+#define I2S_INTCR_TFT_SHIFT	4
+#define I2S_INTCR_TFT(x)	((x - 1) << I2S_INTCR_TFT_SHIFT)
+#define I2S_INTCR_TFT_MASK	(0x1f << I2S_INTCR_TFT_SHIFT)
+#define I2S_INTCR_TXUIC		BIT(2)
+#define I2S_INTCR_TXUIE_SHIFT	1
+#define I2S_INTCR_TXUIE_DISABLE	(0 << I2S_INTCR_TXUIE_SHIFT)
+#define I2S_INTCR_TXUIE_ENABLE	(1 << I2S_INTCR_TXUIE_SHIFT)
+
+/*
+ * INTSR
+ * interrupt status register
+*/
+#define I2S_INTSR_TXEIE_SHIFT	0
+#define I2S_INTSR_TXEIE_DISABLE	(0 << I2S_INTSR_TXEIE_SHIFT)
+#define I2S_INTSR_TXEIE_ENABLE	(1 << I2S_INTSR_TXEIE_SHIFT)
+#define I2S_INTSR_RXOI_SHIFT	17
+#define I2S_INTSR_RXOI_INA	(0 << I2S_INTSR_RXOI_SHIFT)
+#define I2S_INTSR_RXOI_ACT	(1 << I2S_INTSR_RXOI_SHIFT)
+#define I2S_INTSR_RXFI_SHIFT	16
+#define I2S_INTSR_RXFI_INA	(0 << I2S_INTSR_RXFI_SHIFT)
+#define I2S_INTSR_RXFI_ACT	(1 << I2S_INTSR_RXFI_SHIFT)
+#define I2S_INTSR_TXUI_SHIFT	1
+#define I2S_INTSR_TXUI_INA	(0 << I2S_INTSR_TXUI_SHIFT)
+#define I2S_INTSR_TXUI_ACT	(1 << I2S_INTSR_TXUI_SHIFT)
+#define I2S_INTSR_TXEI_SHIFT	0
+#define I2S_INTSR_TXEI_INA	(0 << I2S_INTSR_TXEI_SHIFT)
+#define I2S_INTSR_TXEI_ACT	(1 << I2S_INTSR_TXEI_SHIFT)
+
+/*
+ * XFER
+ * Transfer start register
+*/
+#define I2S_XFER_RXS_SHIFT	1
+#define I2S_XFER_RXS_STOP	(0 << I2S_XFER_RXS_SHIFT)
+#define I2S_XFER_RXS_START	(1 << I2S_XFER_RXS_SHIFT)
+#define I2S_XFER_TXS_SHIFT	0
+#define I2S_XFER_TXS_STOP	(0 << I2S_XFER_TXS_SHIFT)
+#define I2S_XFER_TXS_START	(1 << I2S_XFER_TXS_SHIFT)
+
+/*
+ * CLR
+ * clear SCLK domain logic register
+*/
+#define I2S_CLR_RXC	BIT(1)
+#define I2S_CLR_TXC	BIT(0)
+
+/*
+ * TXDR
+ * Transimt FIFO data register, write only.
+*/
+#define I2S_TXDR_MASK	(0xff)
+
+/*
+ * RXDR
+ * Receive FIFO data register, write only.
+*/
+#define I2S_RXDR_MASK	(0xff)
+
+/* Clock divider id */
+enum {
+	ROCKCHIP_DIV_MCLK = 0,
+	ROCKCHIP_DIV_BCLK,
+};
+
+/* I2S REGS */
+#define I2S_TXCR	(0x0000)
+#define I2S_RXCR	(0x0004)
+#define I2S_CKR		(0x0008)
+#define I2S_FIFOLR	(0x000c)
+#define I2S_DMACR	(0x0010)
+#define I2S_INTCR	(0x0014)
+#define I2S_INTSR	(0x0018)
+#define I2S_XFER	(0x001c)
+#define I2S_CLR		(0x0020)
+#define I2S_TXDR	(0x0024)
+#define I2S_RXDR	(0x0028)
+
+#endif /* _ROCKCHIP_IIS_H */
diff --git a/sound/soc/s6000/Kconfig b/sound/soc/s6000/Kconfig
index c74eb3d4a47c..f244a2566f20 100644
--- a/sound/soc/s6000/Kconfig
+++ b/sound/soc/s6000/Kconfig
@@ -1,17 +1,24 @@
 config SND_S6000_SOC
 	tristate "SoC Audio for the Stretch s6000 family"
-	depends on XTENSA_VARIANT_S6000
+	depends on XTENSA_VARIANT_S6000 || COMPILE_TEST
+	depends on HAS_IOMEM
+	select SND_S6000_SOC_PCM if XTENSA_VARIANT_S6000
 	help
 	  Say Y or M if you want to add support for codecs attached to
 	  s6000 family chips. You will also need to select the platform
 	  to support below.
 
+config SND_S6000_SOC_PCM
+	tristate
+
 config SND_S6000_SOC_I2S
 	tristate
 
 config SND_S6000_SOC_S6IPCAM
-	tristate "SoC Audio support for Stretch 6105 IP Camera"
-	depends on SND_S6000_SOC && XTENSA_PLATFORM_S6105
+	bool "SoC Audio support for Stretch 6105 IP Camera"
+	depends on SND_S6000_SOC=y
+	depends on I2C=y
+	depends on XTENSA_PLATFORM_S6105 || COMPILE_TEST
 	select SND_S6000_SOC_I2S
 	select SND_SOC_TLV320AIC3X
 	help
diff --git a/sound/soc/s6000/Makefile b/sound/soc/s6000/Makefile
index 7a613612e010..0f0ae2a012aa 100644
--- a/sound/soc/s6000/Makefile
+++ b/sound/soc/s6000/Makefile
@@ -2,7 +2,7 @@
 snd-soc-s6000-objs := s6000-pcm.o
 snd-soc-s6000-i2s-objs := s6000-i2s.o
 
-obj-$(CONFIG_SND_S6000_SOC) += snd-soc-s6000.o
+obj-$(CONFIG_SND_S6000_SOC_PCM) += snd-soc-s6000.o
 obj-$(CONFIG_SND_S6000_SOC_I2S) += snd-soc-s6000-i2s.o
 
 # s6105 Machine Support
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
index 7eba7979b9af..1c8d01166e5b 100644
--- a/sound/soc/s6000/s6000-i2s.c
+++ b/sound/soc/s6000/s6000-i2s.c
@@ -570,7 +570,7 @@ err_release_none:
 	return ret;
 }
 
-static void s6000_i2s_remove(struct platform_device *pdev)
+static int s6000_i2s_remove(struct platform_device *pdev)
 {
 	struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
 	struct resource *region;
@@ -597,6 +597,8 @@ static void s6000_i2s_remove(struct platform_device *pdev)
 	iounmap(mmio);
 	region = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	release_mem_region(region->start, resource_size(region));
+
+	return 0;
 }
 
 static struct platform_driver s6000_i2s_driver = {
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c
index 0b21d1dc80c1..3510c01f8a6a 100644
--- a/sound/soc/s6000/s6105-ipcam.c
+++ b/sound/soc/s6000/s6105-ipcam.c
@@ -19,8 +19,6 @@
 #include <sound/pcm.h>
 #include <sound/soc.h>
 
-#include <variant/dmac.h>
-
 #include "s6000-pcm.h"
 #include "s6000-i2s.h"
 
@@ -135,22 +133,8 @@ static const struct snd_kcontrol_new audio_out_mux = {
 /* Logic for a aic3x as connected on the s6105 ip camera ref design */
 static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd)
 {
-	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	struct snd_soc_card *card = rtd->card;
 
-	/* not present */
-	snd_soc_dapm_nc_pin(dapm, "MONO_LOUT");
-	snd_soc_dapm_nc_pin(dapm, "LINE2L");
-	snd_soc_dapm_nc_pin(dapm, "LINE2R");
-
-	/* not connected */
-	snd_soc_dapm_nc_pin(dapm, "MIC3L"); /* LINE2L on this chip */
-	snd_soc_dapm_nc_pin(dapm, "MIC3R"); /* LINE2R on this chip */
-	snd_soc_dapm_nc_pin(dapm, "LLOUT");
-	snd_soc_dapm_nc_pin(dapm, "RLOUT");
-	snd_soc_dapm_nc_pin(dapm, "HPRCOM");
-
 	/* must correspond to audio_out_mux.private_value initializer */
 	snd_soc_dapm_disable_pin(&card->dapm, "Audio Out Differential");
 
@@ -182,6 +166,7 @@ static struct snd_soc_card snd_soc_card_s6105 = {
 	.num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets),
 	.dapm_routes = audio_map,
 	.num_dapm_routes = ARRAY_SIZE(audio_map),
+	.fully_routed = true,
 };
 
 static struct s6000_snd_platform_data s6105_snd_data __initdata = {
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 753b8c93ab51..55a38697443d 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -1,25 +1,16 @@
 config SND_SOC_SAMSUNG
 	tristate "ASoC support for Samsung"
 	depends on PLAT_SAMSUNG
-	select S3C2410_DMA if ARCH_S3C24XX
-	select S3C64XX_PL080 if ARCH_S3C64XX
-	select SND_S3C_DMA if !ARCH_S3C24XX
-	select SND_S3C_DMA_LEGACY if ARCH_S3C24XX
-	select SND_SOC_GENERIC_DMAENGINE_PCM if !ARCH_S3C24XX
+	depends on S3C64XX_PL080 || !ARCH_S3C64XX
+	depends on S3C24XX_DMAC || !ARCH_S3C24XX
+	select SND_SOC_GENERIC_DMAENGINE_PCM
 	help
 	  Say Y or M if you want to add support for codecs attached to
 	  the Samsung SoCs' Audio interfaces. You will also need to
 	  select the audio interfaces to support below.
 
-config SND_S3C_DMA
-	tristate
-
-config SND_S3C_DMA_LEGACY
-	tristate
-
 config SND_S3C24XX_I2S
 	tristate
-	select S3C24XX_DMA
 
 config SND_S3C_I2SV2_SOC
 	tristate
@@ -27,7 +18,6 @@ config SND_S3C_I2SV2_SOC
 config SND_S3C2412_SOC_I2S
 	tristate
 	select SND_S3C_I2SV2_SOC
-	select S3C2410_DMA
 
 config SND_SAMSUNG_PCM
 	tristate
@@ -55,7 +45,7 @@ config SND_SOC_SAMSUNG_NEO1973_WM8753
 
 config SND_SOC_SAMSUNG_JIVE_WM8750
 	tristate "SoC I2S Audio support for Jive"
-	depends on SND_SOC_SAMSUNG && MACH_JIVE
+	depends on SND_SOC_SAMSUNG && MACH_JIVE && I2C
 	select SND_SOC_WM8750
 	select SND_S3C2412_SOC_I2S
 	help
@@ -63,7 +53,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750
 
 config SND_SOC_SAMSUNG_SMDK_WM8580
 	tristate "SoC I2S Audio support for WM8580 on SMDK"
-	depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDK6440 || MACH_SMDK6450 || MACH_SMDKV210 || MACH_SMDKC110)
+	depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110)
 	depends on REGMAP_I2C
 	select SND_SOC_WM8580
 	select SND_SAMSUNG_I2S
@@ -83,7 +73,6 @@ config SND_SOC_SAMSUNG_SMDK_WM8994
 config SND_SOC_SAMSUNG_SMDK2443_WM9710
 	tristate "SoC AC97 Audio support for SMDK2443 - WM9710"
 	depends on SND_SOC_SAMSUNG && MACH_SMDK2443
-	select S3C2410_DMA
 	select AC97_BUS
 	select SND_SOC_AC97_CODEC
 	select SND_SAMSUNG_AC97
@@ -94,7 +83,6 @@ config SND_SOC_SAMSUNG_SMDK2443_WM9710
 config SND_SOC_SAMSUNG_LN2440SBC_ALC650
 	tristate "SoC AC97 Audio support for LN2440SBC - ALC650"
 	depends on SND_SOC_SAMSUNG && ARCH_S3C24XX
-	select S3C2410_DMA
 	select AC97_BUS
 	select SND_SOC_AC97_CODEC
 	select SND_SAMSUNG_AC97
@@ -154,7 +142,7 @@ config SND_SOC_SAMSUNG_SMDK_WM9713
 
 config SND_SOC_SMARTQ
 	tristate "SoC I2S Audio support for SmartQ board"
-	depends on SND_SOC_SAMSUNG && MACH_SMARTQ
+	depends on SND_SOC_SAMSUNG && MACH_SMARTQ && I2C
 	select SND_SAMSUNG_I2S
 	select SND_SOC_WM8750
 
@@ -178,7 +166,7 @@ config SND_SOC_SAMSUNG_SMDK_SPDIF
 
 config SND_SOC_SMDK_WM8580_PCM
 	tristate "SoC PCM Audio support for WM8580 on SMDK"
-	depends on SND_SOC_SAMSUNG && (MACH_SMDK6450 || MACH_SMDKV210 || MACH_SMDKC110)
+	depends on SND_SOC_SAMSUNG && (MACH_SMDKV210 || MACH_SMDKC110)
 	depends on REGMAP_I2C
 	select SND_SOC_WM8580
 	select SND_SAMSUNG_PCM
@@ -206,7 +194,7 @@ config SND_SOC_SPEYSIDE
 
 config SND_SOC_TOBERMORY
 	tristate "Audio support for Wolfson Tobermory"
-	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && INPUT
+	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && INPUT && I2C
 	select SND_SAMSUNG_I2S
 	select SND_SOC_WM8962
 
@@ -222,7 +210,7 @@ config SND_SOC_BELLS
 
 config SND_SOC_LOWLAND
 	tristate "Audio support for Wolfson Lowland"
-	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
+	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && I2C
 	select SND_SAMSUNG_I2S
 	select SND_SOC_WM5100
 	select SND_SOC_WM9081
@@ -236,10 +224,18 @@ config SND_SOC_LITTLEMILL
 
 config SND_SOC_SNOW
 	tristate "Audio support for Google Snow boards"
-	depends on SND_SOC_SAMSUNG
+	depends on SND_SOC_SAMSUNG && I2C
 	select SND_SOC_MAX98090
 	select SND_SOC_MAX98095
 	select SND_SAMSUNG_I2S
 	help
 	  Say Y if you want to add audio support for various Snow
 	  boards based on Exynos5 series of SoCs.
+
+config SND_SOC_ODROIDX2
+	tristate "Audio support for Odroid-X2 and Odroid-U3"
+	depends on SND_SOC_SAMSUNG
+	select SND_SOC_MAX98090
+	select SND_SAMSUNG_I2S
+	help
+	  Say Y here to enable audio support for the Odroid-X2/U3.
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
index 6d0212ba571c..91505ddaaf95 100644
--- a/sound/soc/samsung/Makefile
+++ b/sound/soc/samsung/Makefile
@@ -1,6 +1,5 @@
 # S3c24XX Platform Support
 snd-soc-s3c-dma-objs := dmaengine.o
-snd-soc-s3c-dma-legacy-objs := dma.o
 snd-soc-idma-objs := idma.o
 snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
 snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
@@ -10,8 +9,7 @@ snd-soc-samsung-spdif-objs := spdif.o
 snd-soc-pcm-objs := pcm.o
 snd-soc-i2s-objs := i2s.o
 
-obj-$(CONFIG_SND_S3C_DMA) += snd-soc-s3c-dma.o
-obj-$(CONFIG_SND_S3C_DMA_LEGACY) += snd-soc-s3c-dma-legacy.o
+obj-$(CONFIG_SND_SOC_SAMSUNG) += snd-soc-s3c-dma.o
 obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o
 obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o
 obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
@@ -46,6 +44,7 @@ snd-soc-tobermory-objs := tobermory.o
 snd-soc-lowland-objs := lowland.o
 snd-soc-littlemill-objs := littlemill.o
 snd-soc-bells-objs := bells.o
+snd-soc-odroidx2-max98090-objs := odroidx2_max98090.o
 
 obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o
 obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
@@ -71,3 +70,4 @@ obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o
 obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o
 obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o
 obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o
+obj-$(CONFIG_SND_SOC_ODROIDX2) += snd-soc-odroidx2-max98090.o
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 68d9303047e8..e1615113fd84 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -19,7 +19,6 @@
 
 #include <sound/soc.h>
 
-#include <mach/dma.h>
 #include "regs-ac97.h"
 #include <linux/platform_data/asoc-s3c.h>
 
@@ -39,30 +38,15 @@ struct s3c_ac97_info {
 };
 static struct s3c_ac97_info s3c_ac97;
 
-static struct s3c_dma_client s3c_dma_client_out = {
-	.name = "AC97 PCMOut"
-};
-
-static struct s3c_dma_client s3c_dma_client_in = {
-	.name = "AC97 PCMIn"
-};
-
-static struct s3c_dma_client s3c_dma_client_micin = {
-	.name = "AC97 MicIn"
-};
-
 static struct s3c_dma_params s3c_ac97_pcm_out = {
-	.client		= &s3c_dma_client_out,
 	.dma_size	= 4,
 };
 
 static struct s3c_dma_params s3c_ac97_pcm_in = {
-	.client		= &s3c_dma_client_in,
 	.dma_size	= 4,
 };
 
 static struct s3c_dma_params s3c_ac97_mic_in = {
-	.client		= &s3c_dma_client_micin,
 	.dma_size	= 4,
 };
 
@@ -225,9 +209,6 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
 				struct snd_soc_dai *dai)
 {
 	u32 ac_glbctrl;
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct s3c_dma_params *dma_data =
-		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
 	ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
@@ -253,11 +234,6 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
 
 	writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
-	if (!dma_data->ops)
-		dma_data->ops = samsung_dma_get_ops();
-
-	dma_data->ops->started(dma_data->channel);
-
 	return 0;
 }
 
@@ -265,9 +241,6 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
 				    int cmd, struct snd_soc_dai *dai)
 {
 	u32 ac_glbctrl;
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct s3c_dma_params *dma_data =
-		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
 	ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
 	ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK;
@@ -287,11 +260,6 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
 
 	writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
-	if (!dma_data->ops)
-		dma_data->ops = samsung_dma_get_ops();
-
-	dma_data->ops->started(dma_data->channel);
-
 	return 0;
 }
 
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
deleted file mode 100644
index d9dc7bcc0336..000000000000
--- a/sound/soc/samsung/dma.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * dma.c  --  ALSA Soc Audio Layer
- *
- * (c) 2006 Wolfson Microelectronics PLC.
- * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
- *
- * Copyright 2004-2005 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/module.h>
-
-#include <sound/soc.h>
-#include <sound/pcm_params.h>
-
-#include <asm/dma.h>
-#include <mach/hardware.h>
-#include <mach/dma.h>
-
-#include "dma.h"
-
-#define ST_RUNNING		(1<<0)
-#define ST_OPENED		(1<<1)
-
-static const struct snd_pcm_hardware dma_hardware = {
-	.info			= SNDRV_PCM_INFO_INTERLEAVED |
-				    SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				    SNDRV_PCM_INFO_MMAP |
-				    SNDRV_PCM_INFO_MMAP_VALID,
-	.buffer_bytes_max	= 128*1024,
-	.period_bytes_min	= PAGE_SIZE,
-	.period_bytes_max	= PAGE_SIZE*2,
-	.periods_min		= 2,
-	.periods_max		= 128,
-	.fifo_size		= 32,
-};
-
-struct runtime_data {
-	spinlock_t lock;
-	int state;
-	unsigned int dma_loaded;
-	unsigned int dma_period;
-	dma_addr_t dma_start;
-	dma_addr_t dma_pos;
-	dma_addr_t dma_end;
-	struct s3c_dma_params *params;
-};
-
-static void audio_buffdone(void *data);
-
-/* dma_enqueue
- *
- * place a dma buffer onto the queue for the dma system
- * to handle.
- */
-static void dma_enqueue(struct snd_pcm_substream *substream)
-{
-	struct runtime_data *prtd = substream->runtime->private_data;
-	dma_addr_t pos = prtd->dma_pos;
-	unsigned int limit;
-	struct samsung_dma_prep dma_info;
-
-	pr_debug("Entered %s\n", __func__);
-
-	limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
-
-	pr_debug("%s: loaded %d, limit %d\n",
-				__func__, prtd->dma_loaded, limit);
-
-	dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
-	dma_info.direction =
-		(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
-		? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
-	dma_info.fp = audio_buffdone;
-	dma_info.fp_param = substream;
-	dma_info.period = prtd->dma_period;
-	dma_info.len = prtd->dma_period*limit;
-
-	if (dma_info.cap == DMA_CYCLIC) {
-		dma_info.buf = pos;
-		prtd->params->ops->prepare(prtd->params->ch, &dma_info);
-		prtd->dma_loaded += limit;
-		return;
-	}
-
-	while (prtd->dma_loaded < limit) {
-		pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
-
-		if ((pos + dma_info.period) > prtd->dma_end) {
-			dma_info.period  = prtd->dma_end - pos;
-			pr_debug("%s: corrected dma len %ld\n",
-					__func__, dma_info.period);
-		}
-
-		dma_info.buf = pos;
-		prtd->params->ops->prepare(prtd->params->ch, &dma_info);
-
-		prtd->dma_loaded++;
-		pos += prtd->dma_period;
-		if (pos >= prtd->dma_end)
-			pos = prtd->dma_start;
-	}
-
-	prtd->dma_pos = pos;
-}
-
-static void audio_buffdone(void *data)
-{
-	struct snd_pcm_substream *substream = data;
-	struct runtime_data *prtd = substream->runtime->private_data;
-
-	pr_debug("Entered %s\n", __func__);
-
-	if (prtd->state & ST_RUNNING) {
-		prtd->dma_pos += prtd->dma_period;
-		if (prtd->dma_pos >= prtd->dma_end)
-			prtd->dma_pos = prtd->dma_start;
-
-		if (substream)
-			snd_pcm_period_elapsed(substream);
-
-		spin_lock(&prtd->lock);
-		if (!samsung_dma_has_circular()) {
-			prtd->dma_loaded--;
-			dma_enqueue(substream);
-		}
-		spin_unlock(&prtd->lock);
-	}
-}
-
-static int dma_hw_params(struct snd_pcm_substream *substream,
-	struct snd_pcm_hw_params *params)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct runtime_data *prtd = runtime->private_data;
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	unsigned long totbytes = params_buffer_bytes(params);
-	struct s3c_dma_params *dma =
-		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-	struct samsung_dma_req req;
-	struct samsung_dma_config config;
-
-	pr_debug("Entered %s\n", __func__);
-
-	/* return if this is a bufferless transfer e.g.
-	 * codec <--> BT codec or GSM modem -- lg FIXME */
-	if (!dma)
-		return 0;
-
-	/* this may get called several times by oss emulation
-	 * with different params -HW */
-	if (prtd->params == NULL) {
-		/* prepare DMA */
-		prtd->params = dma;
-
-		pr_debug("params %p, client %p, channel %d\n", prtd->params,
-			prtd->params->client, prtd->params->channel);
-
-		prtd->params->ops = samsung_dma_get_ops();
-
-		req.cap = (samsung_dma_has_circular() ?
-			DMA_CYCLIC : DMA_SLAVE);
-		req.client = prtd->params->client;
-		config.direction =
-			(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
-			? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
-		config.width = prtd->params->dma_size;
-		config.fifo = prtd->params->dma_addr;
-		prtd->params->ch = prtd->params->ops->request(
-				prtd->params->channel, &req, rtd->cpu_dai->dev,
-				prtd->params->ch_name);
-		if (!prtd->params->ch) {
-			pr_err("Failed to allocate DMA channel\n");
-			return -ENXIO;
-		}
-		prtd->params->ops->config(prtd->params->ch, &config);
-	}
-
-	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
-	runtime->dma_bytes = totbytes;
-
-	spin_lock_irq(&prtd->lock);
-	prtd->dma_loaded = 0;
-	prtd->dma_period = params_period_bytes(params);
-	prtd->dma_start = runtime->dma_addr;
-	prtd->dma_pos = prtd->dma_start;
-	prtd->dma_end = prtd->dma_start + totbytes;
-	spin_unlock_irq(&prtd->lock);
-
-	return 0;
-}
-
-static int dma_hw_free(struct snd_pcm_substream *substream)
-{
-	struct runtime_data *prtd = substream->runtime->private_data;
-
-	pr_debug("Entered %s\n", __func__);
-
-	snd_pcm_set_runtime_buffer(substream, NULL);
-
-	if (prtd->params) {
-		prtd->params->ops->flush(prtd->params->ch);
-		prtd->params->ops->release(prtd->params->ch,
-					prtd->params->client);
-		prtd->params = NULL;
-	}
-
-	return 0;
-}
-
-static int dma_prepare(struct snd_pcm_substream *substream)
-{
-	struct runtime_data *prtd = substream->runtime->private_data;
-	int ret = 0;
-
-	pr_debug("Entered %s\n", __func__);
-
-	/* return if this is a bufferless transfer e.g.
-	 * codec <--> BT codec or GSM modem -- lg FIXME */
-	if (!prtd->params)
-		return 0;
-
-	/* flush the DMA channel */
-	prtd->params->ops->flush(prtd->params->ch);
-
-	prtd->dma_loaded = 0;
-	prtd->dma_pos = prtd->dma_start;
-
-	/* enqueue dma buffers */
-	dma_enqueue(substream);
-
-	return ret;
-}
-
-static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct runtime_data *prtd = substream->runtime->private_data;
-	int ret = 0;
-
-	pr_debug("Entered %s\n", __func__);
-
-	spin_lock(&prtd->lock);
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		prtd->state |= ST_RUNNING;
-		prtd->params->ops->trigger(prtd->params->ch);
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-		prtd->state &= ~ST_RUNNING;
-		prtd->params->ops->stop(prtd->params->ch);
-		break;
-
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	spin_unlock(&prtd->lock);
-
-	return ret;
-}
-
-static snd_pcm_uframes_t
-dma_pointer(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct runtime_data *prtd = runtime->private_data;
-	unsigned long res;
-
-	pr_debug("Entered %s\n", __func__);
-
-	res = prtd->dma_pos - prtd->dma_start;
-
-	pr_debug("Pointer offset: %lu\n", res);
-
-	/* we seem to be getting the odd error from the pcm library due
-	 * to out-of-bounds pointers. this is maybe due to the dma engine
-	 * not having loaded the new values for the channel before being
-	 * called... (todo - fix )
-	 */
-
-	if (res >= snd_pcm_lib_buffer_bytes(substream)) {
-		if (res == snd_pcm_lib_buffer_bytes(substream))
-			res = 0;
-	}
-
-	return bytes_to_frames(substream->runtime, res);
-}
-
-static int dma_open(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct runtime_data *prtd;
-
-	pr_debug("Entered %s\n", __func__);
-
-	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
-	snd_soc_set_runtime_hwparams(substream, &dma_hardware);
-
-	prtd = kzalloc(sizeof(struct runtime_data), GFP_KERNEL);
-	if (prtd == NULL)
-		return -ENOMEM;
-
-	spin_lock_init(&prtd->lock);
-
-	runtime->private_data = prtd;
-	return 0;
-}
-
-static int dma_close(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct runtime_data *prtd = runtime->private_data;
-
-	pr_debug("Entered %s\n", __func__);
-
-	if (!prtd)
-		pr_debug("dma_close called with prtd == NULL\n");
-
-	kfree(prtd);
-
-	return 0;
-}
-
-static int dma_mmap(struct snd_pcm_substream *substream,
-	struct vm_area_struct *vma)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-
-	pr_debug("Entered %s\n", __func__);
-
-	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
-				     runtime->dma_area,
-				     runtime->dma_addr,
-				     runtime->dma_bytes);
-}
-
-static struct snd_pcm_ops dma_ops = {
-	.open		= dma_open,
-	.close		= dma_close,
-	.ioctl		= snd_pcm_lib_ioctl,
-	.hw_params	= dma_hw_params,
-	.hw_free	= dma_hw_free,
-	.prepare	= dma_prepare,
-	.trigger	= dma_trigger,
-	.pointer	= dma_pointer,
-	.mmap		= dma_mmap,
-};
-
-static int preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
-	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-	struct snd_dma_buffer *buf = &substream->dma_buffer;
-	size_t size = dma_hardware.buffer_bytes_max;
-
-	pr_debug("Entered %s\n", __func__);
-
-	buf->dev.type = SNDRV_DMA_TYPE_DEV;
-	buf->dev.dev = pcm->card->dev;
-	buf->private_data = NULL;
-	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
-					   &buf->addr, GFP_KERNEL);
-	if (!buf->area)
-		return -ENOMEM;
-	buf->bytes = size;
-	return 0;
-}
-
-static void dma_free_dma_buffers(struct snd_pcm *pcm)
-{
-	struct snd_pcm_substream *substream;
-	struct snd_dma_buffer *buf;
-	int stream;
-
-	pr_debug("Entered %s\n", __func__);
-
-	for (stream = 0; stream < 2; stream++) {
-		substream = pcm->streams[stream].substream;
-		if (!substream)
-			continue;
-
-		buf = &substream->dma_buffer;
-		if (!buf->area)
-			continue;
-
-		dma_free_writecombine(pcm->card->dev, buf->bytes,
-				      buf->area, buf->addr);
-		buf->area = NULL;
-	}
-}
-
-static int dma_new(struct snd_soc_pcm_runtime *rtd)
-{
-	struct snd_card *card = rtd->card->snd_card;
-	struct snd_pcm *pcm = rtd->pcm;
-	int ret;
-
-	pr_debug("Entered %s\n", __func__);
-
-	ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
-	if (ret)
-		return ret;
-
-	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-		ret = preallocate_dma_buffer(pcm,
-			SNDRV_PCM_STREAM_PLAYBACK);
-		if (ret)
-			goto out;
-	}
-
-	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-		ret = preallocate_dma_buffer(pcm,
-			SNDRV_PCM_STREAM_CAPTURE);
-		if (ret)
-			goto out;
-	}
-out:
-	return ret;
-}
-
-static struct snd_soc_platform_driver samsung_asoc_platform = {
-	.ops		= &dma_ops,
-	.pcm_new	= dma_new,
-	.pcm_free	= dma_free_dma_buffers,
-};
-
-void samsung_asoc_init_dma_data(struct snd_soc_dai *dai,
-				struct s3c_dma_params *playback,
-				struct s3c_dma_params *capture)
-{
-	snd_soc_dai_init_dma_data(dai, playback, capture);
-}
-EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data);
-
-int samsung_asoc_dma_platform_register(struct device *dev)
-{
-	return devm_snd_soc_register_platform(dev, &samsung_asoc_platform);
-}
-EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register);
-
-MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
-MODULE_DESCRIPTION("Samsung ASoC DMA Driver");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index 070ab0f09609..0e85dcfec023 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -14,17 +14,10 @@
 
 #include <sound/dmaengine_pcm.h>
 
-struct s3c_dma_client {
-	char *name;
-};
-
 struct s3c_dma_params {
-	struct s3c_dma_client *client;	/* stream identifier */
 	int channel;				/* Channel ID */
 	dma_addr_t dma_addr;
 	int dma_size;			/* Size of the DMA transfer */
-	unsigned ch;
-	struct samsung_dma_ops *ops;
 	char *ch_name;
 	struct snd_dmaengine_dai_dma_data dma_data;
 };
diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c
index a0e4e7948909..506f5bf6d082 100644
--- a/sound/soc/samsung/dmaengine.c
+++ b/sound/soc/samsung/dmaengine.c
@@ -17,6 +17,7 @@
 
 #include <linux/module.h>
 #include <linux/amba/pl08x.h>
+#include <linux/platform_data/dma-s3c24xx.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -29,6 +30,8 @@
 
 #ifdef CONFIG_ARCH_S3C64XX
 #define filter_fn pl08x_filter_id
+#elif defined(CONFIG_ARCH_S3C24XX)
+#define filter_fn s3c24xx_dma_filter
 #else
 #define filter_fn NULL
 #endif
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 2ac76fa3e742..03eec22f0f46 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -68,6 +68,8 @@ struct i2s_dai {
 #define DAI_OPENED	(1 << 0) /* Dai is opened */
 #define DAI_MANAGER	(1 << 1) /* Dai is the manager */
 	unsigned mode;
+	/* CDCLK pin direction: 0  - input, 1 - output */
+	unsigned int cdclk_out:1;
 	/* Driver for this DAI */
 	struct snd_soc_dai_driver i2s_dai_drv;
 	/* DMA parameters */
@@ -737,6 +739,9 @@ static int i2s_startup(struct snd_pcm_substream *substream,
 
 	spin_unlock_irqrestore(&lock, flags);
 
+	if (!is_opened(other) && i2s->cdclk_out)
+		i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK,
+				0, SND_SOC_CLOCK_OUT);
 	return 0;
 }
 
@@ -752,9 +757,13 @@ static void i2s_shutdown(struct snd_pcm_substream *substream,
 	i2s->mode &= ~DAI_OPENED;
 	i2s->mode &= ~DAI_MANAGER;
 
-	if (is_opened(other))
+	if (is_opened(other)) {
 		other->mode |= DAI_MANAGER;
-
+	} else {
+		u32 mod = readl(i2s->addr + I2SMOD);
+		i2s->cdclk_out = !(mod & MOD_CDCLKCON);
+		other->cdclk_out = i2s->cdclk_out;
+	}
 	/* Reset any constraint on RFS and BFS */
 	i2s->rfs = 0;
 	i2s->bfs = 0;
@@ -920,11 +929,9 @@ static int i2s_suspend(struct snd_soc_dai *dai)
 {
 	struct i2s_dai *i2s = to_info(dai);
 
-	if (dai->active) {
-		i2s->suspend_i2smod = readl(i2s->addr + I2SMOD);
-		i2s->suspend_i2scon = readl(i2s->addr + I2SCON);
-		i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR);
-	}
+	i2s->suspend_i2smod = readl(i2s->addr + I2SMOD);
+	i2s->suspend_i2scon = readl(i2s->addr + I2SCON);
+	i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR);
 
 	return 0;
 }
@@ -933,11 +940,9 @@ static int i2s_resume(struct snd_soc_dai *dai)
 {
 	struct i2s_dai *i2s = to_info(dai);
 
-	if (dai->active) {
-		writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
-		writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
-		writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR);
-	}
+	writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
+	writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
+	writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR);
 
 	return 0;
 }
@@ -1216,11 +1221,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 
 	pri_dai->dma_playback.dma_addr = regs_base + I2STXD;
 	pri_dai->dma_capture.dma_addr = regs_base + I2SRXD;
-	pri_dai->dma_playback.client =
-		(struct s3c_dma_client *)&pri_dai->dma_playback;
 	pri_dai->dma_playback.ch_name = "tx";
-	pri_dai->dma_capture.client =
-		(struct s3c_dma_client *)&pri_dai->dma_capture;
 	pri_dai->dma_capture.ch_name = "rx";
 	pri_dai->dma_playback.dma_size = 4;
 	pri_dai->dma_capture.dma_size = 4;
@@ -1238,8 +1239,6 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 			goto err;
 		}
 		sec_dai->dma_playback.dma_addr = regs_base + I2STXDS;
-		sec_dai->dma_playback.client =
-			(struct s3c_dma_client *)&sec_dai->dma_playback;
 		sec_dai->dma_playback.ch_name = "tx-sec";
 
 		if (!np) {
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
index 8cc5770abb39..db6cefa18017 100644
--- a/sound/soc/samsung/idma.c
+++ b/sound/soc/samsung/idma.c
@@ -261,10 +261,9 @@ static int idma_mmap(struct snd_pcm_substream *substream,
 static irqreturn_t iis_irq(int irqno, void *dev_id)
 {
 	struct idma_ctrl *prtd = (struct idma_ctrl *)dev_id;
-	u32 iiscon, iisahb, val, addr;
+	u32 iisahb, val, addr;
 
 	iisahb  = readl(idma.regs + I2SAHB);
-	iiscon  = readl(idma.regs + I2SCON);
 
 	val = (iisahb & AHB_LVL0INT) ? AHB_CLRLVL0INT : 0;
 
diff --git a/sound/soc/samsung/odroidx2_max98090.c b/sound/soc/samsung/odroidx2_max98090.c
new file mode 100644
index 000000000000..278edf9e2a87
--- /dev/null
+++ b/sound/soc/samsung/odroidx2_max98090.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/of.h>
+#include <linux/module.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include "i2s.h"
+
+struct odroidx2_drv_data {
+	const struct snd_soc_dapm_widget *dapm_widgets;
+	unsigned int num_dapm_widgets;
+};
+
+/* The I2S CDCLK output clock frequency for the MAX98090 codec */
+#define MAX98090_MCLK 19200000
+
+static int odroidx2_late_probe(struct snd_soc_card *card)
+{
+	struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+	struct snd_soc_dai *cpu_dai = card->rtd[0].cpu_dai;
+	int ret;
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0, MAX98090_MCLK,
+						SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	/* Set the cpu DAI configuration in order to use CDCLK */
+	return snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK,
+					0, SND_SOC_CLOCK_OUT);
+}
+
+static const struct snd_soc_dapm_widget odroidx2_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_MIC("Mic Jack", NULL),
+	SND_SOC_DAPM_MIC("DMIC", NULL),
+};
+
+static const struct snd_soc_dapm_widget odroidu3_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_SPK("Speakers", NULL),
+};
+
+static struct snd_soc_dai_link odroidx2_dai[] = {
+	{
+		.name		= "MAX98090",
+		.stream_name	= "MAX98090 PCM",
+		.codec_dai_name	= "HiFi",
+		.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+				  SND_SOC_DAIFMT_CBM_CFM,
+	}
+};
+
+static struct snd_soc_card odroidx2 = {
+	.owner			= THIS_MODULE,
+	.dai_link		= odroidx2_dai,
+	.num_links		= ARRAY_SIZE(odroidx2_dai),
+	.fully_routed		= true,
+	.late_probe		= odroidx2_late_probe,
+};
+
+struct odroidx2_drv_data odroidx2_drvdata = {
+	.dapm_widgets		= odroidx2_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(odroidx2_dapm_widgets),
+};
+
+struct odroidx2_drv_data odroidu3_drvdata = {
+	.dapm_widgets		= odroidu3_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(odroidu3_dapm_widgets),
+};
+
+static const struct of_device_id odroidx2_audio_of_match[] = {
+	{
+		.compatible	= "samsung,odroidx2-audio",
+		.data		= &odroidx2_drvdata,
+	}, {
+		.compatible	= "samsung,odroidu3-audio",
+		.data		= &odroidu3_drvdata,
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, odroidx2_audio_of_match);
+
+static int odroidx2_audio_probe(struct platform_device *pdev)
+{
+	struct device_node *snd_node = pdev->dev.of_node;
+	struct snd_soc_card *card = &odroidx2;
+	struct device_node *i2s_node, *codec_node;
+	struct odroidx2_drv_data *dd;
+	const struct of_device_id *of_id;
+	int ret;
+
+	of_id = of_match_node(odroidx2_audio_of_match, snd_node);
+	dd = (struct odroidx2_drv_data *)of_id->data;
+
+	card->num_dapm_widgets = dd->num_dapm_widgets;
+	card->dapm_widgets = dd->dapm_widgets;
+
+	card->dev = &pdev->dev;
+
+	ret = snd_soc_of_parse_card_name(card, "samsung,model");
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing");
+	if (ret < 0)
+		return ret;
+
+	codec_node = of_parse_phandle(snd_node, "samsung,audio-codec", 0);
+	if (!codec_node) {
+		dev_err(&pdev->dev,
+			"Failed parsing samsung,i2s-codec property\n");
+		return -EINVAL;
+	}
+
+	i2s_node = of_parse_phandle(snd_node, "samsung,i2s-controller", 0);
+	if (!i2s_node) {
+		dev_err(&pdev->dev,
+			"Failed parsing samsung,i2s-controller property\n");
+		ret = -EINVAL;
+		goto err_put_codec_n;
+	}
+
+	odroidx2_dai[0].codec_of_node = codec_node;
+	odroidx2_dai[0].cpu_of_node = i2s_node;
+	odroidx2_dai[0].platform_of_node = i2s_node;
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+			ret);
+		goto err_put_i2s_n;
+	}
+	return 0;
+
+err_put_i2s_n:
+	of_node_put(i2s_node);
+err_put_codec_n:
+	of_node_put(codec_node);
+	return ret;
+}
+
+static int odroidx2_audio_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+
+	of_node_put((struct device_node *)odroidx2_dai[0].cpu_of_node);
+	of_node_put((struct device_node *)odroidx2_dai[0].codec_of_node);
+
+	return 0;
+}
+
+static struct platform_driver odroidx2_audio_driver = {
+	.driver = {
+		.name		= "odroidx2-audio",
+		.owner		= THIS_MODULE,
+		.of_match_table	= odroidx2_audio_of_match,
+		.pm		= &snd_soc_pm_ops,
+	},
+	.probe	= odroidx2_audio_probe,
+	.remove	= odroidx2_audio_remove,
+};
+module_platform_driver(odroidx2_audio_driver);
+
+MODULE_AUTHOR("Chen Zhen <zhen1.chen@samsung.com>");
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
+MODULE_DESCRIPTION("ALSA SoC Odroid X2/U3 Audio Support");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 4c5f97fe45c8..bac034b15a27 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -131,32 +131,20 @@ struct s3c_pcm_info {
 	struct s3c_dma_params	*dma_capture;
 };
 
-static struct s3c_dma_client s3c_pcm_dma_client_out = {
-	.name		= "PCM Stereo out"
-};
-
-static struct s3c_dma_client s3c_pcm_dma_client_in = {
-	.name		= "PCM Stereo in"
-};
-
 static struct s3c_dma_params s3c_pcm_stereo_out[] = {
 	[0] = {
-		.client		= &s3c_pcm_dma_client_out,
 		.dma_size	= 4,
 	},
 	[1] = {
-		.client		= &s3c_pcm_dma_client_out,
 		.dma_size	= 4,
 	},
 };
 
 static struct s3c_dma_params s3c_pcm_stereo_in[] = {
 	[0] = {
-		.client		= &s3c_pcm_dma_client_in,
 		.dma_size	= 4,
 	},
 	[1] = {
-		.client		= &s3c_pcm_dma_client_in,
 		.dma_size	= 4,
 	},
 };
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c
index 0ff4bbe23af3..df65c5b494b1 100644
--- a/sound/soc/samsung/s3c-i2s-v2.c
+++ b/sound/soc/samsung/s3c-i2s-v2.c
@@ -22,8 +22,6 @@
 #include <sound/soc.h>
 #include <sound/pcm_params.h>
 
-#include <mach/dma.h>
-
 #include "regs-i2s-v2.h"
 #include "s3c-i2s-v2.h"
 #include "dma.h"
@@ -392,8 +390,6 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 	int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
 	unsigned long irqs;
 	int ret = 0;
-	struct s3c_dma_params *dma_data =
-		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
 	pr_debug("Entered %s\n", __func__);
 
@@ -424,13 +420,6 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 
 		local_irq_restore(irqs);
 
-		/*
-		 * Load the next buffer to DMA to meet the reqirement
-		 * of the auto reload mechanism of S3C24XX.
-		 * This call won't bother S3C64XX.
-		 */
-		s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
-
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
@@ -644,12 +633,6 @@ int s3c_i2sv2_probe(struct snd_soc_dai *dai,
 	/* record our i2s structure for later use in the callbacks */
 	snd_soc_dai_set_drvdata(dai, i2s);
 
-	i2s->regs = ioremap(base, 0x100);
-	if (i2s->regs == NULL) {
-		dev_err(dev, "cannot ioremap registers\n");
-		return -ENXIO;
-	}
-
 	i2s->iis_pclk = clk_get(dev, "iis");
 	if (IS_ERR(i2s->iis_pclk)) {
 		dev_err(dev, "failed to get iis_clock\n");
@@ -729,7 +712,7 @@ int s3c_i2sv2_register_component(struct device *dev, int id,
 			   struct snd_soc_component_driver *cmp_drv,
 			   struct snd_soc_dai_driver *dai_drv)
 {
-	struct snd_soc_dai_ops *ops = dai_drv->ops;
+	struct snd_soc_dai_ops *ops = (struct snd_soc_dai_ops *)dai_drv->ops;
 
 	ops->trigger = s3c2412_i2s_trigger;
 	if (!ops->hw_params)
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index 08c059be9104..27b339c6580e 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -33,25 +33,15 @@
 #include "regs-i2s-v2.h"
 #include "s3c2412-i2s.h"
 
-static struct s3c_dma_client s3c2412_dma_client_out = {
-	.name		= "I2S PCM Stereo out"
-};
-
-static struct s3c_dma_client s3c2412_dma_client_in = {
-	.name		= "I2S PCM Stereo in"
-};
-
 static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = {
-	.client		= &s3c2412_dma_client_out,
 	.channel	= DMACH_I2S_OUT,
-	.dma_addr	= S3C2410_PA_IIS + S3C2412_IISTXD,
+	.ch_name	= "tx",
 	.dma_size	= 4,
 };
 
 static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = {
-	.client		= &s3c2412_dma_client_in,
 	.channel	= DMACH_I2S_IN,
-	.dma_addr	= S3C2410_PA_IIS + S3C2412_IISRXD,
+	.ch_name	= "rx",
 	.dma_size	= 4,
 };
 
@@ -63,6 +53,9 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
 
 	pr_debug("Entered %s\n", __func__);
 
+	samsung_asoc_init_dma_data(dai, &s3c2412_i2s_pcm_stereo_out,
+		&s3c2412_i2s_pcm_stereo_in);
+
 	ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS);
 	if (ret)
 		return ret;
@@ -70,17 +63,16 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
 	s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in;
 	s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out;
 
-	s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk");
+	s3c2412_i2s.iis_cclk = devm_clk_get(dai->dev, "i2sclk");
 	if (IS_ERR(s3c2412_i2s.iis_cclk)) {
 		pr_err("failed to get i2sclk clock\n");
-		iounmap(s3c2412_i2s.regs);
 		return PTR_ERR(s3c2412_i2s.iis_cclk);
 	}
 
 	/* Set MPLL as the source for IIS CLK */
 
 	clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll"));
-	clk_enable(s3c2412_i2s.iis_cclk);
+	clk_prepare_enable(s3c2412_i2s.iis_cclk);
 
 	s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk;
 
@@ -93,9 +85,7 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
 
 static int s3c2412_i2s_remove(struct snd_soc_dai *dai)
 {
-	clk_disable(s3c2412_i2s.iis_cclk);
-	clk_put(s3c2412_i2s.iis_cclk);
-	iounmap(s3c2412_i2s.regs);
+	clk_disable_unprepare(s3c2412_i2s.iis_cclk);
 
 	return 0;
 }
@@ -105,18 +95,10 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
 				 struct snd_soc_dai *cpu_dai)
 {
 	struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai);
-	struct s3c_dma_params *dma_data;
 	u32 iismod;
 
 	pr_debug("Entered %s\n", __func__);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		dma_data = i2s->dma_playback;
-	else
-		dma_data = i2s->dma_capture;
-
-	snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
-
 	iismod = readl(i2s->regs + S3C2412_IISMOD);
 	pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
 
@@ -169,6 +151,15 @@ static const struct snd_soc_component_driver s3c2412_i2s_component = {
 static int s3c2412_iis_dev_probe(struct platform_device *pdev)
 {
 	int ret = 0;
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	s3c2412_i2s.regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(s3c2412_i2s.regs))
+		return PTR_ERR(s3c2412_i2s.regs);
+
+	s3c2412_i2s_pcm_stereo_out.dma_addr = res->start + S3C2412_IISTXD;
+	s3c2412_i2s_pcm_stereo_in.dma_addr = res->start + S3C2412_IISRXD;
 
 	ret = s3c_i2sv2_register_component(&pdev->dev, -1,
 					   &s3c2412_i2s_component,
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index 9aba9fb7df0e..e87d9a2053b8 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -31,25 +31,15 @@
 #include "dma.h"
 #include "s3c24xx-i2s.h"
 
-static struct s3c_dma_client s3c24xx_dma_client_out = {
-	.name = "I2S PCM Stereo out"
-};
-
-static struct s3c_dma_client s3c24xx_dma_client_in = {
-	.name = "I2S PCM Stereo in"
-};
-
 static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = {
-	.client		= &s3c24xx_dma_client_out,
 	.channel	= DMACH_I2S_OUT,
-	.dma_addr	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	.ch_name	= "tx",
 	.dma_size	= 2,
 };
 
 static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = {
-	.client		= &s3c24xx_dma_client_in,
 	.channel	= DMACH_I2S_IN,
-	.dma_addr	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	.ch_name	= "rx",
 	.dma_size	= 2,
 };
 
@@ -231,18 +221,12 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
 				 struct snd_pcm_hw_params *params,
 				 struct snd_soc_dai *dai)
 {
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct s3c_dma_params *dma_data;
+	struct snd_dmaengine_dai_dma_data *dma_data;
 	u32 iismod;
 
 	pr_debug("Entered %s\n", __func__);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		dma_data = &s3c24xx_i2s_pcm_stereo_out;
-	else
-		dma_data = &s3c24xx_i2s_pcm_stereo_in;
-
-	snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
+	dma_data = snd_soc_dai_get_dma_data(dai, substream);
 
 	/* Working copies of register */
 	iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
@@ -251,11 +235,11 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
 	switch (params_width(params)) {
 	case 8:
 		iismod &= ~S3C2410_IISMOD_16BIT;
-		dma_data->dma_size = 1;
+		dma_data->addr_width = 1;
 		break;
 	case 16:
 		iismod |= S3C2410_IISMOD_16BIT;
-		dma_data->dma_size = 2;
+		dma_data->addr_width = 2;
 		break;
 	default:
 		return -EINVAL;
@@ -270,8 +254,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 			       struct snd_soc_dai *dai)
 {
 	int ret = 0;
-	struct s3c_dma_params *dma_data =
-		snd_soc_dai_get_dma_data(dai, substream);
 
 	pr_debug("Entered %s\n", __func__);
 
@@ -290,7 +272,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 		else
 			s3c24xx_snd_txctrl(1);
 
-		s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -380,17 +361,15 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai)
 {
 	pr_debug("Entered %s\n", __func__);
 
-	s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100);
-	if (s3c24xx_i2s.regs == NULL)
-		return -ENXIO;
+	samsung_asoc_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out,
+		&s3c24xx_i2s_pcm_stereo_in);
 
-	s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis");
+	s3c24xx_i2s.iis_clk = devm_clk_get(dai->dev, "iis");
 	if (IS_ERR(s3c24xx_i2s.iis_clk)) {
 		pr_err("failed to get iis_clock\n");
-		iounmap(s3c24xx_i2s.regs);
 		return PTR_ERR(s3c24xx_i2s.iis_clk);
 	}
-	clk_enable(s3c24xx_i2s.iis_clk);
+	clk_prepare_enable(s3c24xx_i2s.iis_clk);
 
 	/* Configure the I2S pins (GPE0...GPE4) in correct mode */
 	s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
@@ -414,7 +393,7 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai)
 	s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
 	s3c24xx_i2s.iispsr = readl(s3c24xx_i2s.regs + S3C2410_IISPSR);
 
-	clk_disable(s3c24xx_i2s.iis_clk);
+	clk_disable_unprepare(s3c24xx_i2s.iis_clk);
 
 	return 0;
 }
@@ -422,7 +401,7 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai)
 static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai)
 {
 	pr_debug("Entered %s\n", __func__);
-	clk_enable(s3c24xx_i2s.iis_clk);
+	clk_prepare_enable(s3c24xx_i2s.iis_clk);
 
 	writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
 	writel(s3c24xx_i2s.iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
@@ -474,6 +453,19 @@ static const struct snd_soc_component_driver s3c24xx_i2s_component = {
 static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
 {
 	int ret = 0;
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Can't get IO resource.\n");
+		return -ENOENT;
+	}
+	s3c24xx_i2s.regs = devm_ioremap_resource(&pdev->dev, res);
+	if (s3c24xx_i2s.regs == NULL)
+		return -ENXIO;
+
+	s3c24xx_i2s_pcm_stereo_out.dma_addr = res->start + S3C2410_IISFIFO;
+	s3c24xx_i2s_pcm_stereo_in.dma_addr = res->start + S3C2410_IISFIFO;
 
 	ret = devm_snd_soc_register_component(&pdev->dev,
 			&s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1);
diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c
index e119aaa91c28..63d079303561 100644
--- a/sound/soc/samsung/smdk_wm8580pcm.c
+++ b/sound/soc/samsung/smdk_wm8580pcm.c
@@ -25,7 +25,7 @@
  *  o '0' means 'OFF'
  *  o 'X' means 'Don't care'
  *
- * SMDK6410, SMDK6440, SMDK6450 Base B/D: CFG1-0000, CFG2-1111
+ * SMDK6410 Base B/D: CFG1-0000, CFG2-1111
  * SMDKC110, SMDKV210: CFGB11-100100, CFGB12-0000
  */
 
diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c
index 014c177840ba..0acf5d0eed53 100644
--- a/sound/soc/samsung/snow.c
+++ b/sound/soc/samsung/snow.c
@@ -92,6 +92,9 @@ static int snow_probe(struct platform_device *pdev)
 
 	card->dev = &pdev->dev;
 
+	/* Update card-name if provided through DT, else use default name */
+	snd_soc_of_parse_card_name(card, "samsung,model");
+
 	ret = devm_snd_soc_register_card(&pdev->dev, card);
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
@@ -103,6 +106,7 @@ static int snow_probe(struct platform_device *pdev)
 
 static const struct of_device_id snow_of_match[] = {
 	{ .compatible = "google,snow-audio-max98090", },
+	{ .compatible = "google,snow-audio-max98091", },
 	{ .compatible = "google,snow-audio-max98095", },
 	{},
 };
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index d9ffc48fce5e..d7d2e208f486 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -93,10 +93,6 @@ struct samsung_spdif_info {
 	struct s3c_dma_params	*dma_playback;
 };
 
-static struct s3c_dma_client spdif_dma_client_out = {
-	.name		= "S/PDIF Stereo out",
-};
-
 static struct s3c_dma_params spdif_stereo_out;
 static struct samsung_spdif_info spdif_info;
 
@@ -435,7 +431,6 @@ static int spdif_probe(struct platform_device *pdev)
 	}
 
 	spdif_stereo_out.dma_size = 2;
-	spdif_stereo_out.client = &spdif_dma_client_out;
 	spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF;
 	spdif_stereo_out.channel = dma_res->start;
 
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index b43fdf0d08af..80245b6eebd6 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -37,7 +37,7 @@ config SND_SOC_SH4_SIU
 config SND_SOC_RCAR
 	tristate "R-Car series SRU/SCU/SSIU/SSI support"
 	select SND_SIMPLE_CARD
-	select REGMAP
+	select REGMAP_MMIO
 	help
 	  This option enables R-Car SUR/SCU/SSIU/SSI sound support
 
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 710a079a7377..c76344350e44 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -232,11 +232,7 @@ struct fsi_stream {
 	 * these are for DMAEngine
 	 */
 	struct dma_chan		*chan;
-	struct work_struct	work;
-	dma_addr_t		dma;
 	int			dma_id;
-	int			loop_cnt;
-	int			additional_pos;
 };
 
 struct fsi_clk {
@@ -264,12 +260,12 @@ struct fsi_priv {
 	u32 fmt;
 
 	int chan_num:16;
-	int clk_master:1;
-	int clk_cpg:1;
-	int spdif:1;
-	int enable_stream:1;
-	int bit_clk_inv:1;
-	int lr_clk_inv:1;
+	unsigned int clk_master:1;
+	unsigned int clk_cpg:1;
+	unsigned int spdif:1;
+	unsigned int enable_stream:1;
+	unsigned int bit_clk_inv:1;
+	unsigned int lr_clk_inv:1;
 };
 
 struct fsi_stream_handler {
@@ -1042,6 +1038,26 @@ static int fsi_clk_set_rate_cpg(struct device *dev,
 	return ret;
 }
 
+static void fsi_pointer_update(struct fsi_stream *io, int size)
+{
+	io->buff_sample_pos += size;
+
+	if (io->buff_sample_pos >=
+	    io->period_samples * (io->period_pos + 1)) {
+		struct snd_pcm_substream *substream = io->substream;
+		struct snd_pcm_runtime *runtime = substream->runtime;
+
+		io->period_pos++;
+
+		if (io->period_pos >= runtime->periods) {
+			io->buff_sample_pos = 0;
+			io->period_pos = 0;
+		}
+
+		snd_pcm_period_elapsed(substream);
+	}
+}
+
 /*
  *		pio data transfer handler
  */
@@ -1108,31 +1124,11 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
 		void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples),
 		int samples)
 {
-	struct snd_pcm_runtime *runtime;
-	struct snd_pcm_substream *substream;
 	u8 *buf;
-	int over_period;
 
 	if (!fsi_stream_is_working(fsi, io))
 		return -EINVAL;
 
-	over_period	= 0;
-	substream	= io->substream;
-	runtime		= substream->runtime;
-
-	/* FSI FIFO has limit.
-	 * So, this driver can not send periods data at a time
-	 */
-	if (io->buff_sample_pos >=
-	    io->period_samples * (io->period_pos + 1)) {
-
-		over_period = 1;
-		io->period_pos = (io->period_pos + 1) % runtime->periods;
-
-		if (0 == io->period_pos)
-			io->buff_sample_pos = 0;
-	}
-
 	buf = fsi_pio_get_area(fsi, io);
 
 	switch (io->sample_width) {
@@ -1146,11 +1142,7 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
 		return -EINVAL;
 	}
 
-	/* update buff_sample_pos */
-	io->buff_sample_pos += samples;
-
-	if (over_period)
-		snd_pcm_period_elapsed(substream);
+	fsi_pointer_update(io, samples);
 
 	return 0;
 }
@@ -1279,11 +1271,6 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
  */
 static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-	struct snd_pcm_runtime *runtime = io->substream->runtime;
-	struct snd_soc_dai *dai = fsi_get_dai(io->substream);
-	enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
-				DMA_TO_DEVICE : DMA_FROM_DEVICE;
-
 	/*
 	 * 24bit data : 24bit bus / package in back
 	 * 16bit data : 16bit bus / stream mode
@@ -1291,107 +1278,48 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
 	io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
 			 BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
 
-	io->loop_cnt = 2; /* push 1st, 2nd period first, then 3rd, 4th... */
-	io->additional_pos = 0;
-	io->dma = dma_map_single(dai->dev, runtime->dma_area,
-				 snd_pcm_lib_buffer_bytes(io->substream), dir);
 	return 0;
 }
 
-static int fsi_dma_quit(struct fsi_priv *fsi, struct fsi_stream *io)
-{
-	struct snd_soc_dai *dai = fsi_get_dai(io->substream);
-	enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
-		DMA_TO_DEVICE : DMA_FROM_DEVICE;
-
-	dma_unmap_single(dai->dev, io->dma,
-			 snd_pcm_lib_buffer_bytes(io->substream), dir);
-	return 0;
-}
-
-static dma_addr_t fsi_dma_get_area(struct fsi_stream *io, int additional)
-{
-	struct snd_pcm_runtime *runtime = io->substream->runtime;
-	int period = io->period_pos + additional;
-
-	if (period >= runtime->periods)
-		period = 0;
-
-	return io->dma + samples_to_bytes(runtime, period * io->period_samples);
-}
-
 static void fsi_dma_complete(void *data)
 {
 	struct fsi_stream *io = (struct fsi_stream *)data;
 	struct fsi_priv *fsi = fsi_stream_to_priv(io);
-	struct snd_pcm_runtime *runtime = io->substream->runtime;
-	struct snd_soc_dai *dai = fsi_get_dai(io->substream);
-	enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
-		DMA_TO_DEVICE : DMA_FROM_DEVICE;
 
-	dma_sync_single_for_cpu(dai->dev, fsi_dma_get_area(io, 0),
-			samples_to_bytes(runtime, io->period_samples), dir);
-
-	io->buff_sample_pos += io->period_samples;
-	io->period_pos++;
-
-	if (io->period_pos >= runtime->periods) {
-		io->period_pos = 0;
-		io->buff_sample_pos = 0;
-	}
+	fsi_pointer_update(io, io->period_samples);
 
 	fsi_count_fifo_err(fsi);
-	fsi_stream_transfer(io);
-
-	snd_pcm_period_elapsed(io->substream);
 }
 
-static void fsi_dma_do_work(struct work_struct *work)
+static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-	struct fsi_stream *io = container_of(work, struct fsi_stream, work);
-	struct fsi_priv *fsi = fsi_stream_to_priv(io);
-	struct snd_soc_dai *dai;
+	struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+	struct snd_pcm_substream *substream = io->substream;
 	struct dma_async_tx_descriptor *desc;
-	struct snd_pcm_runtime *runtime;
-	enum dma_data_direction dir;
 	int is_play = fsi_stream_is_play(fsi, io);
-	int len, i;
-	dma_addr_t buf;
-
-	if (!fsi_stream_is_working(fsi, io))
-		return;
-
-	dai	= fsi_get_dai(io->substream);
-	runtime	= io->substream->runtime;
-	dir	= is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
-	len	= samples_to_bytes(runtime, io->period_samples);
-
-	for (i = 0; i < io->loop_cnt; i++) {
-		buf	= fsi_dma_get_area(io, io->additional_pos);
-
-		dma_sync_single_for_device(dai->dev, buf, len, dir);
-
-		desc = dmaengine_prep_slave_single(io->chan, buf, len, dir,
-					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-		if (!desc) {
-			dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n");
-			return;
-		}
-
-		desc->callback		= fsi_dma_complete;
-		desc->callback_param	= io;
-
-		if (dmaengine_submit(desc) < 0) {
-			dev_err(dai->dev, "tx_submit() fail\n");
-			return;
-		}
+	enum dma_data_direction dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+	int ret = -EIO;
+
+	desc = dmaengine_prep_dma_cyclic(io->chan,
+					 substream->runtime->dma_addr,
+					 snd_pcm_lib_buffer_bytes(substream),
+					 snd_pcm_lib_period_bytes(substream),
+					 dir,
+					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc) {
+		dev_err(dai->dev, "dmaengine_prep_dma_cyclic() fail\n");
+		goto fsi_dma_transfer_err;
+	}
 
-		dma_async_issue_pending(io->chan);
+	desc->callback		= fsi_dma_complete;
+	desc->callback_param	= io;
 
-		io->additional_pos = 1;
+	if (dmaengine_submit(desc) < 0) {
+		dev_err(dai->dev, "tx_submit() fail\n");
+		goto fsi_dma_transfer_err;
 	}
 
-	io->loop_cnt = 1;
+	dma_async_issue_pending(io->chan);
 
 	/*
 	 * FIXME
@@ -1408,13 +1336,11 @@ static void fsi_dma_do_work(struct work_struct *work)
 			fsi_reg_write(fsi, DIFF_ST, 0);
 		}
 	}
-}
 
-static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
-{
-	schedule_work(&io->work);
+	ret = 0;
 
-	return 0;
+fsi_dma_transfer_err:
+	return ret;
 }
 
 static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
@@ -1475,15 +1401,11 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev
 		return fsi_stream_probe(fsi, dev);
 	}
 
-	INIT_WORK(&io->work, fsi_dma_do_work);
-
 	return 0;
 }
 
 static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-	cancel_work_sync(&io->work);
-
 	fsi_stream_stop(fsi, io);
 
 	if (io->chan)
@@ -1495,7 +1417,6 @@ static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
 
 static struct fsi_stream_handler fsi_dma_push_handler = {
 	.init		= fsi_dma_init,
-	.quit		= fsi_dma_quit,
 	.probe		= fsi_dma_probe,
 	.transfer	= fsi_dma_transfer,
 	.remove		= fsi_dma_remove,
@@ -1657,9 +1578,9 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 		if (!ret)
 			ret = fsi_hw_startup(fsi, io, dai->dev);
 		if (!ret)
-			ret = fsi_stream_transfer(io);
+			ret = fsi_stream_start(fsi, io);
 		if (!ret)
-			fsi_stream_start(fsi, io);
+			ret = fsi_stream_transfer(io);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 		if (!ret)
@@ -1850,16 +1771,10 @@ static void fsi_pcm_free(struct snd_pcm *pcm)
 
 static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
-	struct snd_pcm *pcm = rtd->pcm;
-
-	/*
-	 * dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
-	 * in MMAP mode (i.e. aplay -M)
-	 */
 	return snd_pcm_lib_preallocate_pages_for_all(
-		pcm,
-		SNDRV_DMA_TYPE_CONTINUOUS,
-		snd_dma_continuous_data(GFP_KERNEL),
+		rtd->pcm,
+		SNDRV_DMA_TYPE_DEV,
+		rtd->card->snd_card->dev,
 		PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
 }
 
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 4e86265f625c..19f78963e8b9 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -138,6 +138,17 @@ char *rsnd_mod_name(struct rsnd_mod *mod)
 	return mod->ops->name;
 }
 
+char *rsnd_mod_dma_name(struct rsnd_mod *mod)
+{
+	if (!mod || !mod->ops)
+		return "unknown";
+
+	if (!mod->ops->dma_name)
+		return mod->ops->name;
+
+	return mod->ops->dma_name(mod);
+}
+
 void rsnd_mod_init(struct rsnd_priv *priv,
 		   struct rsnd_mod *mod,
 		   struct rsnd_mod_ops *ops,
@@ -153,26 +164,8 @@ void rsnd_mod_init(struct rsnd_priv *priv,
 /*
  *	rsnd_dma functions
  */
-static void __rsnd_dma_start(struct rsnd_dma *dma);
-static void rsnd_dma_continue(struct rsnd_dma *dma)
-{
-	/* push next A or B plane */
-	dma->submit_loop = 1;
-	schedule_work(&dma->work);
-}
-
-void rsnd_dma_start(struct rsnd_dma *dma)
-{
-	/* push both A and B plane*/
-	dma->offset = 0;
-	dma->submit_loop = 2;
-	__rsnd_dma_start(dma);
-}
-
 void rsnd_dma_stop(struct rsnd_dma *dma)
 {
-	dma->submit_loop = 0;
-	cancel_work_sync(&dma->work);
 	dmaengine_terminate_all(dma->chan);
 }
 
@@ -180,11 +173,7 @@ static void rsnd_dma_complete(void *data)
 {
 	struct rsnd_dma *dma = (struct rsnd_dma *)data;
 	struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
-	struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma));
 	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
-	unsigned long flags;
-
-	rsnd_lock(priv, flags);
 
 	/*
 	 * Renesas sound Gen1 needs 1 DMAC,
@@ -197,57 +186,41 @@ static void rsnd_dma_complete(void *data)
 	 * rsnd_dai_pointer_update() will be called twice,
 	 * ant it will breaks io->byte_pos
 	 */
-	if (dma->submit_loop)
-		rsnd_dma_continue(dma);
-
-	rsnd_unlock(priv, flags);
 
 	rsnd_dai_pointer_update(io, io->byte_per_period);
 }
 
-static void __rsnd_dma_start(struct rsnd_dma *dma)
+void rsnd_dma_start(struct rsnd_dma *dma)
 {
 	struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
 	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
-	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+	struct snd_pcm_substream *substream = io->substream;
 	struct device *dev = rsnd_priv_to_dev(priv);
 	struct dma_async_tx_descriptor *desc;
-	dma_addr_t buf;
-	size_t len = io->byte_per_period;
-	int i;
 
-	for (i = 0; i < dma->submit_loop; i++) {
-
-		buf = runtime->dma_addr +
-			rsnd_dai_pointer_offset(io, dma->offset + len);
-		dma->offset = len;
-
-		desc = dmaengine_prep_slave_single(
-			dma->chan, buf, len, dma->dir,
-			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-		if (!desc) {
-			dev_err(dev, "dmaengine_prep_slave_sg() fail\n");
-			return;
-		}
+	desc = dmaengine_prep_dma_cyclic(dma->chan,
+					 (dma->addr) ? dma->addr :
+					 substream->runtime->dma_addr,
+					 snd_pcm_lib_buffer_bytes(substream),
+					 snd_pcm_lib_period_bytes(substream),
+					 dma->dir,
+					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 
-		desc->callback		= rsnd_dma_complete;
-		desc->callback_param	= dma;
+	if (!desc) {
+		dev_err(dev, "dmaengine_prep_slave_sg() fail\n");
+		return;
+	}
 
-		if (dmaengine_submit(desc) < 0) {
-			dev_err(dev, "dmaengine_submit() fail\n");
-			return;
-		}
+	desc->callback		= rsnd_dma_complete;
+	desc->callback_param	= dma;
 
-		dma_async_issue_pending(dma->chan);
+	if (dmaengine_submit(desc) < 0) {
+		dev_err(dev, "dmaengine_submit() fail\n");
+		return;
 	}
-}
-
-static void rsnd_dma_do_work(struct work_struct *work)
-{
-	struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work);
 
-	__rsnd_dma_start(dma);
+	dma_async_issue_pending(dma->chan);
 }
 
 int rsnd_dma_available(struct rsnd_dma *dma)
@@ -261,14 +234,27 @@ static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod)
 {
 	if (mod)
 		return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d",
-			 rsnd_mod_name(mod), rsnd_mod_id(mod));
+			 rsnd_mod_dma_name(mod), rsnd_mod_id(mod));
 	else
 		return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem");
 
 }
 
-static void rsnd_dma_of_name(struct rsnd_dma *dma,
-			     int is_play, char *dma_name)
+static void rsnd_dma_of_name(struct rsnd_mod *mod_from,
+			     struct rsnd_mod *mod_to,
+			     char *dma_name)
+{
+	int index = 0;
+
+	index = _rsnd_dma_of_name(dma_name + index, mod_from);
+	*(dma_name + index++) = '_';
+	index = _rsnd_dma_of_name(dma_name + index, mod_to);
+}
+
+static void rsnd_dma_of_path(struct rsnd_dma *dma,
+			     int is_play,
+			     struct rsnd_mod **mod_from,
+			     struct rsnd_mod **mod_to)
 {
 	struct rsnd_mod *this = rsnd_dma_to_mod(dma);
 	struct rsnd_dai_stream *io = rsnd_mod_to_io(this);
@@ -276,7 +262,6 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
 	struct rsnd_mod *src = rsnd_io_to_mod_src(io);
 	struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
 	struct rsnd_mod *mod[MOD_MAX];
-	struct rsnd_mod *src_mod, *dst_mod;
 	int i, index;
 
 
@@ -297,31 +282,34 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
 	for (i = 1; i < MOD_MAX; i++) {
 		if (!src) {
 			mod[i] = ssi;
-			break;
 		} else if (!dvc) {
 			mod[i] = src;
 			src = NULL;
 		} else {
-			mod[i] = dvc;
+			if ((!is_play) && (this == src))
+				this = dvc;
+
+			mod[i] = (is_play) ? src : dvc;
+			i++;
+			mod[i] = (is_play) ? dvc : src;
+			src = NULL;
 			dvc = NULL;
 		}
 
 		if (mod[i] == this)
 			index = i;
+
+		if (mod[i] == ssi)
+			break;
 	}
 
 	if (is_play) {
-		src_mod = mod[index - 1];
-		dst_mod = mod[index];
+		*mod_from = mod[index - 1];
+		*mod_to   = mod[index];
 	} else {
-		src_mod = mod[index];
-		dst_mod = mod[index - 1];
+		*mod_from = mod[index];
+		*mod_to   = mod[index - 1];
 	}
-
-	index = 0;
-	index = _rsnd_dma_of_name(dma_name + index, src_mod);
-	*(dma_name + index++) = '_';
-	index = _rsnd_dma_of_name(dma_name + index, dst_mod);
 }
 
 int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
@@ -329,6 +317,8 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
 {
 	struct device *dev = rsnd_priv_to_dev(priv);
 	struct dma_slave_config cfg;
+	struct rsnd_mod *mod_from;
+	struct rsnd_mod *mod_to;
 	char dma_name[DMA_NAME_SIZE];
 	dma_cap_mask_t mask;
 	int ret;
@@ -341,13 +331,18 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_SLAVE, mask);
 
-	if (dev->of_node)
-		rsnd_dma_of_name(dma, is_play, dma_name);
-	else
-		snprintf(dma_name, DMA_NAME_SIZE,
-			 is_play ? "tx" : "rx");
+	rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to);
+	rsnd_dma_of_name(mod_from, mod_to, dma_name);
 
-	dev_dbg(dev, "dma name : %s\n", dma_name);
+	cfg.slave_id	= id;
+	cfg.direction	= is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+	cfg.src_addr	= rsnd_gen_dma_addr(priv, mod_from, is_play, 1);
+	cfg.dst_addr	= rsnd_gen_dma_addr(priv, mod_to,   is_play, 0);
+	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+
+	dev_dbg(dev, "dma : %s %pad -> %pad\n",
+		dma_name, &cfg.src_addr, &cfg.dst_addr);
 
 	dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
 						     (void *)id, dev,
@@ -357,14 +352,12 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
 		return -EIO;
 	}
 
-	rsnd_gen_dma_addr(priv, dma, &cfg, is_play, id);
-
 	ret = dmaengine_slave_config(dma->chan, &cfg);
 	if (ret < 0)
 		goto rsnd_dma_init_err;
 
-	dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
-	INIT_WORK(&dma->work, rsnd_dma_do_work);
+	dma->addr = is_play ? cfg.src_addr : cfg.dst_addr;
+	dma->dir = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
 
 	return 0;
 
@@ -631,40 +624,41 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 		return -EINVAL;
 	}
 
-	/* set clock inversion */
-	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-	case SND_SOC_DAIFMT_NB_IF:
-		rdai->bit_clk_inv = 0;
-		rdai->frm_clk_inv = 1;
-		break;
-	case SND_SOC_DAIFMT_IB_NF:
-		rdai->bit_clk_inv = 1;
-		rdai->frm_clk_inv = 0;
-		break;
-	case SND_SOC_DAIFMT_IB_IF:
-		rdai->bit_clk_inv = 1;
-		rdai->frm_clk_inv = 1;
-		break;
-	case SND_SOC_DAIFMT_NB_NF:
-	default:
-		rdai->bit_clk_inv = 0;
-		rdai->frm_clk_inv = 0;
-		break;
-	}
-
 	/* set format */
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_I2S:
 		rdai->sys_delay = 0;
 		rdai->data_alignment = 0;
+		rdai->frm_clk_inv = 0;
 		break;
 	case SND_SOC_DAIFMT_LEFT_J:
 		rdai->sys_delay = 1;
 		rdai->data_alignment = 0;
+		rdai->frm_clk_inv = 1;
 		break;
 	case SND_SOC_DAIFMT_RIGHT_J:
 		rdai->sys_delay = 1;
 		rdai->data_alignment = 1;
+		rdai->frm_clk_inv = 1;
+		break;
+	}
+
+	/* set clock inversion */
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_IF:
+		rdai->bit_clk_inv =  rdai->bit_clk_inv;
+		rdai->frm_clk_inv = !rdai->frm_clk_inv;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		rdai->bit_clk_inv = !rdai->bit_clk_inv;
+		rdai->frm_clk_inv =  rdai->frm_clk_inv;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		rdai->bit_clk_inv = !rdai->bit_clk_inv;
+		rdai->frm_clk_inv = !rdai->frm_clk_inv;
+		break;
+	case SND_SOC_DAIFMT_NB_NF:
+	default:
 		break;
 	}
 
@@ -734,12 +728,13 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
 	struct device_node *dai_node,	*dai_np;
 	struct device_node *ssi_node,	*ssi_np;
 	struct device_node *src_node,	*src_np;
+	struct device_node *dvc_node,	*dvc_np;
 	struct device_node *playback, *capture;
 	struct rsnd_dai_platform_info *dai_info;
 	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
 	struct device *dev = &pdev->dev;
 	int nr, i;
-	int dai_i, ssi_i, src_i;
+	int dai_i, ssi_i, src_i, dvc_i;
 
 	if (!of_data)
 		return;
@@ -765,6 +760,7 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
 
 	ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi");
 	src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src");
+	dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc");
 
 #define mod_parse(name)							\
 if (name##_node) {							\
@@ -800,6 +796,7 @@ if (name##_node) {							\
 
 			mod_parse(ssi);
 			mod_parse(src);
+			mod_parse(dvc);
 
 			if (playback)
 				of_node_put(playback);
@@ -948,19 +945,17 @@ static struct snd_pcm_ops rsnd_pcm_ops = {
 
 static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
-	struct rsnd_priv *priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
-	struct rsnd_dai *rdai;
-	int i, ret;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
+	int ret;
 
-	for_each_rsnd_dai(rdai, priv, i) {
-		ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd);
-		if (ret)
-			return ret;
+	ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd);
+	if (ret)
+		return ret;
 
-		ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd);
-		if (ret)
-			return ret;
-	}
+	ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd);
+	if (ret)
+		return ret;
 
 	return snd_pcm_lib_preallocate_pages_for_all(
 		rtd->pcm,
@@ -1047,11 +1042,11 @@ static int rsnd_probe(struct platform_device *pdev)
 	for_each_rsnd_dai(rdai, priv, i) {
 		ret = rsnd_dai_call(probe, &rdai->playback, rdai);
 		if (ret)
-			return ret;
+			goto exit_snd_probe;
 
 		ret = rsnd_dai_call(probe, &rdai->capture, rdai);
 		if (ret)
-			return ret;
+			goto exit_snd_probe;
 	}
 
 	/*
@@ -1079,6 +1074,11 @@ static int rsnd_probe(struct platform_device *pdev)
 
 exit_snd_soc:
 	snd_soc_unregister_platform(dev);
+exit_snd_probe:
+	for_each_rsnd_dai(rdai, priv, i) {
+		rsnd_dai_call(remove, &rdai->playback, rdai);
+		rsnd_dai_call(remove, &rdai->capture, rdai);
+	}
 
 	return ret;
 }
@@ -1087,21 +1087,16 @@ static int rsnd_remove(struct platform_device *pdev)
 {
 	struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev);
 	struct rsnd_dai *rdai;
-	int ret, i;
+	int ret = 0, i;
 
 	pm_runtime_disable(&pdev->dev);
 
 	for_each_rsnd_dai(rdai, priv, i) {
-		ret = rsnd_dai_call(remove, &rdai->playback, rdai);
-		if (ret)
-			return ret;
-
-		ret = rsnd_dai_call(remove, &rdai->capture, rdai);
-		if (ret)
-			return ret;
+		ret |= rsnd_dai_call(remove, &rdai->playback, rdai);
+		ret |= rsnd_dai_call(remove, &rdai->capture, rdai);
 	}
 
-	return 0;
+	return ret;
 }
 
 static struct platform_driver rsnd_driver = {
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index ed0007006899..3f443930c2b1 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -20,7 +20,8 @@ struct rsnd_dvc {
 	struct rsnd_dvc_platform_info *info; /* rcar_snd.h */
 	struct rsnd_mod mod;
 	struct clk *clk;
-	long volume[RSND_DVC_VOLUME_NUM];
+	u8 volume[RSND_DVC_VOLUME_NUM];
+	u8 mute[RSND_DVC_VOLUME_NUM];
 };
 
 #define rsnd_mod_to_dvc(_mod)	\
@@ -37,13 +38,18 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
 	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
 	u32 max = (0x00800000 - 1);
 	u32 vol[RSND_DVC_VOLUME_NUM];
+	u32 mute = 0;
 	int i;
 
-	for (i = 0; i < RSND_DVC_VOLUME_NUM; i++)
+	for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) {
 		vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i];
+		mute |= (!!dvc->mute[i]) << i;
+	}
 
 	rsnd_mod_write(mod, DVC_VOL0R, vol[0]);
 	rsnd_mod_write(mod, DVC_VOL1R, vol[1]);
+
+	rsnd_mod_write(mod, DVC_ZCMCR, mute);
 }
 
 static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod,
@@ -96,8 +102,8 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,
 
 	rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod));
 
-	/*  enable Volume  */
-	rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x100);
+	/*  enable Volume / Mute */
+	rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x101);
 
 	/* ch0/ch1 Volume */
 	rsnd_dvc_volume_update(dvc_mod);
@@ -140,10 +146,20 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod,
 static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl,
 			       struct snd_ctl_elem_info *uinfo)
 {
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	struct rsnd_mod *mod = snd_kcontrol_chip(kctrl);
+	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
+	u8 *val = (u8 *)kctrl->private_value;
+
 	uinfo->count = RSND_DVC_VOLUME_NUM;
 	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = RSND_DVC_VOLUME_MAX;
+
+	if (val == dvc->volume) {
+		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+		uinfo->value.integer.max = RSND_DVC_VOLUME_MAX;
+	} else {
+		uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+		uinfo->value.integer.max = 1;
+	}
 
 	return 0;
 }
@@ -151,12 +167,11 @@ static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl,
 static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct rsnd_mod *mod = snd_kcontrol_chip(kctrl);
-	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
+	u8 *val = (u8 *)kctrl->private_value;
 	int i;
 
 	for (i = 0; i < RSND_DVC_VOLUME_NUM; i++)
-		ucontrol->value.integer.value[i] = dvc->volume[i];
+		ucontrol->value.integer.value[i] = val[i];
 
 	return 0;
 }
@@ -165,51 +180,38 @@ static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl,
 			      struct snd_ctl_elem_value *ucontrol)
 {
 	struct rsnd_mod *mod = snd_kcontrol_chip(kctrl);
-	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
+	u8 *val = (u8 *)kctrl->private_value;
 	int i, change = 0;
 
 	for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) {
-		if (ucontrol->value.integer.value[i] < 0 ||
-		    ucontrol->value.integer.value[i] > RSND_DVC_VOLUME_MAX)
-			return -EINVAL;
-
-		change |= (ucontrol->value.integer.value[i] != dvc->volume[i]);
+		change |= (ucontrol->value.integer.value[i] != val[i]);
+		val[i] = ucontrol->value.integer.value[i];
 	}
 
-	if (change) {
-		for (i = 0; i < RSND_DVC_VOLUME_NUM; i++)
-			dvc->volume[i] = ucontrol->value.integer.value[i];
-
+	if (change)
 		rsnd_dvc_volume_update(mod);
-	}
 
 	return change;
 }
 
-static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
-			    struct rsnd_dai *rdai,
-			    struct snd_soc_pcm_runtime *rtd)
+static int __rsnd_dvc_pcm_new(struct rsnd_mod *mod,
+			      struct rsnd_dai *rdai,
+			      struct snd_soc_pcm_runtime *rtd,
+			      const unsigned char *name,
+			      u8 *private)
 {
-	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
-	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-	struct device *dev = rsnd_priv_to_dev(priv);
 	struct snd_card *card = rtd->card->snd_card;
 	struct snd_kcontrol *kctrl;
-	static struct snd_kcontrol_new knew = {
+	struct snd_kcontrol_new knew = {
 		.iface		= SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name		= "Playback Volume",
+		.name		= name,
 		.info		= rsnd_dvc_volume_info,
 		.get		= rsnd_dvc_volume_get,
 		.put		= rsnd_dvc_volume_put,
+		.private_value	= (unsigned long)private,
 	};
 	int ret;
 
-	if (!rsnd_dai_is_play(rdai, io)) {
-		dev_err(dev, "DVC%d is connected to Capture DAI\n",
-			rsnd_mod_id(mod));
-		return -EINVAL;
-	}
-
 	kctrl = snd_ctl_new1(&knew, mod);
 	if (!kctrl)
 		return -ENOMEM;
@@ -221,6 +223,33 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
 	return 0;
 }
 
+static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
+			    struct rsnd_dai *rdai,
+			    struct snd_soc_pcm_runtime *rtd)
+{
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
+	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
+	int ret;
+
+	/* Volume */
+	ret = __rsnd_dvc_pcm_new(mod, rdai, rtd,
+			rsnd_dai_is_play(rdai, io) ?
+			"DVC Out Playback Volume" : "DVC In Capture Volume",
+			dvc->volume);
+	if (ret < 0)
+		return ret;
+
+	/* Mute */
+	ret = __rsnd_dvc_pcm_new(mod, rdai, rtd,
+			rsnd_dai_is_play(rdai, io) ?
+			"DVC Out Mute Switch" : "DVC In Mute Switch",
+			dvc->mute);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static struct rsnd_mod_ops rsnd_dvc_ops = {
 	.name		= DVC_NAME,
 	.probe		= rsnd_dvc_probe_gen2,
@@ -239,6 +268,42 @@ struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id)
 	return &((struct rsnd_dvc *)(priv->dvc) + id)->mod;
 }
 
+static void rsnd_of_parse_dvc(struct platform_device *pdev,
+			      const struct rsnd_of_data *of_data,
+			      struct rsnd_priv *priv)
+{
+	struct device_node *node;
+	struct rsnd_dvc_platform_info *dvc_info;
+	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
+	struct device *dev = &pdev->dev;
+	int nr;
+
+	if (!of_data)
+		return;
+
+	node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc");
+	if (!node)
+		return;
+
+	nr = of_get_child_count(node);
+	if (!nr)
+		goto rsnd_of_parse_dvc_end;
+
+	dvc_info = devm_kzalloc(dev,
+				sizeof(struct rsnd_dvc_platform_info) * nr,
+				GFP_KERNEL);
+	if (!dvc_info) {
+		dev_err(dev, "dvc info allocation error\n");
+		goto rsnd_of_parse_dvc_end;
+	}
+
+	info->dvc_info		= dvc_info;
+	info->dvc_info_nr	= nr;
+
+rsnd_of_parse_dvc_end:
+	of_node_put(node);
+}
+
 int rsnd_dvc_probe(struct platform_device *pdev,
 		   const struct rsnd_of_data *of_data,
 		   struct rsnd_priv *priv)
@@ -250,6 +315,8 @@ int rsnd_dvc_probe(struct platform_device *pdev,
 	char name[RSND_DVC_NAME_SIZE];
 	int i, nr;
 
+	rsnd_of_parse_dvc(pdev, of_data, priv);
+
 	nr = info->dvc_info_nr;
 	if (!nr)
 		return 0;
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index 1dd2b7d38c2c..3fdf3be7b99a 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -15,63 +15,35 @@ struct rsnd_gen {
 
 	struct rsnd_gen_ops *ops;
 
-	struct regmap *regmap;
+	struct regmap *regmap[RSND_BASE_MAX];
 	struct regmap_field *regs[RSND_REG_MAX];
 };
 
 #define rsnd_priv_to_gen(p)	((struct rsnd_gen *)(p)->gen)
 
-#define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size)	\
-	[id] = {							\
-		.reg = (unsigned int)gen->base[reg_id] + offset,	\
-		.lsb = 0,						\
-		.msb = 31,						\
-		.id_size = _id_size,					\
-		.id_offset = _id_offset,				\
-	}
-
-/*
- *		basic function
- */
-static int rsnd_regmap_write32(void *context, const void *_data, size_t count)
-{
-	struct rsnd_priv *priv = context;
-	struct device *dev = rsnd_priv_to_dev(priv);
-	u32 *data = (u32 *)_data;
-	u32 val = data[1];
-	void __iomem *reg = (void *)data[0];
-
-	iowrite32(val, reg);
-
-	dev_dbg(dev, "w %p : %08x\n", reg, val);
-
-	return 0;
-}
-
-static int rsnd_regmap_read32(void *context,
-			      const void *_data, size_t reg_size,
-			      void *_val, size_t val_size)
-{
-	struct rsnd_priv *priv = context;
-	struct device *dev = rsnd_priv_to_dev(priv);
-	u32 *data = (u32 *)_data;
-	u32 *val = (u32 *)_val;
-	void __iomem *reg = (void *)data[0];
-
-	*val = ioread32(reg);
-
-	dev_dbg(dev, "r %p : %08x\n", reg, *val);
+struct rsnd_regmap_field_conf {
+	int idx;
+	unsigned int reg_offset;
+	unsigned int id_offset;
+};
 
-	return 0;
+#define RSND_REG_SET(id, offset, _id_offset)	\
+{						\
+	.idx = id,				\
+	.reg_offset = offset,			\
+	.id_offset = _id_offset,		\
 }
+/* single address mapping */
+#define RSND_GEN_S_REG(id, offset)	\
+	RSND_REG_SET(RSND_REG_##id, offset, 0)
 
-static struct regmap_bus rsnd_regmap_bus = {
-	.write				= rsnd_regmap_write32,
-	.read				= rsnd_regmap_read32,
-	.reg_format_endian_default	= REGMAP_ENDIAN_NATIVE,
-	.val_format_endian_default	= REGMAP_ENDIAN_NATIVE,
-};
+/* multi address mapping */
+#define RSND_GEN_M_REG(id, offset, _id_offset)	\
+	RSND_REG_SET(RSND_REG_##id, offset, _id_offset)
 
+/*
+ *		basic function
+ */
 static int rsnd_is_accessible_reg(struct rsnd_priv *priv,
 				  struct rsnd_gen *gen, enum rsnd_reg reg)
 {
@@ -88,6 +60,7 @@ static int rsnd_is_accessible_reg(struct rsnd_priv *priv,
 u32 rsnd_read(struct rsnd_priv *priv,
 	      struct rsnd_mod *mod, enum rsnd_reg reg)
 {
+	struct device *dev = rsnd_priv_to_dev(priv);
 	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
 	u32 val;
 
@@ -96,6 +69,8 @@ u32 rsnd_read(struct rsnd_priv *priv,
 
 	regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val);
 
+	dev_dbg(dev, "r %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, val);
+
 	return val;
 }
 
@@ -103,17 +78,21 @@ void rsnd_write(struct rsnd_priv *priv,
 		struct rsnd_mod *mod,
 		enum rsnd_reg reg, u32 data)
 {
+	struct device *dev = rsnd_priv_to_dev(priv);
 	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
 
 	if (!rsnd_is_accessible_reg(priv, gen, reg))
 		return;
 
 	regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
+
+	dev_dbg(dev, "w %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, data);
 }
 
 void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
 	       enum rsnd_reg reg, u32 mask, u32 data)
 {
+	struct device *dev = rsnd_priv_to_dev(priv);
 	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
 
 	if (!rsnd_is_accessible_reg(priv, gen, reg))
@@ -121,35 +100,63 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
 
 	regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod),
 				  mask, data);
+
+	dev_dbg(dev, "b %s - 0x%04d : %08x/%08x\n",
+		rsnd_mod_name(mod), reg, data, mask);
 }
 
-static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
-				struct rsnd_gen  *gen,
-				struct reg_field *regf)
+#define rsnd_gen_regmap_init(priv, id_size, reg_id, conf)		\
+	_rsnd_gen_regmap_init(priv, id_size, reg_id, conf, ARRAY_SIZE(conf))
+static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
+				 int id_size,
+				 int reg_id,
+				 struct rsnd_regmap_field_conf *conf,
+				 int conf_size)
 {
-	int i;
+	struct platform_device *pdev = rsnd_priv_to_pdev(priv);
+	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
 	struct device *dev = rsnd_priv_to_dev(priv);
+	struct resource *res;
 	struct regmap_config regc;
+	struct regmap_field *regs;
+	struct regmap *regmap;
+	struct reg_field regf;
+	void __iomem *base;
+	int i;
 
 	memset(&regc, 0, sizeof(regc));
 	regc.reg_bits = 32;
 	regc.val_bits = 32;
+	regc.reg_stride = 4;
 
-	gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, &regc);
-	if (IS_ERR(gen->regmap)) {
-		dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap));
-		return PTR_ERR(gen->regmap);
-	}
+	res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id);
+	if (!res)
+		return -ENODEV;
 
-	for (i = 0; i < RSND_REG_MAX; i++) {
-		gen->regs[i] = NULL;
-		if (!regf[i].reg)
-			continue;
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
-		gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]);
-		if (IS_ERR(gen->regs[i]))
-			return PTR_ERR(gen->regs[i]);
+	regmap = devm_regmap_init_mmio(dev, base, &regc);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
 
+	gen->base[reg_id] = base;
+	gen->regmap[reg_id] = regmap;
+
+	for (i = 0; i < conf_size; i++) {
+
+		regf.reg	= conf[i].reg_offset;
+		regf.id_offset	= conf[i].id_offset;
+		regf.lsb	= 0;
+		regf.msb	= 31;
+		regf.id_size	= id_size;
+
+		regs = devm_regmap_field_alloc(dev, regmap, regf);
+		if (IS_ERR(regs))
+			return PTR_ERR(regs);
+
+		gen->regs[conf[i].idx] = regs;
 	}
 
 	return 0;
@@ -165,15 +172,19 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
  *
  *	ex) R-Car H2 case
  *	      mod        / DMAC in    / DMAC out   / DMAC PP in / DMAC pp out
- *	SSI : 0xec541000 / 0xec241008 / 0xec24100c / 0xec400000 / 0xec400000
+ *	SSI : 0xec541000 / 0xec241008 / 0xec24100c
+ *	SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000
  *	SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
- *	CMD : 0xec500000 / 0xec008000                             0xec308000
+ *	CMD : 0xec500000 /            / 0xec008000                0xec308000
  */
 #define RDMA_SSI_I_N(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
 #define RDMA_SSI_O_N(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
 
-#define RDMA_SSI_I_P(addr, i)	(addr ##_reg - 0x00141000 + (0x1000 * i))
-#define RDMA_SSI_O_P(addr, i)	(addr ##_reg - 0x00141000 + (0x1000 * i))
+#define RDMA_SSIU_I_N(addr, i)	(addr ##_reg - 0x00441000 + (0x1000 * i))
+#define RDMA_SSIU_O_N(addr, i)	(addr ##_reg - 0x00441000 + (0x1000 * i))
+
+#define RDMA_SSIU_I_P(addr, i)	(addr ##_reg - 0x00141000 + (0x1000 * i))
+#define RDMA_SSIU_O_P(addr, i)	(addr ##_reg - 0x00141000 + (0x1000 * i))
 
 #define RDMA_SRC_I_N(addr, i)	(addr ##_reg - 0x00500000 + (0x400 * i))
 #define RDMA_SRC_O_N(addr, i)	(addr ##_reg - 0x004fc000 + (0x400 * i))
@@ -184,14 +195,13 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
 #define RDMA_CMD_O_N(addr, i)	(addr ##_reg - 0x004f8000 + (0x400 * i))
 #define RDMA_CMD_O_P(addr, i)	(addr ##_reg - 0x001f8000 + (0x400 * i))
 
-void rsnd_gen_dma_addr(struct rsnd_priv *priv,
-		       struct rsnd_dma *dma,
-		       struct dma_slave_config *cfg,
-		       int is_play, int slave_id)
+static dma_addr_t
+rsnd_gen2_dma_addr(struct rsnd_priv *priv,
+		   struct rsnd_mod *mod,
+		   int is_play, int is_from)
 {
 	struct platform_device *pdev = rsnd_priv_to_pdev(priv);
 	struct device *dev = rsnd_priv_to_dev(priv);
-	struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
 	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
 	dma_addr_t ssi_reg = platform_get_resource(pdev,
 				IORESOURCE_MEM, RSND_GEN2_SSI)->start;
@@ -202,170 +212,152 @@ void rsnd_gen_dma_addr(struct rsnd_priv *priv,
 	int use_dvc = !!rsnd_io_to_mod_dvc(io);
 	int id = rsnd_mod_id(mod);
 	struct dma_addr {
-		dma_addr_t src_addr;
-		dma_addr_t dst_addr;
-	} dma_addrs[2][2][3] = {
-		{ /* SRC */
-			/* Capture */
-			{{ 0,				0 },
-			 { RDMA_SRC_O_N(src, id),	0 },
-			 { RDMA_CMD_O_N(src, id),	0 }},
-			/* Playback */
-			{{ 0,				0, },
-			 { 0,				RDMA_SRC_I_N(src, id) },
-			 { 0,				RDMA_SRC_I_N(src, id) }}
-		}, { /* SSI */
-			/* Capture */
-			{{ RDMA_SSI_O_N(ssi, id),	0 },
-			 { RDMA_SSI_O_P(ssi, id),	RDMA_SRC_I_P(src, id) },
-			 { RDMA_SSI_O_P(ssi, id),	RDMA_SRC_I_P(src, id) }},
-			/* Playback */
-			{{ 0,				RDMA_SSI_I_N(ssi, id) },
-			 { RDMA_SRC_O_P(src, id),	RDMA_SSI_I_P(ssi, id) },
-			 { RDMA_CMD_O_P(src, id),	RDMA_SSI_I_P(ssi, id) }}
-		}
+		dma_addr_t out_addr;
+		dma_addr_t in_addr;
+	} dma_addrs[3][2][3] = {
+		/* SRC */
+		{{{ 0,				0 },
+		/* Capture */
+		  { RDMA_SRC_O_N(src, id),	RDMA_SRC_I_P(src, id) },
+		  { RDMA_CMD_O_N(src, id),	RDMA_SRC_I_P(src, id) } },
+		 /* Playback */
+		 {{ 0,				0, },
+		  { RDMA_SRC_O_P(src, id),	RDMA_SRC_I_N(src, id) },
+		  { RDMA_CMD_O_P(src, id),	RDMA_SRC_I_N(src, id) } }
+		},
+		/* SSI */
+		/* Capture */
+		{{{ RDMA_SSI_O_N(ssi, id),	0 },
+		  { RDMA_SSIU_O_P(ssi, id),	0 },
+		  { RDMA_SSIU_O_P(ssi, id),	0 } },
+		 /* Playback */
+		 {{ 0,				RDMA_SSI_I_N(ssi, id) },
+		  { 0,				RDMA_SSIU_I_P(ssi, id) },
+		  { 0,				RDMA_SSIU_I_P(ssi, id) } }
+		},
+		/* SSIU */
+		/* Capture */
+		{{{ RDMA_SSIU_O_N(ssi, id),	0 },
+		  { RDMA_SSIU_O_P(ssi, id),	0 },
+		  { RDMA_SSIU_O_P(ssi, id),	0 } },
+		 /* Playback */
+		 {{ 0,				RDMA_SSIU_I_N(ssi, id) },
+		  { 0,				RDMA_SSIU_I_P(ssi, id) },
+		  { 0,				RDMA_SSIU_I_P(ssi, id) } } },
 	};
 
-	cfg->slave_id	= slave_id;
-	cfg->src_addr	= 0;
-	cfg->dst_addr	= 0;
-	cfg->direction	= is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+	/* it shouldn't happen */
+	if (use_dvc & !use_src)
+		dev_err(dev, "DVC is selected without SRC\n");
+
+	/* use SSIU or SSI ? */
+	if (is_ssi && (0 == strcmp(rsnd_mod_dma_name(mod), "ssiu")))
+		is_ssi++;
+
+	return (is_from) ?
+		dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr :
+		dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr;
+}
 
+dma_addr_t rsnd_gen_dma_addr(struct rsnd_priv *priv,
+			     struct rsnd_mod *mod,
+			     int is_play, int is_from)
+{
 	/*
 	 * gen1 uses default DMA addr
 	 */
 	if (rsnd_is_gen1(priv))
-		return;
-
-	/* it shouldn't happen */
-	if (use_dvc & !use_src) {
-		dev_err(dev, "DVC is selected without SRC\n");
-		return;
-	}
+		return 0;
 
-	cfg->src_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].src_addr;
-	cfg->dst_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].dst_addr;
+	if (!mod)
+		return 0;
 
-	dev_dbg(dev, "dma%d addr - src : %x / dst : %x\n",
-		id, cfg->src_addr, cfg->dst_addr);
+	return rsnd_gen2_dma_addr(priv, mod, is_play, is_from);
 }
 
 /*
  *		Gen2
  */
-
-/* single address mapping */
-#define RSND_GEN2_S_REG(gen, reg, id, offset)				\
-	RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 10)
-
-/* multi address mapping */
-#define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset)		\
-	RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 10)
-
-static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
-{
-	struct reg_field regf[RSND_REG_MAX] = {
-		RSND_GEN2_S_REG(gen, SSIU,	SSI_MODE0,	0x800),
-		RSND_GEN2_S_REG(gen, SSIU,	SSI_MODE1,	0x804),
-		/* FIXME: it needs SSI_MODE2/3 in the future */
-		RSND_GEN2_M_REG(gen, SSIU,	SSI_BUSIF_MODE,	0x0,	0x80),
-		RSND_GEN2_M_REG(gen, SSIU,	SSI_BUSIF_ADINR,0x4,	0x80),
-		RSND_GEN2_M_REG(gen, SSIU,	SSI_CTRL,	0x10,	0x80),
-		RSND_GEN2_M_REG(gen, SSIU,	INT_ENABLE,	0x18,	0x80),
-
-		RSND_GEN2_M_REG(gen, SCU,	SRC_BUSIF_MODE,	0x0,	0x20),
-		RSND_GEN2_M_REG(gen, SCU,	SRC_ROUTE_MODE0,0xc,	0x20),
-		RSND_GEN2_M_REG(gen, SCU,	SRC_CTRL,	0x10,	0x20),
-		RSND_GEN2_M_REG(gen, SCU,	CMD_ROUTE_SLCT,	0x18c,	0x20),
-		RSND_GEN2_M_REG(gen, SCU,	CMD_CTRL,	0x190,	0x20),
-		RSND_GEN2_M_REG(gen, SCU,	SRC_SWRSR,	0x200,	0x40),
-		RSND_GEN2_M_REG(gen, SCU,	SRC_SRCIR,	0x204,	0x40),
-		RSND_GEN2_M_REG(gen, SCU,	SRC_ADINR,	0x214,	0x40),
-		RSND_GEN2_M_REG(gen, SCU,	SRC_IFSCR,	0x21c,	0x40),
-		RSND_GEN2_M_REG(gen, SCU,	SRC_IFSVR,	0x220,	0x40),
-		RSND_GEN2_M_REG(gen, SCU,	SRC_SRCCR,	0x224,	0x40),
-		RSND_GEN2_M_REG(gen, SCU,	SRC_BSDSR,	0x22c,	0x40),
-		RSND_GEN2_M_REG(gen, SCU,	SRC_BSISR,	0x238,	0x40),
-		RSND_GEN2_M_REG(gen, SCU,	DVC_SWRSR,	0xe00,	0x100),
-		RSND_GEN2_M_REG(gen, SCU,	DVC_DVUIR,	0xe04,	0x100),
-		RSND_GEN2_M_REG(gen, SCU,	DVC_ADINR,	0xe08,	0x100),
-		RSND_GEN2_M_REG(gen, SCU,	DVC_DVUCR,	0xe10,	0x100),
-		RSND_GEN2_M_REG(gen, SCU,	DVC_ZCMCR,	0xe14,	0x100),
-		RSND_GEN2_M_REG(gen, SCU,	DVC_VOL0R,	0xe28,	0x100),
-		RSND_GEN2_M_REG(gen, SCU,	DVC_VOL1R,	0xe2c,	0x100),
-		RSND_GEN2_M_REG(gen, SCU,	DVC_DVUER,	0xe48,	0x100),
-
-		RSND_GEN2_S_REG(gen, ADG,	BRRA,		0x00),
-		RSND_GEN2_S_REG(gen, ADG,	BRRB,		0x04),
-		RSND_GEN2_S_REG(gen, ADG,	SSICKR,		0x08),
-		RSND_GEN2_S_REG(gen, ADG,	AUDIO_CLK_SEL0,	0x0c),
-		RSND_GEN2_S_REG(gen, ADG,	AUDIO_CLK_SEL1,	0x10),
-		RSND_GEN2_S_REG(gen, ADG,	AUDIO_CLK_SEL2,	0x14),
-		RSND_GEN2_S_REG(gen, ADG,	DIV_EN,		0x30),
-		RSND_GEN2_S_REG(gen, ADG,	SRCIN_TIMSEL0,	0x34),
-		RSND_GEN2_S_REG(gen, ADG,	SRCIN_TIMSEL1,	0x38),
-		RSND_GEN2_S_REG(gen, ADG,	SRCIN_TIMSEL2,	0x3c),
-		RSND_GEN2_S_REG(gen, ADG,	SRCIN_TIMSEL3,	0x40),
-		RSND_GEN2_S_REG(gen, ADG,	SRCIN_TIMSEL4,	0x44),
-		RSND_GEN2_S_REG(gen, ADG,	SRCOUT_TIMSEL0,	0x48),
-		RSND_GEN2_S_REG(gen, ADG,	SRCOUT_TIMSEL1,	0x4c),
-		RSND_GEN2_S_REG(gen, ADG,	SRCOUT_TIMSEL2,	0x50),
-		RSND_GEN2_S_REG(gen, ADG,	SRCOUT_TIMSEL3,	0x54),
-		RSND_GEN2_S_REG(gen, ADG,	SRCOUT_TIMSEL4,	0x58),
-		RSND_GEN2_S_REG(gen, ADG,	CMDOUT_TIMSEL,	0x5c),
-
-		RSND_GEN2_M_REG(gen, SSI,	SSICR,		0x00,	0x40),
-		RSND_GEN2_M_REG(gen, SSI,	SSISR,		0x04,	0x40),
-		RSND_GEN2_M_REG(gen, SSI,	SSITDR,		0x08,	0x40),
-		RSND_GEN2_M_REG(gen, SSI,	SSIRDR,		0x0c,	0x40),
-		RSND_GEN2_M_REG(gen, SSI,	SSIWSR,		0x20,	0x40),
-	};
-
-	return rsnd_gen_regmap_init(priv, gen, regf);
-}
-
 static int rsnd_gen2_probe(struct platform_device *pdev,
 			   struct rsnd_priv *priv)
 {
 	struct device *dev = rsnd_priv_to_dev(priv);
-	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-	struct resource *scu_res;
-	struct resource *adg_res;
-	struct resource *ssiu_res;
-	struct resource *ssi_res;
-	int ret;
-
-	/*
-	 * map address
-	 */
-	scu_res  = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SCU);
-	adg_res  = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_ADG);
-	ssiu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSIU);
-	ssi_res  = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSI);
-
-	gen->base[RSND_GEN2_SCU]  = devm_ioremap_resource(dev, scu_res);
-	gen->base[RSND_GEN2_ADG]  = devm_ioremap_resource(dev, adg_res);
-	gen->base[RSND_GEN2_SSIU] = devm_ioremap_resource(dev, ssiu_res);
-	gen->base[RSND_GEN2_SSI]  = devm_ioremap_resource(dev, ssi_res);
-	if (IS_ERR(gen->base[RSND_GEN2_SCU])  ||
-	    IS_ERR(gen->base[RSND_GEN2_ADG])  ||
-	    IS_ERR(gen->base[RSND_GEN2_SSIU]) ||
-	    IS_ERR(gen->base[RSND_GEN2_SSI]))
-		return -ENODEV;
-
-	ret = rsnd_gen2_regmap_init(priv, gen);
-	if (ret < 0)
-		return ret;
-
-	dev_dbg(dev, "Gen2 device probed\n");
-	dev_dbg(dev, "SCU  : %pap => %p\n", &scu_res->start,
-		gen->base[RSND_GEN2_SCU]);
-	dev_dbg(dev, "ADG  : %pap => %p\n", &adg_res->start,
-		gen->base[RSND_GEN2_ADG]);
-	dev_dbg(dev, "SSIU : %pap => %p\n", &ssiu_res->start,
-		gen->base[RSND_GEN2_SSIU]);
-	dev_dbg(dev, "SSI  : %pap => %p\n", &ssi_res->start,
-		gen->base[RSND_GEN2_SSI]);
+	struct rsnd_regmap_field_conf conf_ssiu[] = {
+		RSND_GEN_S_REG(SSI_MODE0,	0x800),
+		RSND_GEN_S_REG(SSI_MODE1,	0x804),
+		/* FIXME: it needs SSI_MODE2/3 in the future */
+		RSND_GEN_M_REG(SSI_BUSIF_MODE,	0x0,	0x80),
+		RSND_GEN_M_REG(SSI_BUSIF_ADINR,	0x4,	0x80),
+		RSND_GEN_M_REG(BUSIF_DALIGN,	0x8,	0x80),
+		RSND_GEN_M_REG(SSI_CTRL,	0x10,	0x80),
+		RSND_GEN_M_REG(INT_ENABLE,	0x18,	0x80),
+	};
+	struct rsnd_regmap_field_conf conf_scu[] = {
+		RSND_GEN_M_REG(SRC_BUSIF_MODE,	0x0,	0x20),
+		RSND_GEN_M_REG(SRC_ROUTE_MODE0,	0xc,	0x20),
+		RSND_GEN_M_REG(SRC_CTRL,	0x10,	0x20),
+		RSND_GEN_M_REG(CMD_ROUTE_SLCT,	0x18c,	0x20),
+		RSND_GEN_M_REG(CMD_CTRL,	0x190,	0x20),
+		RSND_GEN_M_REG(SRC_SWRSR,	0x200,	0x40),
+		RSND_GEN_M_REG(SRC_SRCIR,	0x204,	0x40),
+		RSND_GEN_M_REG(SRC_ADINR,	0x214,	0x40),
+		RSND_GEN_M_REG(SRC_IFSCR,	0x21c,	0x40),
+		RSND_GEN_M_REG(SRC_IFSVR,	0x220,	0x40),
+		RSND_GEN_M_REG(SRC_SRCCR,	0x224,	0x40),
+		RSND_GEN_M_REG(SRC_BSDSR,	0x22c,	0x40),
+		RSND_GEN_M_REG(SRC_BSISR,	0x238,	0x40),
+		RSND_GEN_M_REG(DVC_SWRSR,	0xe00,	0x100),
+		RSND_GEN_M_REG(DVC_DVUIR,	0xe04,	0x100),
+		RSND_GEN_M_REG(DVC_ADINR,	0xe08,	0x100),
+		RSND_GEN_M_REG(DVC_DVUCR,	0xe10,	0x100),
+		RSND_GEN_M_REG(DVC_ZCMCR,	0xe14,	0x100),
+		RSND_GEN_M_REG(DVC_VOL0R,	0xe28,	0x100),
+		RSND_GEN_M_REG(DVC_VOL1R,	0xe2c,	0x100),
+		RSND_GEN_M_REG(DVC_DVUER,	0xe48,	0x100),
+	};
+	struct rsnd_regmap_field_conf conf_adg[] = {
+		RSND_GEN_S_REG(BRRA,		0x00),
+		RSND_GEN_S_REG(BRRB,		0x04),
+		RSND_GEN_S_REG(SSICKR,		0x08),
+		RSND_GEN_S_REG(AUDIO_CLK_SEL0,	0x0c),
+		RSND_GEN_S_REG(AUDIO_CLK_SEL1,	0x10),
+		RSND_GEN_S_REG(AUDIO_CLK_SEL2,	0x14),
+		RSND_GEN_S_REG(DIV_EN,		0x30),
+		RSND_GEN_S_REG(SRCIN_TIMSEL0,	0x34),
+		RSND_GEN_S_REG(SRCIN_TIMSEL1,	0x38),
+		RSND_GEN_S_REG(SRCIN_TIMSEL2,	0x3c),
+		RSND_GEN_S_REG(SRCIN_TIMSEL3,	0x40),
+		RSND_GEN_S_REG(SRCIN_TIMSEL4,	0x44),
+		RSND_GEN_S_REG(SRCOUT_TIMSEL0,	0x48),
+		RSND_GEN_S_REG(SRCOUT_TIMSEL1,	0x4c),
+		RSND_GEN_S_REG(SRCOUT_TIMSEL2,	0x50),
+		RSND_GEN_S_REG(SRCOUT_TIMSEL3,	0x54),
+		RSND_GEN_S_REG(SRCOUT_TIMSEL4,	0x58),
+		RSND_GEN_S_REG(CMDOUT_TIMSEL,	0x5c),
+	};
+	struct rsnd_regmap_field_conf conf_ssi[] = {
+		RSND_GEN_M_REG(SSICR,		0x00,	0x40),
+		RSND_GEN_M_REG(SSISR,		0x04,	0x40),
+		RSND_GEN_M_REG(SSITDR,		0x08,	0x40),
+		RSND_GEN_M_REG(SSIRDR,		0x0c,	0x40),
+		RSND_GEN_M_REG(SSIWSR,		0x20,	0x40),
+	};
+	int ret_ssiu;
+	int ret_scu;
+	int ret_adg;
+	int ret_ssi;
+
+	ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, conf_ssiu);
+	ret_scu  = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU,  conf_scu);
+	ret_adg  = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG,  conf_adg);
+	ret_ssi  = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI,  conf_ssi);
+	if (ret_ssiu < 0 ||
+	    ret_scu  < 0 ||
+	    ret_adg  < 0 ||
+	    ret_ssi  < 0)
+		return ret_ssiu | ret_scu | ret_adg | ret_ssi;
+
+	dev_dbg(dev, "Gen2 is probed\n");
 
 	return 0;
 }
@@ -374,92 +366,60 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
  *		Gen1
  */
 
-/* single address mapping */
-#define RSND_GEN1_S_REG(gen, reg, id, offset)	\
-	RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9)
-
-/* multi address mapping */
-#define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset)	\
-	RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9)
-
-static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
-{
-	struct reg_field regf[RSND_REG_MAX] = {
-		RSND_GEN1_S_REG(gen, SRU,	SRC_ROUTE_SEL,	0x00),
-		RSND_GEN1_S_REG(gen, SRU,	SRC_TMG_SEL0,	0x08),
-		RSND_GEN1_S_REG(gen, SRU,	SRC_TMG_SEL1,	0x0c),
-		RSND_GEN1_S_REG(gen, SRU,	SRC_TMG_SEL2,	0x10),
-		RSND_GEN1_S_REG(gen, SRU,	SRC_ROUTE_CTRL,	0xc0),
-		RSND_GEN1_S_REG(gen, SRU,	SSI_MODE0,	0xD0),
-		RSND_GEN1_S_REG(gen, SRU,	SSI_MODE1,	0xD4),
-		RSND_GEN1_M_REG(gen, SRU,	SRC_BUSIF_MODE,	0x20,	0x4),
-		RSND_GEN1_M_REG(gen, SRU,	SRC_ROUTE_MODE0,0x50,	0x8),
-		RSND_GEN1_M_REG(gen, SRU,	SRC_SWRSR,	0x200,	0x40),
-		RSND_GEN1_M_REG(gen, SRU,	SRC_SRCIR,	0x204,	0x40),
-		RSND_GEN1_M_REG(gen, SRU,	SRC_ADINR,	0x214,	0x40),
-		RSND_GEN1_M_REG(gen, SRU,	SRC_IFSCR,	0x21c,	0x40),
-		RSND_GEN1_M_REG(gen, SRU,	SRC_IFSVR,	0x220,	0x40),
-		RSND_GEN1_M_REG(gen, SRU,	SRC_SRCCR,	0x224,	0x40),
-		RSND_GEN1_M_REG(gen, SRU,	SRC_MNFSR,	0x228,	0x40),
-
-		RSND_GEN1_S_REG(gen, ADG,	BRRA,		0x00),
-		RSND_GEN1_S_REG(gen, ADG,	BRRB,		0x04),
-		RSND_GEN1_S_REG(gen, ADG,	SSICKR,		0x08),
-		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL0,	0x0c),
-		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL1,	0x10),
-		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL3,	0x18),
-		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL4,	0x1c),
-		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL5,	0x20),
-
-		RSND_GEN1_M_REG(gen, SSI,	SSICR,		0x00,	0x40),
-		RSND_GEN1_M_REG(gen, SSI,	SSISR,		0x04,	0x40),
-		RSND_GEN1_M_REG(gen, SSI,	SSITDR,		0x08,	0x40),
-		RSND_GEN1_M_REG(gen, SSI,	SSIRDR,		0x0c,	0x40),
-		RSND_GEN1_M_REG(gen, SSI,	SSIWSR,		0x20,	0x40),
-	};
-
-	return rsnd_gen_regmap_init(priv, gen, regf);
-}
-
 static int rsnd_gen1_probe(struct platform_device *pdev,
 			   struct rsnd_priv *priv)
 {
 	struct device *dev = rsnd_priv_to_dev(priv);
-	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-	struct resource *sru_res;
-	struct resource *adg_res;
-	struct resource *ssi_res;
-	int ret;
-
-	/*
-	 * map address
-	 */
-	sru_res	= platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU);
-	adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_ADG);
-	ssi_res	= platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SSI);
-
-	gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res);
-	gen->base[RSND_GEN1_ADG] = devm_ioremap_resource(dev, adg_res);
-	gen->base[RSND_GEN1_SSI] = devm_ioremap_resource(dev, ssi_res);
-	if (IS_ERR(gen->base[RSND_GEN1_SRU]) ||
-	    IS_ERR(gen->base[RSND_GEN1_ADG]) ||
-	    IS_ERR(gen->base[RSND_GEN1_SSI]))
-		return -ENODEV;
+	struct rsnd_regmap_field_conf conf_sru[] = {
+		RSND_GEN_S_REG(SRC_ROUTE_SEL,	0x00),
+		RSND_GEN_S_REG(SRC_TMG_SEL0,	0x08),
+		RSND_GEN_S_REG(SRC_TMG_SEL1,	0x0c),
+		RSND_GEN_S_REG(SRC_TMG_SEL2,	0x10),
+		RSND_GEN_S_REG(SRC_ROUTE_CTRL,	0xc0),
+		RSND_GEN_S_REG(SSI_MODE0,	0xD0),
+		RSND_GEN_S_REG(SSI_MODE1,	0xD4),
+		RSND_GEN_M_REG(SRC_BUSIF_MODE,	0x20,	0x4),
+		RSND_GEN_M_REG(SRC_ROUTE_MODE0,	0x50,	0x8),
+		RSND_GEN_M_REG(SRC_SWRSR,	0x200,	0x40),
+		RSND_GEN_M_REG(SRC_SRCIR,	0x204,	0x40),
+		RSND_GEN_M_REG(SRC_ADINR,	0x214,	0x40),
+		RSND_GEN_M_REG(SRC_IFSCR,	0x21c,	0x40),
+		RSND_GEN_M_REG(SRC_IFSVR,	0x220,	0x40),
+		RSND_GEN_M_REG(SRC_SRCCR,	0x224,	0x40),
+		RSND_GEN_M_REG(SRC_MNFSR,	0x228,	0x40),
+	};
+	struct rsnd_regmap_field_conf conf_adg[] = {
+		RSND_GEN_S_REG(BRRA,		0x00),
+		RSND_GEN_S_REG(BRRB,		0x04),
+		RSND_GEN_S_REG(SSICKR,		0x08),
+		RSND_GEN_S_REG(AUDIO_CLK_SEL0,	0x0c),
+		RSND_GEN_S_REG(AUDIO_CLK_SEL1,	0x10),
+		RSND_GEN_S_REG(AUDIO_CLK_SEL3,	0x18),
+		RSND_GEN_S_REG(AUDIO_CLK_SEL4,	0x1c),
+		RSND_GEN_S_REG(AUDIO_CLK_SEL5,	0x20),
+	};
+	struct rsnd_regmap_field_conf conf_ssi[] = {
+		RSND_GEN_M_REG(SSICR,		0x00,	0x40),
+		RSND_GEN_M_REG(SSISR,		0x04,	0x40),
+		RSND_GEN_M_REG(SSITDR,		0x08,	0x40),
+		RSND_GEN_M_REG(SSIRDR,		0x0c,	0x40),
+		RSND_GEN_M_REG(SSIWSR,		0x20,	0x40),
+	};
+	int ret_sru;
+	int ret_adg;
+	int ret_ssi;
 
-	ret = rsnd_gen1_regmap_init(priv, gen);
-	if (ret < 0)
-		return ret;
+	ret_sru  = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SRU,  conf_sru);
+	ret_adg  = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG,  conf_adg);
+	ret_ssi  = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI,  conf_ssi);
+	if (ret_sru  < 0 ||
+	    ret_adg  < 0 ||
+	    ret_ssi  < 0)
+		return ret_sru | ret_adg | ret_ssi;
 
-	dev_dbg(dev, "Gen1 device probed\n");
-	dev_dbg(dev, "SRU : %pap => %p\n",	&sru_res->start,
-						gen->base[RSND_GEN1_SRU]);
-	dev_dbg(dev, "ADG : %pap => %p\n",	&adg_res->start,
-						gen->base[RSND_GEN1_ADG]);
-	dev_dbg(dev, "SSI : %pap => %p\n",	&ssi_res->start,
-						gen->base[RSND_GEN1_SSI]);
+	dev_dbg(dev, "Gen1 is probed\n");
 
 	return 0;
-
 }
 
 /*
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index 39d98af5ee05..d119adf97c9c 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -90,6 +90,7 @@ enum rsnd_reg {
 	RSND_REG_SHARE19,
 	RSND_REG_SHARE20,
 	RSND_REG_SHARE21,
+	RSND_REG_SHARE22,
 
 	RSND_REG_MAX,
 };
@@ -127,6 +128,7 @@ enum rsnd_reg {
 #define RSND_REG_AUDIO_CLK_SEL2		RSND_REG_SHARE19
 #define RSND_REG_CMD_CTRL		RSND_REG_SHARE20
 #define RSND_REG_CMDOUT_TIMSEL		RSND_REG_SHARE21
+#define RSND_REG_BUSIF_DALIGN		RSND_REG_SHARE22
 
 struct rsnd_of_data;
 struct rsnd_priv;
@@ -156,12 +158,9 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod);
  */
 struct rsnd_dma {
 	struct sh_dmae_slave	slave;
-	struct work_struct	work;
 	struct dma_chan		*chan;
-	enum dma_data_direction dir;
-
-	int submit_loop;
-	int offset; /* it cares A/B plane */
+	enum dma_transfer_direction dir;
+	dma_addr_t		addr;
 };
 
 void rsnd_dma_start(struct rsnd_dma *dma);
@@ -185,6 +184,7 @@ enum rsnd_mod_type {
 
 struct rsnd_mod_ops {
 	char *name;
+	char* (*dma_name)(struct rsnd_mod *mod);
 	int (*probe)(struct rsnd_mod *mod,
 		     struct rsnd_dai *rdai);
 	int (*remove)(struct rsnd_mod *mod,
@@ -224,6 +224,7 @@ void rsnd_mod_init(struct rsnd_priv *priv,
 		   enum rsnd_mod_type type,
 		   int id);
 char *rsnd_mod_name(struct rsnd_mod *mod);
+char *rsnd_mod_dma_name(struct rsnd_mod *mod);
 
 /*
  *	R-Car sound DAI
@@ -281,10 +282,9 @@ int rsnd_gen_probe(struct platform_device *pdev,
 void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
 			       struct rsnd_mod *mod,
 			       enum rsnd_reg reg);
-void rsnd_gen_dma_addr(struct rsnd_priv *priv,
-		       struct rsnd_dma *dma,
-		       struct dma_slave_config *cfg,
-		       int is_play,  int slave_id);
+dma_addr_t rsnd_gen_dma_addr(struct rsnd_priv *priv,
+		       struct rsnd_mod *mod,
+		       int is_play,  int is_from);
 
 #define rsnd_is_gen1(s)		(((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1)
 #define rsnd_is_gen2(s)		(((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2)
@@ -391,8 +391,12 @@ struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id);
 unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
 				   struct rsnd_dai_stream *io,
 				   struct snd_pcm_runtime *runtime);
-int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod,
-			   struct rsnd_dai *rdai);
+int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
+			struct rsnd_dai *rdai,
+			int use_busif);
+int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod,
+		       struct rsnd_dai *rdai,
+		       int use_busif);
 int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod,
 			    struct rsnd_dai *rdai);
 
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index 200eda019bc7..9183e0145503 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -106,18 +106,19 @@ struct rsnd_src {
 /*
  *		Gen1/Gen2 common functions
  */
-int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod,
-			   struct rsnd_dai *rdai)
+int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
+			struct rsnd_dai *rdai,
+			int use_busif)
 {
 	struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod);
-	struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
+	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
 	int ssi_id = rsnd_mod_id(ssi_mod);
 
 	/*
 	 * SSI_MODE0
 	 */
 	rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id),
-		      src_mod ? 0 : (1 << ssi_id));
+		      !use_busif << ssi_id);
 
 	/*
 	 * SSI_MODE1
@@ -143,6 +144,46 @@ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod,
 				      0x2 << shift : 0x1 << shift);
 	}
 
+	/*
+	 * DMA settings for SSIU
+	 */
+	if (use_busif) {
+		u32 val = 0x76543210;
+		u32 mask = ~0;
+
+		rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR,
+			       rsnd_get_adinr(ssi_mod));
+		rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE,  1);
+		rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1);
+
+		mask <<= runtime->channels * 4;
+		val = val & mask;
+
+		switch (runtime->sample_bits) {
+		case 16:
+			val |= 0x67452301 & ~mask;
+			break;
+		case 32:
+			val |= 0x76543210 & ~mask;
+			break;
+		}
+		rsnd_mod_write(ssi_mod, BUSIF_DALIGN, val);
+
+	}
+
+	return 0;
+}
+
+int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod,
+			struct rsnd_dai *rdai,
+			int use_busif)
+{
+	/*
+	 * DMA settings for SSIU
+	 */
+	if (use_busif)
+		rsnd_mod_write(ssi_mod, SSI_CTRL, 0);
+
 	return 0;
 }
 
@@ -461,18 +502,45 @@ static struct rsnd_mod_ops rsnd_src_gen1_ops = {
 static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod,
 					  struct rsnd_dai *rdai)
 {
+	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
+	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+	struct rsnd_src *src = rsnd_mod_to_src(mod);
+	uint ratio;
 	int ret;
 
+	/* 6 - 1/6 are very enough ratio for SRC_BSDSR */
+	if (!rsnd_src_convert_rate(src))
+		ratio = 0;
+	else if (rsnd_src_convert_rate(src) > runtime->rate)
+		ratio = 100 * rsnd_src_convert_rate(src) / runtime->rate;
+	else
+		ratio = 100 * runtime->rate / rsnd_src_convert_rate(src);
+
+	if (ratio > 600) {
+		dev_err(dev, "FSO/FSI ratio error\n");
+		return -EINVAL;
+	}
+
 	ret = rsnd_src_set_convert_rate(mod, rdai);
 	if (ret < 0)
 		return ret;
 
-	rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_get_adinr(mod));
-	rsnd_mod_write(mod, SSI_BUSIF_MODE,  1);
-
 	rsnd_mod_write(mod, SRC_SRCCR, 0x00011110);
 
-	rsnd_mod_write(mod, SRC_BSDSR, 0x01800000);
+	switch (rsnd_mod_id(mod)) {
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+		rsnd_mod_write(mod, SRC_BSDSR, 0x02400000);
+		break;
+	default:
+		rsnd_mod_write(mod, SRC_BSDSR, 0x01800000);
+		break;
+	}
+
 	rsnd_mod_write(mod, SRC_BSISR, 0x00100060);
 
 	return 0;
@@ -554,7 +622,6 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod,
 
 	rsnd_dma_start(rsnd_mod_to_dma(&src->mod));
 
-	rsnd_mod_write(mod, SSI_CTRL, 0x1);
 	rsnd_mod_write(mod, SRC_CTRL, val);
 
 	return rsnd_src_start(mod, rdai);
@@ -565,7 +632,6 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
 {
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
 
-	rsnd_mod_write(mod, SSI_CTRL, 0);
 	rsnd_mod_write(mod, SRC_CTRL, 0);
 
 	rsnd_dma_stop(rsnd_mod_to_dma(&src->mod));
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 2df723df5d19..34e84009162b 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -90,6 +90,20 @@ struct rsnd_ssi {
 #define rsnd_ssi_mode_flags(p) ((p)->info->flags)
 #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id)
 
+static int rsnd_ssi_use_busif(struct rsnd_mod *mod)
+{
+	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
+	int use_busif = 0;
+
+	if (!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_NO_BUSIF))
+		use_busif = 1;
+	if (rsnd_io_to_mod_src(io))
+		use_busif = 1;
+
+	return use_busif;
+}
+
 static void rsnd_ssi_status_check(struct rsnd_mod *mod,
 				  u32 bit)
 {
@@ -289,8 +303,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
 	ssi->cr_own	= cr;
 	ssi->err	= -1; /* ignore 1st error */
 
-	rsnd_src_ssi_mode_init(mod, rdai);
-
 	return 0;
 }
 
@@ -389,6 +401,8 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
 	/* enable PIO IRQ */
 	ssi->cr_etc = UIEN | OIEN | DIEN;
 
+	rsnd_src_ssiu_start(mod, rdai, 0);
+
 	rsnd_src_enable_ssi_irq(mod, rdai);
 
 	rsnd_ssi_hw_start(ssi, rdai, io);
@@ -405,6 +419,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod,
 
 	rsnd_ssi_hw_stop(ssi, rdai);
 
+	rsnd_src_ssiu_stop(mod, rdai, 0);
+
 	return 0;
 }
 
@@ -457,6 +473,8 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
 	/* enable DMA transfer */
 	ssi->cr_etc = DMEN;
 
+	rsnd_src_ssiu_start(mod, rdai, rsnd_ssi_use_busif(mod));
+
 	rsnd_dma_start(dma);
 
 	rsnd_ssi_hw_start(ssi, ssi->rdai, io);
@@ -482,11 +500,19 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
 
 	rsnd_dma_stop(dma);
 
+	rsnd_src_ssiu_stop(mod, rdai, 1);
+
 	return 0;
 }
 
+static char *rsnd_ssi_dma_name(struct rsnd_mod *mod)
+{
+	return rsnd_ssi_use_busif(mod) ? "ssiu" : SSI_NAME;
+}
+
 static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
 	.name	= SSI_NAME,
+	.dma_name = rsnd_ssi_dma_name,
 	.probe	= rsnd_ssi_dma_probe,
 	.remove	= rsnd_ssi_dma_remove,
 	.init	= rsnd_ssi_init,
@@ -595,6 +621,9 @@ static void rsnd_of_parse_ssi(struct platform_device *pdev,
 		 */
 		ssi_info->dma_id = of_get_property(np, "pio-transfer", NULL) ?
 			0 : 1;
+
+		if (of_get_property(np, "no-busif", NULL))
+			ssi_info->flags |= RSND_SSI_NO_BUSIF;
 	}
 
 rsnd_of_parse_ssi_end:
diff --git a/sound/soc/sirf/Kconfig b/sound/soc/sirf/Kconfig
index 89e89429b04a..840058dcad09 100644
--- a/sound/soc/sirf/Kconfig
+++ b/sound/soc/sirf/Kconfig
@@ -12,3 +12,9 @@ config SND_SOC_SIRF_AUDIO
 config SND_SOC_SIRF_AUDIO_PORT
 	select REGMAP_MMIO
 	tristate
+
+config SND_SOC_SIRF_USP
+	tristate "SoC Audio (I2S protocol) for SiRF SoC USP interface"
+	depends on SND_SOC_SIRF
+	select REGMAP_MMIO
+	tristate
diff --git a/sound/soc/sirf/Makefile b/sound/soc/sirf/Makefile
index 913b93231d4e..dd917f20f12f 100644
--- a/sound/soc/sirf/Makefile
+++ b/sound/soc/sirf/Makefile
@@ -1,5 +1,7 @@
 snd-soc-sirf-audio-objs := sirf-audio.o
 snd-soc-sirf-audio-port-objs := sirf-audio-port.o
+snd-soc-sirf-usp-objs := sirf-usp.o
 
 obj-$(CONFIG_SND_SOC_SIRF_AUDIO) += snd-soc-sirf-audio.o
 obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o
+obj-$(CONFIG_SND_SOC_SIRF_USP) += snd-soc-sirf-usp.o
diff --git a/sound/soc/sirf/sirf-usp.c b/sound/soc/sirf/sirf-usp.c
new file mode 100644
index 000000000000..3a730374e259
--- /dev/null
+++ b/sound/soc/sirf/sirf-usp.c
@@ -0,0 +1,415 @@
+/*
+ * SiRF USP in I2S/DSP mode
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include <sound/dmaengine_pcm.h>
+
+#include "sirf-usp.h"
+
+struct sirf_usp {
+	struct regmap *regmap;
+	struct clk *clk;
+	u32 mode1_reg;
+	u32 mode2_reg;
+	int daifmt_format;
+	struct snd_dmaengine_dai_dma_data playback_dma_data;
+	struct snd_dmaengine_dai_dma_data capture_dma_data;
+};
+
+static void sirf_usp_tx_enable(struct sirf_usp *usp)
+{
+	regmap_update_bits(usp->regmap, USP_TX_FIFO_OP,
+		USP_TX_FIFO_RESET, USP_TX_FIFO_RESET);
+	regmap_write(usp->regmap, USP_TX_FIFO_OP, 0);
+
+	regmap_update_bits(usp->regmap, USP_TX_FIFO_OP,
+		USP_TX_FIFO_START, USP_TX_FIFO_START);
+
+	regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
+		USP_TX_ENA, USP_TX_ENA);
+}
+
+static void sirf_usp_tx_disable(struct sirf_usp *usp)
+{
+	regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
+		USP_TX_ENA, ~USP_TX_ENA);
+	/* FIFO stop */
+	regmap_write(usp->regmap, USP_TX_FIFO_OP, 0);
+}
+
+static void sirf_usp_rx_enable(struct sirf_usp *usp)
+{
+	regmap_update_bits(usp->regmap, USP_RX_FIFO_OP,
+		USP_RX_FIFO_RESET, USP_RX_FIFO_RESET);
+	regmap_write(usp->regmap, USP_RX_FIFO_OP, 0);
+
+	regmap_update_bits(usp->regmap, USP_RX_FIFO_OP,
+		USP_RX_FIFO_START, USP_RX_FIFO_START);
+
+	regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
+		USP_RX_ENA, USP_RX_ENA);
+}
+
+static void sirf_usp_rx_disable(struct sirf_usp *usp)
+{
+	regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
+		USP_RX_ENA, ~USP_RX_ENA);
+	/* FIFO stop */
+	regmap_write(usp->regmap, USP_RX_FIFO_OP, 0);
+}
+
+static int sirf_usp_pcm_dai_probe(struct snd_soc_dai *dai)
+{
+	struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
+	snd_soc_dai_init_dma_data(dai, &usp->playback_dma_data,
+			&usp->capture_dma_data);
+	return 0;
+}
+
+static int sirf_usp_pcm_set_dai_fmt(struct snd_soc_dai *dai,
+		unsigned int fmt)
+{
+	struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
+
+	/* set master/slave audio interface */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		break;
+	default:
+		dev_err(dai->dev, "Only CBM and CFM supported\n");
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+	case SND_SOC_DAIFMT_DSP_A:
+		usp->daifmt_format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+		break;
+	default:
+		dev_err(dai->dev, "Only I2S and DSP_A format supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void sirf_usp_i2s_init(struct sirf_usp *usp)
+{
+	/* Configure RISC mode */
+	regmap_update_bits(usp->regmap, USP_RISC_DSP_MODE,
+		USP_RISC_DSP_SEL, ~USP_RISC_DSP_SEL);
+
+	/*
+	 * Configure DMA IO Length register
+	 * Set no limit, USP can receive data continuously until it is diabled
+	 */
+	regmap_write(usp->regmap, USP_TX_DMA_IO_LEN, 0);
+	regmap_write(usp->regmap, USP_RX_DMA_IO_LEN, 0);
+
+	/* Configure Mode2 register */
+	regmap_write(usp->regmap, USP_MODE2, (1 << USP_RXD_DELAY_LEN_OFFSET) |
+		(0 << USP_TXD_DELAY_LEN_OFFSET) |
+		USP_TFS_CLK_SLAVE_MODE | USP_RFS_CLK_SLAVE_MODE);
+
+	/* Configure Mode1 register */
+	regmap_write(usp->regmap, USP_MODE1,
+		USP_SYNC_MODE | USP_EN | USP_TXD_ACT_EDGE_FALLING |
+		USP_RFS_ACT_LEVEL_LOGIC1 | USP_TFS_ACT_LEVEL_LOGIC1 |
+		USP_TX_UFLOW_REPEAT_ZERO | USP_CLOCK_MODE_SLAVE);
+
+	/* Configure RX DMA IO Control register */
+	regmap_write(usp->regmap, USP_RX_DMA_IO_CTRL, 0);
+
+	/* Congiure RX FIFO Control register */
+	regmap_write(usp->regmap, USP_RX_FIFO_CTRL,
+		(USP_RX_FIFO_THRESHOLD << USP_RX_FIFO_THD_OFFSET) |
+		(USP_TX_RX_FIFO_WIDTH_DWORD << USP_RX_FIFO_WIDTH_OFFSET));
+
+	/* Congiure RX FIFO Level Check register */
+	regmap_write(usp->regmap, USP_RX_FIFO_LEVEL_CHK,
+		RX_FIFO_SC(0x04) | RX_FIFO_LC(0x0E) | RX_FIFO_HC(0x1B));
+
+	/* Configure TX DMA IO Control register*/
+	regmap_write(usp->regmap, USP_TX_DMA_IO_CTRL, 0);
+
+	/* Configure TX FIFO Control register */
+	regmap_write(usp->regmap, USP_TX_FIFO_CTRL,
+		(USP_TX_FIFO_THRESHOLD << USP_TX_FIFO_THD_OFFSET) |
+		(USP_TX_RX_FIFO_WIDTH_DWORD << USP_TX_FIFO_WIDTH_OFFSET));
+	/* Congiure TX FIFO Level Check register */
+	regmap_write(usp->regmap, USP_TX_FIFO_LEVEL_CHK,
+		TX_FIFO_SC(0x1B) | TX_FIFO_LC(0x0E) | TX_FIFO_HC(0x04));
+}
+
+static int sirf_usp_pcm_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
+	u32 data_len, frame_len, shifter_len;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		data_len = 16;
+		frame_len = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		data_len = 24;
+		frame_len = 32;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		data_len = 24;
+		frame_len = 24;
+		break;
+	default:
+		dev_err(dai->dev, "Format unsupported\n");
+		return -EINVAL;
+	}
+
+	shifter_len = data_len;
+
+	switch (usp->daifmt_format) {
+	case SND_SOC_DAIFMT_I2S:
+		regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL,
+			USP_I2S_SYNC_CHG, USP_I2S_SYNC_CHG);
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL,
+			USP_I2S_SYNC_CHG, 0);
+		frame_len = data_len * params_channels(params);
+		data_len = frame_len;
+		break;
+	default:
+		dev_err(dai->dev, "Only support I2S and DSP_A mode\n");
+		return -EINVAL;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		regmap_update_bits(usp->regmap, USP_TX_FRAME_CTRL,
+			USP_TXC_DATA_LEN_MASK | USP_TXC_FRAME_LEN_MASK
+			| USP_TXC_SHIFTER_LEN_MASK | USP_TXC_SLAVE_CLK_SAMPLE,
+			((data_len - 1) << USP_TXC_DATA_LEN_OFFSET)
+			| ((frame_len - 1) << USP_TXC_FRAME_LEN_OFFSET)
+			| ((shifter_len - 1) << USP_TXC_SHIFTER_LEN_OFFSET)
+			| USP_TXC_SLAVE_CLK_SAMPLE);
+	else
+		regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL,
+			USP_RXC_DATA_LEN_MASK | USP_RXC_FRAME_LEN_MASK
+			| USP_RXC_SHIFTER_LEN_MASK | USP_SINGLE_SYNC_MODE,
+			((data_len - 1) << USP_RXC_DATA_LEN_OFFSET)
+			| ((frame_len - 1) << USP_RXC_FRAME_LEN_OFFSET)
+			| ((shifter_len - 1) << USP_RXC_SHIFTER_LEN_OFFSET)
+			| USP_SINGLE_SYNC_MODE);
+
+	return 0;
+}
+
+static int sirf_usp_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
+				struct snd_soc_dai *dai)
+{
+	struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			sirf_usp_tx_enable(usp);
+		else
+			sirf_usp_rx_enable(usp);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			sirf_usp_tx_disable(usp);
+		else
+			sirf_usp_rx_disable(usp);
+		break;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops sirf_usp_pcm_dai_ops = {
+	.trigger = sirf_usp_pcm_trigger,
+	.set_fmt = sirf_usp_pcm_set_dai_fmt,
+	.hw_params = sirf_usp_pcm_hw_params,
+};
+
+static struct snd_soc_dai_driver sirf_usp_pcm_dai = {
+	.probe = sirf_usp_pcm_dai_probe,
+	.name = "sirf-usp-pcm",
+	.id = 0,
+	.playback = {
+		.stream_name = "SiRF USP PCM Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_192000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
+			SNDRV_PCM_FMTBIT_S24_3LE,
+	},
+	.capture = {
+		.stream_name = "SiRF USP PCM Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_192000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
+			SNDRV_PCM_FMTBIT_S24_3LE,
+	},
+	.ops = &sirf_usp_pcm_dai_ops,
+};
+
+static int sirf_usp_pcm_runtime_suspend(struct device *dev)
+{
+	struct sirf_usp *usp = dev_get_drvdata(dev);
+	clk_disable_unprepare(usp->clk);
+	return 0;
+}
+
+static int sirf_usp_pcm_runtime_resume(struct device *dev)
+{
+	struct sirf_usp *usp = dev_get_drvdata(dev);
+	int ret;
+	ret = clk_prepare_enable(usp->clk);
+	if (ret) {
+		dev_err(dev, "clk_enable failed: %d\n", ret);
+		return ret;
+	}
+	sirf_usp_i2s_init(usp);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int sirf_usp_pcm_suspend(struct device *dev)
+{
+	struct sirf_usp *usp = dev_get_drvdata(dev);
+
+	if (!pm_runtime_status_suspended(dev)) {
+		regmap_read(usp->regmap, USP_MODE1, &usp->mode1_reg);
+		regmap_read(usp->regmap, USP_MODE2, &usp->mode2_reg);
+		sirf_usp_pcm_runtime_suspend(dev);
+	}
+	return 0;
+}
+
+static int sirf_usp_pcm_resume(struct device *dev)
+{
+	struct sirf_usp *usp = dev_get_drvdata(dev);
+	int ret;
+
+	if (!pm_runtime_status_suspended(dev)) {
+		ret = sirf_usp_pcm_runtime_resume(dev);
+		if (ret)
+			return ret;
+		regmap_write(usp->regmap, USP_MODE1, usp->mode1_reg);
+		regmap_write(usp->regmap, USP_MODE2, usp->mode2_reg);
+	}
+	return 0;
+}
+#endif
+
+static const struct snd_soc_component_driver sirf_usp_component = {
+	.name		= "sirf-usp",
+};
+
+static const struct regmap_config sirf_usp_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = USP_RX_FIFO_DATA,
+	.cache_type = REGCACHE_NONE,
+};
+
+static int sirf_usp_pcm_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct sirf_usp *usp;
+	void __iomem *base;
+	struct resource *mem_res;
+
+	usp = devm_kzalloc(&pdev->dev, sizeof(struct sirf_usp),
+			GFP_KERNEL);
+	if (!usp)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, usp);
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap(&pdev->dev, mem_res->start,
+		resource_size(mem_res));
+	if (base == NULL)
+		return -ENOMEM;
+	usp->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+					    &sirf_usp_regmap_config);
+	if (IS_ERR(usp->regmap))
+		return PTR_ERR(usp->regmap);
+
+	usp->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(usp->clk)) {
+		dev_err(&pdev->dev, "Get clock failed.\n");
+		return PTR_ERR(usp->clk);
+	}
+
+	pm_runtime_enable(&pdev->dev);
+	if (!pm_runtime_enabled(&pdev->dev)) {
+		ret = sirf_usp_pcm_runtime_resume(&pdev->dev);
+		if (ret)
+			return ret;
+	}
+
+	ret = devm_snd_soc_register_component(&pdev->dev, &sirf_usp_component,
+		&sirf_usp_pcm_dai, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "Register Audio SoC dai failed.\n");
+		return ret;
+	}
+	return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+}
+
+static int sirf_usp_pcm_remove(struct platform_device *pdev)
+{
+	if (!pm_runtime_enabled(&pdev->dev))
+		sirf_usp_pcm_runtime_suspend(&pdev->dev);
+	else
+		pm_runtime_disable(&pdev->dev);
+	return 0;
+}
+
+static const struct of_device_id sirf_usp_pcm_of_match[] = {
+	{ .compatible = "sirf,prima2-usp-pcm", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, sirf_usp_pcm_of_match);
+
+static const struct dev_pm_ops sirf_usp_pcm_pm_ops = {
+	SET_RUNTIME_PM_OPS(sirf_usp_pcm_runtime_suspend,
+		sirf_usp_pcm_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(sirf_usp_pcm_suspend, sirf_usp_pcm_resume)
+};
+
+static struct platform_driver sirf_usp_pcm_driver = {
+	.driver = {
+		.name = "sirf-usp-pcm",
+		.owner = THIS_MODULE,
+		.of_match_table = sirf_usp_pcm_of_match,
+		.pm = &sirf_usp_pcm_pm_ops,
+	},
+	.probe = sirf_usp_pcm_probe,
+	.remove = sirf_usp_pcm_remove,
+};
+
+module_platform_driver(sirf_usp_pcm_driver);
+
+MODULE_DESCRIPTION("SiRF SoC USP PCM bus driver");
+MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/sirf/sirf-usp.h b/sound/soc/sirf/sirf-usp.h
new file mode 100644
index 000000000000..bf0201cb15bc
--- /dev/null
+++ b/sound/soc/sirf/sirf-usp.h
@@ -0,0 +1,293 @@
+/*
+ * arch/arm/mach-prima2/include/mach/sirfsoc_usp.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef _SIRF_USP_H
+#define _SIRF_USP_H
+
+/* USP Registers */
+#define USP_MODE1		0x00
+#define USP_MODE2		0x04
+#define USP_TX_FRAME_CTRL	0x08
+#define USP_RX_FRAME_CTRL	0x0C
+#define USP_TX_RX_ENABLE	0x10
+#define USP_INT_ENABLE		0x14
+#define USP_INT_STATUS		0x18
+#define USP_PIN_IO_DATA		0x1C
+#define USP_RISC_DSP_MODE	0x20
+#define USP_AYSNC_PARAM_REG	0x24
+#define USP_IRDA_X_MODE_DIV	0x28
+#define USP_SM_CFG		0x2C
+#define USP_TX_DMA_IO_CTRL	0x100
+#define USP_TX_DMA_IO_LEN	0x104
+#define USP_TX_FIFO_CTRL	0x108
+#define USP_TX_FIFO_LEVEL_CHK	0x10C
+#define USP_TX_FIFO_OP		0x110
+#define USP_TX_FIFO_STATUS	0x114
+#define USP_TX_FIFO_DATA	0x118
+#define USP_RX_DMA_IO_CTRL	0x120
+#define USP_RX_DMA_IO_LEN	0x124
+#define USP_RX_FIFO_CTRL	0x128
+#define USP_RX_FIFO_LEVEL_CHK	0x12C
+#define USP_RX_FIFO_OP		0x130
+#define USP_RX_FIFO_STATUS	0x134
+#define USP_RX_FIFO_DATA	0x138
+
+/* USP MODE register-1 */
+#define USP_SYNC_MODE			0x00000001
+#define USP_CLOCK_MODE_SLAVE		0x00000002
+#define USP_LOOP_BACK_EN		0x00000004
+#define USP_HPSIR_EN			0x00000008
+#define USP_ENDIAN_CTRL_LSBF		0x00000010
+#define USP_EN				0x00000020
+#define USP_RXD_ACT_EDGE_FALLING	0x00000040
+#define USP_TXD_ACT_EDGE_FALLING	0x00000080
+#define USP_RFS_ACT_LEVEL_LOGIC1	0x00000100
+#define USP_TFS_ACT_LEVEL_LOGIC1	0x00000200
+#define USP_SCLK_IDLE_MODE_TOGGLE	0x00000400
+#define USP_SCLK_IDLE_LEVEL_LOGIC1	0x00000800
+#define USP_SCLK_PIN_MODE_IO	0x00001000
+#define USP_RFS_PIN_MODE_IO	0x00002000
+#define USP_TFS_PIN_MODE_IO	0x00004000
+#define USP_RXD_PIN_MODE_IO	0x00008000
+#define USP_TXD_PIN_MODE_IO	0x00010000
+#define USP_SCLK_IO_MODE_INPUT	0x00020000
+#define USP_RFS_IO_MODE_INPUT	0x00040000
+#define USP_TFS_IO_MODE_INPUT	0x00080000
+#define USP_RXD_IO_MODE_INPUT	0x00100000
+#define USP_TXD_IO_MODE_INPUT	0x00200000
+#define USP_IRDA_WIDTH_DIV_MASK	0x3FC00000
+#define USP_IRDA_WIDTH_DIV_OFFSET	0
+#define USP_IRDA_IDLE_LEVEL_HIGH	0x40000000
+#define USP_TX_UFLOW_REPEAT_ZERO	0x80000000
+#define USP_TX_ENDIAN_MODE		0x00000020
+#define USP_RX_ENDIAN_MODE		0x00000020
+
+/* USP Mode Register-2 */
+#define USP_RXD_DELAY_LEN_MASK		0x000000FF
+#define USP_RXD_DELAY_LEN_OFFSET	0
+
+#define USP_TXD_DELAY_LEN_MASK		0x0000FF00
+#define USP_TXD_DELAY_LEN_OFFSET	8
+
+#define USP_ENA_CTRL_MODE		0x00010000
+#define USP_FRAME_CTRL_MODE		0x00020000
+#define USP_TFS_SOURCE_MODE             0x00040000
+#define USP_TFS_MS_MODE                 0x00080000
+#define USP_CLK_DIVISOR_MASK		0x7FE00000
+#define USP_CLK_DIVISOR_OFFSET		21
+
+#define USP_TFS_CLK_SLAVE_MODE		(1<<20)
+#define USP_RFS_CLK_SLAVE_MODE		(1<<19)
+
+#define USP_IRDA_DATA_WIDTH		0x80000000
+
+/* USP Transmit Frame Control Register */
+
+#define USP_TXC_DATA_LEN_MASK		0x000000FF
+#define USP_TXC_DATA_LEN_OFFSET		0
+
+#define USP_TXC_SYNC_LEN_MASK		0x0000FF00
+#define USP_TXC_SYNC_LEN_OFFSET		8
+
+#define USP_TXC_FRAME_LEN_MASK		0x00FF0000
+#define USP_TXC_FRAME_LEN_OFFSET	16
+
+#define USP_TXC_SHIFTER_LEN_MASK	0x1F000000
+#define USP_TXC_SHIFTER_LEN_OFFSET	24
+
+#define USP_TXC_SLAVE_CLK_SAMPLE	0x20000000
+
+#define USP_TXC_CLK_DIVISOR_MASK	0xC0000000
+#define USP_TXC_CLK_DIVISOR_OFFSET	30
+
+/* USP Receive Frame Control Register */
+
+#define USP_RXC_DATA_LEN_MASK		0x000000FF
+#define USP_RXC_DATA_LEN_OFFSET		0
+
+#define USP_RXC_FRAME_LEN_MASK		0x0000FF00
+#define USP_RXC_FRAME_LEN_OFFSET	8
+
+#define USP_RXC_SHIFTER_LEN_MASK	0x001F0000
+#define USP_RXC_SHIFTER_LEN_OFFSET	16
+
+#define USP_START_EDGE_MODE	0x00800000
+#define USP_I2S_SYNC_CHG	0x00200000
+
+#define USP_RXC_CLK_DIVISOR_MASK	0x0F000000
+#define USP_RXC_CLK_DIVISOR_OFFSET	24
+#define USP_SINGLE_SYNC_MODE		0x00400000
+
+/* Tx - RX Enable Register */
+
+#define USP_RX_ENA		0x00000001
+#define USP_TX_ENA		0x00000002
+
+/* USP Interrupt Enable and status Register */
+#define USP_RX_DONE_INT			0x00000001
+#define USP_TX_DONE_INT			0x00000002
+#define USP_RX_OFLOW_INT		0x00000004
+#define USP_TX_UFLOW_INT		0x00000008
+#define USP_RX_IO_DMA_INT		0x00000010
+#define USP_TX_IO_DMA_INT		0x00000020
+#define USP_RXFIFO_FULL_INT		0x00000040
+#define USP_TXFIFO_EMPTY_INT		0x00000080
+#define USP_RXFIFO_THD_INT		0x00000100
+#define USP_TXFIFO_THD_INT		0x00000200
+#define USP_UART_FRM_ERR_INT		0x00000400
+#define USP_RX_TIMEOUT_INT		0x00000800
+#define USP_TX_ALLOUT_INT		0x00001000
+#define USP_RXD_BREAK_INT		0x00008000
+
+/* All possible TX interruots */
+#define USP_TX_INTERRUPT		(USP_TX_DONE_INT|USP_TX_UFLOW_INT|\
+					USP_TX_IO_DMA_INT|\
+					USP_TXFIFO_EMPTY_INT|\
+					USP_TXFIFO_THD_INT)
+/* All possible RX interruots */
+#define USP_RX_INTERRUPT		(USP_RX_DONE_INT|USP_RX_OFLOW_INT|\
+					USP_RX_IO_DMA_INT|\
+					USP_RXFIFO_FULL_INT|\
+					USP_RXFIFO_THD_INT|\
+					USP_RXFIFO_THD_INT|USP_RX_TIMEOUT_INT)
+
+#define USP_INT_ALL        0x1FFF
+
+/* USP Pin I/O Data Register */
+
+#define USP_RFS_PIN_VALUE_MASK	0x00000001
+#define USP_TFS_PIN_VALUE_MASK	0x00000002
+#define USP_RXD_PIN_VALUE_MASK	0x00000004
+#define USP_TXD_PIN_VALUE_MASK	0x00000008
+#define USP_SCLK_PIN_VALUE_MASK	0x00000010
+
+/* USP RISC/DSP Mode Register */
+#define USP_RISC_DSP_SEL	0x00000001
+
+/* USP ASYNC PARAMETER Register*/
+
+#define USP_ASYNC_TIMEOUT_MASK	0x0000FFFF
+#define USP_ASYNC_TIMEOUT_OFFSET	0
+#define USP_ASYNC_TIMEOUT(x)	(((x)&USP_ASYNC_TIMEOUT_MASK) \
+				<<USP_ASYNC_TIMEOUT_OFFSET)
+
+#define USP_ASYNC_DIV2_MASK		0x003F0000
+#define USP_ASYNC_DIV2_OFFSET		16
+
+/* USP TX DMA I/O MODE Register */
+#define USP_TX_MODE_IO			0x00000001
+
+/* USP TX DMA I/O Length Register */
+#define USP_TX_DATA_LEN_MASK		0xFFFFFFFF
+#define USP_TX_DATA_LEN_OFFSET		0
+
+/* USP TX FIFO Control Register */
+#define USP_TX_FIFO_WIDTH_MASK		0x00000003
+#define USP_TX_FIFO_WIDTH_OFFSET	0
+
+#define USP_TX_FIFO_THD_MASK		0x000001FC
+#define USP_TX_FIFO_THD_OFFSET		2
+
+/* USP TX FIFO Level Check Register */
+#define USP_TX_FIFO_LEVEL_CHECK_MASK	0x1F
+#define USP_TX_FIFO_SC_OFFSET	0
+#define USP_TX_FIFO_LC_OFFSET	10
+#define USP_TX_FIFO_HC_OFFSET	20
+
+#define TX_FIFO_SC(x)		(((x) & USP_TX_FIFO_LEVEL_CHECK_MASK) \
+				<< USP_TX_FIFO_SC_OFFSET)
+#define TX_FIFO_LC(x)		(((x) & USP_TX_FIFO_LEVEL_CHECK_MASK) \
+				<< USP_TX_FIFO_LC_OFFSET)
+#define TX_FIFO_HC(x)		(((x) & USP_TX_FIFO_LEVEL_CHECK_MASK) \
+				<< USP_TX_FIFO_HC_OFFSET)
+
+/* USP TX FIFO Operation Register */
+#define USP_TX_FIFO_RESET		0x00000001
+#define USP_TX_FIFO_START		0x00000002
+
+/* USP TX FIFO Status Register */
+#define USP_TX_FIFO_LEVEL_MASK		0x0000007F
+#define USP_TX_FIFO_LEVEL_OFFSET	0
+
+#define USP_TX_FIFO_FULL		0x00000080
+#define USP_TX_FIFO_EMPTY		0x00000100
+
+/* USP TX FIFO Data Register */
+#define USP_TX_FIFO_DATA_MASK		0xFFFFFFFF
+#define USP_TX_FIFO_DATA_OFFSET		0
+
+/* USP RX DMA I/O MODE Register */
+#define USP_RX_MODE_IO			0x00000001
+#define USP_RX_DMA_FLUSH		0x00000004
+
+/* USP RX DMA I/O Length Register */
+#define USP_RX_DATA_LEN_MASK		0xFFFFFFFF
+#define USP_RX_DATA_LEN_OFFSET		0
+
+/* USP RX FIFO Control Register */
+#define USP_RX_FIFO_WIDTH_MASK		0x00000003
+#define USP_RX_FIFO_WIDTH_OFFSET	0
+
+#define USP_RX_FIFO_THD_MASK		0x000001FC
+#define USP_RX_FIFO_THD_OFFSET		2
+
+/* USP RX FIFO Level Check Register */
+
+#define USP_RX_FIFO_LEVEL_CHECK_MASK	0x1F
+#define USP_RX_FIFO_SC_OFFSET	0
+#define USP_RX_FIFO_LC_OFFSET	10
+#define USP_RX_FIFO_HC_OFFSET	20
+
+#define RX_FIFO_SC(x)		(((x) & USP_RX_FIFO_LEVEL_CHECK_MASK) \
+				<< USP_RX_FIFO_SC_OFFSET)
+#define RX_FIFO_LC(x)		(((x) & USP_RX_FIFO_LEVEL_CHECK_MASK) \
+				<< USP_RX_FIFO_LC_OFFSET)
+#define RX_FIFO_HC(x)		(((x) & USP_RX_FIFO_LEVEL_CHECK_MASK) \
+				<< USP_RX_FIFO_HC_OFFSET)
+
+/* USP RX FIFO Operation Register */
+#define USP_RX_FIFO_RESET		0x00000001
+#define USP_RX_FIFO_START		0x00000002
+
+/* USP RX FIFO Status Register */
+
+#define USP_RX_FIFO_LEVEL_MASK		0x0000007F
+#define USP_RX_FIFO_LEVEL_OFFSET	0
+
+#define USP_RX_FIFO_FULL		0x00000080
+#define USP_RX_FIFO_EMPTY		0x00000100
+
+/* USP RX FIFO Data Register */
+
+#define USP_RX_FIFO_DATA_MASK		0xFFFFFFFF
+#define USP_RX_FIFO_DATA_OFFSET		0
+
+/*
+ * When rx thd irq occur, sender just disable tx empty irq,
+ * Remaining data in tx fifo wil also be sent out.
+ */
+#define USP_FIFO_SIZE			128
+#define USP_TX_FIFO_THRESHOLD		(USP_FIFO_SIZE/2)
+#define USP_RX_FIFO_THRESHOLD		(USP_FIFO_SIZE/2)
+
+/* FIFO_WIDTH for the USP_TX_FIFO_CTRL and USP_RX_FIFO_CTRL registers */
+#define USP_FIFO_WIDTH_BYTE  0x00
+#define USP_FIFO_WIDTH_WORD  0x01
+#define USP_FIFO_WIDTH_DWORD 0x02
+
+#define USP_ASYNC_DIV2          16
+
+#define USP_PLUGOUT_RETRY_CNT	2
+
+#define USP_TX_RX_FIFO_WIDTH_DWORD    2
+
+#define SIRF_USP_DIV_MCLK	0
+
+#define SIRF_USP_I2S_TFS_SYNC	0
+#define SIRF_USP_I2S_RFS_SYNC	1
+#endif
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index 00e70b6c7da2..a9f82b5aba9d 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -78,7 +78,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec)
 	mutex_init(&codec->cache_rw_mutex);
 
 	dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n",
-				codec->name);
+				codec->component.name);
 
 	if (codec_drv->reg_cache_default)
 		codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
@@ -98,8 +98,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec)
 int snd_soc_cache_exit(struct snd_soc_codec *codec)
 {
 	dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n",
-			codec->name);
-
+			codec->component.name);
 	kfree(codec->reg_cache);
 	codec->reg_cache = NULL;
 	return 0;
@@ -192,7 +191,7 @@ int snd_soc_cache_sync(struct snd_soc_codec *codec)
 		return 0;
 
 	dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n",
-		codec->name);
+		codec->component.name);
 	trace_snd_soc_cache_sync(codec, name, "start");
 	ret = snd_soc_flat_cache_sync(codec);
 	if (!ret)
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 10f7f1da2aca..27c06acce205 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -37,7 +37,8 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
 	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
 		ret = platform->driver->compr_ops->open(cstream);
 		if (ret < 0) {
-			pr_err("compress asoc: can't open platform %s\n", platform->name);
+			pr_err("compress asoc: can't open platform %s\n",
+				platform->component.name);
 			goto out;
 		}
 	}
@@ -84,7 +85,8 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
 	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
 		ret = platform->driver->compr_ops->open(cstream);
 		if (ret < 0) {
-			pr_err("compress asoc: can't open platform %s\n", platform->name);
+			pr_err("compress asoc: can't open platform %s\n",
+				platform->component.name);
 			goto out;
 		}
 	}
@@ -627,6 +629,11 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
 	char new_name[64];
 	int ret = 0, direction = 0;
 
+	if (rtd->num_codecs > 1) {
+		dev_err(rtd->card->dev, "Multicodec not supported for compressed stream\n");
+		return -EINVAL;
+	}
+
 	/* check client and interface hw capabilities */
 	snprintf(new_name, sizeof(new_name), "%s %s-%d",
 			rtd->dai_link->stream_name, codec_dai->name, num);
@@ -680,7 +687,7 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
 	ret = snd_compress_new(rtd->card->snd_card, num, direction, compr);
 	if (ret < 0) {
 		pr_err("compress asoc: can't create compress for codec %s\n",
-			codec->name);
+			codec->component.name);
 		goto compr_err;
 	}
 
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b87d7d882e6d..d4bfd4a9076f 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -270,12 +270,33 @@ static const struct file_operations codec_reg_fops = {
 	.llseek = default_llseek,
 };
 
+static struct dentry *soc_debugfs_create_dir(struct dentry *parent,
+	const char *fmt, ...)
+{
+	struct dentry *de;
+	va_list ap;
+	char *s;
+
+	va_start(ap, fmt);
+	s = kvasprintf(GFP_KERNEL, fmt, ap);
+	va_end(ap);
+
+	if (!s)
+		return NULL;
+
+	de = debugfs_create_dir(s, parent);
+	kfree(s);
+
+	return de;
+}
+
 static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
 {
-	struct dentry *debugfs_card_root = codec->card->debugfs_card_root;
+	struct dentry *debugfs_card_root = codec->component.card->debugfs_card_root;
 
-	codec->debugfs_codec_root = debugfs_create_dir(codec->name,
-						       debugfs_card_root);
+	codec->debugfs_codec_root = soc_debugfs_create_dir(debugfs_card_root,
+						"codec:%s",
+						codec->component.name);
 	if (!codec->debugfs_codec_root) {
 		dev_warn(codec->dev,
 			"ASoC: Failed to create codec debugfs directory\n");
@@ -304,17 +325,18 @@ static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
 
 static void soc_init_platform_debugfs(struct snd_soc_platform *platform)
 {
-	struct dentry *debugfs_card_root = platform->card->debugfs_card_root;
+	struct dentry *debugfs_card_root = platform->component.card->debugfs_card_root;
 
-	platform->debugfs_platform_root = debugfs_create_dir(platform->name,
-						       debugfs_card_root);
+	platform->debugfs_platform_root = soc_debugfs_create_dir(debugfs_card_root,
+						"platform:%s",
+						platform->component.name);
 	if (!platform->debugfs_platform_root) {
 		dev_warn(platform->dev,
 			"ASoC: Failed to create platform debugfs directory\n");
 		return;
 	}
 
-	snd_soc_dapm_debugfs_init(&platform->dapm,
+	snd_soc_dapm_debugfs_init(&platform->component.dapm,
 		platform->debugfs_platform_root);
 }
 
@@ -335,7 +357,7 @@ static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
 
 	list_for_each_entry(codec, &codec_list, list) {
 		len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
-			       codec->name);
+			       codec->component.name);
 		if (len >= 0)
 			ret += len;
 		if (ret > PAGE_SIZE) {
@@ -406,7 +428,7 @@ static ssize_t platform_list_read_file(struct file *file,
 
 	list_for_each_entry(platform, &platform_list, list) {
 		len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
-			       platform->name);
+			       platform->component.name);
 		if (len >= 0)
 			ret += len;
 		if (ret > PAGE_SIZE) {
@@ -524,11 +546,12 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
 	int err;
 
 	codec->ac97->dev.bus = &ac97_bus_type;
-	codec->ac97->dev.parent = codec->card->dev;
+	codec->ac97->dev.parent = codec->component.card->dev;
 	codec->ac97->dev.release = soc_ac97_device_release;
 
 	dev_set_name(&codec->ac97->dev, "%d-%d:%s",
-		     codec->card->snd_card->number, 0, codec->name);
+		     codec->component.card->snd_card->number, 0,
+		     codec->component.name);
 	err = device_register(&codec->ac97->dev);
 	if (err < 0) {
 		dev_err(codec->dev, "ASoC: Can't register ac97 bus\n");
@@ -554,7 +577,7 @@ int snd_soc_suspend(struct device *dev)
 {
 	struct snd_soc_card *card = dev_get_drvdata(dev);
 	struct snd_soc_codec *codec;
-	int i;
+	int i, j;
 
 	/* If the initialization of this soc device failed, there is no codec
 	 * associated with it. Just bail out in this case.
@@ -574,14 +597,17 @@ int snd_soc_suspend(struct device *dev)
 
 	/* mute any active DACs */
 	for (i = 0; i < card->num_rtd; i++) {
-		struct snd_soc_dai *dai = card->rtd[i].codec_dai;
-		struct snd_soc_dai_driver *drv = dai->driver;
 
 		if (card->rtd[i].dai_link->ignore_suspend)
 			continue;
 
-		if (drv->ops->digital_mute && dai->playback_active)
-			drv->ops->digital_mute(dai, 1);
+		for (j = 0; j < card->rtd[i].num_codecs; j++) {
+			struct snd_soc_dai *dai = card->rtd[i].codec_dais[j];
+			struct snd_soc_dai_driver *drv = dai->driver;
+
+			if (drv->ops->digital_mute && dai->playback_active)
+				drv->ops->digital_mute(dai, 1);
+		}
 	}
 
 	/* suspend all pcms */
@@ -612,8 +638,12 @@ int snd_soc_suspend(struct device *dev)
 
 	/* close any waiting streams and save state */
 	for (i = 0; i < card->num_rtd; i++) {
+		struct snd_soc_dai **codec_dais = card->rtd[i].codec_dais;
 		flush_delayed_work(&card->rtd[i].delayed_work);
-		card->rtd[i].codec->dapm.suspend_bias_level = card->rtd[i].codec->dapm.bias_level;
+		for (j = 0; j < card->rtd[i].num_codecs; j++) {
+			codec_dais[j]->codec->dapm.suspend_bias_level =
+					codec_dais[j]->codec->dapm.bias_level;
+		}
 	}
 
 	for (i = 0; i < card->num_rtd; i++) {
@@ -697,7 +727,7 @@ static void soc_resume_deferred(struct work_struct *work)
 	struct snd_soc_card *card =
 			container_of(work, struct snd_soc_card, deferred_resume_work);
 	struct snd_soc_codec *codec;
-	int i;
+	int i, j;
 
 	/* our power state is still SNDRV_CTL_POWER_D3hot from suspend time,
 	 * so userspace apps are blocked from touching us
@@ -758,14 +788,17 @@ static void soc_resume_deferred(struct work_struct *work)
 
 	/* unmute any active DACs */
 	for (i = 0; i < card->num_rtd; i++) {
-		struct snd_soc_dai *dai = card->rtd[i].codec_dai;
-		struct snd_soc_dai_driver *drv = dai->driver;
 
 		if (card->rtd[i].dai_link->ignore_suspend)
 			continue;
 
-		if (drv->ops->digital_mute && dai->playback_active)
-			drv->ops->digital_mute(dai, 0);
+		for (j = 0; j < card->rtd[i].num_codecs; j++) {
+			struct snd_soc_dai *dai = card->rtd[i].codec_dais[j];
+			struct snd_soc_dai_driver *drv = dai->driver;
+
+			if (drv->ops->digital_mute && dai->playback_active)
+				drv->ops->digital_mute(dai, 0);
+		}
 	}
 
 	for (i = 0; i < card->num_rtd; i++) {
@@ -810,12 +843,19 @@ int snd_soc_resume(struct device *dev)
 
 	/* activate pins from sleep state */
 	for (i = 0; i < card->num_rtd; i++) {
-		struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
-		struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
+		struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
+		struct snd_soc_dai **codec_dais = rtd->codec_dais;
+		struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+		int j;
+
 		if (cpu_dai->active)
 			pinctrl_pm_select_default_state(cpu_dai->dev);
-		if (codec_dai->active)
-			pinctrl_pm_select_default_state(codec_dai->dev);
+
+		for (j = 0; j < rtd->num_codecs; j++) {
+			struct snd_soc_dai *codec_dai = codec_dais[j];
+			if (codec_dai->active)
+				pinctrl_pm_select_default_state(codec_dai->dev);
+		}
 	}
 
 	/* AC97 devices might have other drivers hanging off them so
@@ -847,8 +887,9 @@ EXPORT_SYMBOL_GPL(snd_soc_resume);
 static const struct snd_soc_dai_ops null_dai_ops = {
 };
 
-static struct snd_soc_codec *soc_find_codec(const struct device_node *codec_of_node,
-					    const char *codec_name)
+static struct snd_soc_codec *soc_find_codec(
+					const struct device_node *codec_of_node,
+					const char *codec_name)
 {
 	struct snd_soc_codec *codec;
 
@@ -857,7 +898,7 @@ static struct snd_soc_codec *soc_find_codec(const struct device_node *codec_of_n
 			if (codec->dev->of_node != codec_of_node)
 				continue;
 		} else {
-			if (strcmp(codec->name, codec_name))
+			if (strcmp(codec->component.name, codec_name))
 				continue;
 		}
 
@@ -886,9 +927,12 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
 	struct snd_soc_dai_link *dai_link = &card->dai_link[num];
 	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
 	struct snd_soc_component *component;
+	struct snd_soc_dai_link_component *codecs = dai_link->codecs;
+	struct snd_soc_dai **codec_dais = rtd->codec_dais;
 	struct snd_soc_platform *platform;
 	struct snd_soc_dai *cpu_dai;
 	const char *platform_name;
+	int i;
 
 	dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num);
 
@@ -915,24 +959,30 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
 		return -EPROBE_DEFER;
 	}
 
-	/* Find CODEC from registered list */
-	rtd->codec = soc_find_codec(dai_link->codec_of_node,
-				    dai_link->codec_name);
-	if (!rtd->codec) {
-		dev_err(card->dev, "ASoC: CODEC %s not registered\n",
-			dai_link->codec_name);
-		return -EPROBE_DEFER;
-	}
+	rtd->num_codecs = dai_link->num_codecs;
 
-	/* Find CODEC DAI from registered list */
-	rtd->codec_dai = soc_find_codec_dai(rtd->codec,
-					    dai_link->codec_dai_name);
-	if (!rtd->codec_dai) {
-		dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n",
-			dai_link->codec_dai_name);
-		return -EPROBE_DEFER;
+	/* Find CODEC from registered CODECs */
+	for (i = 0; i < rtd->num_codecs; i++) {
+		struct snd_soc_codec *codec;
+		codec = soc_find_codec(codecs[i].of_node, codecs[i].name);
+		if (!codec) {
+			dev_err(card->dev, "ASoC: CODEC %s not registered\n",
+				codecs[i].name);
+			return -EPROBE_DEFER;
+		}
+
+		codec_dais[i] = soc_find_codec_dai(codec, codecs[i].dai_name);
+		if (!codec_dais[i]) {
+			dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n",
+				codecs[i].dai_name);
+			return -EPROBE_DEFER;
+		}
 	}
 
+	/* Single codec links expect codec and codec_dai in runtime data */
+	rtd->codec_dai = codec_dais[0];
+	rtd->codec = rtd->codec_dai->codec;
+
 	/* if there's no platform we match on the empty platform */
 	platform_name = dai_link->platform_name;
 	if (!platform_name && !dai_link->platform_of_node)
@@ -945,7 +995,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
 			    dai_link->platform_of_node)
 				continue;
 		} else {
-			if (strcmp(platform->name, platform_name))
+			if (strcmp(platform->component.name, platform_name))
 				continue;
 		}
 
@@ -974,11 +1024,10 @@ static int soc_remove_platform(struct snd_soc_platform *platform)
 	}
 
 	/* Make sure all DAPM widgets are freed */
-	snd_soc_dapm_free(&platform->dapm);
+	snd_soc_dapm_free(&platform->component.dapm);
 
 	soc_cleanup_platform_debugfs(platform);
 	platform->probed = 0;
-	list_del(&platform->card_list);
 	module_put(platform->dev->driver->owner);
 
 	return 0;
@@ -1023,8 +1072,8 @@ static void soc_remove_codec_dai(struct snd_soc_dai *codec_dai, int order)
 static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
 {
 	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
-	struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
-	int err;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int i, err;
 
 	/* unregister the rtd device */
 	if (rtd->dev_registered) {
@@ -1035,7 +1084,8 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
 	}
 
 	/* remove the CODEC DAI */
-	soc_remove_codec_dai(codec_dai, order);
+	for (i = 0; i < rtd->num_codecs; i++)
+		soc_remove_codec_dai(rtd->codec_dais[i], order);
 
 	/* remove the cpu_dai */
 	if (cpu_dai && cpu_dai->probed &&
@@ -1048,11 +1098,8 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
 					cpu_dai->name, err);
 		}
 		cpu_dai->probed = 0;
-
-		if (!cpu_dai->codec) {
-			snd_soc_dapm_free(&cpu_dai->dapm);
+		if (!cpu_dai->codec)
 			module_put(cpu_dai->dev->driver->owner);
-		}
 	}
 }
 
@@ -1061,9 +1108,9 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num,
 {
 	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_codec *codec;
+	int i;
 
 	/* remove the platform */
 	if (platform && platform->probed &&
@@ -1072,8 +1119,8 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num,
 	}
 
 	/* remove the CODEC-side CODEC */
-	if (codec_dai) {
-		codec = codec_dai->codec;
+	for (i = 0; i < rtd->num_codecs; i++) {
+		codec = rtd->codec_dais[i]->codec;
 		if (codec && codec->probed &&
 		    codec->driver->remove_order == order)
 			soc_remove_codec(codec);
@@ -1108,7 +1155,7 @@ static void soc_remove_dai_links(struct snd_soc_card *card)
 }
 
 static void soc_set_name_prefix(struct snd_soc_card *card,
-				struct snd_soc_codec *codec)
+				struct snd_soc_component *component)
 {
 	int i;
 
@@ -1117,11 +1164,11 @@ static void soc_set_name_prefix(struct snd_soc_card *card,
 
 	for (i = 0; i < card->num_configs; i++) {
 		struct snd_soc_codec_conf *map = &card->codec_conf[i];
-		if (map->of_node && codec->dev->of_node != map->of_node)
+		if (map->of_node && component->dev->of_node != map->of_node)
 			continue;
-		if (map->dev_name && strcmp(codec->name, map->dev_name))
+		if (map->dev_name && strcmp(component->name, map->dev_name))
 			continue;
-		codec->name_prefix = map->name_prefix;
+		component->name_prefix = map->name_prefix;
 		break;
 	}
 }
@@ -1133,9 +1180,9 @@ static int soc_probe_codec(struct snd_soc_card *card,
 	const struct snd_soc_codec_driver *driver = codec->driver;
 	struct snd_soc_dai *dai;
 
-	codec->card = card;
+	codec->component.card = card;
 	codec->dapm.card = card;
-	soc_set_name_prefix(card, codec);
+	soc_set_name_prefix(card, &codec->component);
 
 	if (!try_module_get(codec->dev->driver->owner))
 		return -ENODEV;
@@ -1177,7 +1224,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
 		WARN(codec->dapm.idle_bias_off &&
 			codec->dapm.bias_level != SND_SOC_BIAS_OFF,
 			"codec %s can not start from non-off bias with idle_bias_off==1\n",
-			codec->name);
+			codec->component.name);
 	}
 
 	if (driver->controls)
@@ -1209,8 +1256,8 @@ static int soc_probe_platform(struct snd_soc_card *card,
 	struct snd_soc_component *component;
 	struct snd_soc_dai *dai;
 
-	platform->card = card;
-	platform->dapm.card = card;
+	platform->component.card = card;
+	platform->component.dapm.card = card;
 
 	if (!try_module_get(platform->dev->driver->owner))
 		return -ENODEV;
@@ -1218,7 +1265,7 @@ static int soc_probe_platform(struct snd_soc_card *card,
 	soc_init_platform_debugfs(platform);
 
 	if (driver->dapm_widgets)
-		snd_soc_dapm_new_controls(&platform->dapm,
+		snd_soc_dapm_new_controls(&platform->component.dapm,
 			driver->dapm_widgets, driver->num_dapm_widgets);
 
 	/* Create DAPM widgets for each DAI stream */
@@ -1226,10 +1273,11 @@ static int soc_probe_platform(struct snd_soc_card *card,
 		if (component->dev != platform->dev)
 			continue;
 		list_for_each_entry(dai, &component->dai_list, list)
-			snd_soc_dapm_new_dai_widgets(&platform->dapm, dai);
+			snd_soc_dapm_new_dai_widgets(&platform->component.dapm,
+				dai);
 	}
 
-	platform->dapm.idle_bias_off = 1;
+	platform->component.dapm.idle_bias_off = 1;
 
 	if (driver->probe) {
 		ret = driver->probe(platform);
@@ -1244,13 +1292,12 @@ static int soc_probe_platform(struct snd_soc_card *card,
 		snd_soc_add_platform_controls(platform, driver->controls,
 				     driver->num_controls);
 	if (driver->dapm_routes)
-		snd_soc_dapm_add_routes(&platform->dapm, driver->dapm_routes,
-					driver->num_dapm_routes);
+		snd_soc_dapm_add_routes(&platform->component.dapm,
+			driver->dapm_routes, driver->num_dapm_routes);
 
 	/* mark platform as probed and add to card platform list */
 	platform->probed = 1;
-	list_add(&platform->card_list, &card->platform_dev_list);
-	list_add(&platform->dapm.list, &card->dapm_list);
+	list_add(&platform->component.dapm.list, &card->dapm_list);
 
 	return 0;
 
@@ -1266,83 +1313,17 @@ static void rtd_release(struct device *dev)
 	kfree(dev);
 }
 
-static int soc_aux_dev_init(struct snd_soc_card *card,
-			    struct snd_soc_codec *codec,
-			    int num)
-{
-	struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
-	struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num];
-	int ret;
-
-	rtd->card = card;
-
-	/* do machine specific initialization */
-	if (aux_dev->init) {
-		ret = aux_dev->init(&codec->dapm);
-		if (ret < 0)
-			return ret;
-	}
-
-	rtd->codec = codec;
-
-	return 0;
-}
-
-static int soc_dai_link_init(struct snd_soc_card *card,
-			     struct snd_soc_codec *codec,
-			     int num)
+static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd,
+	const char *name)
 {
-	struct snd_soc_dai_link *dai_link =  &card->dai_link[num];
-	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
-	int ret;
-
-	rtd->card = card;
-
-	/* do machine specific initialization */
-	if (dai_link->init) {
-		ret = dai_link->init(rtd);
-		if (ret < 0)
-			return ret;
-	}
-
-	rtd->codec = codec;
-
-	return 0;
-}
-
-static int soc_post_component_init(struct snd_soc_card *card,
-				   struct snd_soc_codec *codec,
-				   int num, int dailess)
-{
-	struct snd_soc_dai_link *dai_link = NULL;
-	struct snd_soc_aux_dev *aux_dev = NULL;
-	struct snd_soc_pcm_runtime *rtd;
-	const char *name;
 	int ret = 0;
 
-	if (!dailess) {
-		dai_link = &card->dai_link[num];
-		rtd = &card->rtd[num];
-		name = dai_link->name;
-		ret = soc_dai_link_init(card, codec, num);
-	} else {
-		aux_dev = &card->aux_dev[num];
-		rtd = &card->rtd_aux[num];
-		name = aux_dev->name;
-		ret = soc_aux_dev_init(card, codec, num);
-	}
-
-	if (ret < 0) {
-		dev_err(card->dev, "ASoC: failed to init %s: %d\n", name, ret);
-		return ret;
-	}
-
 	/* register the rtd device */
 	rtd->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
 	if (!rtd->dev)
 		return -ENOMEM;
 	device_initialize(rtd->dev);
-	rtd->dev->parent = card->dev;
+	rtd->dev->parent = rtd->card->dev;
 	rtd->dev->release = rtd_release;
 	rtd->dev->init_name = name;
 	dev_set_drvdata(rtd->dev, rtd);
@@ -1355,7 +1336,7 @@ static int soc_post_component_init(struct snd_soc_card *card,
 	if (ret < 0) {
 		/* calling put_device() here to free the rtd->dev */
 		put_device(rtd->dev);
-		dev_err(card->dev,
+		dev_err(rtd->card->dev,
 			"ASoC: failed to register runtime device: %d\n", ret);
 		return ret;
 	}
@@ -1364,26 +1345,15 @@ static int soc_post_component_init(struct snd_soc_card *card,
 	/* add DAPM sysfs entries for this codec */
 	ret = snd_soc_dapm_sys_add(rtd->dev);
 	if (ret < 0)
-		dev_err(codec->dev,
+		dev_err(rtd->dev,
 			"ASoC: failed to add codec dapm sysfs entries: %d\n", ret);
 
 	/* add codec sysfs entries */
 	ret = device_create_file(rtd->dev, &dev_attr_codec_reg);
 	if (ret < 0)
-		dev_err(codec->dev,
+		dev_err(rtd->dev,
 			"ASoC: failed to add codec sysfs files: %d\n", ret);
 
-#ifdef CONFIG_DEBUG_FS
-	/* add DPCM sysfs entries */
-	if (!dailess && !dai_link->dynamic)
-		goto out;
-
-	ret = soc_dpcm_debugfs_add(rtd);
-	if (ret < 0)
-		dev_err(rtd->dev, "ASoC: failed to add dpcm sysfs entries: %d\n", ret);
-
-out:
-#endif
 	return 0;
 }
 
@@ -1392,9 +1362,8 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num,
 {
 	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_platform *platform = rtd->platform;
-	int ret;
+	int i, ret;
 
 	/* probe the CPU-side component, if it is a CODEC */
 	if (cpu_dai->codec &&
@@ -1405,12 +1374,14 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num,
 			return ret;
 	}
 
-	/* probe the CODEC-side component */
-	if (!codec_dai->codec->probed &&
-	    codec_dai->codec->driver->probe_order == order) {
-		ret = soc_probe_codec(card, codec_dai->codec);
-		if (ret < 0)
-			return ret;
+	/* probe the CODEC-side components */
+	for (i = 0; i < rtd->num_codecs; i++) {
+		if (!rtd->codec_dais[i]->codec->probed &&
+		    rtd->codec_dais[i]->codec->driver->probe_order == order) {
+			ret = soc_probe_codec(card, rtd->codec_dais[i]->codec);
+			if (ret < 0)
+				return ret;
+		}
 	}
 
 	/* probe the platform */
@@ -1450,12 +1421,16 @@ static int soc_probe_codec_dai(struct snd_soc_card *card,
 
 static int soc_link_dai_widgets(struct snd_soc_card *card,
 				struct snd_soc_dai_link *dai_link,
-				struct snd_soc_dai *cpu_dai,
-				struct snd_soc_dai *codec_dai)
+				struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_dapm_widget *play_w, *capture_w;
 	int ret;
 
+	if (rtd->num_codecs > 1)
+		dev_warn(card->dev, "ASoC: Multiple codecs not supported yet\n");
+
 	/* link the DAI widgets */
 	play_w = codec_dai->playback_widget;
 	capture_w = cpu_dai->capture_widget;
@@ -1488,19 +1463,18 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
 {
 	struct snd_soc_dai_link *dai_link = &card->dai_link[num];
 	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
-	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_platform *platform = rtd->platform;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	int ret;
+	int i, ret;
 
 	dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n",
 			card->name, num, order);
 
 	/* config components */
 	cpu_dai->platform = platform;
-	codec_dai->card = card;
 	cpu_dai->card = card;
+	for (i = 0; i < rtd->num_codecs; i++)
+		rtd->codec_dais[i]->card = card;
 
 	/* set default power off timeout */
 	rtd->pmdown_time = pmdown_time;
@@ -1509,11 +1483,8 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
 	if (!cpu_dai->probed &&
 			cpu_dai->driver->probe_order == order) {
 		if (!cpu_dai->codec) {
-			cpu_dai->dapm.card = card;
 			if (!try_module_get(cpu_dai->dev->driver->owner))
 				return -ENODEV;
-
-			list_add(&cpu_dai->dapm.list, &card->dapm_list);
 		}
 
 		if (cpu_dai->driver->probe) {
@@ -1530,18 +1501,43 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
 	}
 
 	/* probe the CODEC DAI */
-	ret = soc_probe_codec_dai(card, codec_dai, order);
-	if (ret)
-		return ret;
+	for (i = 0; i < rtd->num_codecs; i++) {
+		ret = soc_probe_codec_dai(card, rtd->codec_dais[i], order);
+		if (ret)
+			return ret;
+	}
 
 	/* complete DAI probe during last probe */
 	if (order != SND_SOC_COMP_ORDER_LAST)
 		return 0;
 
-	ret = soc_post_component_init(card, codec, num, 0);
+	/* do machine specific initialization */
+	if (dai_link->init) {
+		ret = dai_link->init(rtd);
+		if (ret < 0) {
+			dev_err(card->dev, "ASoC: failed to init %s: %d\n",
+				dai_link->name, ret);
+			return ret;
+		}
+	}
+
+	ret = soc_post_component_init(rtd, dai_link->name);
 	if (ret)
 		return ret;
 
+#ifdef CONFIG_DEBUG_FS
+	/* add DPCM sysfs entries */
+	if (dai_link->dynamic) {
+		ret = soc_dpcm_debugfs_add(rtd);
+		if (ret < 0) {
+			dev_err(rtd->dev,
+				"ASoC: failed to add dpcm sysfs entries: %d\n",
+				ret);
+			return ret;
+		}
+	}
+#endif
+
 	ret = device_create_file(rtd->dev, &dev_attr_pmdown_time);
 	if (ret < 0)
 		dev_warn(rtd->dev, "ASoC: failed to add pmdown_time sysfs: %d\n",
@@ -1570,16 +1566,18 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
 						codec2codec_close_delayed_work);
 
 			/* link the DAI widgets */
-			ret = soc_link_dai_widgets(card, dai_link,
-					cpu_dai, codec_dai);
+			ret = soc_link_dai_widgets(card, dai_link, rtd);
 			if (ret)
 				return ret;
 		}
 	}
 
 	/* add platform data for AC97 devices */
-	if (rtd->codec_dai->driver->ac97_control)
-		snd_ac97_dev_add_pdata(codec->ac97, rtd->cpu_dai->ac97_pdata);
+	for (i = 0; i < rtd->num_codecs; i++) {
+		if (rtd->codec_dais[i]->driver->ac97_control)
+			snd_ac97_dev_add_pdata(rtd->codec_dais[i]->codec->ac97,
+					       rtd->cpu_dai->ac97_pdata);
+	}
 
 	return 0;
 }
@@ -1617,11 +1615,6 @@ static int soc_register_ac97_codec(struct snd_soc_codec *codec,
 	return 0;
 }
 
-static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
-{
-	return soc_register_ac97_codec(rtd->codec, rtd->codec_dai);
-}
-
 static void soc_unregister_ac97_codec(struct snd_soc_codec *codec)
 {
 	if (codec->ac97_registered) {
@@ -1630,74 +1623,77 @@ static void soc_unregister_ac97_codec(struct snd_soc_codec *codec)
 	}
 }
 
-static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
+static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
 {
-	soc_unregister_ac97_codec(rtd->codec);
-}
-#endif
+	int i, ret;
 
-static struct snd_soc_codec *soc_find_matching_codec(struct snd_soc_card *card,
-	int num)
-{
-	struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
-	struct snd_soc_codec *codec;
+	for (i = 0; i < rtd->num_codecs; i++) {
+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
 
-	/* find CODEC from registered CODECs */
-	list_for_each_entry(codec, &codec_list, list) {
-		if (aux_dev->codec_of_node &&
-		   (codec->dev->of_node != aux_dev->codec_of_node))
-			continue;
-		if (aux_dev->codec_name && strcmp(codec->name, aux_dev->codec_name))
-			continue;
-		return codec;
+		ret = soc_register_ac97_codec(codec_dai->codec, codec_dai);
+		if (ret) {
+			while (--i >= 0)
+				soc_unregister_ac97_codec(codec_dai->codec);
+			return ret;
+		}
 	}
 
-	return NULL;
+	return 0;
 }
 
-static int soc_check_aux_dev(struct snd_soc_card *card, int num)
+static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
 {
-	struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
-	const char *codecname = aux_dev->codec_name;
-	struct snd_soc_codec *codec = soc_find_matching_codec(card, num);
-
-	if (codec)
-		return 0;
-	if (aux_dev->codec_of_node)
-		codecname = of_node_full_name(aux_dev->codec_of_node);
+	int i;
 
-	dev_err(card->dev, "ASoC: %s not registered\n", codecname);
-	return -EPROBE_DEFER;
+	for (i = 0; i < rtd->num_codecs; i++)
+		soc_unregister_ac97_codec(rtd->codec_dais[i]->codec);
 }
+#endif
 
-static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
+static int soc_bind_aux_dev(struct snd_soc_card *card, int num)
 {
+	struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num];
 	struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
 	const char *codecname = aux_dev->codec_name;
-	int ret = -ENODEV;
-	struct snd_soc_codec *codec = soc_find_matching_codec(card, num);
 
-	if (!codec) {
+	rtd->codec = soc_find_codec(aux_dev->codec_of_node, codecname);
+	if (!rtd->codec) {
 		if (aux_dev->codec_of_node)
 			codecname = of_node_full_name(aux_dev->codec_of_node);
 
-		/* codec not found */
-		dev_err(card->dev, "ASoC: codec %s not found", codecname);
+		dev_err(card->dev, "ASoC: %s not registered\n", codecname);
 		return -EPROBE_DEFER;
 	}
 
-	if (codec->probed) {
-		dev_err(codec->dev, "ASoC: codec already probed");
+	return 0;
+}
+
+static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
+{
+	struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num];
+	struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
+	int ret;
+
+	if (rtd->codec->probed) {
+		dev_err(rtd->codec->dev, "ASoC: codec already probed\n");
 		return -EBUSY;
 	}
 
-	ret = soc_probe_codec(card, codec);
+	ret = soc_probe_codec(card, rtd->codec);
 	if (ret < 0)
 		return ret;
 
-	ret = soc_post_component_init(card, codec, num, 1);
+	/* do machine specific initialization */
+	if (aux_dev->init) {
+		ret = aux_dev->init(&rtd->codec->dapm);
+		if (ret < 0) {
+			dev_err(card->dev, "ASoC: failed to init %s: %d\n",
+				aux_dev->name, ret);
+			return ret;
+		}
+	}
 
-	return ret;
+	return soc_post_component_init(rtd, aux_dev->name);
 }
 
 static void soc_remove_aux_dev(struct snd_soc_card *card, int num)
@@ -1749,9 +1745,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
 			goto base_error;
 	}
 
-	/* check aux_devs too */
+	/* bind aux_devs too */
 	for (i = 0; i < card->num_aux_devs; i++) {
-		ret = soc_check_aux_dev(card, i);
+		ret = soc_bind_aux_dev(card, i);
 		if (ret != 0)
 			goto base_error;
 	}
@@ -1849,16 +1845,23 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
 					card->num_dapm_routes);
 
 	for (i = 0; i < card->num_links; i++) {
+		struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
 		dai_link = &card->dai_link[i];
 		dai_fmt = dai_link->dai_fmt;
 
 		if (dai_fmt) {
-			ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai,
-						  dai_fmt);
-			if (ret != 0 && ret != -ENOTSUPP)
-				dev_warn(card->rtd[i].codec_dai->dev,
-					 "ASoC: Failed to set DAI format: %d\n",
-					 ret);
+			struct snd_soc_dai **codec_dais = rtd->codec_dais;
+			int j;
+
+			for (j = 0; j < rtd->num_codecs; j++) {
+				struct snd_soc_dai *codec_dai = codec_dais[j];
+
+				ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
+				if (ret != 0 && ret != -ENOTSUPP)
+					dev_warn(codec_dai->dev,
+						 "ASoC: Failed to set DAI format: %d\n",
+						 ret);
+			}
 		}
 
 		/* If this is a regular CPU link there will be a platform */
@@ -1927,8 +1930,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
 	}
 
 	if (card->fully_routed)
-		list_for_each_entry(codec, &card->codec_dev_list, card_list)
-			snd_soc_dapm_auto_nc_codec_pins(codec);
+		snd_soc_dapm_auto_nc_pins(card);
 
 	snd_soc_dapm_new_widgets(card);
 
@@ -2058,10 +2060,15 @@ int snd_soc_poweroff(struct device *dev)
 
 	/* deactivate pins to sleep state */
 	for (i = 0; i < card->num_rtd; i++) {
-		struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
-		struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
-		pinctrl_pm_select_sleep_state(codec_dai->dev);
+		struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
+		struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+		int j;
+
 		pinctrl_pm_select_sleep_state(cpu_dai->dev);
+		for (j = 0; j < rtd->num_codecs; j++) {
+			struct snd_soc_dai *codec_dai = rtd->codec_dais[j];
+			pinctrl_pm_select_sleep_state(codec_dai->dev);
+		}
 	}
 
 	return 0;
@@ -2387,6 +2394,25 @@ struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
 EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol);
 
 /**
+ * snd_soc_add_component_controls - Add an array of controls to a component.
+ *
+ * @component: Component to add controls to
+ * @controls: Array of controls to add
+ * @num_controls: Number of elements in the array
+ *
+ * Return: 0 for success, else error.
+ */
+int snd_soc_add_component_controls(struct snd_soc_component *component,
+	const struct snd_kcontrol_new *controls, unsigned int num_controls)
+{
+	struct snd_card *card = component->card->snd_card;
+
+	return snd_soc_add_controls(card, component->dev, controls,
+			num_controls, component->name_prefix, component);
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_component_controls);
+
+/**
  * snd_soc_add_codec_controls - add an array of controls to a codec.
  * Convenience function to add a list of controls. Many codecs were
  * duplicating this code.
@@ -2398,12 +2424,10 @@ EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol);
  * Return 0 for success, else error.
  */
 int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
-	const struct snd_kcontrol_new *controls, int num_controls)
+	const struct snd_kcontrol_new *controls, unsigned int num_controls)
 {
-	struct snd_card *card = codec->card->snd_card;
-
-	return snd_soc_add_controls(card, codec->dev, controls, num_controls,
-			codec->name_prefix, &codec->component);
+	return snd_soc_add_component_controls(&codec->component, controls,
+		num_controls);
 }
 EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls);
 
@@ -2418,12 +2442,10 @@ EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls);
  * Return 0 for success, else error.
  */
 int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
-	const struct snd_kcontrol_new *controls, int num_controls)
+	const struct snd_kcontrol_new *controls, unsigned int num_controls)
 {
-	struct snd_card *card = platform->card->snd_card;
-
-	return snd_soc_add_controls(card, platform->dev, controls, num_controls,
-			NULL, &platform->component);
+	return snd_soc_add_component_controls(&platform->component, controls,
+		num_controls);
 }
 EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls);
 
@@ -3095,7 +3117,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
 int snd_soc_limit_volume(struct snd_soc_codec *codec,
 	const char *name, int max)
 {
-	struct snd_card *card = codec->card->snd_card;
+	struct snd_card *card = codec->component.card->snd_card;
 	struct snd_kcontrol *kctl;
 	struct soc_mixer_control *mc;
 	int found = 0;
@@ -3267,6 +3289,27 @@ int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
 }
 EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext);
 
+int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
+				unsigned int size, unsigned int __user *tlv)
+{
+	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
+	unsigned int count = size < params->max ? size : params->max;
+	int ret = -ENXIO;
+
+	switch (op_flag) {
+	case SNDRV_CTL_TLV_OP_READ:
+		if (params->get)
+			ret = params->get(tlv, count);
+		break;
+	case SNDRV_CTL_TLV_OP_WRITE:
+		if (params->put)
+			ret = params->put(tlv, count);
+		break;
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback);
+
 /**
  * snd_soc_info_xr_sx - signed multi register info callback
  * @kcontrol: mreg control
@@ -3641,6 +3684,9 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
 	else
 		snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
 
+	dai->tx_mask = tx_mask;
+	dai->rx_mask = rx_mask;
+
 	if (dai->driver && dai->driver->ops->set_tdm_slot)
 		return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
 				slots, slot_width);
@@ -3713,6 +3759,33 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
 }
 EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
 
+static int snd_soc_init_multicodec(struct snd_soc_card *card,
+				   struct snd_soc_dai_link *dai_link)
+{
+	/* Legacy codec/codec_dai link is a single entry in multicodec */
+	if (dai_link->codec_name || dai_link->codec_of_node ||
+	    dai_link->codec_dai_name) {
+		dai_link->num_codecs = 1;
+
+		dai_link->codecs = devm_kzalloc(card->dev,
+				sizeof(struct snd_soc_dai_link_component),
+				GFP_KERNEL);
+		if (!dai_link->codecs)
+			return -ENOMEM;
+
+		dai_link->codecs[0].name = dai_link->codec_name;
+		dai_link->codecs[0].of_node = dai_link->codec_of_node;
+		dai_link->codecs[0].dai_name = dai_link->codec_dai_name;
+	}
+
+	if (!dai_link->codecs) {
+		dev_err(card->dev, "ASoC: DAI link has no CODECs\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /**
  * snd_soc_register_card - Register a card with the ASoC core
  *
@@ -3721,7 +3794,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
  */
 int snd_soc_register_card(struct snd_soc_card *card)
 {
-	int i, ret;
+	int i, j, ret;
 
 	if (!card->name || !card->dev)
 		return -EINVAL;
@@ -3729,22 +3802,29 @@ int snd_soc_register_card(struct snd_soc_card *card)
 	for (i = 0; i < card->num_links; i++) {
 		struct snd_soc_dai_link *link = &card->dai_link[i];
 
-		/*
-		 * Codec must be specified by 1 of name or OF node,
-		 * not both or neither.
-		 */
-		if (!!link->codec_name == !!link->codec_of_node) {
-			dev_err(card->dev,
-				"ASoC: Neither/both codec name/of_node are set for %s\n",
-				link->name);
-			return -EINVAL;
+		ret = snd_soc_init_multicodec(card, link);
+		if (ret) {
+			dev_err(card->dev, "ASoC: failed to init multicodec\n");
+			return ret;
 		}
-		/* Codec DAI name must be specified */
-		if (!link->codec_dai_name) {
-			dev_err(card->dev,
-				"ASoC: codec_dai_name not set for %s\n",
-				link->name);
-			return -EINVAL;
+
+		for (j = 0; j < link->num_codecs; j++) {
+			/*
+			 * Codec must be specified by 1 of name or OF node,
+			 * not both or neither.
+			 */
+			if (!!link->codecs[j].name ==
+			    !!link->codecs[j].of_node) {
+				dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n",
+					link->name);
+				return -EINVAL;
+			}
+			/* Codec DAI name must be specified */
+			if (!link->codecs[j].dai_name) {
+				dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n",
+					link->name);
+				return -EINVAL;
+			}
 		}
 
 		/*
@@ -3797,8 +3877,19 @@ int snd_soc_register_card(struct snd_soc_card *card)
 	card->num_rtd = 0;
 	card->rtd_aux = &card->rtd[card->num_links];
 
-	for (i = 0; i < card->num_links; i++)
+	for (i = 0; i < card->num_links; i++) {
+		card->rtd[i].card = card;
 		card->rtd[i].dai_link = &card->dai_link[i];
+		card->rtd[i].codec_dais = devm_kzalloc(card->dev,
+					sizeof(struct snd_soc_dai *) *
+					(card->rtd[i].dai_link->num_codecs),
+					GFP_KERNEL);
+		if (card->rtd[i].codec_dais == NULL)
+			return -ENOMEM;
+	}
+
+	for (i = 0; i < card->num_aux_devs; i++)
+		card->rtd_aux[i].card = card;
 
 	INIT_LIST_HEAD(&card->dapm_dirty);
 	card->instantiated = 0;
@@ -3811,10 +3902,16 @@ int snd_soc_register_card(struct snd_soc_card *card)
 
 	/* deactivate pins to sleep state */
 	for (i = 0; i < card->num_rtd; i++) {
-		struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
-		struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
-		if (!codec_dai->active)
-			pinctrl_pm_select_sleep_state(codec_dai->dev);
+		struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
+		struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+		int j;
+
+		for (j = 0; j < rtd->num_codecs; j++) {
+			struct snd_soc_dai *codec_dai = rtd->codec_dais[j];
+			if (!codec_dai->active)
+				pinctrl_pm_select_sleep_state(codec_dai->dev);
+		}
+
 		if (!cpu_dai->active)
 			pinctrl_pm_select_sleep_state(cpu_dai->dev);
 	}
@@ -3921,16 +4018,14 @@ static void snd_soc_unregister_dais(struct snd_soc_component *component)
  * snd_soc_register_dais - Register a DAI with the ASoC core
  *
  * @component: The component the DAIs are registered for
- * @codec: The CODEC that the DAIs are registered for, NULL if the component is
- *         not a CODEC.
  * @dai_drv: DAI driver to use for the DAIs
  * @count: Number of DAIs
  * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the
  *                     parent's name.
  */
 static int snd_soc_register_dais(struct snd_soc_component *component,
-	struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv,
-	size_t count, bool legacy_dai_naming)
+	struct snd_soc_dai_driver *dai_drv, size_t count,
+	bool legacy_dai_naming)
 {
 	struct device *dev = component->dev;
 	struct snd_soc_dai *dai;
@@ -3939,6 +4034,9 @@ static int snd_soc_register_dais(struct snd_soc_component *component,
 
 	dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count);
 
+	component->dai_drv = dai_drv;
+	component->num_dai = count;
+
 	for (i = 0; i < count; i++) {
 
 		dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
@@ -3971,16 +4069,11 @@ static int snd_soc_register_dais(struct snd_soc_component *component,
 		}
 
 		dai->component = component;
-		dai->codec = codec;
 		dai->dev = dev;
 		dai->driver = &dai_drv[i];
-		dai->dapm.dev = dev;
 		if (!dai->driver->ops)
 			dai->driver->ops = &null_dai_ops;
 
-		if (!dai->codec)
-			dai->dapm.idle_bias_off = 1;
-
 		list_add(&dai->list, &component->dai_list);
 
 		dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name);
@@ -3994,60 +4087,82 @@ err:
 	return ret;
 }
 
-/**
- * snd_soc_register_component - Register a component with the ASoC core
- *
- */
-static int
-__snd_soc_register_component(struct device *dev,
-			     struct snd_soc_component *cmpnt,
-			     const struct snd_soc_component_driver *cmpnt_drv,
-			     struct snd_soc_codec *codec,
-			     struct snd_soc_dai_driver *dai_drv,
-			     int num_dai, bool allow_single_dai)
+static void snd_soc_component_seq_notifier(struct snd_soc_dapm_context *dapm,
+	enum snd_soc_dapm_type type, int subseq)
 {
-	int ret;
+	struct snd_soc_component *component = dapm->component;
 
-	dev_dbg(dev, "component register %s\n", dev_name(dev));
+	component->driver->seq_notifier(component, type, subseq);
+}
 
-	if (!cmpnt) {
-		dev_err(dev, "ASoC: Failed to connecting component\n");
-		return -ENOMEM;
-	}
+static int snd_soc_component_stream_event(struct snd_soc_dapm_context *dapm,
+	int event)
+{
+	struct snd_soc_component *component = dapm->component;
 
-	mutex_init(&cmpnt->io_mutex);
+	return component->driver->stream_event(component, event);
+}
+
+static int snd_soc_component_initialize(struct snd_soc_component *component,
+	const struct snd_soc_component_driver *driver, struct device *dev)
+{
+	struct snd_soc_dapm_context *dapm;
 
-	cmpnt->name = fmt_single_name(dev, &cmpnt->id);
-	if (!cmpnt->name) {
-		dev_err(dev, "ASoC: Failed to simplifying name\n");
+	component->name = fmt_single_name(dev, &component->id);
+	if (!component->name) {
+		dev_err(dev, "ASoC: Failed to allocate name\n");
 		return -ENOMEM;
 	}
 
-	cmpnt->dev	= dev;
-	cmpnt->driver	= cmpnt_drv;
-	cmpnt->dai_drv	= dai_drv;
-	cmpnt->num_dai	= num_dai;
-	INIT_LIST_HEAD(&cmpnt->dai_list);
+	component->dev = dev;
+	component->driver = driver;
 
-	ret = snd_soc_register_dais(cmpnt, codec, dai_drv, num_dai,
-		allow_single_dai);
-	if (ret < 0) {
-		dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
-		goto error_component_name;
-	}
+	if (!component->dapm_ptr)
+		component->dapm_ptr = &component->dapm;
+
+	dapm = component->dapm_ptr;
+	dapm->dev = dev;
+	dapm->component = component;
+	dapm->bias_level = SND_SOC_BIAS_OFF;
+	if (driver->seq_notifier)
+		dapm->seq_notifier = snd_soc_component_seq_notifier;
+	if (driver->stream_event)
+		dapm->stream_event = snd_soc_component_stream_event;
+
+	INIT_LIST_HEAD(&component->dai_list);
+	mutex_init(&component->io_mutex);
 
+	return 0;
+}
+
+static void snd_soc_component_add_unlocked(struct snd_soc_component *component)
+{
+	list_add(&component->list, &component_list);
+}
+
+static void snd_soc_component_add(struct snd_soc_component *component)
+{
 	mutex_lock(&client_mutex);
-	list_add(&cmpnt->list, &component_list);
+	snd_soc_component_add_unlocked(component);
 	mutex_unlock(&client_mutex);
+}
 
-	dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name);
-
-	return ret;
+static void snd_soc_component_cleanup(struct snd_soc_component *component)
+{
+	snd_soc_unregister_dais(component);
+	kfree(component->name);
+}
 
-error_component_name:
-	kfree(cmpnt->name);
+static void snd_soc_component_del_unlocked(struct snd_soc_component *component)
+{
+	list_del(&component->list);
+}
 
-	return ret;
+static void snd_soc_component_del(struct snd_soc_component *component)
+{
+	mutex_lock(&client_mutex);
+	snd_soc_component_del_unlocked(component);
+	mutex_unlock(&client_mutex);
 }
 
 int snd_soc_register_component(struct device *dev,
@@ -4056,32 +4171,38 @@ int snd_soc_register_component(struct device *dev,
 			       int num_dai)
 {
 	struct snd_soc_component *cmpnt;
+	int ret;
 
-	cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL);
+	cmpnt = kzalloc(sizeof(*cmpnt), GFP_KERNEL);
 	if (!cmpnt) {
 		dev_err(dev, "ASoC: Failed to allocate memory\n");
 		return -ENOMEM;
 	}
 
+	ret = snd_soc_component_initialize(cmpnt, cmpnt_drv, dev);
+	if (ret)
+		goto err_free;
+
 	cmpnt->ignore_pmdown_time = true;
 	cmpnt->registered_as_component = true;
 
-	return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, NULL,
-					    dai_drv, num_dai, true);
-}
-EXPORT_SYMBOL_GPL(snd_soc_register_component);
+	ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai, true);
+	if (ret < 0) {
+		dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
+		goto err_cleanup;
+	}
 
-static void __snd_soc_unregister_component(struct snd_soc_component *cmpnt)
-{
-	snd_soc_unregister_dais(cmpnt);
+	snd_soc_component_add(cmpnt);
 
-	mutex_lock(&client_mutex);
-	list_del(&cmpnt->list);
-	mutex_unlock(&client_mutex);
+	return 0;
 
-	dev_dbg(cmpnt->dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
-	kfree(cmpnt->name);
+err_cleanup:
+	snd_soc_component_cleanup(cmpnt);
+err_free:
+	kfree(cmpnt);
+	return ret;
 }
+EXPORT_SYMBOL_GPL(snd_soc_register_component);
 
 /**
  * snd_soc_unregister_component - Unregister a component from the ASoC core
@@ -4098,7 +4219,9 @@ void snd_soc_unregister_component(struct device *dev)
 	return;
 
 found:
-	__snd_soc_unregister_component(cmpnt);
+	snd_soc_component_del(cmpnt);
+	snd_soc_component_cleanup(cmpnt);
+	kfree(cmpnt);
 }
 EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
 
@@ -4131,37 +4254,25 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
 {
 	int ret;
 
-	/* create platform component name */
-	platform->name = fmt_single_name(dev, &platform->id);
-	if (platform->name == NULL)
-		return -ENOMEM;
+	ret = snd_soc_component_initialize(&platform->component,
+			&platform_drv->component_driver, dev);
+	if (ret)
+		return ret;
 
 	platform->dev = dev;
 	platform->driver = platform_drv;
-	platform->dapm.dev = dev;
-	platform->dapm.platform = platform;
-	platform->dapm.component = &platform->component;
-	platform->dapm.stream_event = platform_drv->stream_event;
 	if (platform_drv->write)
 		platform->component.write = snd_soc_platform_drv_write;
 	if (platform_drv->read)
 		platform->component.read = snd_soc_platform_drv_read;
 
-	/* register component */
-	ret = __snd_soc_register_component(dev, &platform->component,
-					   &platform_drv->component_driver,
-					   NULL, NULL, 0, false);
-	if (ret < 0) {
-		dev_err(platform->component.dev,
-			"ASoC: Failed to register component: %d\n", ret);
-		return ret;
-	}
-
 	mutex_lock(&client_mutex);
+	snd_soc_component_add_unlocked(&platform->component);
 	list_add(&platform->list, &platform_list);
 	mutex_unlock(&client_mutex);
 
-	dev_dbg(dev, "ASoC: Registered platform '%s'\n", platform->name);
+	dev_dbg(dev, "ASoC: Registered platform '%s'\n",
+		platform->component.name);
 
 	return 0;
 }
@@ -4198,15 +4309,16 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform);
  */
 void snd_soc_remove_platform(struct snd_soc_platform *platform)
 {
-	__snd_soc_unregister_component(&platform->component);
 
 	mutex_lock(&client_mutex);
 	list_del(&platform->list);
+	snd_soc_component_del_unlocked(&platform->component);
 	mutex_unlock(&client_mutex);
 
+	snd_soc_component_cleanup(&platform->component);
+
 	dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n",
-		platform->name);
-	kfree(platform->name);
+		platform->component.name);
 }
 EXPORT_SYMBOL_GPL(snd_soc_remove_platform);
 
@@ -4292,6 +4404,14 @@ static int snd_soc_codec_drv_read(struct snd_soc_component *component,
 	return 0;
 }
 
+static int snd_soc_codec_set_bias_level(struct snd_soc_dapm_context *dapm,
+	enum snd_soc_bias_level level)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
+
+	return codec->driver->set_bias_level(codec, level);
+}
+
 /**
  * snd_soc_register_codec - Register a codec with the ASoC core
  *
@@ -4303,6 +4423,7 @@ int snd_soc_register_codec(struct device *dev,
 			   int num_dai)
 {
 	struct snd_soc_codec *codec;
+	struct snd_soc_dai *dai;
 	struct regmap *regmap;
 	int ret, i;
 
@@ -4312,24 +4433,23 @@ int snd_soc_register_codec(struct device *dev,
 	if (codec == NULL)
 		return -ENOMEM;
 
-	/* create CODEC component name */
-	codec->name = fmt_single_name(dev, &codec->id);
-	if (codec->name == NULL) {
-		ret = -ENOMEM;
-		goto fail_codec;
-	}
+	codec->component.dapm_ptr = &codec->dapm;
+
+	ret = snd_soc_component_initialize(&codec->component,
+			&codec_drv->component_driver, dev);
+	if (ret)
+		goto err_free;
 
 	if (codec_drv->write)
 		codec->component.write = snd_soc_codec_drv_write;
 	if (codec_drv->read)
 		codec->component.read = snd_soc_codec_drv_read;
 	codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time;
-	codec->dapm.bias_level = SND_SOC_BIAS_OFF;
-	codec->dapm.dev = dev;
 	codec->dapm.codec = codec;
-	codec->dapm.component = &codec->component;
-	codec->dapm.seq_notifier = codec_drv->seq_notifier;
-	codec->dapm.stream_event = codec_drv->stream_event;
+	if (codec_drv->seq_notifier)
+		codec->dapm.seq_notifier = codec_drv->seq_notifier;
+	if (codec_drv->set_bias_level)
+		codec->dapm.set_bias_level = snd_soc_codec_set_bias_level;
 	codec->dev = dev;
 	codec->driver = codec_drv;
 	codec->component.val_bytes = codec_drv->reg_word_size;
@@ -4348,7 +4468,7 @@ int snd_soc_register_codec(struct device *dev,
 				dev_err(codec->dev,
 						"Failed to set cache I/O:%d\n",
 						ret);
-				return ret;
+				goto err_cleanup;
 			}
 		}
 	}
@@ -4358,29 +4478,27 @@ int snd_soc_register_codec(struct device *dev,
 		fixup_codec_formats(&dai_drv[i].capture);
 	}
 
-	mutex_lock(&client_mutex);
-	list_add(&codec->list, &codec_list);
-	mutex_unlock(&client_mutex);
-
-	/* register component */
-	ret = __snd_soc_register_component(dev, &codec->component,
-					   &codec_drv->component_driver,
-					   codec, dai_drv, num_dai, false);
+	ret = snd_soc_register_dais(&codec->component, dai_drv, num_dai, false);
 	if (ret < 0) {
-		dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret);
-		goto fail_codec_name;
+		dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
+		goto err_cleanup;
 	}
 
-	dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", codec->name);
-	return 0;
+	list_for_each_entry(dai, &codec->component.dai_list, list)
+		dai->codec = codec;
 
-fail_codec_name:
 	mutex_lock(&client_mutex);
-	list_del(&codec->list);
+	snd_soc_component_add_unlocked(&codec->component);
+	list_add(&codec->list, &codec_list);
 	mutex_unlock(&client_mutex);
 
-	kfree(codec->name);
-fail_codec:
+	dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n",
+		codec->component.name);
+	return 0;
+
+err_cleanup:
+	snd_soc_component_cleanup(&codec->component);
+err_free:
 	kfree(codec);
 	return ret;
 }
@@ -4402,16 +4520,17 @@ void snd_soc_unregister_codec(struct device *dev)
 	return;
 
 found:
-	__snd_soc_unregister_component(&codec->component);
 
 	mutex_lock(&client_mutex);
 	list_del(&codec->list);
+	snd_soc_component_del_unlocked(&codec->component);
 	mutex_unlock(&client_mutex);
 
-	dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->name);
+	dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n",
+			codec->component.name);
 
+	snd_soc_component_cleanup(&codec->component);
 	snd_soc_cache_exit(codec);
-	kfree(codec->name);
 	kfree(codec);
 }
 EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
@@ -4420,9 +4539,16 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
 int snd_soc_of_parse_card_name(struct snd_soc_card *card,
 			       const char *propname)
 {
-	struct device_node *np = card->dev->of_node;
+	struct device_node *np;
 	int ret;
 
+	if (!card->dev) {
+		pr_err("card->dev is not set before calling %s\n", __func__);
+		return -EINVAL;
+	}
+
+	np = card->dev->of_node;
+
 	ret = of_property_read_string_index(np, propname, 0, &card->name);
 	/*
 	 * EINVAL means the property does not exist. This is fine providing
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index cdc837ed144d..8348352dc2c6 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -350,12 +350,27 @@ static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol,
 }
 
 /**
+ * snd_soc_dapm_kcontrol_dapm() - Returns the dapm context associated to a
+ *  kcontrol
+ * @kcontrol: The kcontrol
+ *
+ * Note: This function must only be used on kcontrols that are known to have
+ * been registered for a CODEC. Otherwise the behaviour is undefined.
+ */
+struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(
+	struct snd_kcontrol *kcontrol)
+{
+	return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->dapm;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_dapm);
+
+/**
  * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol
  * @kcontrol: The kcontrol
  */
 struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol)
 {
-	return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->codec;
+	return snd_soc_dapm_to_codec(snd_soc_dapm_kcontrol_dapm(kcontrol));
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec);
 
@@ -375,23 +390,38 @@ static void dapm_reset(struct snd_soc_card *card)
 	}
 }
 
-static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg,
+static const char *soc_dapm_prefix(struct snd_soc_dapm_context *dapm)
+{
+	if (!dapm->component)
+		return NULL;
+	return dapm->component->name_prefix;
+}
+
+static int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg,
 	unsigned int *value)
 {
-	if (!w->dapm->component)
+	if (!dapm->component)
 		return -EIO;
-	return snd_soc_component_read(w->dapm->component, reg, value);
+	return snd_soc_component_read(dapm->component, reg, value);
 }
 
-static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
+static int soc_dapm_update_bits(struct snd_soc_dapm_context *dapm,
 	int reg, unsigned int mask, unsigned int value)
 {
-	if (!w->dapm->component)
+	if (!dapm->component)
 		return -EIO;
-	return snd_soc_component_update_bits_async(w->dapm->component, reg,
+	return snd_soc_component_update_bits_async(dapm->component, reg,
 		mask, value);
 }
 
+static int soc_dapm_test_bits(struct snd_soc_dapm_context *dapm,
+	int reg, unsigned int mask, unsigned int value)
+{
+	if (!dapm->component)
+		return -EIO;
+	return snd_soc_component_test_bits(dapm->component, reg, mask, value);
+}
+
 static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)
 {
 	if (dapm->component)
@@ -420,15 +450,10 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
 	if (ret != 0)
 		goto out;
 
-	if (dapm->codec) {
-		if (dapm->codec->driver->set_bias_level)
-			ret = dapm->codec->driver->set_bias_level(dapm->codec,
-								  level);
-		else
-			dapm->bias_level = level;
-	} else if (!card || dapm != &card->dapm) {
+	if (dapm->set_bias_level)
+		ret = dapm->set_bias_level(dapm, level);
+	else if (!card || dapm != &card->dapm)
 		dapm->bias_level = level;
-	}
 
 	if (ret != 0)
 		goto out;
@@ -452,7 +477,7 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
 	int i;
 
 	if (e->reg != SND_SOC_NOPM) {
-		soc_widget_read(dest, e->reg, &val);
+		soc_dapm_read(dapm, e->reg, &val);
 		val = (val >> e->shift_l) & e->mask;
 		item = snd_soc_enum_val_to_item(e, val);
 	} else {
@@ -496,7 +521,7 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w,
 	unsigned int val;
 
 	if (reg != SND_SOC_NOPM) {
-		soc_widget_read(w, reg, &val);
+		soc_dapm_read(w->dapm, reg, &val);
 		val = (val >> shift) & mask;
 		if (invert)
 			val = max - val;
@@ -570,11 +595,7 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
 	const char *name;
 	int ret;
 
-	if (dapm->codec)
-		prefix = dapm->codec->name_prefix;
-	else
-		prefix = NULL;
-
+	prefix = soc_dapm_prefix(dapm);
 	if (prefix)
 		prefix_len = strlen(prefix) + 1;
 	else
@@ -1308,16 +1329,18 @@ static void dapm_seq_check_event(struct snd_soc_card *card,
 static void dapm_seq_run_coalesced(struct snd_soc_card *card,
 				   struct list_head *pending)
 {
+	struct snd_soc_dapm_context *dapm;
 	struct snd_soc_dapm_widget *w;
 	int reg;
 	unsigned int value = 0;
 	unsigned int mask = 0;
 
-	reg = list_first_entry(pending, struct snd_soc_dapm_widget,
-			       power_list)->reg;
+	w = list_first_entry(pending, struct snd_soc_dapm_widget, power_list);
+	reg = w->reg;
+	dapm = w->dapm;
 
 	list_for_each_entry(w, pending, power_list) {
-		WARN_ON(reg != w->reg);
+		WARN_ON(reg != w->reg || dapm != w->dapm);
 		w->power = w->new_power;
 
 		mask |= w->mask << w->shift;
@@ -1326,7 +1349,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card,
 		else
 			value |= w->off_val << w->shift;
 
-		pop_dbg(w->dapm->dev, card->pop_time,
+		pop_dbg(dapm->dev, card->pop_time,
 			"pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
 			w->name, reg, value, mask);
 
@@ -1339,14 +1362,12 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card,
 		/* Any widget will do, they should all be updating the
 		 * same register.
 		 */
-		w = list_first_entry(pending, struct snd_soc_dapm_widget,
-				     power_list);
 
-		pop_dbg(w->dapm->dev, card->pop_time,
+		pop_dbg(dapm->dev, card->pop_time,
 			"pop test : Applying 0x%x/0x%x to %x in %dms\n",
 			value, mask, reg, card->pop_time);
 		pop_wait(card->pop_time);
-		soc_widget_update_bits(w, reg, mask, value);
+		soc_dapm_update_bits(dapm, reg, mask, value);
 	}
 
 	list_for_each_entry(w, pending, power_list) {
@@ -1492,7 +1513,8 @@ static void dapm_widget_update(struct snd_soc_card *card)
 	if (!w)
 		return;
 
-	ret = soc_widget_update_bits(w, update->reg, update->mask, update->val);
+	ret = soc_dapm_update_bits(w->dapm, update->reg, update->mask,
+		update->val);
 	if (ret < 0)
 		dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n",
 			w->name, ret);
@@ -2062,17 +2084,13 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
 
-/* show dapm widget status in sys fs */
-static ssize_t dapm_widget_show(struct device *dev,
-	struct device_attribute *attr, char *buf)
+static ssize_t dapm_widget_show_codec(struct snd_soc_codec *codec, char *buf)
 {
-	struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
-	struct snd_soc_codec *codec =rtd->codec;
 	struct snd_soc_dapm_widget *w;
 	int count = 0;
 	char *state = "not set";
 
-	list_for_each_entry(w, &codec->card->widgets, list) {
+	list_for_each_entry(w, &codec->component.card->widgets, list) {
 		if (w->dapm != &codec->dapm)
 			continue;
 
@@ -2120,6 +2138,21 @@ static ssize_t dapm_widget_show(struct device *dev,
 	return count;
 }
 
+/* show dapm widget status in sys fs */
+static ssize_t dapm_widget_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
+	int i, count = 0;
+
+	for (i = 0; i < rtd->num_codecs; i++) {
+		struct snd_soc_codec *codec = rtd->codec_dais[i]->codec;
+		count += dapm_widget_show_codec(codec, buf + count);
+	}
+
+	return count;
+}
+
 static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
 
 int snd_soc_dapm_sys_add(struct device *dev)
@@ -2371,14 +2404,16 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
 	const char *source;
 	char prefixed_sink[80];
 	char prefixed_source[80];
+	const char *prefix;
 	int ret;
 
-	if (dapm->codec && dapm->codec->name_prefix) {
+	prefix = soc_dapm_prefix(dapm);
+	if (prefix) {
 		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
-			 dapm->codec->name_prefix, route->sink);
+			 prefix, route->sink);
 		sink = prefixed_sink;
 		snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
-			 dapm->codec->name_prefix, route->source);
+			 prefix, route->source);
 		source = prefixed_source;
 	} else {
 		sink = route->sink;
@@ -2439,6 +2474,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
 	const char *source;
 	char prefixed_sink[80];
 	char prefixed_source[80];
+	const char *prefix;
 
 	if (route->control) {
 		dev_err(dapm->dev,
@@ -2446,12 +2482,13 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
 		return -EINVAL;
 	}
 
-	if (dapm->codec && dapm->codec->name_prefix) {
+	prefix = soc_dapm_prefix(dapm);
+	if (prefix) {
 		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
-			 dapm->codec->name_prefix, route->sink);
+			 prefix, route->sink);
 		sink = prefixed_sink;
 		snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
-			 dapm->codec->name_prefix, route->source);
+			 prefix, route->source);
 		source = prefixed_source;
 	} else {
 		sink = route->sink;
@@ -2670,7 +2707,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card)
 
 		/* Read the initial power state from the device */
 		if (w->reg >= 0) {
-			soc_widget_read(w, w->reg, &val);
+			soc_dapm_read(w->dapm, w->reg, &val);
 			val = val >> w->shift;
 			val &= w->mask;
 			if (val == w->on_val)
@@ -2701,8 +2738,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
 int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
+	struct snd_soc_card *card = dapm->card;
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	int reg = mc->reg;
@@ -2711,17 +2748,20 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
 	unsigned int mask = (1 << fls(max)) - 1;
 	unsigned int invert = mc->invert;
 	unsigned int val;
+	int ret = 0;
 
 	if (snd_soc_volsw_is_stereo(mc))
-		dev_warn(codec->dapm.dev,
+		dev_warn(dapm->dev,
 			 "ASoC: Control '%s' is stereo, which is not supported\n",
 			 kcontrol->id.name);
 
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-	if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM)
-		val = (snd_soc_read(codec, reg) >> shift) & mask;
-	else
+	if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) {
+		ret = soc_dapm_read(dapm, reg, &val);
+		val = (val >> shift) & mask;
+	} else {
 		val = dapm_kcontrol_get_value(kcontrol);
+	}
 	mutex_unlock(&card->dapm_mutex);
 
 	if (invert)
@@ -2729,7 +2769,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
 	else
 		ucontrol->value.integer.value[0] = val;
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
 
@@ -2745,8 +2785,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
 int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
+	struct snd_soc_card *card = dapm->card;
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	int reg = mc->reg;
@@ -2760,7 +2800,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
 	int ret = 0;
 
 	if (snd_soc_volsw_is_stereo(mc))
-		dev_warn(codec->dapm.dev,
+		dev_warn(dapm->dev,
 			 "ASoC: Control '%s' is stereo, which is not supported\n",
 			 kcontrol->id.name);
 
@@ -2778,7 +2818,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
 		mask = mask << shift;
 		val = val << shift;
 
-		reg_change = snd_soc_test_bits(codec, reg, mask, val);
+		reg_change = soc_dapm_test_bits(dapm, reg, mask, val);
 	}
 
 	if (change || reg_change) {
@@ -2817,12 +2857,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
 int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
+	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	unsigned int reg_val, val;
+	int ret = 0;
 
 	if (e->reg != SND_SOC_NOPM)
-		reg_val = snd_soc_read(codec, e->reg);
+		ret = soc_dapm_read(dapm, e->reg, &reg_val);
 	else
 		reg_val = dapm_kcontrol_get_value(kcontrol);
 
@@ -2834,7 +2875,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
 		ucontrol->value.enumerated.item[1] = val;
 	}
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
 
@@ -2850,8 +2891,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
 int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
+	struct snd_soc_card *card = dapm->card;
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	unsigned int *item = ucontrol->value.enumerated.item;
 	unsigned int val, change;
@@ -2874,7 +2915,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 
 	if (e->reg != SND_SOC_NOPM)
-		change = snd_soc_test_bits(codec, e->reg, mask, val);
+		change = soc_dapm_test_bits(dapm, e->reg, mask, val);
 	else
 		change = dapm_kcontrol_set_value(kcontrol, val);
 
@@ -2971,6 +3012,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 			 const struct snd_soc_dapm_widget *widget)
 {
 	struct snd_soc_dapm_widget *w;
+	const char *prefix;
 	int ret;
 
 	if ((w = dapm_cnew_widget(widget)) == NULL)
@@ -3011,9 +3053,9 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 		break;
 	}
 
-	if (dapm->codec && dapm->codec->name_prefix)
-		w->name = kasprintf(GFP_KERNEL, "%s %s",
-			dapm->codec->name_prefix, widget->name);
+	prefix = soc_dapm_prefix(dapm);
+	if (prefix)
+		w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, widget->name);
 	else
 		w->name = kasprintf(GFP_KERNEL, "%s", widget->name);
 
@@ -3066,7 +3108,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 
 	w->dapm = dapm;
 	w->codec = dapm->codec;
-	w->platform = dapm->platform;
 	INIT_LIST_HEAD(&w->sources);
 	INIT_LIST_HEAD(&w->sinks);
 	INIT_LIST_HEAD(&w->list);
@@ -3173,27 +3214,15 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		if (source->driver->ops && source->driver->ops->hw_params) {
-			substream.stream = SNDRV_PCM_STREAM_CAPTURE;
-			ret = source->driver->ops->hw_params(&substream,
-							     params, source);
-			if (ret != 0) {
-				dev_err(source->dev,
-					"ASoC: hw_params() failed: %d\n", ret);
-				goto out;
-			}
-		}
+		substream.stream = SNDRV_PCM_STREAM_CAPTURE;
+		ret = soc_dai_hw_params(&substream, params, source);
+		if (ret < 0)
+			goto out;
 
-		if (sink->driver->ops && sink->driver->ops->hw_params) {
-			substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
-			ret = sink->driver->ops->hw_params(&substream, params,
-							   sink);
-			if (ret != 0) {
-				dev_err(sink->dev,
-					"ASoC: hw_params() failed: %d\n", ret);
-				goto out;
-			}
-		}
+		substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
+		ret = soc_dai_hw_params(&substream, params, sink);
+		if (ret < 0)
+			goto out;
 		break;
 
 	case SND_SOC_DAPM_POST_PMU:
@@ -3365,25 +3394,15 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
 	return 0;
 }
 
-void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
+static void dapm_connect_dai_link_widgets(struct snd_soc_card *card,
+					  struct snd_soc_pcm_runtime *rtd)
 {
-	struct snd_soc_pcm_runtime *rtd = card->rtd;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct snd_soc_dapm_widget *sink, *source;
-	struct snd_soc_dai *cpu_dai, *codec_dai;
 	int i;
 
-	/* for each BE DAI link... */
-	for (i = 0; i < card->num_rtd; i++) {
-		rtd = &card->rtd[i];
-		cpu_dai = rtd->cpu_dai;
-		codec_dai = rtd->codec_dai;
-
-		/*
-		 * dynamic FE links have no fixed DAI mapping.
-		 * CODEC<->CODEC links have no direct connection.
-		 */
-		if (rtd->dai_link->dynamic || rtd->dai_link->params)
-			continue;
+	for (i = 0; i < rtd->num_codecs; i++) {
+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
 
 		/* there is no point in connecting BE DAI links with dummies */
 		if (snd_soc_dai_is_dummy(codec_dai) ||
@@ -3395,8 +3414,8 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
 			source = cpu_dai->playback_widget;
 			sink = codec_dai->playback_widget;
 			dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
-				cpu_dai->codec->name, source->name,
-				codec_dai->platform->name, sink->name);
+				cpu_dai->component->name, source->name,
+				codec_dai->component->name, sink->name);
 
 			snd_soc_dapm_add_path(&card->dapm, source, sink,
 				NULL, NULL);
@@ -3407,8 +3426,8 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
 			source = codec_dai->capture_widget;
 			sink = cpu_dai->capture_widget;
 			dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
-				codec_dai->codec->name, source->name,
-				cpu_dai->platform->name, sink->name);
+				codec_dai->component->name, source->name,
+				cpu_dai->component->name, sink->name);
 
 			snd_soc_dapm_add_path(&card->dapm, source, sink,
 				NULL, NULL);
@@ -3445,11 +3464,34 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
 	}
 }
 
+void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
+{
+	struct snd_soc_pcm_runtime *rtd = card->rtd;
+	int i;
+
+	/* for each BE DAI link... */
+	for (i = 0; i < card->num_rtd; i++) {
+		rtd = &card->rtd[i];
+
+		/*
+		 * dynamic FE links have no fixed DAI mapping.
+		 * CODEC<->CODEC links have no direct connection.
+		 */
+		if (rtd->dai_link->dynamic || rtd->dai_link->params)
+			continue;
+
+		dapm_connect_dai_link_widgets(card, rtd);
+	}
+}
+
 static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
 	int event)
 {
+	int i;
+
 	soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event);
-	soc_dapm_dai_stream_event(rtd->codec_dai, stream, event);
+	for (i = 0; i < rtd->num_codecs; i++)
+		soc_dapm_dai_stream_event(rtd->codec_dais[i], stream, event);
 
 	dapm_power_widgets(rtd->card, event);
 }
@@ -3758,36 +3800,31 @@ static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card,
 }
 
 /**
- * snd_soc_dapm_auto_nc_codec_pins - call snd_soc_dapm_nc_pin for unused pins
- * @codec: The codec whose pins should be processed
+ * snd_soc_dapm_auto_nc_pins - call snd_soc_dapm_nc_pin for unused pins
+ * @card: The card whose pins should be processed
  *
- * Automatically call snd_soc_dapm_nc_pin() for any external pins in the codec
- * which are unused. Pins are used if they are connected externally to the
- * codec, whether that be to some other device, or a loop-back connection to
- * the codec itself.
+ * Automatically call snd_soc_dapm_nc_pin() for any external pins in the card
+ * which are unused. Pins are used if they are connected externally to a
+ * component, whether that be to some other device, or a loop-back connection to
+ * the component itself.
  */
-void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec)
+void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card)
 {
-	struct snd_soc_card *card = codec->card;
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	struct snd_soc_dapm_widget *w;
 
-	dev_dbg(codec->dev, "ASoC: Auto NC: DAPMs: card:%p codec:%p\n",
-		&card->dapm, &codec->dapm);
+	dev_dbg(card->dev, "ASoC: Auto NC: DAPMs: card:%p\n", &card->dapm);
 
 	list_for_each_entry(w, &card->widgets, list) {
-		if (w->dapm != dapm)
-			continue;
 		switch (w->id) {
 		case snd_soc_dapm_input:
 		case snd_soc_dapm_output:
 		case snd_soc_dapm_micbias:
-			dev_dbg(codec->dev, "ASoC: Auto NC: Checking widget %s\n",
+			dev_dbg(card->dev, "ASoC: Auto NC: Checking widget %s\n",
 				w->name);
 			if (!snd_soc_dapm_widget_in_card_paths(card, w)) {
-				dev_dbg(codec->dev,
+				dev_dbg(card->dev,
 					"... Not in map; disabling\n");
-				snd_soc_dapm_nc_pin(dapm, w->name);
+				snd_soc_dapm_nc_pin(w->dapm, w->name);
 			}
 			break;
 		default:
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index 5bace124ef43..6307f85e871b 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -119,7 +119,10 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
 	struct snd_dmaengine_dai_dma_data *dma_data;
 	struct dma_slave_caps dma_caps;
 	struct snd_pcm_hardware hw;
-	int ret;
+	u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+			  BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+			  BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+	int i, ret;
 
 	if (pcm->config && pcm->config->pcm_hardware)
 		return snd_soc_set_runtime_hwparams(substream,
@@ -146,6 +149,38 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
 			hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME;
 		if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT)
 			hw.info |= SNDRV_PCM_INFO_BATCH;
+
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			addr_widths = dma_caps.dstn_addr_widths;
+		else
+			addr_widths = dma_caps.src_addr_widths;
+	}
+
+	/*
+	 * Prepare formats mask for valid/allowed sample types. If the dma does
+	 * not have support for the given physical word size, it needs to be
+	 * masked out so user space can not use the format which produces
+	 * corrupted audio.
+	 * In case the dma driver does not implement the slave_caps the default
+	 * assumption is that it supports 1, 2 and 4 bytes widths.
+	 */
+	for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
+		int bits = snd_pcm_format_physical_width(i);
+
+		/* Enable only samples with DMA supported physical widths */
+		switch (bits) {
+		case 8:
+		case 16:
+		case 24:
+		case 32:
+		case 64:
+			if (addr_widths & (1 << (bits / 8)))
+				hw.formats |= (1LL << i);
+			break;
+		default:
+			/* Unsupported types */
+			break;
+		}
 	}
 
 	return snd_soc_set_runtime_hwparams(substream, &hw);
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index d0d98810af91..ab47fea997a3 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -43,7 +43,7 @@ int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
 	INIT_LIST_HEAD(&jack->jack_zones);
 	BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier);
 
-	return snd_jack_new(codec->card->snd_card, id, type, &jack->jack);
+	return snd_jack_new(codec->component.card->snd_card, id, type, &jack->jack);
 }
 EXPORT_SYMBOL_GPL(snd_soc_jack_new);
 
@@ -260,7 +260,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
 static irqreturn_t gpio_handler(int irq, void *data)
 {
 	struct snd_soc_jack_gpio *gpio = data;
-	struct device *dev = gpio->jack->codec->card->dev;
+	struct device *dev = gpio->jack->codec->component.card->dev;
 
 	trace_snd_soc_jack_irq(gpio->name);
 
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 54d18f22a33e..731fdb5b5f9b 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -7,7 +7,7 @@
  * Copyright (C) 2010 Texas Instruments Inc.
  *
  * Authors: Liam Girdwood <lrg@ti.com>
- *          Mark Brown <broonie@opensource.wolfsonmicro.com>       
+ *          Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
@@ -47,22 +47,26 @@
 void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
 {
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int i;
 
 	lockdep_assert_held(&rtd->pcm_mutex);
 
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		cpu_dai->playback_active++;
-		codec_dai->playback_active++;
+		for (i = 0; i < rtd->num_codecs; i++)
+			rtd->codec_dais[i]->playback_active++;
 	} else {
 		cpu_dai->capture_active++;
-		codec_dai->capture_active++;
+		for (i = 0; i < rtd->num_codecs; i++)
+			rtd->codec_dais[i]->capture_active++;
 	}
 
 	cpu_dai->active++;
-	codec_dai->active++;
 	cpu_dai->component->active++;
-	codec_dai->component->active++;
+	for (i = 0; i < rtd->num_codecs; i++) {
+		rtd->codec_dais[i]->active++;
+		rtd->codec_dais[i]->component->active++;
+	}
 }
 
 /**
@@ -78,22 +82,26 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
 void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
 {
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int i;
 
 	lockdep_assert_held(&rtd->pcm_mutex);
 
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		cpu_dai->playback_active--;
-		codec_dai->playback_active--;
+		for (i = 0; i < rtd->num_codecs; i++)
+			rtd->codec_dais[i]->playback_active--;
 	} else {
 		cpu_dai->capture_active--;
-		codec_dai->capture_active--;
+		for (i = 0; i < rtd->num_codecs; i++)
+			rtd->codec_dais[i]->capture_active--;
 	}
 
 	cpu_dai->active--;
-	codec_dai->active--;
 	cpu_dai->component->active--;
-	codec_dai->component->active--;
+	for (i = 0; i < rtd->num_codecs; i++) {
+		rtd->codec_dais[i]->component->active--;
+		rtd->codec_dais[i]->active--;
+	}
 }
 
 /**
@@ -107,11 +115,16 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
  */
 bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd)
 {
+	int i;
+	bool ignore = true;
+
 	if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time)
 		return true;
 
-	return rtd->cpu_dai->component->ignore_pmdown_time &&
-			rtd->codec_dai->component->ignore_pmdown_time;
+	for (i = 0; i < rtd->num_codecs; i++)
+		ignore &= rtd->codec_dais[i]->component->ignore_pmdown_time;
+
+	return rtd->cpu_dai->component->ignore_pmdown_time && ignore;
 }
 
 /**
@@ -222,8 +235,7 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	unsigned int rate, channels, sample_bits, symmetry;
+	unsigned int rate, channels, sample_bits, symmetry, i;
 
 	rate = params_rate(params);
 	channels = params_channels(params);
@@ -231,8 +243,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
 
 	/* reject unmatched parameters when applying symmetry */
 	symmetry = cpu_dai->driver->symmetric_rates ||
-		codec_dai->driver->symmetric_rates ||
 		rtd->dai_link->symmetric_rates;
+
+	for (i = 0; i < rtd->num_codecs; i++)
+		symmetry |= rtd->codec_dais[i]->driver->symmetric_rates;
+
 	if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) {
 		dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n",
 				cpu_dai->rate, rate);
@@ -240,8 +255,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
 	}
 
 	symmetry = cpu_dai->driver->symmetric_channels ||
-		codec_dai->driver->symmetric_channels ||
 		rtd->dai_link->symmetric_channels;
+
+	for (i = 0; i < rtd->num_codecs; i++)
+		symmetry |= rtd->codec_dais[i]->driver->symmetric_channels;
+
 	if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) {
 		dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n",
 				cpu_dai->channels, channels);
@@ -249,8 +267,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
 	}
 
 	symmetry = cpu_dai->driver->symmetric_samplebits ||
-		codec_dai->driver->symmetric_samplebits ||
 		rtd->dai_link->symmetric_samplebits;
+
+	for (i = 0; i < rtd->num_codecs; i++)
+		symmetry |= rtd->codec_dais[i]->driver->symmetric_samplebits;
+
 	if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) {
 		dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n",
 				cpu_dai->sample_bits, sample_bits);
@@ -264,15 +285,20 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver;
-	struct snd_soc_dai_driver *codec_driver = rtd->codec_dai->driver;
 	struct snd_soc_dai_link *link = rtd->dai_link;
+	unsigned int symmetry, i;
 
-	return cpu_driver->symmetric_rates || codec_driver->symmetric_rates ||
-		link->symmetric_rates || cpu_driver->symmetric_channels ||
-		codec_driver->symmetric_channels || link->symmetric_channels ||
-		cpu_driver->symmetric_samplebits ||
-		codec_driver->symmetric_samplebits ||
-		link->symmetric_samplebits;
+	symmetry = cpu_driver->symmetric_rates || link->symmetric_rates ||
+		cpu_driver->symmetric_channels || link->symmetric_channels ||
+		cpu_driver->symmetric_samplebits || link->symmetric_samplebits;
+
+	for (i = 0; i < rtd->num_codecs; i++)
+		symmetry = symmetry ||
+			rtd->codec_dais[i]->driver->symmetric_rates ||
+			rtd->codec_dais[i]->driver->symmetric_channels ||
+			rtd->codec_dais[i]->driver->symmetric_samplebits;
+
+	return symmetry;
 }
 
 /*
@@ -284,15 +310,10 @@ static int sample_sizes[] = {
 	24, 32,
 };
 
-static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
-			      struct snd_soc_dai *dai)
+static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits)
 {
-	int ret, i, bits;
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		bits = dai->driver->playback.sig_bits;
-	else
-		bits = dai->driver->capture.sig_bits;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	int ret, i;
 
 	if (!bits)
 		return;
@@ -304,38 +325,105 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
 		ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0,
 						   sample_sizes[i], bits);
 		if (ret != 0)
-			dev_warn(dai->dev,
+			dev_warn(rtd->dev,
 				 "ASoC: Failed to set MSB %d/%d: %d\n",
 				 bits, sample_sizes[i], ret);
 	}
 }
 
-static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime,
-	struct snd_soc_pcm_stream *codec_stream,
-	struct snd_soc_pcm_stream *cpu_stream)
+static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai;
+	int i;
+	unsigned int bits = 0, cpu_bits;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		for (i = 0; i < rtd->num_codecs; i++) {
+			codec_dai = rtd->codec_dais[i];
+			if (codec_dai->driver->playback.sig_bits == 0) {
+				bits = 0;
+				break;
+			}
+			bits = max(codec_dai->driver->playback.sig_bits, bits);
+		}
+		cpu_bits = cpu_dai->driver->playback.sig_bits;
+	} else {
+		for (i = 0; i < rtd->num_codecs; i++) {
+			codec_dai = rtd->codec_dais[i];
+			if (codec_dai->driver->playback.sig_bits == 0) {
+				bits = 0;
+				break;
+			}
+			bits = max(codec_dai->driver->capture.sig_bits, bits);
+		}
+		cpu_bits = cpu_dai->driver->capture.sig_bits;
+	}
+
+	soc_pcm_set_msb(substream, bits);
+	soc_pcm_set_msb(substream, cpu_bits);
+}
+
+static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
 {
+	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_pcm_hardware *hw = &runtime->hw;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai_driver *cpu_dai_drv = rtd->cpu_dai->driver;
+	struct snd_soc_dai_driver *codec_dai_drv;
+	struct snd_soc_pcm_stream *codec_stream;
+	struct snd_soc_pcm_stream *cpu_stream;
+	unsigned int chan_min = 0, chan_max = UINT_MAX;
+	unsigned int rate_min = 0, rate_max = UINT_MAX;
+	unsigned int rates = UINT_MAX;
+	u64 formats = ULLONG_MAX;
+	int i;
 
-	hw->channels_min = max(codec_stream->channels_min,
-		cpu_stream->channels_min);
-	hw->channels_max = min(codec_stream->channels_max,
-		cpu_stream->channels_max);
-	if (hw->formats)
-		hw->formats &= codec_stream->formats & cpu_stream->formats;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		cpu_stream = &cpu_dai_drv->playback;
 	else
-		hw->formats = codec_stream->formats & cpu_stream->formats;
-	hw->rates = snd_pcm_rate_mask_intersect(codec_stream->rates,
-		cpu_stream->rates);
+		cpu_stream = &cpu_dai_drv->capture;
 
-	hw->rate_min = 0;
-	hw->rate_max = UINT_MAX;
+	/* first calculate min/max only for CODECs in the DAI link */
+	for (i = 0; i < rtd->num_codecs; i++) {
+		codec_dai_drv = rtd->codec_dais[i]->driver;
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			codec_stream = &codec_dai_drv->playback;
+		else
+			codec_stream = &codec_dai_drv->capture;
+		chan_min = max(chan_min, codec_stream->channels_min);
+		chan_max = min(chan_max, codec_stream->channels_max);
+		rate_min = max(rate_min, codec_stream->rate_min);
+		rate_max = min_not_zero(rate_max, codec_stream->rate_max);
+		formats &= codec_stream->formats;
+		rates = snd_pcm_rate_mask_intersect(codec_stream->rates, rates);
+	}
+
+	/*
+	 * chan min/max cannot be enforced if there are multiple CODEC DAIs
+	 * connected to a single CPU DAI, use CPU DAI's directly and let
+	 * channel allocation be fixed up later
+	 */
+	if (rtd->num_codecs > 1) {
+		chan_min = cpu_stream->channels_min;
+		chan_max = cpu_stream->channels_max;
+	}
+
+	hw->channels_min = max(chan_min, cpu_stream->channels_min);
+	hw->channels_max = min(chan_max, cpu_stream->channels_max);
+	if (hw->formats)
+		hw->formats &= formats & cpu_stream->formats;
+	else
+		hw->formats = formats & cpu_stream->formats;
+	hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_stream->rates);
 
 	snd_pcm_limit_hw_rates(runtime);
 
 	hw->rate_min = max(hw->rate_min, cpu_stream->rate_min);
-	hw->rate_min = max(hw->rate_min, codec_stream->rate_min);
+	hw->rate_min = max(hw->rate_min, rate_min);
 	hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max);
-	hw->rate_max = min_not_zero(hw->rate_max, codec_stream->rate_max);
+	hw->rate_max = min_not_zero(hw->rate_max, rate_max);
 }
 
 /*
@@ -349,15 +437,16 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
-	struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
-	int ret = 0;
+	struct snd_soc_dai *codec_dai;
+	const char *codec_dai_name = "multicodec";
+	int i, ret = 0;
 
 	pinctrl_pm_select_default_state(cpu_dai->dev);
-	pinctrl_pm_select_default_state(codec_dai->dev);
+	for (i = 0; i < rtd->num_codecs; i++)
+		pinctrl_pm_select_default_state(rtd->codec_dais[i]->dev);
 	pm_runtime_get_sync(cpu_dai->dev);
-	pm_runtime_get_sync(codec_dai->dev);
+	for (i = 0; i < rtd->num_codecs; i++)
+		pm_runtime_get_sync(rtd->codec_dais[i]->dev);
 	pm_runtime_get_sync(platform->dev);
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
@@ -376,18 +465,28 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 		ret = platform->driver->ops->open(substream);
 		if (ret < 0) {
 			dev_err(platform->dev, "ASoC: can't open platform"
-				" %s: %d\n", platform->name, ret);
+				" %s: %d\n", platform->component.name, ret);
 			goto platform_err;
 		}
 	}
 
-	if (codec_dai->driver->ops && codec_dai->driver->ops->startup) {
-		ret = codec_dai->driver->ops->startup(substream, codec_dai);
-		if (ret < 0) {
-			dev_err(codec_dai->dev, "ASoC: can't open codec"
-				" %s: %d\n", codec_dai->name, ret);
-			goto codec_dai_err;
+	for (i = 0; i < rtd->num_codecs; i++) {
+		codec_dai = rtd->codec_dais[i];
+		if (codec_dai->driver->ops && codec_dai->driver->ops->startup) {
+			ret = codec_dai->driver->ops->startup(substream,
+							      codec_dai);
+			if (ret < 0) {
+				dev_err(codec_dai->dev,
+					"ASoC: can't open codec %s: %d\n",
+					codec_dai->name, ret);
+				goto codec_dai_err;
+			}
 		}
+
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			codec_dai->tx_mask = 0;
+		else
+			codec_dai->rx_mask = 0;
 	}
 
 	if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
@@ -404,13 +503,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 		goto dynamic;
 
 	/* Check that the codec and cpu DAIs are compatible */
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->playback,
-			&cpu_dai_drv->playback);
-	} else {
-		soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->capture,
-			&cpu_dai_drv->capture);
-	}
+	soc_pcm_init_runtime_hw(substream);
+
+	if (rtd->num_codecs == 1)
+		codec_dai_name = rtd->codec_dai->name;
 
 	if (soc_pcm_has_symmetry(substream))
 		runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
@@ -418,23 +514,22 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 	ret = -EINVAL;
 	if (!runtime->hw.rates) {
 		printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n",
-			codec_dai->name, cpu_dai->name);
+			codec_dai_name, cpu_dai->name);
 		goto config_err;
 	}
 	if (!runtime->hw.formats) {
 		printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n",
-			codec_dai->name, cpu_dai->name);
+			codec_dai_name, cpu_dai->name);
 		goto config_err;
 	}
 	if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
 	    runtime->hw.channels_min > runtime->hw.channels_max) {
 		printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n",
-				codec_dai->name, cpu_dai->name);
+				codec_dai_name, cpu_dai->name);
 		goto config_err;
 	}
 
-	soc_pcm_apply_msb(substream, codec_dai);
-	soc_pcm_apply_msb(substream, cpu_dai);
+	soc_pcm_apply_msb(substream);
 
 	/* Symmetry only applies if we've already got an active stream. */
 	if (cpu_dai->active) {
@@ -443,14 +538,17 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 			goto config_err;
 	}
 
-	if (codec_dai->active) {
-		ret = soc_pcm_apply_symmetry(substream, codec_dai);
-		if (ret != 0)
-			goto config_err;
+	for (i = 0; i < rtd->num_codecs; i++) {
+		if (rtd->codec_dais[i]->active) {
+			ret = soc_pcm_apply_symmetry(substream,
+						     rtd->codec_dais[i]);
+			if (ret != 0)
+				goto config_err;
+		}
 	}
 
 	pr_debug("ASoC: %s <-> %s info:\n",
-			codec_dai->name, cpu_dai->name);
+			codec_dai_name, cpu_dai->name);
 	pr_debug("ASoC: rate mask 0x%x\n", runtime->hw.rates);
 	pr_debug("ASoC: min ch %d max ch %d\n", runtime->hw.channels_min,
 		 runtime->hw.channels_max);
@@ -469,10 +567,15 @@ config_err:
 		rtd->dai_link->ops->shutdown(substream);
 
 machine_err:
-	if (codec_dai->driver->ops->shutdown)
-		codec_dai->driver->ops->shutdown(substream, codec_dai);
+	i = rtd->num_codecs;
 
 codec_dai_err:
+	while (--i >= 0) {
+		codec_dai = rtd->codec_dais[i];
+		if (codec_dai->driver->ops->shutdown)
+			codec_dai->driver->ops->shutdown(substream, codec_dai);
+	}
+
 	if (platform->driver->ops && platform->driver->ops->close)
 		platform->driver->ops->close(substream);
 
@@ -483,10 +586,13 @@ out:
 	mutex_unlock(&rtd->pcm_mutex);
 
 	pm_runtime_put(platform->dev);
-	pm_runtime_put(codec_dai->dev);
+	for (i = 0; i < rtd->num_codecs; i++)
+		pm_runtime_put(rtd->codec_dais[i]->dev);
 	pm_runtime_put(cpu_dai->dev);
-	if (!codec_dai->active)
-		pinctrl_pm_select_sleep_state(codec_dai->dev);
+	for (i = 0; i < rtd->num_codecs; i++) {
+		if (!rtd->codec_dais[i]->active)
+			pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev);
+	}
 	if (!cpu_dai->active)
 		pinctrl_pm_select_sleep_state(cpu_dai->dev);
 
@@ -502,7 +608,7 @@ static void close_delayed_work(struct work_struct *work)
 {
 	struct snd_soc_pcm_runtime *rtd =
 			container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dais[0];
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
@@ -531,7 +637,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *codec_dai;
+	int i;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
@@ -541,14 +648,20 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 	if (!cpu_dai->active)
 		cpu_dai->rate = 0;
 
-	if (!codec_dai->active)
-		codec_dai->rate = 0;
+	for (i = 0; i < rtd->num_codecs; i++) {
+		codec_dai = rtd->codec_dais[i];
+		if (!codec_dai->active)
+			codec_dai->rate = 0;
+	}
 
 	if (cpu_dai->driver->ops->shutdown)
 		cpu_dai->driver->ops->shutdown(substream, cpu_dai);
 
-	if (codec_dai->driver->ops->shutdown)
-		codec_dai->driver->ops->shutdown(substream, codec_dai);
+	for (i = 0; i < rtd->num_codecs; i++) {
+		codec_dai = rtd->codec_dais[i];
+		if (codec_dai->driver->ops->shutdown)
+			codec_dai->driver->ops->shutdown(substream, codec_dai);
+	}
 
 	if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
 		rtd->dai_link->ops->shutdown(substream);
@@ -578,10 +691,13 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 	mutex_unlock(&rtd->pcm_mutex);
 
 	pm_runtime_put(platform->dev);
-	pm_runtime_put(codec_dai->dev);
+	for (i = 0; i < rtd->num_codecs; i++)
+		pm_runtime_put(rtd->codec_dais[i]->dev);
 	pm_runtime_put(cpu_dai->dev);
-	if (!codec_dai->active)
-		pinctrl_pm_select_sleep_state(codec_dai->dev);
+	for (i = 0; i < rtd->num_codecs; i++) {
+		if (!rtd->codec_dais[i]->active)
+			pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev);
+	}
 	if (!cpu_dai->active)
 		pinctrl_pm_select_sleep_state(cpu_dai->dev);
 
@@ -598,8 +714,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	int ret = 0;
+	struct snd_soc_dai *codec_dai;
+	int i, ret = 0;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
@@ -621,12 +737,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
 		}
 	}
 
-	if (codec_dai->driver->ops && codec_dai->driver->ops->prepare) {
-		ret = codec_dai->driver->ops->prepare(substream, codec_dai);
-		if (ret < 0) {
-			dev_err(codec_dai->dev, "ASoC: DAI prepare error: %d\n",
-				ret);
-			goto out;
+	for (i = 0; i < rtd->num_codecs; i++) {
+		codec_dai = rtd->codec_dais[i];
+		if (codec_dai->driver->ops && codec_dai->driver->ops->prepare) {
+			ret = codec_dai->driver->ops->prepare(substream,
+							      codec_dai);
+			if (ret < 0) {
+				dev_err(codec_dai->dev,
+					"ASoC: DAI prepare error: %d\n", ret);
+				goto out;
+			}
 		}
 	}
 
@@ -649,13 +769,44 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
 	snd_soc_dapm_stream_event(rtd, substream->stream,
 			SND_SOC_DAPM_STREAM_START);
 
-	snd_soc_dai_digital_mute(codec_dai, 0, substream->stream);
+	for (i = 0; i < rtd->num_codecs; i++)
+		snd_soc_dai_digital_mute(rtd->codec_dais[i], 0,
+					 substream->stream);
 
 out:
 	mutex_unlock(&rtd->pcm_mutex);
 	return ret;
 }
 
+static void soc_pcm_codec_params_fixup(struct snd_pcm_hw_params *params,
+				       unsigned int mask)
+{
+	struct snd_interval *interval;
+	int channels = hweight_long(mask);
+
+	interval = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	interval->min = channels;
+	interval->max = channels;
+}
+
+int soc_dai_hw_params(struct snd_pcm_substream *substream,
+		      struct snd_pcm_hw_params *params,
+		      struct snd_soc_dai *dai)
+{
+	int ret;
+
+	if (dai->driver->ops && dai->driver->ops->hw_params) {
+		ret = dai->driver->ops->hw_params(substream, params, dai);
+		if (ret < 0) {
+			dev_err(dai->dev, "ASoC: can't set %s hw params: %d\n",
+				dai->name, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 /*
  * Called by ALSA when the hardware params are set by application. This
  * function can also be called multiple times and can allocate buffers
@@ -667,8 +818,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	int ret = 0;
+	int i, ret = 0;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
@@ -685,29 +835,40 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 		}
 	}
 
-	if (codec_dai->driver->ops && codec_dai->driver->ops->hw_params) {
-		ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
-		if (ret < 0) {
-			dev_err(codec_dai->dev, "ASoC: can't set %s hw params:"
-				" %d\n", codec_dai->name, ret);
+	for (i = 0; i < rtd->num_codecs; i++) {
+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
+		struct snd_pcm_hw_params codec_params;
+
+		/* copy params for each codec */
+		codec_params = *params;
+
+		/* fixup params based on TDM slot masks */
+		if (codec_dai->tx_mask)
+			soc_pcm_codec_params_fixup(&codec_params,
+						   codec_dai->tx_mask);
+		if (codec_dai->rx_mask)
+			soc_pcm_codec_params_fixup(&codec_params,
+						   codec_dai->rx_mask);
+
+		ret = soc_dai_hw_params(substream, &codec_params, codec_dai);
+		if(ret < 0)
 			goto codec_err;
-		}
-	}
 
-	if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_params) {
-		ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
-		if (ret < 0) {
-			dev_err(cpu_dai->dev, "ASoC: %s hw params failed: %d\n",
-				cpu_dai->name, ret);
-			goto interface_err;
-		}
+		codec_dai->rate = params_rate(&codec_params);
+		codec_dai->channels = params_channels(&codec_params);
+		codec_dai->sample_bits = snd_pcm_format_physical_width(
+						params_format(&codec_params));
 	}
 
+	ret = soc_dai_hw_params(substream, params, cpu_dai);
+	if (ret < 0)
+		goto interface_err;
+
 	if (platform->driver->ops && platform->driver->ops->hw_params) {
 		ret = platform->driver->ops->hw_params(substream, params);
 		if (ret < 0) {
 			dev_err(platform->dev, "ASoC: %s hw params failed: %d\n",
-			       platform->name, ret);
+			       platform->component.name, ret);
 			goto platform_err;
 		}
 	}
@@ -718,11 +879,6 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 	cpu_dai->sample_bits =
 		snd_pcm_format_physical_width(params_format(params));
 
-	codec_dai->rate = params_rate(params);
-	codec_dai->channels = params_channels(params);
-	codec_dai->sample_bits =
-		snd_pcm_format_physical_width(params_format(params));
-
 out:
 	mutex_unlock(&rtd->pcm_mutex);
 	return ret;
@@ -732,10 +888,16 @@ platform_err:
 		cpu_dai->driver->ops->hw_free(substream, cpu_dai);
 
 interface_err:
-	if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
-		codec_dai->driver->ops->hw_free(substream, codec_dai);
+	i = rtd->num_codecs;
 
 codec_err:
+	while (--i >= 0) {
+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
+		if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
+			codec_dai->driver->ops->hw_free(substream, codec_dai);
+		codec_dai->rate = 0;
+	}
+
 	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
 		rtd->dai_link->ops->hw_free(substream);
 
@@ -751,8 +913,9 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *codec_dai;
 	bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+	int i;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
@@ -763,16 +926,22 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
 		cpu_dai->sample_bits = 0;
 	}
 
-	if (codec_dai->active == 1) {
-		codec_dai->rate = 0;
-		codec_dai->channels = 0;
-		codec_dai->sample_bits = 0;
+	for (i = 0; i < rtd->num_codecs; i++) {
+		codec_dai = rtd->codec_dais[i];
+		if (codec_dai->active == 1) {
+			codec_dai->rate = 0;
+			codec_dai->channels = 0;
+			codec_dai->sample_bits = 0;
+		}
 	}
 
 	/* apply codec digital mute */
-	if ((playback && codec_dai->playback_active == 1) ||
-	    (!playback && codec_dai->capture_active == 1))
-		snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
+	for (i = 0; i < rtd->num_codecs; i++) {
+		if ((playback && rtd->codec_dais[i]->playback_active == 1) ||
+		    (!playback && rtd->codec_dais[i]->capture_active == 1))
+			snd_soc_dai_digital_mute(rtd->codec_dais[i], 1,
+						 substream->stream);
+	}
 
 	/* free any machine hw params */
 	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
@@ -783,8 +952,11 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
 		platform->driver->ops->hw_free(substream);
 
 	/* now free hw params for the DAIs  */
-	if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
-		codec_dai->driver->ops->hw_free(substream, codec_dai);
+	for (i = 0; i < rtd->num_codecs; i++) {
+		codec_dai = rtd->codec_dais[i];
+		if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
+			codec_dai->driver->ops->hw_free(substream, codec_dai);
+	}
 
 	if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free)
 		cpu_dai->driver->ops->hw_free(substream, cpu_dai);
@@ -798,13 +970,17 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	int ret;
-
-	if (codec_dai->driver->ops && codec_dai->driver->ops->trigger) {
-		ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
-		if (ret < 0)
-			return ret;
+	struct snd_soc_dai *codec_dai;
+	int i, ret;
+
+	for (i = 0; i < rtd->num_codecs; i++) {
+		codec_dai = rtd->codec_dais[i];
+		if (codec_dai->driver->ops && codec_dai->driver->ops->trigger) {
+			ret = codec_dai->driver->ops->trigger(substream,
+							      cmd, codec_dai);
+			if (ret < 0)
+				return ret;
+		}
 	}
 
 	if (platform->driver->ops && platform->driver->ops->trigger) {
@@ -834,14 +1010,18 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	int ret;
-
-	if (codec_dai->driver->ops &&
-	    codec_dai->driver->ops->bespoke_trigger) {
-		ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai);
-		if (ret < 0)
-			return ret;
+	struct snd_soc_dai *codec_dai;
+	int i, ret;
+
+	for (i = 0; i < rtd->num_codecs; i++) {
+		codec_dai = rtd->codec_dais[i];
+		if (codec_dai->driver->ops &&
+		    codec_dai->driver->ops->bespoke_trigger) {
+			ret = codec_dai->driver->ops->bespoke_trigger(substream,
+								cmd, codec_dai);
+			if (ret < 0)
+				return ret;
+		}
 	}
 
 	if (platform->driver->bespoke_trigger) {
@@ -867,10 +1047,12 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *codec_dai;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	snd_pcm_uframes_t offset = 0;
 	snd_pcm_sframes_t delay = 0;
+	snd_pcm_sframes_t codec_delay = 0;
+	int i;
 
 	if (platform->driver->ops && platform->driver->ops->pointer)
 		offset = platform->driver->ops->pointer(substream);
@@ -878,11 +1060,21 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
 	if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay)
 		delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
 
-	if (codec_dai->driver->ops && codec_dai->driver->ops->delay)
-		delay += codec_dai->driver->ops->delay(substream, codec_dai);
+	for (i = 0; i < rtd->num_codecs; i++) {
+		codec_dai = rtd->codec_dais[i];
+		if (codec_dai->driver->ops && codec_dai->driver->ops->delay)
+			codec_delay = max(codec_delay,
+					codec_dai->driver->ops->delay(substream,
+								    codec_dai));
+	}
+	delay += codec_delay;
 
+	/*
+	 * None of the existing platform drivers implement delay(), so
+	 * for now the codec_dai of first multicodec entry is used
+	 */
 	if (platform->driver->delay)
-		delay += platform->driver->delay(substream, codec_dai);
+		delay += platform->driver->delay(substream, rtd->codec_dais[0]);
 
 	runtime->delay = delay;
 
@@ -985,7 +1177,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
 		struct snd_soc_dapm_widget *widget, int stream)
 {
 	struct snd_soc_pcm_runtime *be;
-	int i;
+	int i, j;
 
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		for (i = 0; i < card->num_links; i++) {
@@ -994,9 +1186,14 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
 			if (!be->dai_link->no_pcm)
 				continue;
 
-			if (be->cpu_dai->playback_widget == widget ||
-				be->codec_dai->playback_widget == widget)
+			if (be->cpu_dai->playback_widget == widget)
 				return be;
+
+			for (j = 0; j < be->num_codecs; j++) {
+				struct snd_soc_dai *dai = be->codec_dais[j];
+				if (dai->playback_widget == widget)
+					return be;
+			}
 		}
 	} else {
 
@@ -1006,9 +1203,14 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
 			if (!be->dai_link->no_pcm)
 				continue;
 
-			if (be->cpu_dai->capture_widget == widget ||
-				be->codec_dai->capture_widget == widget)
+			if (be->cpu_dai->capture_widget == widget)
 				return be;
+
+			for (j = 0; j < be->num_codecs; j++) {
+				struct snd_soc_dai *dai = be->codec_dais[j];
+				if (dai->capture_widget == widget)
+					return be;
+			}
 		}
 	}
 
@@ -1071,6 +1273,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
 
 	/* Destroy any old FE <--> BE connections */
 	list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+		unsigned int i;
 
 		/* is there a valid CPU DAI widget for this BE */
 		widget = dai_get_widget(dpcm->be->cpu_dai, stream);
@@ -1080,11 +1283,14 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
 			continue;
 
 		/* is there a valid CODEC DAI widget for this BE */
-		widget = dai_get_widget(dpcm->be->codec_dai, stream);
+		for (i = 0; i < dpcm->be->num_codecs; i++) {
+			struct snd_soc_dai *dai = dpcm->be->codec_dais[i];
+			widget = dai_get_widget(dai, stream);
 
-		/* prune the BE if it's no longer in our active list */
-		if (widget && widget_in_list(list, widget))
-			continue;
+			/* prune the BE if it's no longer in our active list */
+			if (widget && widget_in_list(list, widget))
+				continue;
+		}
 
 		dev_dbg(fe->dev, "ASoC: pruning %s BE %s for %s\n",
 			stream ? "capture" : "playback",
@@ -2069,6 +2275,7 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card)
 			dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
 		}
 
+		dpcm_path_put(&list);
 capture:
 		/* skip if FE doesn't have capture capability */
 		if (!fe->cpu_dai->driver->capture.channels_min)
@@ -2113,16 +2320,22 @@ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
 	list_for_each_entry(dpcm, clients, list_be) {
 
 		struct snd_soc_pcm_runtime *be = dpcm->be;
-		struct snd_soc_dai *dai = be->codec_dai;
-		struct snd_soc_dai_driver *drv = dai->driver;
+		int i;
 
 		if (be->dai_link->ignore_suspend)
 			continue;
 
-		dev_dbg(be->dev, "ASoC: BE digital mute %s\n", be->dai_link->name);
+		for (i = 0; i < be->num_codecs; i++) {
+			struct snd_soc_dai *dai = be->codec_dais[i];
+			struct snd_soc_dai_driver *drv = dai->driver;
+
+			dev_dbg(be->dev, "ASoC: BE digital mute %s\n",
+					 be->dai_link->name);
 
-		if (drv->ops && drv->ops->digital_mute && dai->playback_active)
-			drv->ops->digital_mute(dai, mute);
+			if (drv->ops && drv->ops->digital_mute &&
+							dai->playback_active)
+				drv->ops->digital_mute(dai, mute);
+		}
 	}
 
 	return 0;
@@ -2187,22 +2400,27 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
 int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 {
 	struct snd_soc_platform *platform = rtd->platform;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct snd_pcm *pcm;
 	char new_name[64];
 	int ret = 0, playback = 0, capture = 0;
+	int i;
 
 	if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
 		playback = rtd->dai_link->dpcm_playback;
 		capture = rtd->dai_link->dpcm_capture;
 	} else {
-		if (codec_dai->driver->playback.channels_min &&
-		    cpu_dai->driver->playback.channels_min)
-			playback = 1;
-		if (codec_dai->driver->capture.channels_min &&
-		    cpu_dai->driver->capture.channels_min)
-			capture = 1;
+		for (i = 0; i < rtd->num_codecs; i++) {
+			codec_dai = rtd->codec_dais[i];
+			if (codec_dai->driver->playback.channels_min)
+				playback = 1;
+			if (codec_dai->driver->capture.channels_min)
+				capture = 1;
+		}
+
+		capture = capture && cpu_dai->driver->capture.channels_min;
+		playback = playback && cpu_dai->driver->playback.channels_min;
 	}
 
 	if (rtd->dai_link->playback_only) {
@@ -2228,7 +2446,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 				rtd->dai_link->stream_name);
 		else
 			snprintf(new_name, sizeof(new_name), "%s %s-%d",
-				rtd->dai_link->stream_name, codec_dai->name, num);
+				rtd->dai_link->stream_name,
+				(rtd->num_codecs > 1) ?
+				"multicodec" : rtd->codec_dai->name, num);
 
 		ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
 			capture, &pcm);
@@ -2301,8 +2521,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 
 	pcm->private_free = platform->driver->pcm_free;
 out:
-	dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", codec_dai->name,
-		cpu_dai->name);
+	dev_info(rtd->card->dev, "%s <-> %s mapping ok\n",
+		 (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name,
+		 cpu_dai->name);
 	return ret;
 }
 
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index 02734bd4f09b..a83aff09dce2 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -41,8 +41,7 @@ static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_codec *codec = codec_dai->codec;
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_card *card = rtd->card;
 	struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card);
 	int srate, mclk;
 	int err;
@@ -105,7 +104,7 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_codec *codec = codec_dai->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
-	struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card);
+	struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(rtd->card);
 
 	snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
 			 &tegra_alc5632_hs_jack);
diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c
index ce73e1f62c4b..b86cd9936ef1 100644
--- a/sound/soc/tegra/tegra_max98090.c
+++ b/sound/soc/tegra/tegra_max98090.c
@@ -49,8 +49,7 @@ static int tegra_max98090_asoc_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_codec *codec = codec_dai->codec;
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_card *card = rtd->card;
 	struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card);
 	int srate, mclk;
 	int err;
@@ -127,7 +126,7 @@ static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_codec *codec = codec_dai->codec;
-	struct tegra_max98090 *machine = snd_soc_card_get_drvdata(codec->card);
+	struct tegra_max98090 *machine = snd_soc_card_get_drvdata(rtd->card);
 
 	if (gpio_is_valid(machine->gpio_hp_det)) {
 		snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE,
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c
index 4feb16a99e02..a6898831fb9f 100644
--- a/sound/soc/tegra/tegra_rt5640.c
+++ b/sound/soc/tegra/tegra_rt5640.c
@@ -51,8 +51,7 @@ static int tegra_rt5640_asoc_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_codec *codec = codec_dai->codec;
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_card *card = rtd->card;
 	struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
 	int srate, mclk;
 	int err;
@@ -110,7 +109,7 @@ static int tegra_rt5640_asoc_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_codec *codec = codec_dai->codec;
-	struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(codec->card);
+	struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(rtd->card);
 
 	snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE,
 			 &tegra_rt5640_hp_jack);
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index 8e774d1a243c..769e28f6642e 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -55,8 +55,7 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_codec *codec = codec_dai->codec;
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_card *card = rtd->card;
 	struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
 	int srate, mclk;
 	int err;
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index 0939661df60b..86e05e938585 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -60,8 +60,7 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_codec *codec = codec_dai->codec;
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_card *card = rtd->card;
 	struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
 	int srate, mclk;
 	int err;
@@ -173,7 +172,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_codec *codec = codec_dai->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_card *card = rtd->card;
 	struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
 
 	if (gpio_is_valid(machine->gpio_hp_det)) {
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
index 734bfcd21148..589d2d9b553a 100644
--- a/sound/soc/tegra/trimslice.c
+++ b/sound/soc/tegra/trimslice.c
@@ -50,8 +50,7 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_codec *codec = codec_dai->codec;
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_card *card = rtd->card;
 	struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card);
 	int srate, mclk;
 	int err;
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index be1b1aa96b7e..b2c3d0d5dca3 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -2534,12 +2534,10 @@ static int snd_dbri_create(struct snd_card *card,
 	dbri->op = op;
 	dbri->irq = irq;
 
-	dbri->dma = dma_alloc_coherent(&op->dev,
-				       sizeof(struct dbri_dma),
-				       &dbri->dma_dvma, GFP_ATOMIC);
+	dbri->dma = dma_zalloc_coherent(&op->dev, sizeof(struct dbri_dma),
+					&dbri->dma_dvma, GFP_ATOMIC);
 	if (!dbri->dma)
 		return -ENOMEM;
-	memset((void *)dbri->dma, 0, sizeof(struct dbri_dma));
 
 	dprintk(D_GEN, "DMA Cmd Block 0x%p (0x%08x)\n",
 		dbri->dma, dbri->dma_dvma);
diff --git a/sound/usb/card.c b/sound/usb/card.c
index a09e5f3519e3..7ecd0e8a5c51 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -680,6 +680,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 	struct snd_usb_audio *chip = usb_get_intfdata(intf);
 	struct snd_usb_stream *as;
 	struct usb_mixer_interface *mixer;
+	struct list_head *p;
 
 	if (chip == (void *)-1L)
 		return 0;
@@ -692,6 +693,9 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 				as->substream[0].need_setup_ep =
 					as->substream[1].need_setup_ep = true;
 			}
+			list_for_each(p, &chip->midi_list) {
+				snd_usbmidi_suspend(p);
+			}
 		}
 	} else {
 		/*
@@ -713,6 +717,7 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
 {
 	struct snd_usb_audio *chip = usb_get_intfdata(intf);
 	struct usb_mixer_interface *mixer;
+	struct list_head *p;
 	int err = 0;
 
 	if (chip == (void *)-1L)
@@ -731,6 +736,10 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
 			goto err_out;
 	}
 
+	list_for_each(p, &chip->midi_list) {
+		snd_usbmidi_resume(p);
+	}
+
 	if (!chip->autosuspended)
 		snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
 	chip->autosuspended = 0;
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 9da74d2e8eee..7b166c2be0f7 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -102,8 +102,8 @@ struct usb_protocol_ops {
 	void (*input)(struct snd_usb_midi_in_endpoint*, uint8_t*, int);
 	void (*output)(struct snd_usb_midi_out_endpoint *ep, struct urb *urb);
 	void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t);
-	void (*init_out_endpoint)(struct snd_usb_midi_out_endpoint*);
-	void (*finish_out_endpoint)(struct snd_usb_midi_out_endpoint*);
+	void (*init_out_endpoint)(struct snd_usb_midi_out_endpoint *);
+	void (*finish_out_endpoint)(struct snd_usb_midi_out_endpoint *);
 };
 
 struct snd_usb_midi {
@@ -112,7 +112,7 @@ struct snd_usb_midi {
 	struct usb_interface *iface;
 	const struct snd_usb_audio_quirk *quirk;
 	struct snd_rawmidi *rmidi;
-	struct usb_protocol_ops* usb_protocol_ops;
+	struct usb_protocol_ops *usb_protocol_ops;
 	struct list_head list;
 	struct timer_list error_timer;
 	spinlock_t disc_lock;
@@ -134,7 +134,7 @@ struct snd_usb_midi {
 };
 
 struct snd_usb_midi_out_endpoint {
-	struct snd_usb_midi* umidi;
+	struct snd_usb_midi *umidi;
 	struct out_urb_context {
 		struct urb *urb;
 		struct snd_usb_midi_out_endpoint *ep;
@@ -147,7 +147,7 @@ struct snd_usb_midi_out_endpoint {
 	spinlock_t buffer_lock;
 
 	struct usbmidi_out_port {
-		struct snd_usb_midi_out_endpoint* ep;
+		struct snd_usb_midi_out_endpoint *ep;
 		struct snd_rawmidi_substream *substream;
 		int active;
 		uint8_t cable;		/* cable number << 4 */
@@ -167,8 +167,8 @@ struct snd_usb_midi_out_endpoint {
 };
 
 struct snd_usb_midi_in_endpoint {
-	struct snd_usb_midi* umidi;
-	struct urb* urbs[INPUT_URBS];
+	struct snd_usb_midi *umidi;
+	struct urb *urbs[INPUT_URBS];
 	struct usbmidi_in_port {
 		struct snd_rawmidi_substream *substream;
 		u8 running_status_length;
@@ -178,7 +178,7 @@ struct snd_usb_midi_in_endpoint {
 	int current_port;
 };
 
-static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep);
+static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint *ep);
 
 static const uint8_t snd_usbmidi_cin_length[] = {
 	0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1
@@ -187,7 +187,7 @@ static const uint8_t snd_usbmidi_cin_length[] = {
 /*
  * Submits the URB, with error handling.
  */
-static int snd_usbmidi_submit_urb(struct urb* urb, gfp_t flags)
+static int snd_usbmidi_submit_urb(struct urb *urb, gfp_t flags)
 {
 	int err = usb_submit_urb(urb, flags);
 	if (err < 0 && err != -ENODEV)
@@ -221,10 +221,10 @@ static int snd_usbmidi_urb_error(const struct urb *urb)
 /*
  * Receives a chunk of MIDI data.
  */
-static void snd_usbmidi_input_data(struct snd_usb_midi_in_endpoint* ep, int portidx,
-				   uint8_t* data, int length)
+static void snd_usbmidi_input_data(struct snd_usb_midi_in_endpoint *ep,
+				   int portidx, uint8_t *data, int length)
 {
-	struct usbmidi_in_port* port = &ep->ports[portidx];
+	struct usbmidi_in_port *port = &ep->ports[portidx];
 
 	if (!port->substream) {
 		dev_dbg(&ep->umidi->dev->dev, "unexpected port %d!\n", portidx);
@@ -250,9 +250,9 @@ static void dump_urb(const char *type, const u8 *data, int length)
 /*
  * Processes the data read from the device.
  */
-static void snd_usbmidi_in_urb_complete(struct urb* urb)
+static void snd_usbmidi_in_urb_complete(struct urb *urb)
 {
-	struct snd_usb_midi_in_endpoint* ep = urb->context;
+	struct snd_usb_midi_in_endpoint *ep = urb->context;
 
 	if (urb->status == 0) {
 		dump_urb("received", urb->transfer_buffer, urb->actual_length);
@@ -274,10 +274,10 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb)
 	snd_usbmidi_submit_urb(urb, GFP_ATOMIC);
 }
 
-static void snd_usbmidi_out_urb_complete(struct urb* urb)
+static void snd_usbmidi_out_urb_complete(struct urb *urb)
 {
 	struct out_urb_context *context = urb->context;
-	struct snd_usb_midi_out_endpoint* ep = context->ep;
+	struct snd_usb_midi_out_endpoint *ep = context->ep;
 	unsigned int urb_index;
 
 	spin_lock(&ep->buffer_lock);
@@ -304,10 +304,10 @@ static void snd_usbmidi_out_urb_complete(struct urb* urb)
  * This is called when some data should be transferred to the device
  * (from one or more substreams).
  */
-static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep)
+static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint *ep)
 {
 	unsigned int urb_index;
-	struct urb* urb;
+	struct urb *urb;
 	unsigned long flags;
 
 	spin_lock_irqsave(&ep->buffer_lock, flags);
@@ -343,7 +343,8 @@ static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep)
 
 static void snd_usbmidi_out_tasklet(unsigned long data)
 {
-	struct snd_usb_midi_out_endpoint* ep = (struct snd_usb_midi_out_endpoint *) data;
+	struct snd_usb_midi_out_endpoint *ep =
+		(struct snd_usb_midi_out_endpoint *) data;
 
 	snd_usbmidi_do_output(ep);
 }
@@ -375,7 +376,7 @@ static void snd_usbmidi_error_timer(unsigned long data)
 }
 
 /* helper function to send static data that may not DMA-able */
-static int send_bulk_static_data(struct snd_usb_midi_out_endpoint* ep,
+static int send_bulk_static_data(struct snd_usb_midi_out_endpoint *ep,
 				 const void *data, int len)
 {
 	int err = 0;
@@ -396,8 +397,8 @@ static int send_bulk_static_data(struct snd_usb_midi_out_endpoint* ep,
  * fourth byte in each packet, and uses length instead of CIN.
  */
 
-static void snd_usbmidi_standard_input(struct snd_usb_midi_in_endpoint* ep,
-				       uint8_t* buffer, int buffer_length)
+static void snd_usbmidi_standard_input(struct snd_usb_midi_in_endpoint *ep,
+				       uint8_t *buffer, int buffer_length)
 {
 	int i;
 
@@ -405,12 +406,13 @@ static void snd_usbmidi_standard_input(struct snd_usb_midi_in_endpoint* ep,
 		if (buffer[i] != 0) {
 			int cable = buffer[i] >> 4;
 			int length = snd_usbmidi_cin_length[buffer[i] & 0x0f];
-			snd_usbmidi_input_data(ep, cable, &buffer[i + 1], length);
+			snd_usbmidi_input_data(ep, cable, &buffer[i + 1],
+					       length);
 		}
 }
 
-static void snd_usbmidi_midiman_input(struct snd_usb_midi_in_endpoint* ep,
-				      uint8_t* buffer, int buffer_length)
+static void snd_usbmidi_midiman_input(struct snd_usb_midi_in_endpoint *ep,
+				      uint8_t *buffer, int buffer_length)
 {
 	int i;
 
@@ -427,8 +429,8 @@ static void snd_usbmidi_midiman_input(struct snd_usb_midi_in_endpoint* ep,
  * the data bytes but not the status byte and that is marked with CIN 4.
  */
 static void snd_usbmidi_maudio_broken_running_status_input(
-					struct snd_usb_midi_in_endpoint* ep,
-					uint8_t* buffer, int buffer_length)
+					struct snd_usb_midi_in_endpoint *ep,
+					uint8_t *buffer, int buffer_length)
 {
 	int i;
 
@@ -458,7 +460,8 @@ static void snd_usbmidi_maudio_broken_running_status_input(
 				 * doesn't use this format.)
 				 */
 				port->running_status_length = 0;
-			snd_usbmidi_input_data(ep, cable, &buffer[i + 1], length);
+			snd_usbmidi_input_data(ep, cable, &buffer[i + 1],
+					       length);
 		}
 }
 
@@ -479,11 +482,13 @@ static void snd_usbmidi_cme_input(struct snd_usb_midi_in_endpoint *ep,
 /*
  * Adds one USB MIDI packet to the output buffer.
  */
-static void snd_usbmidi_output_standard_packet(struct urb* urb, uint8_t p0,
-					       uint8_t p1, uint8_t p2, uint8_t p3)
+static void snd_usbmidi_output_standard_packet(struct urb *urb, uint8_t p0,
+					       uint8_t p1, uint8_t p2,
+					       uint8_t p3)
 {
 
-	uint8_t* buf = (uint8_t*)urb->transfer_buffer + urb->transfer_buffer_length;
+	uint8_t *buf =
+		(uint8_t *)urb->transfer_buffer + urb->transfer_buffer_length;
 	buf[0] = p0;
 	buf[1] = p1;
 	buf[2] = p2;
@@ -494,11 +499,13 @@ static void snd_usbmidi_output_standard_packet(struct urb* urb, uint8_t p0,
 /*
  * Adds one Midiman packet to the output buffer.
  */
-static void snd_usbmidi_output_midiman_packet(struct urb* urb, uint8_t p0,
-					      uint8_t p1, uint8_t p2, uint8_t p3)
+static void snd_usbmidi_output_midiman_packet(struct urb *urb, uint8_t p0,
+					      uint8_t p1, uint8_t p2,
+					      uint8_t p3)
 {
 
-	uint8_t* buf = (uint8_t*)urb->transfer_buffer + urb->transfer_buffer_length;
+	uint8_t *buf =
+		(uint8_t *)urb->transfer_buffer + urb->transfer_buffer_length;
 	buf[0] = p1;
 	buf[1] = p2;
 	buf[2] = p3;
@@ -509,8 +516,8 @@ static void snd_usbmidi_output_midiman_packet(struct urb* urb, uint8_t p0,
 /*
  * Converts MIDI commands to USB MIDI packets.
  */
-static void snd_usbmidi_transmit_byte(struct usbmidi_out_port* port,
-				      uint8_t b, struct urb* urb)
+static void snd_usbmidi_transmit_byte(struct usbmidi_out_port *port,
+				      uint8_t b, struct urb *urb)
 {
 	uint8_t p0 = port->cable;
 	void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t) =
@@ -547,10 +554,12 @@ static void snd_usbmidi_transmit_byte(struct usbmidi_out_port* port,
 				output_packet(urb, p0 | 0x05, 0xf7, 0, 0);
 				break;
 			case STATE_SYSEX_1:
-				output_packet(urb, p0 | 0x06, port->data[0], 0xf7, 0);
+				output_packet(urb, p0 | 0x06, port->data[0],
+					      0xf7, 0);
 				break;
 			case STATE_SYSEX_2:
-				output_packet(urb, p0 | 0x07, port->data[0], port->data[1], 0xf7);
+				output_packet(urb, p0 | 0x07, port->data[0],
+					      port->data[1], 0xf7);
 				break;
 			}
 			port->state = STATE_UNKNOWN;
@@ -596,21 +605,22 @@ static void snd_usbmidi_transmit_byte(struct usbmidi_out_port* port,
 			port->state = STATE_SYSEX_2;
 			break;
 		case STATE_SYSEX_2:
-			output_packet(urb, p0 | 0x04, port->data[0], port->data[1], b);
+			output_packet(urb, p0 | 0x04, port->data[0],
+				      port->data[1], b);
 			port->state = STATE_SYSEX_0;
 			break;
 		}
 	}
 }
 
-static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint* ep,
+static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint *ep,
 					struct urb *urb)
 {
 	int p;
 
 	/* FIXME: lower-numbered ports can starve higher-numbered ports */
 	for (p = 0; p < 0x10; ++p) {
-		struct usbmidi_out_port* port = &ep->ports[p];
+		struct usbmidi_out_port *port = &ep->ports[p];
 		if (!port->active)
 			continue;
 		while (urb->transfer_buffer_length + 3 < ep->max_transfer) {
@@ -753,18 +763,18 @@ static struct usb_protocol_ops snd_usbmidi_akai_ops = {
  * at the third byte.
  */
 
-static void snd_usbmidi_novation_input(struct snd_usb_midi_in_endpoint* ep,
-				       uint8_t* buffer, int buffer_length)
+static void snd_usbmidi_novation_input(struct snd_usb_midi_in_endpoint *ep,
+				       uint8_t *buffer, int buffer_length)
 {
 	if (buffer_length < 2 || !buffer[0] || buffer_length < buffer[0] + 1)
 		return;
 	snd_usbmidi_input_data(ep, 0, &buffer[2], buffer[0] - 1);
 }
 
-static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint* ep,
+static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint *ep,
 					struct urb *urb)
 {
-	uint8_t* transfer_buffer;
+	uint8_t *transfer_buffer;
 	int count;
 
 	if (!ep->ports[0].active)
@@ -791,13 +801,13 @@ static struct usb_protocol_ops snd_usbmidi_novation_ops = {
  * "raw" protocol: just move raw MIDI bytes from/to the endpoint
  */
 
-static void snd_usbmidi_raw_input(struct snd_usb_midi_in_endpoint* ep,
-				  uint8_t* buffer, int buffer_length)
+static void snd_usbmidi_raw_input(struct snd_usb_midi_in_endpoint *ep,
+				  uint8_t *buffer, int buffer_length)
 {
 	snd_usbmidi_input_data(ep, 0, buffer, buffer_length);
 }
 
-static void snd_usbmidi_raw_output(struct snd_usb_midi_out_endpoint* ep,
+static void snd_usbmidi_raw_output(struct snd_usb_midi_out_endpoint *ep,
 				   struct urb *urb)
 {
 	int count;
@@ -823,8 +833,8 @@ static struct usb_protocol_ops snd_usbmidi_raw_ops = {
  * FTDI protocol: raw MIDI bytes, but input packets have two modem status bytes.
  */
 
-static void snd_usbmidi_ftdi_input(struct snd_usb_midi_in_endpoint* ep,
-				   uint8_t* buffer, int buffer_length)
+static void snd_usbmidi_ftdi_input(struct snd_usb_midi_in_endpoint *ep,
+				   uint8_t *buffer, int buffer_length)
 {
 	if (buffer_length > 2)
 		snd_usbmidi_input_data(ep, 0, buffer + 2, buffer_length - 2);
@@ -883,7 +893,7 @@ static struct usb_protocol_ops snd_usbmidi_122l_ops = {
  * Emagic USB MIDI protocol: raw MIDI with "F5 xx" port switching.
  */
 
-static void snd_usbmidi_emagic_init_out(struct snd_usb_midi_out_endpoint* ep)
+static void snd_usbmidi_emagic_init_out(struct snd_usb_midi_out_endpoint *ep)
 {
 	static const u8 init_data[] = {
 		/* initialization magic: "get version" */
@@ -900,7 +910,7 @@ static void snd_usbmidi_emagic_init_out(struct snd_usb_midi_out_endpoint* ep)
 	send_bulk_static_data(ep, init_data, sizeof(init_data));
 }
 
-static void snd_usbmidi_emagic_finish_out(struct snd_usb_midi_out_endpoint* ep)
+static void snd_usbmidi_emagic_finish_out(struct snd_usb_midi_out_endpoint *ep)
 {
 	static const u8 finish_data[] = {
 		/* switch to patch mode with last preset */
@@ -916,8 +926,8 @@ static void snd_usbmidi_emagic_finish_out(struct snd_usb_midi_out_endpoint* ep)
 	send_bulk_static_data(ep, finish_data, sizeof(finish_data));
 }
 
-static void snd_usbmidi_emagic_input(struct snd_usb_midi_in_endpoint* ep,
-				     uint8_t* buffer, int buffer_length)
+static void snd_usbmidi_emagic_input(struct snd_usb_midi_in_endpoint *ep,
+				     uint8_t *buffer, int buffer_length)
 {
 	int i;
 
@@ -960,18 +970,18 @@ static void snd_usbmidi_emagic_input(struct snd_usb_midi_in_endpoint* ep,
 	}
 }
 
-static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint* ep,
+static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint *ep,
 				      struct urb *urb)
 {
 	int port0 = ep->current_port;
-	uint8_t* buf = urb->transfer_buffer;
+	uint8_t *buf = urb->transfer_buffer;
 	int buf_free = ep->max_transfer;
 	int length, i;
 
 	for (i = 0; i < 0x10; ++i) {
 		/* round-robin, starting at the last current port */
 		int portnum = (port0 + i) & 15;
-		struct usbmidi_out_port* port = &ep->ports[portnum];
+		struct usbmidi_out_port *port = &ep->ports[portnum];
 
 		if (!port->active)
 			continue;
@@ -1015,7 +1025,7 @@ static struct usb_protocol_ops snd_usbmidi_emagic_ops = {
 };
 
 
-static void update_roland_altsetting(struct snd_usb_midi* umidi)
+static void update_roland_altsetting(struct snd_usb_midi *umidi)
 {
 	struct usb_interface *intf;
 	struct usb_host_interface *hostif;
@@ -1037,7 +1047,7 @@ static void update_roland_altsetting(struct snd_usb_midi* umidi)
 static int substream_open(struct snd_rawmidi_substream *substream, int dir,
 			  int open)
 {
-	struct snd_usb_midi* umidi = substream->rmidi->private_data;
+	struct snd_usb_midi *umidi = substream->rmidi->private_data;
 	struct snd_kcontrol *ctl;
 
 	down_read(&umidi->disc_rwsem);
@@ -1051,7 +1061,8 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir,
 		if (!umidi->opened[0] && !umidi->opened[1]) {
 			if (umidi->roland_load_ctl) {
 				ctl = umidi->roland_load_ctl;
-				ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+				ctl->vd[0].access |=
+					SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 				snd_ctl_notify(umidi->card,
 				       SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
 				update_roland_altsetting(umidi);
@@ -1067,7 +1078,8 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir,
 		if (!umidi->opened[0] && !umidi->opened[1]) {
 			if (umidi->roland_load_ctl) {
 				ctl = umidi->roland_load_ctl;
-				ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+				ctl->vd[0].access &=
+					~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 				snd_ctl_notify(umidi->card,
 				       SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
 			}
@@ -1080,8 +1092,8 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir,
 
 static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
 {
-	struct snd_usb_midi* umidi = substream->rmidi->private_data;
-	struct usbmidi_out_port* port = NULL;
+	struct snd_usb_midi *umidi = substream->rmidi->private_data;
+	struct usbmidi_out_port *port = NULL;
 	int i, j;
 
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
@@ -1106,9 +1118,11 @@ static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
 	return substream_open(substream, 0, 0);
 }
 
-static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream, int up)
+static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream,
+				       int up)
 {
-	struct usbmidi_out_port* port = (struct usbmidi_out_port*)substream->runtime->private_data;
+	struct usbmidi_out_port *port =
+		(struct usbmidi_out_port *)substream->runtime->private_data;
 
 	port->active = up;
 	if (up) {
@@ -1125,7 +1139,7 @@ static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream,
 
 static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream)
 {
-	struct usbmidi_out_port* port = substream->runtime->private_data;
+	struct usbmidi_out_port *port = substream->runtime->private_data;
 	struct snd_usb_midi_out_endpoint *ep = port->ep;
 	unsigned int drain_urbs;
 	DEFINE_WAIT(wait);
@@ -1164,9 +1178,10 @@ static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream)
 	return substream_open(substream, 1, 0);
 }
 
-static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)
+static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream,
+				      int up)
 {
-	struct snd_usb_midi* umidi = substream->rmidi->private_data;
+	struct snd_usb_midi *umidi = substream->rmidi->private_data;
 
 	if (up)
 		set_bit(substream->number, &umidi->input_triggered);
@@ -1199,7 +1214,7 @@ static void free_urb_and_buffer(struct snd_usb_midi *umidi, struct urb *urb,
  * Frees an input endpoint.
  * May be called when ep hasn't been initialized completely.
  */
-static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep)
+static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint *ep)
 {
 	unsigned int i;
 
@@ -1213,12 +1228,12 @@ static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep)
 /*
  * Creates an input endpoint.
  */
-static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi,
-					  struct snd_usb_midi_endpoint_info* ep_info,
-					  struct snd_usb_midi_endpoint* rep)
+static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
+					  struct snd_usb_midi_endpoint_info *ep_info,
+					  struct snd_usb_midi_endpoint *rep)
 {
-	struct snd_usb_midi_in_endpoint* ep;
-	void* buffer;
+	struct snd_usb_midi_in_endpoint *ep;
+	void *buffer;
 	unsigned int pipe;
 	int length;
 	unsigned int i;
@@ -1289,14 +1304,14 @@ static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint *ep
 /*
  * Creates an output endpoint, and initializes output ports.
  */
-static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
-					   struct snd_usb_midi_endpoint_info* ep_info,
-					   struct snd_usb_midi_endpoint* rep)
+static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
+					   struct snd_usb_midi_endpoint_info *ep_info,
+					   struct snd_usb_midi_endpoint *rep)
 {
-	struct snd_usb_midi_out_endpoint* ep;
+	struct snd_usb_midi_out_endpoint *ep;
 	unsigned int i;
 	unsigned int pipe;
-	void* buffer;
+	void *buffer;
 
 	rep->out = NULL;
 	ep = kzalloc(sizeof(*ep), GFP_KERNEL);
@@ -1381,12 +1396,12 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
 /*
  * Frees everything.
  */
-static void snd_usbmidi_free(struct snd_usb_midi* umidi)
+static void snd_usbmidi_free(struct snd_usb_midi *umidi)
 {
 	int i;
 
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
-		struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
+		struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i];
 		if (ep->out)
 			snd_usbmidi_out_endpoint_delete(ep->out);
 		if (ep->in)
@@ -1399,9 +1414,9 @@ static void snd_usbmidi_free(struct snd_usb_midi* umidi)
 /*
  * Unlinks all URBs (must be done before the usb_device is deleted).
  */
-void snd_usbmidi_disconnect(struct list_head* p)
+void snd_usbmidi_disconnect(struct list_head *p)
 {
-	struct snd_usb_midi* umidi;
+	struct snd_usb_midi *umidi;
 	unsigned int i, j;
 
 	umidi = list_entry(p, struct snd_usb_midi, list);
@@ -1417,7 +1432,7 @@ void snd_usbmidi_disconnect(struct list_head* p)
 	up_write(&umidi->disc_rwsem);
 
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
-		struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
+		struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i];
 		if (ep->out)
 			tasklet_kill(&ep->out->tasklet);
 		if (ep->out) {
@@ -1448,16 +1463,18 @@ EXPORT_SYMBOL(snd_usbmidi_disconnect);
 
 static void snd_usbmidi_rawmidi_free(struct snd_rawmidi *rmidi)
 {
-	struct snd_usb_midi* umidi = rmidi->private_data;
+	struct snd_usb_midi *umidi = rmidi->private_data;
 	snd_usbmidi_free(umidi);
 }
 
-static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi* umidi,
-								int stream, int number)
+static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi *umidi,
+								int stream,
+								int number)
 {
 	struct snd_rawmidi_substream *substream;
 
-	list_for_each_entry(substream, &umidi->rmidi->streams[stream].substreams, list) {
+	list_for_each_entry(substream, &umidi->rmidi->streams[stream].substreams,
+			    list) {
 		if (substream->number == number)
 			return substream;
 	}
@@ -1633,7 +1650,7 @@ static struct port_info {
 		SNDRV_SEQ_PORT_TYPE_SYNTHESIZER),
 };
 
-static struct port_info *find_port_info(struct snd_usb_midi* umidi, int number)
+static struct port_info *find_port_info(struct snd_usb_midi *umidi, int number)
 {
 	int i;
 
@@ -1659,16 +1676,18 @@ static void snd_usbmidi_get_port_info(struct snd_rawmidi *rmidi, int number,
 	}
 }
 
-static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi,
+static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi,
 				       int stream, int number,
-				       struct snd_rawmidi_substream ** rsubstream)
+				       struct snd_rawmidi_substream **rsubstream)
 {
 	struct port_info *port_info;
 	const char *name_format;
 
-	struct snd_rawmidi_substream *substream = snd_usbmidi_find_substream(umidi, stream, number);
+	struct snd_rawmidi_substream *substream =
+		snd_usbmidi_find_substream(umidi, stream, number);
 	if (!substream) {
-		dev_err(&umidi->dev->dev, "substream %d:%d not found\n", stream, number);
+		dev_err(&umidi->dev->dev, "substream %d:%d not found\n", stream,
+			number);
 		return;
 	}
 
@@ -1684,21 +1703,23 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi,
 /*
  * Creates the endpoints and their ports.
  */
-static int snd_usbmidi_create_endpoints(struct snd_usb_midi* umidi,
-					struct snd_usb_midi_endpoint_info* endpoints)
+static int snd_usbmidi_create_endpoints(struct snd_usb_midi *umidi,
+					struct snd_usb_midi_endpoint_info *endpoints)
 {
 	int i, j, err;
 	int out_ports = 0, in_ports = 0;
 
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
 		if (endpoints[i].out_cables) {
-			err = snd_usbmidi_out_endpoint_create(umidi, &endpoints[i],
+			err = snd_usbmidi_out_endpoint_create(umidi,
+							      &endpoints[i],
 							      &umidi->endpoints[i]);
 			if (err < 0)
 				return err;
 		}
 		if (endpoints[i].in_cables) {
-			err = snd_usbmidi_in_endpoint_create(umidi, &endpoints[i],
+			err = snd_usbmidi_in_endpoint_create(umidi,
+							     &endpoints[i],
 							     &umidi->endpoints[i]);
 			if (err < 0)
 				return err;
@@ -1706,12 +1727,16 @@ static int snd_usbmidi_create_endpoints(struct snd_usb_midi* umidi,
 
 		for (j = 0; j < 0x10; ++j) {
 			if (endpoints[i].out_cables & (1 << j)) {
-				snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_OUTPUT, out_ports,
+				snd_usbmidi_init_substream(umidi,
+							   SNDRV_RAWMIDI_STREAM_OUTPUT,
+							   out_ports,
 							   &umidi->endpoints[i].out->ports[j].substream);
 				++out_ports;
 			}
 			if (endpoints[i].in_cables & (1 << j)) {
-				snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_INPUT, in_ports,
+				snd_usbmidi_init_substream(umidi,
+							   SNDRV_RAWMIDI_STREAM_INPUT,
+							   in_ports,
 							   &umidi->endpoints[i].in->ports[j].substream);
 				++in_ports;
 			}
@@ -1725,16 +1750,16 @@ static int snd_usbmidi_create_endpoints(struct snd_usb_midi* umidi,
 /*
  * Returns MIDIStreaming device capabilities.
  */
-static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
-			   	   struct snd_usb_midi_endpoint_info* endpoints)
+static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi,
+				   struct snd_usb_midi_endpoint_info *endpoints)
 {
-	struct usb_interface* intf;
+	struct usb_interface *intf;
 	struct usb_host_interface *hostif;
-	struct usb_interface_descriptor* intfd;
-	struct usb_ms_header_descriptor* ms_header;
+	struct usb_interface_descriptor *intfd;
+	struct usb_ms_header_descriptor *ms_header;
 	struct usb_host_endpoint *hostep;
-	struct usb_endpoint_descriptor* ep;
-	struct usb_ms_endpoint_descriptor* ms_ep;
+	struct usb_endpoint_descriptor *ep;
+	struct usb_ms_endpoint_descriptor *ms_ep;
 	int i, epidx;
 
 	intf = umidi->iface;
@@ -1742,7 +1767,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
 		return -ENXIO;
 	hostif = &intf->altsetting[0];
 	intfd = get_iface_desc(hostif);
-	ms_header = (struct usb_ms_header_descriptor*)hostif->extra;
+	ms_header = (struct usb_ms_header_descriptor *)hostif->extra;
 	if (hostif->extralen >= 7 &&
 	    ms_header->bLength >= 7 &&
 	    ms_header->bDescriptorType == USB_DT_CS_INTERFACE &&
@@ -1759,7 +1784,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
 		ep = get_ep_desc(hostep);
 		if (!usb_endpoint_xfer_bulk(ep) && !usb_endpoint_xfer_int(ep))
 			continue;
-		ms_ep = (struct usb_ms_endpoint_descriptor*)hostep->extra;
+		ms_ep = (struct usb_ms_endpoint_descriptor *)hostep->extra;
 		if (hostep->extralen < 4 ||
 		    ms_ep->bLength < 4 ||
 		    ms_ep->bDescriptorType != USB_DT_CS_ENDPOINT ||
@@ -1783,9 +1808,10 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
 				 * ESI MIDI Mate that try to use them anyway.
 				 */
 				endpoints[epidx].out_interval = 1;
-			endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
+			endpoints[epidx].out_cables =
+				(1 << ms_ep->bNumEmbMIDIJack) - 1;
 			dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n",
-				    ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
+				ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
 		} else {
 			if (endpoints[epidx].in_ep) {
 				if (++epidx >= MIDI_MAX_ENDPOINTS) {
@@ -1799,9 +1825,10 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
 				endpoints[epidx].in_interval = ep->bInterval;
 			else if (snd_usb_get_speed(umidi->dev) == USB_SPEED_LOW)
 				endpoints[epidx].in_interval = 1;
-			endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
+			endpoints[epidx].in_cables =
+				(1 << ms_ep->bNumEmbMIDIJack) - 1;
 			dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n",
-				    ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
+				ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
 		}
 	}
 	return 0;
@@ -1825,7 +1852,7 @@ static int roland_load_get(struct snd_kcontrol *kcontrol,
 static int roland_load_put(struct snd_kcontrol *kcontrol,
 			   struct snd_ctl_elem_value *value)
 {
-	struct snd_usb_midi* umidi = kcontrol->private_data;
+	struct snd_usb_midi *umidi = kcontrol->private_data;
 	int changed;
 
 	if (value->value.enumerated.item[0] > 1)
@@ -1851,11 +1878,11 @@ static struct snd_kcontrol_new roland_load_ctl = {
  * On Roland devices, use the second alternate setting to be able to use
  * the interrupt input endpoint.
  */
-static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi* umidi)
+static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi *umidi)
 {
-	struct usb_interface* intf;
+	struct usb_interface *intf;
 	struct usb_host_interface *hostif;
-	struct usb_interface_descriptor* intfd;
+	struct usb_interface_descriptor *intfd;
 
 	intf = umidi->iface;
 	if (!intf || intf->num_altsetting != 2)
@@ -1864,8 +1891,10 @@ static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi* umidi)
 	hostif = &intf->altsetting[1];
 	intfd = get_iface_desc(hostif);
 	if (intfd->bNumEndpoints != 2 ||
-	    (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
-	    (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+	    (get_endpoint(hostif, 0)->bmAttributes &
+	     USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
+	    (get_endpoint(hostif, 1)->bmAttributes &
+	     USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
 		return;
 
 	dev_dbg(&umidi->dev->dev, "switching to altsetting %d with int ep\n",
@@ -1881,14 +1910,14 @@ static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi* umidi)
 /*
  * Try to find any usable endpoints in the interface.
  */
-static int snd_usbmidi_detect_endpoints(struct snd_usb_midi* umidi,
-					struct snd_usb_midi_endpoint_info* endpoint,
+static int snd_usbmidi_detect_endpoints(struct snd_usb_midi *umidi,
+					struct snd_usb_midi_endpoint_info *endpoint,
 					int max_endpoints)
 {
-	struct usb_interface* intf;
+	struct usb_interface *intf;
 	struct usb_host_interface *hostif;
-	struct usb_interface_descriptor* intfd;
-	struct usb_endpoint_descriptor* epd;
+	struct usb_interface_descriptor *intfd;
+	struct usb_endpoint_descriptor *epd;
 	int i, out_eps = 0, in_eps = 0;
 
 	if (USB_ID_VENDOR(umidi->usb_id) == 0x0582)
@@ -1929,8 +1958,8 @@ static int snd_usbmidi_detect_endpoints(struct snd_usb_midi* umidi,
 /*
  * Detects the endpoints for one-port-per-endpoint protocols.
  */
-static int snd_usbmidi_detect_per_port_endpoints(struct snd_usb_midi* umidi,
-						 struct snd_usb_midi_endpoint_info* endpoints)
+static int snd_usbmidi_detect_per_port_endpoints(struct snd_usb_midi *umidi,
+						 struct snd_usb_midi_endpoint_info *endpoints)
 {
 	int err, i;
 
@@ -1947,13 +1976,13 @@ static int snd_usbmidi_detect_per_port_endpoints(struct snd_usb_midi* umidi,
 /*
  * Detects the endpoints and ports of Yamaha devices.
  */
-static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi,
-				     struct snd_usb_midi_endpoint_info* endpoint)
+static int snd_usbmidi_detect_yamaha(struct snd_usb_midi *umidi,
+				     struct snd_usb_midi_endpoint_info *endpoint)
 {
-	struct usb_interface* intf;
+	struct usb_interface *intf;
 	struct usb_host_interface *hostif;
-	struct usb_interface_descriptor* intfd;
-	uint8_t* cs_desc;
+	struct usb_interface_descriptor *intfd;
+	uint8_t *cs_desc;
 
 	intf = umidi->iface;
 	if (!intf)
@@ -1972,9 +2001,11 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi,
 	     cs_desc += cs_desc[0]) {
 		if (cs_desc[1] == USB_DT_CS_INTERFACE) {
 			if (cs_desc[2] == UAC_MIDI_IN_JACK)
-				endpoint->in_cables = (endpoint->in_cables << 1) | 1;
+				endpoint->in_cables =
+					(endpoint->in_cables << 1) | 1;
 			else if (cs_desc[2] == UAC_MIDI_OUT_JACK)
-				endpoint->out_cables = (endpoint->out_cables << 1) | 1;
+				endpoint->out_cables =
+					(endpoint->out_cables << 1) | 1;
 		}
 	}
 	if (!endpoint->in_cables && !endpoint->out_cables)
@@ -1986,12 +2017,12 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi,
 /*
  * Detects the endpoints and ports of Roland devices.
  */
-static int snd_usbmidi_detect_roland(struct snd_usb_midi* umidi,
-				     struct snd_usb_midi_endpoint_info* endpoint)
+static int snd_usbmidi_detect_roland(struct snd_usb_midi *umidi,
+				     struct snd_usb_midi_endpoint_info *endpoint)
 {
-	struct usb_interface* intf;
+	struct usb_interface *intf;
 	struct usb_host_interface *hostif;
-	u8* cs_desc;
+	u8 *cs_desc;
 
 	intf = umidi->iface;
 	if (!intf)
@@ -2024,14 +2055,14 @@ static int snd_usbmidi_detect_roland(struct snd_usb_midi* umidi,
 /*
  * Creates the endpoints and their ports for Midiman devices.
  */
-static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi,
-						struct snd_usb_midi_endpoint_info* endpoint)
+static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi *umidi,
+						struct snd_usb_midi_endpoint_info *endpoint)
 {
 	struct snd_usb_midi_endpoint_info ep_info;
-	struct usb_interface* intf;
+	struct usb_interface *intf;
 	struct usb_host_interface *hostif;
-	struct usb_interface_descriptor* intfd;
-	struct usb_endpoint_descriptor* epd;
+	struct usb_interface_descriptor *intfd;
+	struct usb_endpoint_descriptor *epd;
 	int cable, err;
 
 	intf = umidi->iface;
@@ -2068,39 +2099,50 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi,
 		epd = get_endpoint(hostif, 4);
 		if (!usb_endpoint_dir_out(epd) ||
 		    !usb_endpoint_xfer_bulk(epd)) {
-			dev_dbg(&umidi->dev->dev, "endpoint[4] isn't bulk output\n");
+			dev_dbg(&umidi->dev->dev,
+				"endpoint[4] isn't bulk output\n");
 			return -ENXIO;
 		}
 	}
 
-	ep_info.out_ep = get_endpoint(hostif, 2)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	ep_info.out_ep = get_endpoint(hostif, 2)->bEndpointAddress &
+		USB_ENDPOINT_NUMBER_MASK;
 	ep_info.out_interval = 0;
 	ep_info.out_cables = endpoint->out_cables & 0x5555;
-	err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]);
+	err = snd_usbmidi_out_endpoint_create(umidi, &ep_info,
+					      &umidi->endpoints[0]);
 	if (err < 0)
 		return err;
 
-	ep_info.in_ep = get_endpoint(hostif, 0)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	ep_info.in_ep = get_endpoint(hostif, 0)->bEndpointAddress &
+		USB_ENDPOINT_NUMBER_MASK;
 	ep_info.in_interval = get_endpoint(hostif, 0)->bInterval;
 	ep_info.in_cables = endpoint->in_cables;
-	err = snd_usbmidi_in_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]);
+	err = snd_usbmidi_in_endpoint_create(umidi, &ep_info,
+					     &umidi->endpoints[0]);
 	if (err < 0)
 		return err;
 
 	if (endpoint->out_cables > 0x0001) {
-		ep_info.out_ep = get_endpoint(hostif, 4)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+		ep_info.out_ep = get_endpoint(hostif, 4)->bEndpointAddress &
+			USB_ENDPOINT_NUMBER_MASK;
 		ep_info.out_cables = endpoint->out_cables & 0xaaaa;
-		err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[1]);
+		err = snd_usbmidi_out_endpoint_create(umidi, &ep_info,
+						      &umidi->endpoints[1]);
 		if (err < 0)
 			return err;
 	}
 
 	for (cable = 0; cable < 0x10; ++cable) {
 		if (endpoint->out_cables & (1 << cable))
-			snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_OUTPUT, cable,
+			snd_usbmidi_init_substream(umidi,
+						   SNDRV_RAWMIDI_STREAM_OUTPUT,
+						   cable,
 						   &umidi->endpoints[cable & 1].out->ports[cable].substream);
 		if (endpoint->in_cables & (1 << cable))
-			snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_INPUT, cable,
+			snd_usbmidi_init_substream(umidi,
+						   SNDRV_RAWMIDI_STREAM_INPUT,
+						   cable,
 						   &umidi->endpoints[0].in->ports[cable].substream);
 	}
 	return 0;
@@ -2110,7 +2152,7 @@ static struct snd_rawmidi_global_ops snd_usbmidi_ops = {
 	.get_port_info = snd_usbmidi_get_port_info,
 };
 
-static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi,
+static int snd_usbmidi_create_rawmidi(struct snd_usb_midi *umidi,
 				      int out_ports, int in_ports)
 {
 	struct snd_rawmidi *rmidi;
@@ -2128,8 +2170,10 @@ static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi,
 	rmidi->ops = &snd_usbmidi_ops;
 	rmidi->private_data = umidi;
 	rmidi->private_free = snd_usbmidi_rawmidi_free;
-	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usbmidi_output_ops);
-	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_usbmidi_input_ops);
+	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
+			    &snd_usbmidi_output_ops);
+	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
+			    &snd_usbmidi_input_ops);
 
 	umidi->rmidi = rmidi;
 	return 0;
@@ -2138,16 +2182,16 @@ static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi,
 /*
  * Temporarily stop input.
  */
-void snd_usbmidi_input_stop(struct list_head* p)
+void snd_usbmidi_input_stop(struct list_head *p)
 {
-	struct snd_usb_midi* umidi;
+	struct snd_usb_midi *umidi;
 	unsigned int i, j;
 
 	umidi = list_entry(p, struct snd_usb_midi, list);
 	if (!umidi->input_running)
 		return;
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
-		struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
+		struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i];
 		if (ep->in)
 			for (j = 0; j < INPUT_URBS; ++j)
 				usb_kill_urb(ep->in->urbs[j]);
@@ -2156,14 +2200,14 @@ void snd_usbmidi_input_stop(struct list_head* p)
 }
 EXPORT_SYMBOL(snd_usbmidi_input_stop);
 
-static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep)
+static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint *ep)
 {
 	unsigned int i;
 
 	if (!ep)
 		return;
 	for (i = 0; i < INPUT_URBS; ++i) {
-		struct urb* urb = ep->urbs[i];
+		struct urb *urb = ep->urbs[i];
 		urb->dev = ep->umidi->dev;
 		snd_usbmidi_submit_urb(urb, GFP_KERNEL);
 	}
@@ -2172,9 +2216,9 @@ static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep)
 /*
  * Resume input after a call to snd_usbmidi_input_stop().
  */
-void snd_usbmidi_input_start(struct list_head* p)
+void snd_usbmidi_input_start(struct list_head *p)
 {
-	struct snd_usb_midi* umidi;
+	struct snd_usb_midi *umidi;
 	int i;
 
 	umidi = list_entry(p, struct snd_usb_midi, list);
@@ -2187,14 +2231,42 @@ void snd_usbmidi_input_start(struct list_head* p)
 EXPORT_SYMBOL(snd_usbmidi_input_start);
 
 /*
+ * Prepare for suspend. Typically called from the USB suspend callback.
+ */
+void snd_usbmidi_suspend(struct list_head *p)
+{
+	struct snd_usb_midi *umidi;
+
+	umidi = list_entry(p, struct snd_usb_midi, list);
+	mutex_lock(&umidi->mutex);
+	snd_usbmidi_input_stop(p);
+	mutex_unlock(&umidi->mutex);
+}
+EXPORT_SYMBOL(snd_usbmidi_suspend);
+
+/*
+ * Resume. Typically called from the USB resume callback.
+ */
+void snd_usbmidi_resume(struct list_head *p)
+{
+	struct snd_usb_midi *umidi;
+
+	umidi = list_entry(p, struct snd_usb_midi, list);
+	mutex_lock(&umidi->mutex);
+	snd_usbmidi_input_start(p);
+	mutex_unlock(&umidi->mutex);
+}
+EXPORT_SYMBOL(snd_usbmidi_resume);
+
+/*
  * Creates and registers everything needed for a MIDI streaming interface.
  */
 int snd_usbmidi_create(struct snd_card *card,
-		       struct usb_interface* iface,
+		       struct usb_interface *iface,
 		       struct list_head *midi_list,
-		       const struct snd_usb_audio_quirk* quirk)
+		       const struct snd_usb_audio_quirk *quirk)
 {
-	struct snd_usb_midi* umidi;
+	struct snd_usb_midi *umidi;
 	struct snd_usb_midi_endpoint_info endpoints[MIDI_MAX_ENDPOINTS];
 	int out_ports, in_ports;
 	int i, err;
@@ -2292,7 +2364,8 @@ int snd_usbmidi_create(struct snd_card *card,
 		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
 		break;
 	default:
-		dev_err(&umidi->dev->dev, "invalid quirk type %d\n", quirk->type);
+		dev_err(&umidi->dev->dev, "invalid quirk type %d\n",
+			quirk->type);
 		err = -ENXIO;
 		break;
 	}
diff --git a/sound/usb/midi.h b/sound/usb/midi.h
index 2fca80b744c0..ad8a3211f8e7 100644
--- a/sound/usb/midi.h
+++ b/sound/usb/midi.h
@@ -43,8 +43,10 @@ int snd_usbmidi_create(struct snd_card *card,
 		       struct usb_interface *iface,
 		       struct list_head *midi_list,
 		       const struct snd_usb_audio_quirk *quirk);
-void snd_usbmidi_input_stop(struct list_head* p);
-void snd_usbmidi_input_start(struct list_head* p);
+void snd_usbmidi_input_stop(struct list_head *p);
+void snd_usbmidi_input_start(struct list_head *p);
 void snd_usbmidi_disconnect(struct list_head *p);
+void snd_usbmidi_suspend(struct list_head *p);
+void snd_usbmidi_resume(struct list_head *p);
 
 #endif /* __USBMIDI_H */
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 0b728d886f0d..2e4a9dbc51fa 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1340,12 +1340,11 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
 	 */
 	if (range > 384) {
 		usb_audio_warn(state->chip,
-			       "Warning! Unlikely big volume range (=%u), "
-			       "cval->res is probably wrong.",
+			       "Warning! Unlikely big volume range (=%u), cval->res is probably wrong.",
 			       range);
-		usb_audio_warn(state->chip, "[%d] FU [%s] ch = %d, "
-			       "val = %d/%d/%d", cval->id,
-			       kctl->id.name, cval->channels,
+		usb_audio_warn(state->chip,
+			       "[%d] FU [%s] ch = %d, val = %d/%d/%d",
+			       cval->id, kctl->id.name, cval->channels,
 			       cval->min, cval->max, cval->res);
 	}
 
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 7c57f2268dd7..19a921eb75f1 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -670,7 +670,7 @@ static int snd_usb_gamecon780_boot_quirk(struct usb_device *dev)
 	/* set the initial volume and don't change; other values are either
 	 * too loud or silent due to firmware bug (bko#65251)
 	 */
-	u8 buf[2] = { 0x74, 0xdc };
+	u8 buf[2] = { 0x74, 0xe3 };
 	return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
 			USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
 			UAC_FU_VOLUME << 8, 9 << 8, buf, 2);